mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-18 08:51:01 +00:00
Merge quagga mainline into the google ISIS code.
The steps were: $ git checkout google-is-is $ git merge quagga $ git checkout google-is-is -- isisd # Resolve conflicts in the following: lib/md5.h zebra/rt_netlink.c zebra/zebra_rib.c zebra/zserv.c Note that the content in the isisd directory is left unchanged in the merge. As a result, changes made to isisd as part of the following commits on the quagga mainline are dropped. #8ced4e82
is the merge base,e96b3121
is the current quagga master $ git log --oneline --reverse 8ced4e82..e96b3121 -- isisd5574999
isisd: fix crash on "no router isis" (BZ#536)8998075
isisd: raise hello rate for DIS (BZ#539)306ca83
isisd: include hash.h, not hash.cb82cdeb
delete CVS keywords2f65867
isisd: indent longopts arrayb511468
quagga: option "-z" ("--socket <path>") added05e54ee
build: delete .cvsignore filesb4e45f6
fix zebra protocol after MP-BGP changes7fd6cd8
isisd: fix circuit state machine907fd95
isisd: send proper LSP after DIS electiond034aa0
isisd: fix wrong next-hops from SPFc25eaff
isisd: unexpected kernel routing table (BZ#544)e6b03b7
isisd: implement MD5 circuit authentication
This commit is contained in:
commit
14d2bbaa3f
30
.cvsignore
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}
|
|
357
HACKING
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.
|
|
@ -14,6 +14,11 @@ collected in his git repository.
|
|||||||
|
|
||||||
* public git repositories
|
* 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/
|
** git remote add equinox git://git.spaceboyz.net/equinox/quagga.git/
|
||||||
|
|
||||||
This repository has topic branches for patches intended for inclusion
|
This repository has topic branches for patches intended for inclusion
|
||||||
|
462
HACKING.tex
Normal file
462
HACKING.tex
Normal file
@ -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}
|
@ -1,5 +1,3 @@
|
|||||||
# $Id$
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
Building and Installing Quagga from releases or snapshots:
|
Building and Installing Quagga from releases or snapshots:
|
||||||
|
|
||||||
|
14
Makefile.am
14
Makefile.am
@ -1,10 +1,10 @@
|
|||||||
## Process this file with automake to produce Makefile.in.
|
## 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@ \
|
@ISISD@ @WATCHQUAGGA@ @VTYSH@ @OSPFCLIENT@ @DOC@ m4 @pkgsrcdir@ \
|
||||||
redhat @SOLARIS@
|
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 \
|
isisd watchquagga vtysh ospfclient doc m4 pkgsrc redhat tests \
|
||||||
solaris
|
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/mrlg.cgi tools/rrcheck.pl tools/rrlookup.pl tools/zc.pl \
|
||||||
tools/zebra.el tools/multiple-bgpd.sh
|
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
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
7
babeld/.gitignore
vendored
Normal file
7
babeld/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
*
|
||||||
|
!*.c
|
||||||
|
!*.h
|
||||||
|
!LICENCE
|
||||||
|
!Makefile.am
|
||||||
|
!babeld.conf.sample
|
||||||
|
!.gitignore
|
36
babeld/LICENCE
Normal file
36
babeld/LICENCE
Normal file
@ -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
babeld/Makefile.am
Normal file
29
babeld/Makefile.am
Normal file
@ -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
babeld/babel_filter.c
Normal file
124
babeld/babel_filter.c
Normal file
@ -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
babeld/babel_filter.h
Normal file
49
babeld/babel_filter.h
Normal file
@ -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 */
|
1022
babeld/babel_interface.c
Normal file
1022
babeld/babel_interface.c
Normal file
File diff suppressed because it is too large
Load Diff
152
babeld/babel_interface.h
Normal file
152
babeld/babel_interface.h
Normal file
@ -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
babeld/babel_main.c
Normal file
532
babeld/babel_main.c
Normal file
@ -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
babeld/babel_main.h
Normal file
57
babeld/babel_main.h
Normal file
@ -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
babeld/babel_zebra.c
Normal file
378
babeld/babel_zebra.c
Normal file
@ -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
babeld/babel_zebra.h
Normal file
50
babeld/babel_zebra.h
Normal file
@ -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
babeld/babeld.c
Normal file
728
babeld/babeld.c
Normal file
@ -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) {
|
||||||
|
thread_cancel(babel_routing_process->t_update);
|
||||||
|
}
|
||||||
|
babel_routing_process->t_update =
|
||||||
|
thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
|
||||||
|
void
|
||||||
|
schedule_neighbours_check(int msecs, int override)
|
||||||
|
{
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
|
||||||
|
if(override)
|
||||||
|
check_neighbours_timeout = timeout;
|
||||||
|
else
|
||||||
|
timeval_min(&check_neighbours_timeout, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
resize_receive_buffer(int size)
|
||||||
|
{
|
||||||
|
if(size <= receive_buffer_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(receive_buffer == NULL) {
|
||||||
|
receive_buffer = malloc(size);
|
||||||
|
if(receive_buffer == NULL) {
|
||||||
|
zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
receive_buffer_size = size;
|
||||||
|
} else {
|
||||||
|
unsigned char *new;
|
||||||
|
new = realloc(receive_buffer, size);
|
||||||
|
if(new == NULL) {
|
||||||
|
zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
receive_buffer = new;
|
||||||
|
receive_buffer_size = size;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_distribute_update (struct distribute *dist)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
babel_interface_nfo *babel_ifp;
|
||||||
|
struct access_list *alist;
|
||||||
|
struct prefix_list *plist;
|
||||||
|
|
||||||
|
if (! dist->ifname)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ifp = if_lookup_by_name (dist->ifname);
|
||||||
|
if (ifp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
babel_ifp = babel_get_if_nfo(ifp);
|
||||||
|
|
||||||
|
if (dist->list[DISTRIBUTE_IN]) {
|
||||||
|
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
|
||||||
|
if (alist)
|
||||||
|
babel_ifp->list[BABEL_FILTER_IN] = alist;
|
||||||
|
else
|
||||||
|
babel_ifp->list[BABEL_FILTER_IN] = NULL;
|
||||||
|
} else {
|
||||||
|
babel_ifp->list[BABEL_FILTER_IN] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist->list[DISTRIBUTE_OUT]) {
|
||||||
|
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
|
||||||
|
if (alist)
|
||||||
|
babel_ifp->list[BABEL_FILTER_OUT] = alist;
|
||||||
|
else
|
||||||
|
babel_ifp->list[BABEL_FILTER_OUT] = NULL;
|
||||||
|
} else {
|
||||||
|
babel_ifp->list[BABEL_FILTER_OUT] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist->prefix[DISTRIBUTE_IN]) {
|
||||||
|
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
|
||||||
|
if (plist)
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_IN] = plist;
|
||||||
|
else
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
|
||||||
|
} else {
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dist->prefix[DISTRIBUTE_OUT]) {
|
||||||
|
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
|
||||||
|
if (plist)
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
|
||||||
|
else
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
|
||||||
|
} else {
|
||||||
|
babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_distribute_update_interface (struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct distribute *dist;
|
||||||
|
|
||||||
|
dist = distribute_lookup (ifp->name);
|
||||||
|
if (dist)
|
||||||
|
babel_distribute_update (dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update all interface's distribute list. */
|
||||||
|
static void
|
||||||
|
babel_distribute_update_all (struct prefix_list *notused)
|
||||||
|
{
|
||||||
|
struct interface *ifp;
|
||||||
|
struct listnode *node;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
|
||||||
|
babel_distribute_update_interface (ifp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
babel_distribute_update_all_wrapper (struct access_list *notused)
|
||||||
|
{
|
||||||
|
babel_distribute_update_all(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* [Command] */
|
||||||
|
DEFUN (router_babel,
|
||||||
|
router_babel_cmd,
|
||||||
|
"router babel",
|
||||||
|
"Enable a routing process\n"
|
||||||
|
"Make Babel instance command\n"
|
||||||
|
"No attributes\n")
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
vty->node = BABEL_NODE;
|
||||||
|
|
||||||
|
if (!babel_routing_process) {
|
||||||
|
ret = babel_create_routing_process ();
|
||||||
|
|
||||||
|
/* Notice to user we couldn't create Babel. */
|
||||||
|
if (ret < 0) {
|
||||||
|
zlog_warn ("can't create Babel");
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [Command] */
|
||||||
|
DEFUN (no_router_babel,
|
||||||
|
no_router_babel_cmd,
|
||||||
|
"no router babel",
|
||||||
|
NO_STR
|
||||||
|
"Disable a routing process\n"
|
||||||
|
"Remove Babel instance command\n"
|
||||||
|
"No attributes\n")
|
||||||
|
{
|
||||||
|
if(babel_routing_process)
|
||||||
|
babel_clean_routing_process();
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [Babel Command] */
|
||||||
|
DEFUN (babel_set_resend_delay,
|
||||||
|
babel_set_resend_delay_cmd,
|
||||||
|
"babel resend-delay <20-655340>",
|
||||||
|
"Babel commands\n"
|
||||||
|
"Time before resending a message\n"
|
||||||
|
"Milliseconds\n")
|
||||||
|
{
|
||||||
|
int interval;
|
||||||
|
|
||||||
|
VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
|
||||||
|
|
||||||
|
resend_delay = interval;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
babeld_quagga_init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
install_node(&cmd_babel_node, &babel_config_write);
|
||||||
|
|
||||||
|
install_element(CONFIG_NODE, &router_babel_cmd);
|
||||||
|
install_element(CONFIG_NODE, &no_router_babel_cmd);
|
||||||
|
|
||||||
|
install_default(BABEL_NODE);
|
||||||
|
install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
|
||||||
|
|
||||||
|
babel_if_init();
|
||||||
|
|
||||||
|
/* Access list install. */
|
||||||
|
access_list_init ();
|
||||||
|
access_list_add_hook (babel_distribute_update_all_wrapper);
|
||||||
|
access_list_delete_hook (babel_distribute_update_all_wrapper);
|
||||||
|
|
||||||
|
/* Prefix list initialize.*/
|
||||||
|
prefix_list_init ();
|
||||||
|
prefix_list_add_hook (babel_distribute_update_all);
|
||||||
|
prefix_list_delete_hook (babel_distribute_update_all);
|
||||||
|
|
||||||
|
/* Distribute list install. */
|
||||||
|
distribute_list_init (BABEL_NODE);
|
||||||
|
distribute_list_add_hook (babel_distribute_update);
|
||||||
|
distribute_list_delete_hook (babel_distribute_update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
|
||||||
|
|
||||||
|
int
|
||||||
|
input_filter(const unsigned char *id,
|
||||||
|
const unsigned char *prefix, unsigned short plen,
|
||||||
|
const unsigned char *neigh, unsigned int ifindex)
|
||||||
|
{
|
||||||
|
return babel_filter(0, prefix, plen, ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
output_filter(const unsigned char *id, const unsigned char *prefix,
|
||||||
|
unsigned short plen, unsigned int ifindex)
|
||||||
|
{
|
||||||
|
return babel_filter(1, prefix, plen, ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There's no redistribute filter in Quagga -- the zebra daemon does its
|
||||||
|
own filtering. */
|
||||||
|
int
|
||||||
|
redistribute_filter(const unsigned char *prefix, unsigned short plen,
|
||||||
|
unsigned int ifindex, int proto)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
30
babeld/babeld.conf.sample
Normal file
30
babeld/babeld.conf.sample
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
debug babel common
|
||||||
|
!debug babel kernel
|
||||||
|
!debug babel filter
|
||||||
|
!debug babel timeout
|
||||||
|
!debug babel interface
|
||||||
|
!debug babel route
|
||||||
|
!debug babel all
|
||||||
|
|
||||||
|
router babel
|
||||||
|
! network wlan0
|
||||||
|
! network eth0
|
||||||
|
! redistribute kernel
|
||||||
|
! no redistribute static
|
||||||
|
|
||||||
|
! The defaults are fine for a wireless interface
|
||||||
|
|
||||||
|
!interface wlan0
|
||||||
|
|
||||||
|
! A few optimisation tweaks are optional but recommended on a wired interface
|
||||||
|
! Disable link quality estimation, enable split horizon processing, and
|
||||||
|
! increase the hello and update intervals.
|
||||||
|
|
||||||
|
!interface eth0
|
||||||
|
! babel wired
|
||||||
|
! babel split-horizon
|
||||||
|
! babel hello-interval 12000
|
||||||
|
! babel update-interval 36000
|
||||||
|
|
||||||
|
! log file /var/log/quagga/babeld.log
|
||||||
|
log stdout
|
141
babeld/babeld.h
Normal file
141
babeld/babeld.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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_BABELD_H
|
||||||
|
#define BABEL_BABELD_H
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "vty.h"
|
||||||
|
|
||||||
|
#define INFINITY ((unsigned short)(~0))
|
||||||
|
|
||||||
|
#ifndef RTPROT_BABEL
|
||||||
|
#define RTPROT_BABEL 42
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTPROT_BABEL_LOCAL -2
|
||||||
|
|
||||||
|
#undef MAX
|
||||||
|
#undef MIN
|
||||||
|
|
||||||
|
#define MAX(x,y) ((x)<=(y)?(y):(x))
|
||||||
|
#define MIN(x,y) ((x)<=(y)?(x):(y))
|
||||||
|
|
||||||
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||||
|
/* nothing */
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define inline __inline
|
||||||
|
#if (__GNUC__ >= 3)
|
||||||
|
#define restrict __restrict
|
||||||
|
#else
|
||||||
|
#define restrict /**/
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define inline /**/
|
||||||
|
#define restrict /**/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
|
#define ATTRIBUTE(x) __attribute__ (x)
|
||||||
|
#define LIKELY(_x) __builtin_expect(!!(_x), 1)
|
||||||
|
#define UNLIKELY(_x) __builtin_expect(!!(_x), 0)
|
||||||
|
#else
|
||||||
|
#define ATTRIBUTE(x) /**/
|
||||||
|
#define LIKELY(_x) !!(_x)
|
||||||
|
#define UNLIKELY(_x) !!(_x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
|
||||||
|
#define COLD __attribute__ ((cold))
|
||||||
|
#else
|
||||||
|
#define COLD /**/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IF_NAMESIZE
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#else
|
||||||
|
#ifndef VALGRIND_MAKE_MEM_UNDEFINED
|
||||||
|
#define VALGRIND_MAKE_MEM_UNDEFINED(a, b) do {} while(0)
|
||||||
|
#endif
|
||||||
|
#ifndef VALGRIND_CHECK_MEM_IS_DEFINED
|
||||||
|
#define VALGRIND_CHECK_MEM_IS_DEFINED(a, b) do {} while(0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define BABEL_VTY_PORT 2609
|
||||||
|
#define BABEL_DEFAULT_CONFIG "babeld.conf"
|
||||||
|
#define BABEL_VERSION "0.1 for quagga"
|
||||||
|
|
||||||
|
/* Values in milliseconds */
|
||||||
|
#define BABEL_DEFAULT_HELLO_INTERVAL 4000
|
||||||
|
#define BABEL_DEFAULT_UPDATE_INTERVAL 16000
|
||||||
|
#define BABEL_DEFAULT_RESEND_DELAY 2000
|
||||||
|
|
||||||
|
|
||||||
|
/* Babel socket. */
|
||||||
|
extern int protocol_socket;
|
||||||
|
|
||||||
|
/* Babel structure. */
|
||||||
|
struct babel
|
||||||
|
{
|
||||||
|
/* Babel threads. */
|
||||||
|
struct thread *t_read; /* on Babel protocol's socket */
|
||||||
|
struct thread *t_update; /* timers */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern void babeld_quagga_init(void);
|
||||||
|
extern int input_filter(const unsigned char *id,
|
||||||
|
const unsigned char *prefix, unsigned short plen,
|
||||||
|
const unsigned char *neigh, unsigned int ifindex);
|
||||||
|
extern int output_filter(const unsigned char *id, const unsigned char *prefix,
|
||||||
|
unsigned short plen, unsigned int ifindex);
|
||||||
|
extern int redistribute_filter(const unsigned char *prefix, unsigned short plen,
|
||||||
|
unsigned int ifindex, int proto);
|
||||||
|
extern int resize_receive_buffer(int size);
|
||||||
|
extern void schedule_neighbours_check(int msecs, int override);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* BABEL_BABELD_H */
|
76
babeld/kernel.c
Normal file
76
babeld/kernel.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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 2007, 2008 by Grégoire Henry, Julien Cristau 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 <sys/time.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "babeld.h"
|
||||||
|
|
||||||
|
#include "kernel_zebra.c"
|
||||||
|
|
||||||
|
/* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
|
||||||
|
available, falls back to gettimeofday but enforces monotonicity. */
|
||||||
|
int
|
||||||
|
gettime(struct timeval *tv)
|
||||||
|
{
|
||||||
|
return quagga_gettime(QUAGGA_CLK_MONOTONIC, tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
|
||||||
|
caller will deal with gracefully. */
|
||||||
|
|
||||||
|
int
|
||||||
|
read_random_bytes(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
fd = open("/dev/urandom", O_RDONLY);
|
||||||
|
if(fd < 0) {
|
||||||
|
rc = -1;
|
||||||
|
} else {
|
||||||
|
rc = read(fd, buf, len);
|
||||||
|
if(rc < 0 || (unsigned) rc < len)
|
||||||
|
rc = -1;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
69
babeld/kernel.h
Normal file
69
babeld/kernel.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "if.h"
|
||||||
|
|
||||||
|
#define KERNEL_INFINITY 0xFFFF
|
||||||
|
|
||||||
|
struct kernel_route {
|
||||||
|
unsigned char prefix[16];
|
||||||
|
int plen;
|
||||||
|
int metric;
|
||||||
|
unsigned int ifindex;
|
||||||
|
int proto;
|
||||||
|
unsigned char gw[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ROUTE_FLUSH 0
|
||||||
|
#define ROUTE_ADD 1
|
||||||
|
#define ROUTE_MODIFY 2
|
||||||
|
|
||||||
|
extern int export_table, import_table;
|
||||||
|
|
||||||
|
int kernel_interface_operational(struct interface *interface);
|
||||||
|
int kernel_interface_mtu(struct interface *interface);
|
||||||
|
int kernel_interface_wireless(struct interface *interface);
|
||||||
|
int kernel_route(int operation, const unsigned char *dest, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex, unsigned int metric,
|
||||||
|
const unsigned char *newgate, int newifindex,
|
||||||
|
unsigned int newmetric);
|
||||||
|
int if_eui64(char *ifname, int ifindex, unsigned char *eui);
|
||||||
|
int gettime(struct timeval *tv);
|
||||||
|
int read_random_bytes(void *buf, size_t len);
|
275
babeld/kernel_zebra.c
Normal file
275
babeld/kernel_zebra.c
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* 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 <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "prefix.h"
|
||||||
|
#include "zclient.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "privs.h"
|
||||||
|
#include "command.h"
|
||||||
|
#include "vty.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "babel_interface.h"
|
||||||
|
#include "babel_zebra.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
kernel_route_v4(int add, const unsigned char *pref, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex,
|
||||||
|
unsigned int metric);
|
||||||
|
static int
|
||||||
|
kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex,
|
||||||
|
unsigned int metric);
|
||||||
|
|
||||||
|
int
|
||||||
|
kernel_interface_operational(struct interface *interface)
|
||||||
|
{
|
||||||
|
return if_is_operative(interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kernel_interface_mtu(struct interface *interface)
|
||||||
|
{
|
||||||
|
return MIN(interface->mtu, interface->mtu6);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kernel_interface_wireless(struct interface *interface)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kernel_route(int operation, const unsigned char *pref, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex, unsigned int metric,
|
||||||
|
const unsigned char *newgate, int newifindex,
|
||||||
|
unsigned int newmetric)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int ipv4;
|
||||||
|
|
||||||
|
/* Check that the protocol family is consistent. */
|
||||||
|
if(plen >= 96 && v4mapped(pref)) {
|
||||||
|
if(!v4mapped(gate)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ipv4 = 1;
|
||||||
|
} else {
|
||||||
|
if(v4mapped(gate)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ipv4 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
case ROUTE_ADD:
|
||||||
|
return ipv4 ?
|
||||||
|
kernel_route_v4(1, pref, plen, gate, ifindex, metric):
|
||||||
|
kernel_route_v6(1, pref, plen, gate, ifindex, metric);
|
||||||
|
break;
|
||||||
|
case ROUTE_FLUSH:
|
||||||
|
return ipv4 ?
|
||||||
|
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
|
||||||
|
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
|
||||||
|
break;
|
||||||
|
case ROUTE_MODIFY:
|
||||||
|
if(newmetric == metric && memcmp(newgate, gate, 16) == 0 &&
|
||||||
|
newifindex == ifindex)
|
||||||
|
return 0;
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new.");
|
||||||
|
rc = ipv4 ?
|
||||||
|
kernel_route_v4(0, pref, plen, gate, ifindex, metric):
|
||||||
|
kernel_route_v6(0, pref, plen, gate, ifindex, metric);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = ipv4 ?
|
||||||
|
kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric):
|
||||||
|
kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zlog_err("this should never appens (false value - kernel_route)");
|
||||||
|
assert(0);
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kernel_route_v4(int add,
|
||||||
|
const unsigned char *pref, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex, unsigned int metric)
|
||||||
|
{
|
||||||
|
struct zapi_ipv4 api; /* quagga's communication system */
|
||||||
|
struct prefix_ipv4 quagga_prefix; /* quagga's prefix */
|
||||||
|
struct in_addr babel_prefix_addr; /* babeld's prefix addr */
|
||||||
|
struct in_addr nexthop; /* next router to go */
|
||||||
|
struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */
|
||||||
|
|
||||||
|
/* convert to be understandable by quagga */
|
||||||
|
/* convert given addresses */
|
||||||
|
uchar_to_inaddr(&babel_prefix_addr, pref);
|
||||||
|
uchar_to_inaddr(&nexthop, gate);
|
||||||
|
|
||||||
|
/* make prefix structure */
|
||||||
|
memset (&quagga_prefix, 0, sizeof(quagga_prefix));
|
||||||
|
quagga_prefix.family = AF_INET;
|
||||||
|
IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
|
||||||
|
quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */
|
||||||
|
apply_mask_ipv4(&quagga_prefix);
|
||||||
|
|
||||||
|
api.type = ZEBRA_ROUTE_BABEL;
|
||||||
|
api.flags = 0;
|
||||||
|
api.message = 0;
|
||||||
|
api.safi = SAFI_UNICAST;
|
||||||
|
|
||||||
|
/* Unlike the native Linux and BSD interfaces, Quagga doesn't like
|
||||||
|
there to be both and IPv4 nexthop and an ifindex. Omit the
|
||||||
|
ifindex, and assume that the connected prefixes be set up
|
||||||
|
correctly. */
|
||||||
|
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
|
api.ifindex_num = 0;
|
||||||
|
if(metric >= KERNEL_INFINITY) {
|
||||||
|
api.flags = ZEBRA_FLAG_BLACKHOLE;
|
||||||
|
api.nexthop_num = 0;
|
||||||
|
} else {
|
||||||
|
api.nexthop_num = 1;
|
||||||
|
api.nexthop = &nexthop_pointer;
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||||
|
api.metric = metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra",
|
||||||
|
add ? "adding" : "removing" );
|
||||||
|
return zapi_ipv4_route (add ? ZEBRA_IPV4_ROUTE_ADD :
|
||||||
|
ZEBRA_IPV4_ROUTE_DELETE,
|
||||||
|
zclient, &quagga_prefix, &api);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
kernel_route_v6(int add, const unsigned char *pref, unsigned short plen,
|
||||||
|
const unsigned char *gate, int ifindex, unsigned int metric)
|
||||||
|
{
|
||||||
|
unsigned int tmp_ifindex = ifindex; /* (for typing) */
|
||||||
|
struct zapi_ipv6 api; /* quagga's communication system */
|
||||||
|
struct prefix_ipv6 quagga_prefix; /* quagga's prefix */
|
||||||
|
struct in6_addr babel_prefix_addr; /* babeld's prefix addr */
|
||||||
|
struct in6_addr nexthop; /* next router to go */
|
||||||
|
struct in6_addr *nexthop_pointer = &nexthop;
|
||||||
|
|
||||||
|
/* convert to be understandable by quagga */
|
||||||
|
/* convert given addresses */
|
||||||
|
uchar_to_in6addr(&babel_prefix_addr, pref);
|
||||||
|
uchar_to_in6addr(&nexthop, gate);
|
||||||
|
|
||||||
|
/* make prefix structure */
|
||||||
|
memset (&quagga_prefix, 0, sizeof(quagga_prefix));
|
||||||
|
quagga_prefix.family = AF_INET6;
|
||||||
|
IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr);
|
||||||
|
quagga_prefix.prefixlen = plen;
|
||||||
|
apply_mask_ipv6(&quagga_prefix);
|
||||||
|
|
||||||
|
api.type = ZEBRA_ROUTE_BABEL;
|
||||||
|
api.flags = 0;
|
||||||
|
api.message = 0;
|
||||||
|
api.safi = SAFI_UNICAST;
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
|
if(metric >= KERNEL_INFINITY) {
|
||||||
|
api.flags = ZEBRA_FLAG_BLACKHOLE;
|
||||||
|
api.nexthop_num = 0;
|
||||||
|
api.ifindex_num = 0;
|
||||||
|
} else {
|
||||||
|
api.nexthop_num = 1;
|
||||||
|
api.nexthop = &nexthop_pointer;
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX);
|
||||||
|
api.ifindex_num = 1;
|
||||||
|
api.ifindex = &tmp_ifindex;
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||||
|
api.metric = metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra",
|
||||||
|
add ? "adding" : "removing" );
|
||||||
|
return zapi_ipv6_route (add ? ZEBRA_IPV6_ROUTE_ADD :
|
||||||
|
ZEBRA_IPV6_ROUTE_DELETE,
|
||||||
|
zclient, &quagga_prefix, &api);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
if_eui64(char *ifname, int ifindex, unsigned char *eui)
|
||||||
|
{
|
||||||
|
struct interface *ifp = if_lookup_by_index(ifindex);
|
||||||
|
if (ifp == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_STRUCT_SOCKADDR_DL
|
||||||
|
u_char len = ifp->sdl.sdl_alen;
|
||||||
|
char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen;
|
||||||
|
#else
|
||||||
|
u_char len = (u_char) ifp->hw_addr_len;
|
||||||
|
char *tmp = (void*) ifp->hw_addr;
|
||||||
|
#endif
|
||||||
|
if (len == 8) {
|
||||||
|
memcpy(eui, tmp, 8);
|
||||||
|
eui[0] ^= 2;
|
||||||
|
} else if (len == 6) {
|
||||||
|
memcpy(eui, tmp, 3);
|
||||||
|
eui[3] = 0xFF;
|
||||||
|
eui[4] = 0xFE;
|
||||||
|
memcpy(eui+5, tmp+3, 3);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
1561
babeld/message.c
Normal file
1561
babeld/message.c
Normal file
File diff suppressed because it is too large
Load Diff
111
babeld/message.h
Normal file
111
babeld/message.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BABEL_MESSAGE_H
|
||||||
|
#define BABEL_MESSAGE_H
|
||||||
|
|
||||||
|
#include "babel_interface.h"
|
||||||
|
|
||||||
|
#define MAX_BUFFERED_UPDATES 200
|
||||||
|
|
||||||
|
#define BUCKET_TOKENS_MAX 200
|
||||||
|
#define BUCKET_TOKENS_PER_SEC 40
|
||||||
|
|
||||||
|
#define MESSAGE_PAD1 0
|
||||||
|
#define MESSAGE_PADN 1
|
||||||
|
#define MESSAGE_ACK_REQ 2
|
||||||
|
#define MESSAGE_ACK 3
|
||||||
|
#define MESSAGE_HELLO 4
|
||||||
|
#define MESSAGE_IHU 5
|
||||||
|
#define MESSAGE_ROUTER_ID 6
|
||||||
|
#define MESSAGE_NH 7
|
||||||
|
#define MESSAGE_UPDATE 8
|
||||||
|
#define MESSAGE_REQUEST 9
|
||||||
|
#define MESSAGE_MH_REQUEST 10
|
||||||
|
|
||||||
|
|
||||||
|
extern unsigned short myseqno;
|
||||||
|
extern struct timeval seqno_time;
|
||||||
|
|
||||||
|
extern int broadcast_ihu;
|
||||||
|
extern int split_horizon;
|
||||||
|
|
||||||
|
extern unsigned char packet_header[4];
|
||||||
|
|
||||||
|
extern struct neighbour *unicast_neighbour;
|
||||||
|
extern struct timeval unicast_flush_timeout;
|
||||||
|
|
||||||
|
void parse_packet(const unsigned char *from, struct interface *ifp,
|
||||||
|
const unsigned char *packet, int packetlen);
|
||||||
|
void flushbuf(struct interface *ifp);
|
||||||
|
void flushupdates(struct interface *ifp);
|
||||||
|
void send_ack(struct neighbour *neigh, unsigned short nonce,
|
||||||
|
unsigned short interval);
|
||||||
|
void send_hello_noupdate(struct interface *ifp, unsigned interval);
|
||||||
|
void send_hello(struct interface *ifp);
|
||||||
|
void flush_unicast(int dofree);
|
||||||
|
void send_update(struct interface *ifp, int urgent,
|
||||||
|
const unsigned char *prefix, unsigned char plen);
|
||||||
|
void send_update_resend(struct interface *ifp,
|
||||||
|
const unsigned char *prefix, unsigned char plen);
|
||||||
|
void send_wildcard_retraction(struct interface *ifp);
|
||||||
|
void update_myseqno(void);
|
||||||
|
void send_self_update(struct interface *ifp);
|
||||||
|
void send_ihu(struct neighbour *neigh, struct interface *ifp);
|
||||||
|
void send_marginal_ihu(struct interface *ifp);
|
||||||
|
void send_request(struct interface *ifp,
|
||||||
|
const unsigned char *prefix, unsigned char plen);
|
||||||
|
void send_unicast_request(struct neighbour *neigh,
|
||||||
|
const unsigned char *prefix, unsigned char plen);
|
||||||
|
void send_multihop_request(struct interface *ifp,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
unsigned short hop_count);
|
||||||
|
void
|
||||||
|
send_unicast_multihop_request(struct neighbour *neigh,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
unsigned short hop_count);
|
||||||
|
void send_request_resend(struct neighbour *neigh,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, unsigned char *id);
|
||||||
|
void handle_request(struct neighbour *neigh, const unsigned char *prefix,
|
||||||
|
unsigned char plen, unsigned char hop_count,
|
||||||
|
unsigned short seqno, const unsigned char *id);
|
||||||
|
|
||||||
|
#endif
|
343
babeld/neighbour.c
Normal file
343
babeld/neighbour.c
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "if.h"
|
||||||
|
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "babel_interface.h"
|
||||||
|
#include "neighbour.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include "route.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include "resend.h"
|
||||||
|
|
||||||
|
struct neighbour *neighs = NULL;
|
||||||
|
|
||||||
|
static struct neighbour *
|
||||||
|
find_neighbour_nocreate(const unsigned char *address, struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct neighbour *neigh;
|
||||||
|
FOR_ALL_NEIGHBOURS(neigh) {
|
||||||
|
if(memcmp(address, neigh->address, 16) == 0 &&
|
||||||
|
neigh->ifp == ifp)
|
||||||
|
return neigh;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_neighbour(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
flush_neighbour_routes(neigh);
|
||||||
|
if(unicast_neighbour == neigh)
|
||||||
|
flush_unicast(1);
|
||||||
|
flush_resends(neigh);
|
||||||
|
|
||||||
|
if(neighs == neigh) {
|
||||||
|
neighs = neigh->next;
|
||||||
|
} else {
|
||||||
|
struct neighbour *previous = neighs;
|
||||||
|
while(previous->next != neigh)
|
||||||
|
previous = previous->next;
|
||||||
|
previous->next = neigh->next;
|
||||||
|
}
|
||||||
|
free(neigh);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct neighbour *
|
||||||
|
find_neighbour(const unsigned char *address, struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct neighbour *neigh;
|
||||||
|
const struct timeval zero = {0, 0};
|
||||||
|
|
||||||
|
neigh = find_neighbour_nocreate(address, ifp);
|
||||||
|
if(neigh)
|
||||||
|
return neigh;
|
||||||
|
|
||||||
|
debugf(BABEL_DEBUG_COMMON,"Creating neighbour %s on %s.",
|
||||||
|
format_address(address), ifp->name);
|
||||||
|
|
||||||
|
neigh = malloc(sizeof(struct neighbour));
|
||||||
|
if(neigh == NULL) {
|
||||||
|
zlog_err("malloc(neighbour): %s", safe_strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
neigh->hello_seqno = -1;
|
||||||
|
memcpy(neigh->address, address, 16);
|
||||||
|
neigh->reach = 0;
|
||||||
|
neigh->txcost = INFINITY;
|
||||||
|
neigh->ihu_time = babel_now;
|
||||||
|
neigh->hello_time = zero;
|
||||||
|
neigh->hello_interval = 0;
|
||||||
|
neigh->ihu_interval = 0;
|
||||||
|
neigh->ifp = ifp;
|
||||||
|
neigh->next = neighs;
|
||||||
|
neighs = neigh;
|
||||||
|
send_hello(ifp);
|
||||||
|
return neigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recompute a neighbour's rxcost. Return true if anything changed.
|
||||||
|
This does not call local_notify_neighbour, see update_neighbour_metric. */
|
||||||
|
int
|
||||||
|
update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
|
||||||
|
{
|
||||||
|
int missed_hellos;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if(hello < 0) {
|
||||||
|
if(neigh->hello_interval <= 0)
|
||||||
|
return rc;
|
||||||
|
missed_hellos =
|
||||||
|
((int)timeval_minus_msec(&babel_now, &neigh->hello_time) -
|
||||||
|
neigh->hello_interval * 7) /
|
||||||
|
(neigh->hello_interval * 10);
|
||||||
|
if(missed_hellos <= 0)
|
||||||
|
return rc;
|
||||||
|
timeval_add_msec(&neigh->hello_time, &neigh->hello_time,
|
||||||
|
missed_hellos * neigh->hello_interval * 10);
|
||||||
|
} else {
|
||||||
|
if(neigh->hello_seqno >= 0 && neigh->reach > 0) {
|
||||||
|
missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1;
|
||||||
|
if(missed_hellos < -8) {
|
||||||
|
/* Probably a neighbour that rebooted and lost its seqno.
|
||||||
|
Reboot the universe. */
|
||||||
|
neigh->reach = 0;
|
||||||
|
missed_hellos = 0;
|
||||||
|
rc = 1;
|
||||||
|
} else if(missed_hellos < 0) {
|
||||||
|
if(hello_interval > neigh->hello_interval) {
|
||||||
|
/* This neighbour has increased its hello interval,
|
||||||
|
and we didn't notice. */
|
||||||
|
neigh->reach <<= -missed_hellos;
|
||||||
|
missed_hellos = 0;
|
||||||
|
} else {
|
||||||
|
/* Late hello. Probably due to the link layer buffering
|
||||||
|
packets during a link outage. Ignore it, but reset
|
||||||
|
the expected seqno. */
|
||||||
|
neigh->hello_seqno = hello;
|
||||||
|
hello = -1;
|
||||||
|
missed_hellos = 0;
|
||||||
|
}
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
missed_hellos = 0;
|
||||||
|
}
|
||||||
|
neigh->hello_time = babel_now;
|
||||||
|
neigh->hello_interval = hello_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(missed_hellos > 0) {
|
||||||
|
neigh->reach >>= missed_hellos;
|
||||||
|
neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos);
|
||||||
|
missed_hellos = 0;
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hello >= 0) {
|
||||||
|
neigh->hello_seqno = hello;
|
||||||
|
neigh->reach >>= 1;
|
||||||
|
neigh->reach |= 0x8000;
|
||||||
|
if((neigh->reach & 0xFC00) != 0xFC00)
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure to give neighbours some feedback early after association */
|
||||||
|
if((neigh->reach & 0xBF00) == 0x8000) {
|
||||||
|
/* A new neighbour */
|
||||||
|
send_hello(neigh->ifp);
|
||||||
|
} else {
|
||||||
|
/* Don't send hellos, in order to avoid a positive feedback loop. */
|
||||||
|
int a = (neigh->reach & 0xC000);
|
||||||
|
int b = (neigh->reach & 0x3000);
|
||||||
|
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
|
||||||
|
/* Reachability is either 1100 or 0011 */
|
||||||
|
send_self_update(neigh->ifp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((neigh->reach & 0xFC00) == 0xC000) {
|
||||||
|
/* This is a newish neighbour, let's request a full route dump.
|
||||||
|
We ought to avoid this when the network is dense */
|
||||||
|
send_unicast_request(neigh, NULL, 0);
|
||||||
|
send_ihu(neigh, NULL);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
reset_txcost(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
unsigned delay;
|
||||||
|
|
||||||
|
delay = timeval_minus_msec(&babel_now, &neigh->ihu_time);
|
||||||
|
|
||||||
|
if(neigh->ihu_interval > 0 && delay < neigh->ihu_interval * 10U * 3U)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* If we're losing a lot of packets, we probably lost an IHU too */
|
||||||
|
if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 ||
|
||||||
|
(neigh->ihu_interval > 0 &&
|
||||||
|
delay >= neigh->ihu_interval * 10U * 10U)) {
|
||||||
|
neigh->txcost = INFINITY;
|
||||||
|
neigh->ihu_time = babel_now;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
neighbour_txcost(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
return neigh->txcost;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
check_neighbours()
|
||||||
|
{
|
||||||
|
struct neighbour *neigh;
|
||||||
|
int changed, rc;
|
||||||
|
unsigned msecs = 50000;
|
||||||
|
|
||||||
|
debugf(BABEL_DEBUG_COMMON,"Checking neighbours.");
|
||||||
|
|
||||||
|
neigh = neighs;
|
||||||
|
while(neigh) {
|
||||||
|
changed = update_neighbour(neigh, -1, 0);
|
||||||
|
|
||||||
|
if(neigh->reach == 0 ||
|
||||||
|
neigh->hello_time.tv_sec > babel_now.tv_sec || /* clock stepped */
|
||||||
|
timeval_minus_msec(&babel_now, &neigh->hello_time) > 300000) {
|
||||||
|
struct neighbour *old = neigh;
|
||||||
|
neigh = neigh->next;
|
||||||
|
flush_neighbour(old);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = reset_txcost(neigh);
|
||||||
|
changed = changed || rc;
|
||||||
|
|
||||||
|
update_neighbour_metric(neigh, changed);
|
||||||
|
|
||||||
|
if(neigh->hello_interval > 0)
|
||||||
|
msecs = MIN(msecs, neigh->hello_interval * 10U);
|
||||||
|
if(neigh->ihu_interval > 0)
|
||||||
|
msecs = MIN(msecs, neigh->ihu_interval * 10U);
|
||||||
|
neigh = neigh->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
neighbour_rxcost(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
unsigned delay;
|
||||||
|
unsigned short reach = neigh->reach;
|
||||||
|
|
||||||
|
delay = timeval_minus_msec(&babel_now, &neigh->hello_time);
|
||||||
|
|
||||||
|
if((reach & 0xFFF0) == 0 || delay >= 180000) {
|
||||||
|
return INFINITY;
|
||||||
|
} else if(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) {
|
||||||
|
int sreach =
|
||||||
|
((reach & 0x8000) >> 2) +
|
||||||
|
((reach & 0x4000) >> 1) +
|
||||||
|
(reach & 0x3FFF);
|
||||||
|
/* 0 <= sreach <= 0x7FFF */
|
||||||
|
int cost = (0x8000 * babel_get_if_nfo(neigh->ifp)->cost) / (sreach + 1);
|
||||||
|
/* cost >= interface->cost */
|
||||||
|
if(delay >= 40000)
|
||||||
|
cost = (cost * (delay - 20000) + 10000) / 20000;
|
||||||
|
return MIN(cost, INFINITY);
|
||||||
|
} else {
|
||||||
|
/* To lose one hello is a misfortune, to lose two is carelessness. */
|
||||||
|
if((reach & 0xC000) == 0xC000)
|
||||||
|
return babel_get_if_nfo(neigh->ifp)->cost;
|
||||||
|
else if((reach & 0xC000) == 0)
|
||||||
|
return INFINITY;
|
||||||
|
else if((reach & 0x2000))
|
||||||
|
return babel_get_if_nfo(neigh->ifp)->cost;
|
||||||
|
else
|
||||||
|
return INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
neighbour_cost(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
unsigned a, b;
|
||||||
|
|
||||||
|
if(!if_up(neigh->ifp))
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
a = neighbour_txcost(neigh);
|
||||||
|
|
||||||
|
if(a >= INFINITY)
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
b = neighbour_rxcost(neigh);
|
||||||
|
if(b >= INFINITY)
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
if(!(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ)
|
||||||
|
|| (a < 256 && b < 256)) {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
/* a = 256/alpha, b = 256/beta, where alpha and beta are the expected
|
||||||
|
probabilities of a packet getting through in the direct and reverse
|
||||||
|
directions. */
|
||||||
|
a = MAX(a, 256);
|
||||||
|
b = MAX(b, 256);
|
||||||
|
/* 1/(alpha * beta), which is just plain ETX. */
|
||||||
|
/* Since a and b are capped to 16 bits, overflow is impossible. */
|
||||||
|
return (a * b + 128) >> 8;
|
||||||
|
}
|
||||||
|
}
|
66
babeld/neighbour.h
Normal file
66
babeld/neighbour.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct neighbour {
|
||||||
|
struct neighbour *next;
|
||||||
|
/* This is -1 when unknown, so don't make it unsigned */
|
||||||
|
int hello_seqno;
|
||||||
|
unsigned char address[16];
|
||||||
|
unsigned short reach;
|
||||||
|
unsigned short txcost;
|
||||||
|
struct timeval hello_time;
|
||||||
|
struct timeval ihu_time;
|
||||||
|
unsigned short hello_interval; /* in centiseconds */
|
||||||
|
unsigned short ihu_interval; /* in centiseconds */
|
||||||
|
struct interface *ifp;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct neighbour *neighs;
|
||||||
|
|
||||||
|
#define FOR_ALL_NEIGHBOURS(_neigh) \
|
||||||
|
for(_neigh = neighs; _neigh; _neigh = _neigh->next)
|
||||||
|
|
||||||
|
int neighbour_valid(struct neighbour *neigh);
|
||||||
|
void flush_neighbour(struct neighbour *neigh);
|
||||||
|
struct neighbour *find_neighbour(const unsigned char *address,
|
||||||
|
struct interface *ifp);
|
||||||
|
int update_neighbour(struct neighbour *neigh, int hello, int hello_interval);
|
||||||
|
unsigned check_neighbours(void);
|
||||||
|
unsigned neighbour_txcost(struct neighbour *neigh);
|
||||||
|
unsigned neighbour_rxcost(struct neighbour *neigh);
|
||||||
|
unsigned neighbour_cost(struct neighbour *neigh);
|
239
babeld/net.c
Normal file
239
babeld/net.c
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
babel_socket(int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
int s, rc;
|
||||||
|
int saved_errno;
|
||||||
|
int one = 1, zero = 0;
|
||||||
|
const int ds = 0xc0; /* CS6 - Network Control */
|
||||||
|
|
||||||
|
s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if(s < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
|
||||||
|
&zero, sizeof(zero));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
|
||||||
|
&one, sizeof(one));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||||
|
&one, sizeof(one));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#ifdef IPV6_TCLASS
|
||||||
|
rc = setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &ds, sizeof(ds));
|
||||||
|
#else
|
||||||
|
rc = -1;
|
||||||
|
errno = ENOSYS;
|
||||||
|
#endif
|
||||||
|
if(rc < 0)
|
||||||
|
perror("Couldn't set traffic class");
|
||||||
|
|
||||||
|
rc = fcntl(s, F_GETFL, 0);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_GETFD, 0);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
memset(&sin6, 0, sizeof(sin6));
|
||||||
|
sin6.sin6_family = AF_INET6;
|
||||||
|
sin6.sin6_port = htons(port);
|
||||||
|
rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
saved_errno = errno;
|
||||||
|
close(s);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen)
|
||||||
|
{
|
||||||
|
struct iovec iovec;
|
||||||
|
struct msghdr msg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
iovec.iov_base = buf;
|
||||||
|
iovec.iov_len = buflen;
|
||||||
|
msg.msg_name = sin;
|
||||||
|
msg.msg_namelen = slen;
|
||||||
|
msg.msg_iov = &iovec;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
|
||||||
|
rc = recvmsg(s, &msg, 0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
babel_send(int s,
|
||||||
|
void *buf1, int buflen1, void *buf2, int buflen2,
|
||||||
|
struct sockaddr *sin, int slen)
|
||||||
|
{
|
||||||
|
struct iovec iovec[2];
|
||||||
|
struct msghdr msg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
iovec[0].iov_base = buf1;
|
||||||
|
iovec[0].iov_len = buflen1;
|
||||||
|
iovec[1].iov_base = buf2;
|
||||||
|
iovec[1].iov_len = buflen2;
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.msg_name = (struct sockaddr*)sin;
|
||||||
|
msg.msg_namelen = slen;
|
||||||
|
msg.msg_iov = iovec;
|
||||||
|
msg.msg_iovlen = 2;
|
||||||
|
|
||||||
|
again:
|
||||||
|
rc = sendmsg(s, &msg, 0);
|
||||||
|
if(rc < 0) {
|
||||||
|
if(errno == EINTR)
|
||||||
|
goto again;
|
||||||
|
else if(errno == EAGAIN) {
|
||||||
|
int rc2;
|
||||||
|
rc2 = wait_for_fd(1, s, 5);
|
||||||
|
if(rc2 > 0)
|
||||||
|
goto again;
|
||||||
|
errno = EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tcp_server_socket(int port, int local)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
int s, rc, saved_errno;
|
||||||
|
int one = 1;
|
||||||
|
|
||||||
|
s = socket(PF_INET6, SOCK_STREAM, 0);
|
||||||
|
if(s < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_GETFL, 0);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_GETFD, 0);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
memset(&sin6, 0, sizeof(sin6));
|
||||||
|
sin6.sin6_family = AF_INET6;
|
||||||
|
sin6.sin6_port = htons(port);
|
||||||
|
if(local) {
|
||||||
|
rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = listen(s, 2);
|
||||||
|
if(rc < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
saved_errno = errno;
|
||||||
|
close(s);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
44
babeld/net.h
Normal file
44
babeld/net.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int babel_socket(int port);
|
||||||
|
int babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen);
|
||||||
|
int babel_send(int s,
|
||||||
|
void *buf1, int buflen1, void *buf2, int buflen2,
|
||||||
|
struct sockaddr *sin, int slen);
|
||||||
|
int tcp_server_socket(int port, int local);
|
330
babeld/resend.c
Normal file
330
babeld/resend.c
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "if.h"
|
||||||
|
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "neighbour.h"
|
||||||
|
#include "resend.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include "babel_interface.h"
|
||||||
|
|
||||||
|
struct timeval resend_time = {0, 0};
|
||||||
|
struct resend *to_resend = NULL;
|
||||||
|
|
||||||
|
static int
|
||||||
|
resend_match(struct resend *resend,
|
||||||
|
int kind, const unsigned char *prefix, unsigned char plen)
|
||||||
|
{
|
||||||
|
return (resend->kind == kind &&
|
||||||
|
resend->plen == plen && memcmp(resend->prefix, prefix, 16) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is called by neigh.c when a neighbour is flushed */
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_resends(struct neighbour *neigh)
|
||||||
|
{
|
||||||
|
/* Nothing for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct resend *
|
||||||
|
find_resend(int kind, const unsigned char *prefix, unsigned char plen,
|
||||||
|
struct resend **previous_return)
|
||||||
|
{
|
||||||
|
struct resend *current, *previous;
|
||||||
|
|
||||||
|
previous = NULL;
|
||||||
|
current = to_resend;
|
||||||
|
while(current) {
|
||||||
|
if(resend_match(current, kind, prefix, plen)) {
|
||||||
|
if(previous_return)
|
||||||
|
*previous_return = previous;
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct resend *
|
||||||
|
find_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
struct resend **previous_return)
|
||||||
|
{
|
||||||
|
return find_resend(RESEND_REQUEST, prefix, plen, previous_return);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
record_resend(int kind, const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
struct interface *ifp, int delay)
|
||||||
|
{
|
||||||
|
struct resend *resend;
|
||||||
|
unsigned int ifindex = ifp ? ifp->ifindex : 0;
|
||||||
|
|
||||||
|
if((kind == RESEND_REQUEST &&
|
||||||
|
input_filter(NULL, prefix, plen, NULL, ifindex) >= INFINITY) ||
|
||||||
|
(kind == RESEND_UPDATE &&
|
||||||
|
output_filter(NULL, prefix, plen, ifindex) >= INFINITY))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(delay >= 0xFFFF)
|
||||||
|
delay = 0xFFFF;
|
||||||
|
|
||||||
|
resend = find_resend(kind, prefix, plen, NULL);
|
||||||
|
if(resend) {
|
||||||
|
if(resend->delay && delay)
|
||||||
|
resend->delay = MIN(resend->delay, delay);
|
||||||
|
else if(delay)
|
||||||
|
resend->delay = delay;
|
||||||
|
resend->time = babel_now;
|
||||||
|
resend->max = RESEND_MAX;
|
||||||
|
if(id && memcmp(resend->id, id, 8) == 0 &&
|
||||||
|
seqno_compare(resend->seqno, seqno) > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(id)
|
||||||
|
memcpy(resend->id, id, 8);
|
||||||
|
else
|
||||||
|
memset(resend->id, 0, 8);
|
||||||
|
resend->seqno = seqno;
|
||||||
|
if(resend->ifp != ifp)
|
||||||
|
resend->ifp = NULL;
|
||||||
|
} else {
|
||||||
|
resend = malloc(sizeof(struct resend));
|
||||||
|
if(resend == NULL)
|
||||||
|
return -1;
|
||||||
|
resend->kind = kind;
|
||||||
|
resend->max = RESEND_MAX;
|
||||||
|
resend->delay = delay;
|
||||||
|
memcpy(resend->prefix, prefix, 16);
|
||||||
|
resend->plen = plen;
|
||||||
|
resend->seqno = seqno;
|
||||||
|
if(id)
|
||||||
|
memcpy(resend->id, id, 8);
|
||||||
|
else
|
||||||
|
memset(resend->id, 0, 8);
|
||||||
|
resend->ifp = ifp;
|
||||||
|
resend->time = babel_now;
|
||||||
|
resend->next = to_resend;
|
||||||
|
to_resend = resend;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resend->delay) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeval_add_msec(&timeout, &resend->time, resend->delay);
|
||||||
|
timeval_min(&resend_time, &timeout);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
resend_expired(struct resend *resend)
|
||||||
|
{
|
||||||
|
switch(resend->kind) {
|
||||||
|
case RESEND_REQUEST:
|
||||||
|
return timeval_minus_msec(&babel_now, &resend->time) >= REQUEST_TIMEOUT;
|
||||||
|
default:
|
||||||
|
return resend->max <= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
unsatisfied_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id)
|
||||||
|
{
|
||||||
|
struct resend *request;
|
||||||
|
|
||||||
|
request = find_request(prefix, plen, NULL);
|
||||||
|
if(request == NULL || resend_expired(request))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(memcmp(request->id, id, 8) != 0 ||
|
||||||
|
seqno_compare(request->seqno, seqno) <= 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine whether a given request should be forwarded. */
|
||||||
|
int
|
||||||
|
request_redundant(struct interface *ifp,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id)
|
||||||
|
{
|
||||||
|
struct resend *request;
|
||||||
|
|
||||||
|
request = find_request(prefix, plen, NULL);
|
||||||
|
if(request == NULL || resend_expired(request))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(memcmp(request->id, id, 8) == 0 &&
|
||||||
|
seqno_compare(request->seqno, seqno) > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(request->ifp != NULL && request->ifp != ifp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(request->max > 0)
|
||||||
|
/* Will be resent. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(timeval_minus_msec(&babel_now, &request->time) <
|
||||||
|
(ifp ? MIN(babel_get_if_nfo(ifp)->hello_interval, 1000) : 1000))
|
||||||
|
/* Fairly recent. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
satisfy_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct resend *request, *previous;
|
||||||
|
|
||||||
|
request = find_request(prefix, plen, &previous);
|
||||||
|
if(request == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(ifp != NULL && request->ifp != ifp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(memcmp(request->id, id, 8) != 0 ||
|
||||||
|
seqno_compare(request->seqno, seqno) <= 0) {
|
||||||
|
/* We cannot remove the request, as we may be walking the list right
|
||||||
|
now. Mark it as expired, so that expire_resend will remove it. */
|
||||||
|
request->max = 0;
|
||||||
|
request->time.tv_sec = 0;
|
||||||
|
recompute_resend_time();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
expire_resend()
|
||||||
|
{
|
||||||
|
struct resend *current, *previous;
|
||||||
|
int recompute = 0;
|
||||||
|
|
||||||
|
previous = NULL;
|
||||||
|
current = to_resend;
|
||||||
|
while(current) {
|
||||||
|
if(resend_expired(current)) {
|
||||||
|
if(previous == NULL) {
|
||||||
|
to_resend = current->next;
|
||||||
|
free(current);
|
||||||
|
current = to_resend;
|
||||||
|
} else {
|
||||||
|
previous->next = current->next;
|
||||||
|
free(current);
|
||||||
|
current = previous->next;
|
||||||
|
}
|
||||||
|
recompute = 1;
|
||||||
|
} else {
|
||||||
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(recompute)
|
||||||
|
recompute_resend_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
recompute_resend_time()
|
||||||
|
{
|
||||||
|
struct resend *request;
|
||||||
|
struct timeval resend = {0, 0};
|
||||||
|
|
||||||
|
request = to_resend;
|
||||||
|
while(request) {
|
||||||
|
if(!resend_expired(request) && request->delay > 0 && request->max > 0) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeval_add_msec(&timeout, &request->time, request->delay);
|
||||||
|
timeval_min(&resend, &timeout);
|
||||||
|
}
|
||||||
|
request = request->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
resend_time = resend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_resend()
|
||||||
|
{
|
||||||
|
struct resend *resend;
|
||||||
|
|
||||||
|
resend = to_resend;
|
||||||
|
while(resend) {
|
||||||
|
if(!resend_expired(resend) && resend->delay > 0 && resend->max > 0) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeval_add_msec(&timeout, &resend->time, resend->delay);
|
||||||
|
if(timeval_compare(&babel_now, &timeout) >= 0) {
|
||||||
|
switch(resend->kind) {
|
||||||
|
case RESEND_REQUEST:
|
||||||
|
send_multihop_request(resend->ifp,
|
||||||
|
resend->prefix, resend->plen,
|
||||||
|
resend->seqno, resend->id, 127);
|
||||||
|
break;
|
||||||
|
case RESEND_UPDATE:
|
||||||
|
send_update(resend->ifp, 1,
|
||||||
|
resend->prefix, resend->plen);
|
||||||
|
break;
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
resend->delay = MIN(0xFFFF, resend->delay * 2);
|
||||||
|
resend->max--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resend = resend->next;
|
||||||
|
}
|
||||||
|
recompute_resend_time();
|
||||||
|
}
|
77
babeld/resend.h
Normal file
77
babeld/resend.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REQUEST_TIMEOUT 65000
|
||||||
|
#define RESEND_MAX 3
|
||||||
|
|
||||||
|
#define RESEND_REQUEST 1
|
||||||
|
#define RESEND_UPDATE 2
|
||||||
|
|
||||||
|
struct resend {
|
||||||
|
unsigned char kind;
|
||||||
|
unsigned char max;
|
||||||
|
unsigned short delay;
|
||||||
|
struct timeval time;
|
||||||
|
unsigned char prefix[16];
|
||||||
|
unsigned char plen;
|
||||||
|
unsigned short seqno;
|
||||||
|
unsigned char id[8];
|
||||||
|
struct interface *ifp;
|
||||||
|
struct resend *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct timeval resend_time;
|
||||||
|
|
||||||
|
struct resend *find_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
struct resend **previous_return);
|
||||||
|
void flush_resends(struct neighbour *neigh);
|
||||||
|
int record_resend(int kind, const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
struct interface *ifp, int delay);
|
||||||
|
int unsatisfied_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id);
|
||||||
|
int request_redundant(struct interface *ifp,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id);
|
||||||
|
int satisfy_request(const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, const unsigned char *id,
|
||||||
|
struct interface *ifp);
|
||||||
|
|
||||||
|
void expire_resend(void);
|
||||||
|
void recompute_resend_time(void);
|
||||||
|
void do_resend(void);
|
1019
babeld/route.c
Normal file
1019
babeld/route.c
Normal file
File diff suppressed because it is too large
Load Diff
135
babeld/route.h
Normal file
135
babeld/route.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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_ROUTE_H
|
||||||
|
#define BABEL_ROUTE_H
|
||||||
|
|
||||||
|
#include "babel_interface.h"
|
||||||
|
#include "source.h"
|
||||||
|
|
||||||
|
#define DIVERSITY_NONE 0
|
||||||
|
#define DIVERSITY_INTERFACE_1 1
|
||||||
|
#define DIVERSITY_CHANNEL_1 2
|
||||||
|
#define DIVERSITY_CHANNEL 3
|
||||||
|
|
||||||
|
#define DIVERSITY_HOPS 8
|
||||||
|
|
||||||
|
struct babel_route {
|
||||||
|
struct source *src;
|
||||||
|
unsigned short refmetric;
|
||||||
|
unsigned short cost;
|
||||||
|
unsigned short add_metric;
|
||||||
|
unsigned short seqno;
|
||||||
|
struct neighbour *neigh;
|
||||||
|
unsigned char nexthop[16];
|
||||||
|
time_t time;
|
||||||
|
unsigned short hold_time; /* in seconds */
|
||||||
|
short installed;
|
||||||
|
unsigned char channels[DIVERSITY_HOPS];
|
||||||
|
struct babel_route *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct babel_route **routes;
|
||||||
|
extern int kernel_metric, allow_duplicates;
|
||||||
|
extern int diversity_kind, diversity_factor;
|
||||||
|
extern int keep_unfeasible;
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
route_metric(const struct babel_route *route)
|
||||||
|
{
|
||||||
|
int m = (int)route->refmetric + route->cost + route->add_metric;
|
||||||
|
return MIN(m, INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
route_metric_noninterfering(const struct babel_route *route)
|
||||||
|
{
|
||||||
|
int m =
|
||||||
|
(int)route->refmetric +
|
||||||
|
(diversity_factor * route->cost + 128) / 256 +
|
||||||
|
route->add_metric;
|
||||||
|
m = MAX(m, route->refmetric + 1);
|
||||||
|
return MIN(m, INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct babel_route *find_route(const unsigned char *prefix, unsigned char plen,
|
||||||
|
struct neighbour *neigh, const unsigned char *nexthop);
|
||||||
|
struct babel_route *find_installed_route(const unsigned char *prefix,
|
||||||
|
unsigned char plen);
|
||||||
|
int installed_routes_estimate(void);
|
||||||
|
void flush_route(struct babel_route *route);
|
||||||
|
void flush_all_routes(void);
|
||||||
|
void flush_neighbour_routes(struct neighbour *neigh);
|
||||||
|
void flush_interface_routes(struct interface *ifp, int v4only);
|
||||||
|
void for_all_routes(void (*f)(struct babel_route*, void*), void *closure);
|
||||||
|
void for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure);
|
||||||
|
void install_route(struct babel_route *route);
|
||||||
|
void uninstall_route(struct babel_route *route);
|
||||||
|
void switch_route(struct babel_route *old, struct babel_route *new);
|
||||||
|
int route_feasible(struct babel_route *route);
|
||||||
|
int route_old(struct babel_route *route);
|
||||||
|
int route_expired(struct babel_route *route);
|
||||||
|
int route_interferes(struct babel_route *route, struct interface *ifp);
|
||||||
|
int update_feasible(struct source *src,
|
||||||
|
unsigned short seqno, unsigned short refmetric);
|
||||||
|
struct babel_route *find_best_route(const unsigned char *prefix, unsigned char plen,
|
||||||
|
int feasible, struct neighbour *exclude);
|
||||||
|
struct babel_route *install_best_route(const unsigned char prefix[16],
|
||||||
|
unsigned char plen);
|
||||||
|
void update_neighbour_metric(struct neighbour *neigh, int change);
|
||||||
|
void update_interface_metric(struct interface *ifp);
|
||||||
|
void update_route_metric(struct babel_route *route);
|
||||||
|
struct babel_route *update_route(const unsigned char *id,
|
||||||
|
const unsigned char *prefix, unsigned char plen,
|
||||||
|
unsigned short seqno, unsigned short refmetric,
|
||||||
|
unsigned short interval, struct neighbour *neigh,
|
||||||
|
const unsigned char *nexthop,
|
||||||
|
const unsigned char *channels, int channels_len);
|
||||||
|
void retract_neighbour_routes(struct neighbour *neigh);
|
||||||
|
void send_unfeasible_request(struct neighbour *neigh, int force,
|
||||||
|
unsigned short seqno, unsigned short metric,
|
||||||
|
struct source *src);
|
||||||
|
void send_triggered_update(struct babel_route *route,
|
||||||
|
struct source *oldsrc, unsigned oldmetric);
|
||||||
|
void route_changed(struct babel_route *route,
|
||||||
|
struct source *oldsrc, unsigned short oldmetric);
|
||||||
|
void route_lost(struct source *src, unsigned oldmetric);
|
||||||
|
void expire_routes(void);
|
||||||
|
|
||||||
|
#endif
|
180
babeld/source.c
Normal file
180
babeld/source.c
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include "babel_interface.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
|
struct source *srcs = NULL;
|
||||||
|
|
||||||
|
struct source*
|
||||||
|
find_source(const unsigned char *id, const unsigned char *p, unsigned char plen,
|
||||||
|
int create, unsigned short seqno)
|
||||||
|
{
|
||||||
|
struct source *src;
|
||||||
|
|
||||||
|
for(src = srcs; src; src = src->next) {
|
||||||
|
/* This should really be a hash table. For now, check the
|
||||||
|
last byte first. */
|
||||||
|
if(src->id[7] != id[7])
|
||||||
|
continue;
|
||||||
|
if(memcmp(src->id, id, 8) != 0)
|
||||||
|
continue;
|
||||||
|
if(src->plen != plen)
|
||||||
|
continue;
|
||||||
|
if(memcmp(src->prefix, p, 16) == 0)
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!create)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
src = malloc(sizeof(struct source));
|
||||||
|
if(src == NULL) {
|
||||||
|
zlog_err("malloc(source): %s", safe_strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(src->id, id, 8);
|
||||||
|
memcpy(src->prefix, p, 16);
|
||||||
|
src->plen = plen;
|
||||||
|
src->seqno = seqno;
|
||||||
|
src->metric = INFINITY;
|
||||||
|
src->time = babel_now.tv_sec;
|
||||||
|
src->route_count = 0;
|
||||||
|
src->next = srcs;
|
||||||
|
srcs = src;
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct source *
|
||||||
|
retain_source(struct source *src)
|
||||||
|
{
|
||||||
|
assert(src->route_count < 0xffff);
|
||||||
|
src->route_count++;
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release_source(struct source *src)
|
||||||
|
{
|
||||||
|
assert(src->route_count > 0);
|
||||||
|
src->route_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
flush_source(struct source *src)
|
||||||
|
{
|
||||||
|
if(src->route_count > 0)
|
||||||
|
/* The source is in use by a route. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(srcs == src) {
|
||||||
|
srcs = src->next;
|
||||||
|
} else {
|
||||||
|
struct source *previous = srcs;
|
||||||
|
while(previous->next != src)
|
||||||
|
previous = previous->next;
|
||||||
|
previous->next = src->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(src);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
update_source(struct source *src,
|
||||||
|
unsigned short seqno, unsigned short metric)
|
||||||
|
{
|
||||||
|
if(metric >= INFINITY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If a source is expired, pretend that it doesn't exist and update
|
||||||
|
it unconditionally. This makes ensures that old data will
|
||||||
|
eventually be overridden, and prevents us from getting stuck if
|
||||||
|
a router loses its sequence number. */
|
||||||
|
if(src->time < babel_now.tv_sec - SOURCE_GC_TIME ||
|
||||||
|
seqno_compare(src->seqno, seqno) < 0 ||
|
||||||
|
(src->seqno == seqno && src->metric > metric)) {
|
||||||
|
src->seqno = seqno;
|
||||||
|
src->metric = metric;
|
||||||
|
}
|
||||||
|
src->time = babel_now.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
expire_sources()
|
||||||
|
{
|
||||||
|
struct source *src;
|
||||||
|
|
||||||
|
src = srcs;
|
||||||
|
while(src) {
|
||||||
|
if(src->time > babel_now.tv_sec)
|
||||||
|
/* clock stepped */
|
||||||
|
src->time = babel_now.tv_sec;
|
||||||
|
if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) {
|
||||||
|
struct source *old = src;
|
||||||
|
src = src->next;
|
||||||
|
flush_source(old);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
src = src->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_sources_released(void)
|
||||||
|
{
|
||||||
|
struct source *src;
|
||||||
|
|
||||||
|
for(src = srcs; src; src = src->next) {
|
||||||
|
if(src->route_count != 0)
|
||||||
|
fprintf(stderr, "Warning: source %s %s has refcount %d.\n",
|
||||||
|
format_eui64(src->id),
|
||||||
|
format_prefix(src->prefix, src->plen),
|
||||||
|
(int)src->route_count);
|
||||||
|
}
|
||||||
|
}
|
67
babeld/source.h
Normal file
67
babeld/source.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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 (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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BABEL_SOURCE_H
|
||||||
|
#define BABEL_SOURCE_H
|
||||||
|
|
||||||
|
#define SOURCE_GC_TIME 200
|
||||||
|
|
||||||
|
struct source {
|
||||||
|
struct source *next;
|
||||||
|
unsigned char id[8];
|
||||||
|
unsigned char prefix[16];
|
||||||
|
unsigned char plen;
|
||||||
|
unsigned short seqno;
|
||||||
|
unsigned short metric;
|
||||||
|
unsigned short route_count;
|
||||||
|
time_t time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct source *find_source(const unsigned char *id,
|
||||||
|
const unsigned char *p,
|
||||||
|
unsigned char plen,
|
||||||
|
int create, unsigned short seqno);
|
||||||
|
struct source *retain_source(struct source *src);
|
||||||
|
void release_source(struct source *src);
|
||||||
|
int flush_source(struct source *src);
|
||||||
|
void update_source(struct source *src,
|
||||||
|
unsigned short seqno, unsigned short metric);
|
||||||
|
void expire_sources(void);
|
||||||
|
void check_sources_released(void);
|
||||||
|
|
||||||
|
#endif
|
445
babeld/util.c
Normal file
445
babeld/util.c
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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 <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
roughly(unsigned value)
|
||||||
|
{
|
||||||
|
return value * 3 / 4 + random() % (value / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* d = s1 - s2 */
|
||||||
|
void
|
||||||
|
timeval_minus(struct timeval *d,
|
||||||
|
const struct timeval *s1, const struct timeval *s2)
|
||||||
|
{
|
||||||
|
if(s1->tv_usec >= s2->tv_usec) {
|
||||||
|
d->tv_usec = s1->tv_usec - s2->tv_usec;
|
||||||
|
d->tv_sec = s1->tv_sec - s2->tv_sec;
|
||||||
|
} else {
|
||||||
|
d->tv_usec = s1->tv_usec + 1000000 - s2->tv_usec;
|
||||||
|
d->tv_sec = s1->tv_sec - s2->tv_sec - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
|
||||||
|
{
|
||||||
|
if(s1->tv_sec < s2->tv_sec)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Avoid overflow. */
|
||||||
|
if(s1->tv_sec - s2->tv_sec > 2000000)
|
||||||
|
return 2000000000;
|
||||||
|
|
||||||
|
if(s1->tv_sec > s2->tv_sec)
|
||||||
|
return
|
||||||
|
(unsigned)((unsigned)(s1->tv_sec - s2->tv_sec) * 1000 +
|
||||||
|
((int)s1->tv_usec - s2->tv_usec) / 1000);
|
||||||
|
|
||||||
|
if(s1->tv_usec <= s2->tv_usec)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (unsigned)(s1->tv_usec - s2->tv_usec) / 1000u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* d = s + msecs */
|
||||||
|
void
|
||||||
|
timeval_add_msec(struct timeval *d, const struct timeval *s, const int msecs)
|
||||||
|
{
|
||||||
|
int usecs;
|
||||||
|
d->tv_sec = s->tv_sec + msecs / 1000;
|
||||||
|
usecs = s->tv_usec + (msecs % 1000) * 1000;
|
||||||
|
if(usecs < 1000000) {
|
||||||
|
d->tv_usec = usecs;
|
||||||
|
} else {
|
||||||
|
d->tv_usec = usecs - 1000000;
|
||||||
|
d->tv_sec++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_timeout(struct timeval *timeout, int msecs)
|
||||||
|
{
|
||||||
|
timeval_add_msec(timeout, &babel_now, roughly(msecs));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns <0 if "s1" < "s2", etc. */
|
||||||
|
int
|
||||||
|
timeval_compare(const struct timeval *s1, const struct timeval *s2)
|
||||||
|
{
|
||||||
|
if(s1->tv_sec < s2->tv_sec)
|
||||||
|
return -1;
|
||||||
|
else if(s1->tv_sec > s2->tv_sec)
|
||||||
|
return 1;
|
||||||
|
else if(s1->tv_usec < s2->tv_usec)
|
||||||
|
return -1;
|
||||||
|
else if(s1->tv_usec > s2->tv_usec)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set d at min(d, s) */
|
||||||
|
/* {0, 0} represents infinity */
|
||||||
|
void
|
||||||
|
timeval_min(struct timeval *d, const struct timeval *s)
|
||||||
|
{
|
||||||
|
if(s->tv_sec == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(d->tv_sec == 0 || timeval_compare(d, s) > 0) {
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set d to min(d, x) with x in [secs, secs+1] */
|
||||||
|
void
|
||||||
|
timeval_min_sec(struct timeval *d, time_t secs)
|
||||||
|
{
|
||||||
|
if(d->tv_sec == 0 || d->tv_sec > secs) {
|
||||||
|
d->tv_sec = secs;
|
||||||
|
d->tv_usec = random() % 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a float value in second and return the corresponding mili-seconds.
|
||||||
|
For example:
|
||||||
|
parse_msec("12.342345") returns 12342 */
|
||||||
|
int
|
||||||
|
parse_msec(const char *string)
|
||||||
|
{
|
||||||
|
unsigned int in, fl;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
in = fl = 0;
|
||||||
|
i = 0;
|
||||||
|
while(string[i] == ' ' || string[i] == '\t')
|
||||||
|
i++;
|
||||||
|
while(string[i] >= '0' && string[i] <= '9') {
|
||||||
|
in = in * 10 + string[i] - '0';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(string[i] == '.') {
|
||||||
|
i++;
|
||||||
|
j = 0;
|
||||||
|
while(string[i] >= '0' && string[i] <= '9') {
|
||||||
|
fl = fl * 10 + string[i] - '0';
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(j > 3) {
|
||||||
|
fl /= 10;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
while(j < 3) {
|
||||||
|
fl *= 10;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(string[i] == ' ' || string[i] == '\t')
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if(string[i] == '\0')
|
||||||
|
return in * 1000 + fl;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
in_prefix(const unsigned char *restrict address,
|
||||||
|
const unsigned char *restrict prefix, unsigned char plen)
|
||||||
|
{
|
||||||
|
unsigned char m;
|
||||||
|
|
||||||
|
if(plen > 128)
|
||||||
|
plen = 128;
|
||||||
|
|
||||||
|
if(memcmp(address, prefix, plen / 8) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(plen % 8 == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
m = 0xFF << (8 - (plen % 8));
|
||||||
|
|
||||||
|
return ((address[plen / 8] & m) == (prefix[plen / 8] & m));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
mask_prefix(unsigned char *restrict ret,
|
||||||
|
const unsigned char *restrict prefix, unsigned char plen)
|
||||||
|
{
|
||||||
|
if(plen >= 128) {
|
||||||
|
memcpy(ret, prefix, 16);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ret, 0, 16);
|
||||||
|
memcpy(ret, prefix, plen / 8);
|
||||||
|
if(plen % 8 != 0)
|
||||||
|
ret[plen / 8] =
|
||||||
|
(prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char v4prefix[16] =
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static const unsigned char llprefix[16] =
|
||||||
|
{0xFE, 0x80};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
format_address(const unsigned char *address)
|
||||||
|
{
|
||||||
|
static char buf[4][INET6_ADDRSTRLEN];
|
||||||
|
static int i = 0;
|
||||||
|
i = (i + 1) % 4;
|
||||||
|
if(v4mapped(address))
|
||||||
|
inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN);
|
||||||
|
else
|
||||||
|
inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
|
||||||
|
return buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
format_prefix(const unsigned char *prefix, unsigned char plen)
|
||||||
|
{
|
||||||
|
static char buf[4][INET6_ADDRSTRLEN + 4];
|
||||||
|
static int i = 0;
|
||||||
|
int n;
|
||||||
|
i = (i + 1) % 4;
|
||||||
|
if(plen >= 96 && v4mapped(prefix)) {
|
||||||
|
inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN);
|
||||||
|
n = strlen(buf[i]);
|
||||||
|
snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96);
|
||||||
|
} else {
|
||||||
|
inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
|
||||||
|
n = strlen(buf[i]);
|
||||||
|
snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
|
||||||
|
}
|
||||||
|
return buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
format_eui64(const unsigned char *eui)
|
||||||
|
{
|
||||||
|
static char buf[4][28];
|
||||||
|
static int i = 0;
|
||||||
|
i = (i + 1) % 4;
|
||||||
|
snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
eui[0], eui[1], eui[2], eui[3],
|
||||||
|
eui[4], eui[5], eui[6], eui[7]);
|
||||||
|
return buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *format_bool(const int b) {
|
||||||
|
return b ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_address(const char *address, unsigned char *addr_r, int *af_r)
|
||||||
|
{
|
||||||
|
struct in_addr ina;
|
||||||
|
struct in6_addr ina6;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = inet_pton(AF_INET, address, &ina);
|
||||||
|
if(rc > 0) {
|
||||||
|
memcpy(addr_r, v4prefix, 12);
|
||||||
|
memcpy(addr_r + 12, &ina, 4);
|
||||||
|
if(af_r) *af_r = AF_INET;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = inet_pton(AF_INET6, address, &ina6);
|
||||||
|
if(rc > 0) {
|
||||||
|
memcpy(addr_r, &ina6, 16);
|
||||||
|
if(af_r) *af_r = AF_INET6;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_eui64(const char *eui, unsigned char *eui_r)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||||
|
&eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
|
||||||
|
&eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
|
||||||
|
if(n == 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
|
||||||
|
&eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
|
||||||
|
&eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
|
||||||
|
if(n == 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||||
|
&eui_r[0], &eui_r[1], &eui_r[2],
|
||||||
|
&eui_r[5], &eui_r[6], &eui_r[7]);
|
||||||
|
if(n == 6) {
|
||||||
|
eui_r[3] = 0xFF;
|
||||||
|
eui_r[4] = 0xFE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wait_for_fd(int direction, int fd, int msecs)
|
||||||
|
{
|
||||||
|
fd_set fds;
|
||||||
|
int rc;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = msecs / 1000;
|
||||||
|
tv.tv_usec = (msecs % 1000) * 1000;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
if(direction)
|
||||||
|
rc = select(fd + 1, NULL, &fds, NULL, &tv);
|
||||||
|
else
|
||||||
|
rc = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
martian_prefix(const unsigned char *prefix, int plen)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(plen >= 8 && prefix[0] == 0xFF) ||
|
||||||
|
(plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
|
||||||
|
(plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
|
||||||
|
(prefix[15] == 0 || prefix[15] == 1)) ||
|
||||||
|
(plen >= 96 && v4mapped(prefix) &&
|
||||||
|
((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
|
||||||
|
(plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
linklocal(const unsigned char *address)
|
||||||
|
{
|
||||||
|
return memcmp(address, llprefix, 8) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
v4mapped(const unsigned char *address)
|
||||||
|
{
|
||||||
|
return memcmp(address, v4prefix, 12) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
v4tov6(unsigned char *dst, const unsigned char *src)
|
||||||
|
{
|
||||||
|
memcpy(dst, v4prefix, 12);
|
||||||
|
memcpy(dst + 12, src, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
|
||||||
|
{
|
||||||
|
memcpy(dest, v4prefix, 12);
|
||||||
|
memcpy(dest + 12, src, 4);
|
||||||
|
assert(v4mapped(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
|
||||||
|
{
|
||||||
|
assert(v4mapped(src));
|
||||||
|
memcpy(dest, src + 12, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
|
||||||
|
{
|
||||||
|
memcpy(dest, src, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
|
||||||
|
{
|
||||||
|
memcpy(dest, src, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
daemonise()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
rc = fork();
|
||||||
|
if(rc < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(rc > 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
rc = setsid();
|
||||||
|
if(rc < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
165
babeld/util.h
Normal file
165
babeld/util.h
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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 "babeld.h"
|
||||||
|
#include "babel_main.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#if defined(i386) || defined(__mc68020__) || defined(__x86_64__)
|
||||||
|
#define DO_NTOHS(_d, _s) do{ _d = ntohs(*(const unsigned short*)(_s)); }while(0)
|
||||||
|
#define DO_NTOHL(_d, _s) do{ _d = ntohl(*(const unsigned*)(_s)); } while(0)
|
||||||
|
#define DO_HTONS(_d, _s) do{ *(unsigned short*)(_d) = htons(_s); } while(0)
|
||||||
|
#define DO_HTONL(_d, _s) do{ *(unsigned*)(_d) = htonl(_s); } while(0)
|
||||||
|
/* Some versions of gcc seem to be buggy, and ignore the packed attribute.
|
||||||
|
Disable this code until the issue is clarified. */
|
||||||
|
/* #elif defined __GNUC__*/
|
||||||
|
#elif 0
|
||||||
|
struct __us { unsigned short x __attribute__((packed)); };
|
||||||
|
#define DO_NTOHS(_d, _s) \
|
||||||
|
do { _d = ntohs(((const struct __us*)(_s))->x); } while(0)
|
||||||
|
#define DO_HTONS(_d, _s) \
|
||||||
|
do { ((struct __us*)(_d))->x = htons(_s); } while(0)
|
||||||
|
#else
|
||||||
|
#define DO_NTOHS(_d, _s) \
|
||||||
|
do { short _dd; \
|
||||||
|
memcpy(&(_dd), (_s), 2); \
|
||||||
|
_d = ntohs(_dd); } while(0)
|
||||||
|
#define DO_HTONS(_d, _s) \
|
||||||
|
do { unsigned short _dd; \
|
||||||
|
_dd = htons(_s); \
|
||||||
|
memcpy((_d), &(_dd), 2); } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
seqno_compare(unsigned short s1, unsigned short s2)
|
||||||
|
{
|
||||||
|
if(s1 == s2)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return ((s2 - s1) & 0x8000) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline short
|
||||||
|
seqno_minus(unsigned short s1, unsigned short s2)
|
||||||
|
{
|
||||||
|
return (short)((s1 - s2) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned short
|
||||||
|
seqno_plus(unsigned short s, int plus)
|
||||||
|
{
|
||||||
|
return ((s + plus) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned roughly(unsigned value);
|
||||||
|
void timeval_minus(struct timeval *d,
|
||||||
|
const struct timeval *s1, const struct timeval *s2);
|
||||||
|
unsigned timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
|
||||||
|
ATTRIBUTE ((pure));
|
||||||
|
void timeval_add_msec(struct timeval *d,
|
||||||
|
const struct timeval *s, const int msecs);
|
||||||
|
void set_timeout (struct timeval *timeout, int msecs);
|
||||||
|
int timeval_compare(const struct timeval *s1, const struct timeval *s2)
|
||||||
|
ATTRIBUTE ((pure));
|
||||||
|
void timeval_min(struct timeval *d, const struct timeval *s);
|
||||||
|
void timeval_min_sec(struct timeval *d, time_t secs);
|
||||||
|
int parse_msec(const char *string) ATTRIBUTE ((pure));
|
||||||
|
int in_prefix(const unsigned char *restrict address,
|
||||||
|
const unsigned char *restrict prefix, unsigned char plen)
|
||||||
|
ATTRIBUTE ((pure));
|
||||||
|
unsigned char *mask_prefix(unsigned char *restrict ret,
|
||||||
|
const unsigned char *restrict prefix,
|
||||||
|
unsigned char plen);
|
||||||
|
const char *format_address(const unsigned char *address);
|
||||||
|
const char *format_prefix(const unsigned char *address, unsigned char prefix);
|
||||||
|
const char *format_eui64(const unsigned char *eui);
|
||||||
|
const char *format_bool(const int b);
|
||||||
|
int parse_address(const char *address, unsigned char *addr_r, int *af_r);
|
||||||
|
int parse_eui64(const char *eui, unsigned char *eui_r);
|
||||||
|
int wait_for_fd(int direction, int fd, int msecs);
|
||||||
|
int martian_prefix(const unsigned char *prefix, int plen) ATTRIBUTE ((pure));
|
||||||
|
int linklocal(const unsigned char *address) ATTRIBUTE ((pure));
|
||||||
|
int v4mapped(const unsigned char *address) ATTRIBUTE ((pure));
|
||||||
|
void v4tov6(unsigned char *dst, const unsigned char *src);
|
||||||
|
void inaddr_to_uchar(unsigned char *dest, const struct in_addr *src);
|
||||||
|
void uchar_to_inaddr(struct in_addr *dest, const unsigned char *src);
|
||||||
|
void in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src);
|
||||||
|
void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src);
|
||||||
|
int daemonise(void);
|
||||||
|
|
||||||
|
/* If debugging is disabled, we want to avoid calling format_address
|
||||||
|
for every omitted debugging message. So debug is a macro. But
|
||||||
|
vararg macros are not portable. */
|
||||||
|
#if defined NO_DEBUG
|
||||||
|
|
||||||
|
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||||
|
#define debugf(...) do {} while(0)
|
||||||
|
#elif defined __GNUC__
|
||||||
|
#define debugf(_args...) do {} while(0)
|
||||||
|
#else
|
||||||
|
static inline void debugf(int level, const char *format, ...) { return; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* NO_DEBUG */
|
||||||
|
|
||||||
|
/* some levels */
|
||||||
|
#define BABEL_DEBUG_COMMON (1 << 0)
|
||||||
|
#define BABEL_DEBUG_KERNEL (1 << 1)
|
||||||
|
#define BABEL_DEBUG_FILTER (1 << 2)
|
||||||
|
#define BABEL_DEBUG_TIMEOUT (1 << 3)
|
||||||
|
#define BABEL_DEBUG_IF (1 << 4)
|
||||||
|
#define BABEL_DEBUG_ROUTE (1 << 5)
|
||||||
|
#define BABEL_DEBUG_ALL (0xFFFF)
|
||||||
|
|
||||||
|
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||||
|
#define debugf(level, ...) \
|
||||||
|
do { \
|
||||||
|
if(UNLIKELY(debug & level)) zlog_debug(__VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
#elif defined __GNUC__
|
||||||
|
#define debugf(level, _args...) \
|
||||||
|
do { \
|
||||||
|
if(UNLIKELY(debug & level)) zlog_debug(_args); \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
static inline void debugf(int level, const char *format, ...) { return; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NO_DEBUG */
|
||||||
|
|
237
babeld/xroute.c
Normal file
237
babeld/xroute.c
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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 "if.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "babeld.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "neighbour.h"
|
||||||
|
#include "message.h"
|
||||||
|
#include "route.h"
|
||||||
|
#include "xroute.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "babel_interface.h"
|
||||||
|
|
||||||
|
static int xroute_add_new_route(unsigned char prefix[16], unsigned char plen,
|
||||||
|
unsigned short metric, unsigned int ifindex,
|
||||||
|
int proto, int send_updates);
|
||||||
|
|
||||||
|
static struct xroute *xroutes;
|
||||||
|
static int numxroutes = 0, maxxroutes = 0;
|
||||||
|
|
||||||
|
/* Add redistributed route to Babel table. */
|
||||||
|
int
|
||||||
|
babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||||
|
unsigned int ifindex, struct in_addr *nexthop)
|
||||||
|
{
|
||||||
|
unsigned char uchar_prefix[16];
|
||||||
|
|
||||||
|
inaddr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route comming from Zebra.");
|
||||||
|
xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96,
|
||||||
|
api->metric, ifindex, 0, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove redistributed route from Babel table. */
|
||||||
|
int
|
||||||
|
babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||||
|
unsigned int ifindex)
|
||||||
|
{
|
||||||
|
unsigned char uchar_prefix[16];
|
||||||
|
struct xroute *xroute = NULL;
|
||||||
|
|
||||||
|
inaddr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||||
|
xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96);
|
||||||
|
if (xroute != NULL) {
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra).");
|
||||||
|
flush_xroute(xroute);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add redistributed route to Babel table. */
|
||||||
|
int
|
||||||
|
babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
|
||||||
|
unsigned int ifindex, struct in6_addr *nexthop)
|
||||||
|
{
|
||||||
|
unsigned char uchar_prefix[16];
|
||||||
|
|
||||||
|
in6addr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "Adding new route comming from Zebra.");
|
||||||
|
xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex,
|
||||||
|
0, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove redistributed route from Babel table. */
|
||||||
|
int
|
||||||
|
babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
|
||||||
|
unsigned int ifindex)
|
||||||
|
{
|
||||||
|
unsigned char uchar_prefix[16];
|
||||||
|
struct xroute *xroute = NULL;
|
||||||
|
|
||||||
|
in6addr_to_uchar(uchar_prefix, &prefix->prefix);
|
||||||
|
xroute = find_xroute(uchar_prefix, prefix->prefixlen);
|
||||||
|
if (xroute != NULL) {
|
||||||
|
debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra).");
|
||||||
|
flush_xroute(xroute);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xroute *
|
||||||
|
find_xroute(const unsigned char *prefix, unsigned char plen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < numxroutes; i++) {
|
||||||
|
if(xroutes[i].plen == plen &&
|
||||||
|
memcmp(xroutes[i].prefix, prefix, 16) == 0)
|
||||||
|
return &xroutes[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_xroute(struct xroute *xroute)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = xroute - xroutes;
|
||||||
|
assert(i >= 0 && i < numxroutes);
|
||||||
|
|
||||||
|
if(i != numxroutes - 1)
|
||||||
|
memcpy(xroutes + i, xroutes + numxroutes - 1, sizeof(struct xroute));
|
||||||
|
numxroutes--;
|
||||||
|
VALGRIND_MAKE_MEM_UNDEFINED(xroutes + numxroutes, sizeof(struct xroute));
|
||||||
|
|
||||||
|
if(numxroutes == 0) {
|
||||||
|
free(xroutes);
|
||||||
|
xroutes = NULL;
|
||||||
|
maxxroutes = 0;
|
||||||
|
} else if(maxxroutes > 8 && numxroutes < maxxroutes / 4) {
|
||||||
|
struct xroute *new_xroutes;
|
||||||
|
int n = maxxroutes / 2;
|
||||||
|
new_xroutes = realloc(xroutes, n * sizeof(struct xroute));
|
||||||
|
if(new_xroutes == NULL)
|
||||||
|
return;
|
||||||
|
xroutes = new_xroutes;
|
||||||
|
maxxroutes = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_xroute(unsigned char prefix[16], unsigned char plen,
|
||||||
|
unsigned short metric, unsigned int ifindex, int proto)
|
||||||
|
{
|
||||||
|
struct xroute *xroute = find_xroute(prefix, plen);
|
||||||
|
if(xroute) {
|
||||||
|
if(xroute->metric <= metric)
|
||||||
|
return 0;
|
||||||
|
xroute->metric = metric;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numxroutes >= maxxroutes) {
|
||||||
|
struct xroute *new_xroutes;
|
||||||
|
int n = maxxroutes < 1 ? 8 : 2 * maxxroutes;
|
||||||
|
new_xroutes = xroutes == NULL ?
|
||||||
|
malloc(n * sizeof(struct xroute)) :
|
||||||
|
realloc(xroutes, n * sizeof(struct xroute));
|
||||||
|
if(new_xroutes == NULL)
|
||||||
|
return -1;
|
||||||
|
maxxroutes = n;
|
||||||
|
xroutes = new_xroutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(xroutes[numxroutes].prefix, prefix, 16);
|
||||||
|
xroutes[numxroutes].plen = plen;
|
||||||
|
xroutes[numxroutes].metric = metric;
|
||||||
|
xroutes[numxroutes].ifindex = ifindex;
|
||||||
|
xroutes[numxroutes].proto = proto;
|
||||||
|
numxroutes++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns an overestimate of the number of xroutes. */
|
||||||
|
int
|
||||||
|
xroutes_estimate()
|
||||||
|
{
|
||||||
|
return numxroutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
for_all_xroutes(void (*f)(struct xroute*, void*), void *closure)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < numxroutes; i++)
|
||||||
|
(*f)(&xroutes[i], closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add an xroute, verifying some conditions; return 0 if there is no changes */
|
||||||
|
static int
|
||||||
|
xroute_add_new_route(unsigned char prefix[16], unsigned char plen,
|
||||||
|
unsigned short metric, unsigned int ifindex,
|
||||||
|
int proto, int send_updates)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
if(martian_prefix(prefix, plen))
|
||||||
|
return 0;
|
||||||
|
metric = redistribute_filter(prefix, plen, ifindex, proto);
|
||||||
|
if(metric < INFINITY) {
|
||||||
|
rc = add_xroute(prefix, plen, metric, ifindex, proto);
|
||||||
|
if(rc > 0) {
|
||||||
|
struct babel_route *route;
|
||||||
|
route = find_installed_route(prefix, plen);
|
||||||
|
if(route) {
|
||||||
|
if(allow_duplicates < 0 ||
|
||||||
|
metric < allow_duplicates)
|
||||||
|
uninstall_route(route);
|
||||||
|
}
|
||||||
|
if(send_updates)
|
||||||
|
send_update(NULL, 0, prefix, plen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
59
babeld/xroute.h
Normal file
59
babeld/xroute.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 (c) 2007, 2008 by Juliusz Chroboczek
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct xroute {
|
||||||
|
unsigned char prefix[16];
|
||||||
|
unsigned char plen;
|
||||||
|
unsigned short metric;
|
||||||
|
unsigned int ifindex;
|
||||||
|
int proto;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen);
|
||||||
|
void flush_xroute(struct xroute *xroute);
|
||||||
|
int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||||
|
unsigned int ifindex, struct in_addr *nexthop);
|
||||||
|
int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix,
|
||||||
|
unsigned int ifindex);
|
||||||
|
int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
|
||||||
|
unsigned int ifindex, struct in6_addr *nexthop);
|
||||||
|
int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix,
|
||||||
|
unsigned int ifindex);
|
||||||
|
int xroutes_estimate(void);
|
||||||
|
void for_all_xroutes(void (*f)(struct xroute*, void*), void *closure);
|
@ -1,15 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
*.o
|
|
||||||
bgpd
|
|
||||||
bgp_btoa
|
|
||||||
bgpd.conf
|
|
||||||
tags
|
|
||||||
TAGS
|
|
||||||
.deps
|
|
||||||
.nfs*
|
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
*.libs
|
|
||||||
.arch-inventory
|
|
||||||
.arch-ids
|
|
@ -140,13 +140,13 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
|
|||||||
baa->refcnt--;
|
baa->refcnt--;
|
||||||
|
|
||||||
if (baa->refcnt && baa->attr)
|
if (baa->refcnt && baa->attr)
|
||||||
bgp_attr_unintern (baa->attr);
|
bgp_attr_unintern (&baa->attr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (baa->attr)
|
if (baa->attr)
|
||||||
{
|
{
|
||||||
hash_release (hash, baa);
|
hash_release (hash, baa);
|
||||||
bgp_attr_unintern (baa->attr);
|
bgp_attr_unintern (&baa->attr);
|
||||||
}
|
}
|
||||||
baa_free (baa);
|
baa_free (baa);
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
|
|||||||
struct peer *peer, afi_t afi, safi_t safi)
|
struct peer *peer, afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
if (adj->attr)
|
if (adj->attr)
|
||||||
bgp_attr_unintern (adj->attr);
|
bgp_attr_unintern (&adj->attr);
|
||||||
|
|
||||||
if (adj->adv)
|
if (adj->adv)
|
||||||
bgp_advertise_clean (peer, adj, afi, safi);
|
bgp_advertise_clean (peer, adj, afi, safi);
|
||||||
@ -339,7 +339,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
|
|||||||
{
|
{
|
||||||
if (adj->attr != attr)
|
if (adj->attr != attr)
|
||||||
{
|
{
|
||||||
bgp_attr_unintern (adj->attr);
|
bgp_attr_unintern (&adj->attr);
|
||||||
adj->attr = bgp_attr_intern (attr);
|
adj->attr = bgp_attr_intern (attr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -355,7 +355,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
|
|||||||
void
|
void
|
||||||
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
|
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
|
||||||
{
|
{
|
||||||
bgp_attr_unintern (bai->attr);
|
bgp_attr_unintern (&bai->attr);
|
||||||
BGP_ADJ_IN_DEL (rn, bai);
|
BGP_ADJ_IN_DEL (rn, bai);
|
||||||
peer_unlock (bai->peer); /* adj_in peer reference */
|
peer_unlock (bai->peer); /* adj_in peer reference */
|
||||||
XFREE (MTYPE_BGP_ADJ_IN, bai);
|
XFREE (MTYPE_BGP_ADJ_IN, bai);
|
||||||
|
@ -91,13 +91,13 @@ static struct hash *ashash;
|
|||||||
/* Stream for SNMP. See aspath_snmp_pathseg */
|
/* Stream for SNMP. See aspath_snmp_pathseg */
|
||||||
static struct stream *snmp_stream;
|
static struct stream *snmp_stream;
|
||||||
|
|
||||||
static inline as_t *
|
static as_t *
|
||||||
assegment_data_new (int num)
|
assegment_data_new (int num)
|
||||||
{
|
{
|
||||||
return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
|
return (XCALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
assegment_data_free (as_t *asdata)
|
assegment_data_free (as_t *asdata)
|
||||||
{
|
{
|
||||||
XFREE (MTYPE_AS_SEG_DATA,asdata);
|
XFREE (MTYPE_AS_SEG_DATA,asdata);
|
||||||
@ -340,19 +340,21 @@ aspath_free (struct aspath *aspath)
|
|||||||
|
|
||||||
/* Unintern aspath from AS path bucket. */
|
/* Unintern aspath from AS path bucket. */
|
||||||
void
|
void
|
||||||
aspath_unintern (struct aspath *aspath)
|
aspath_unintern (struct aspath **aspath)
|
||||||
{
|
{
|
||||||
struct aspath *ret;
|
struct aspath *ret;
|
||||||
|
struct aspath *asp = *aspath;
|
||||||
|
|
||||||
|
if (asp->refcnt)
|
||||||
|
asp->refcnt--;
|
||||||
|
|
||||||
if (aspath->refcnt)
|
if (asp->refcnt == 0)
|
||||||
aspath->refcnt--;
|
|
||||||
|
|
||||||
if (aspath->refcnt == 0)
|
|
||||||
{
|
{
|
||||||
/* This aspath must exist in aspath hash table. */
|
/* This aspath must exist in aspath hash table. */
|
||||||
ret = hash_release (ashash, aspath);
|
ret = hash_release (ashash, asp);
|
||||||
assert (ret != NULL);
|
assert (ret != NULL);
|
||||||
aspath_free (aspath);
|
aspath_free (asp);
|
||||||
|
*aspath = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,79 +673,78 @@ aspath_hash_alloc (void *arg)
|
|||||||
return aspath;
|
return aspath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse as-segment byte stream in struct assegment
|
/* parse as-segment byte stream in struct assegment */
|
||||||
*
|
static int
|
||||||
* Returns NULL if the AS_PATH or AS4_PATH is not valid.
|
assegments_parse (struct stream *s, size_t length,
|
||||||
*/
|
struct assegment **result, int use32bit)
|
||||||
static struct assegment *
|
|
||||||
assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
|
|
||||||
{
|
{
|
||||||
struct assegment_header segh;
|
struct assegment_header segh;
|
||||||
struct assegment *seg, *prev = NULL, *head = NULL;
|
struct assegment *seg, *prev = NULL, *head = NULL;
|
||||||
|
size_t bytes = 0;
|
||||||
|
|
||||||
assert (length > 0); /* does not expect empty AS_PATH or AS4_PATH */
|
/* empty aspath (ie iBGP or somesuch) */
|
||||||
|
if (length == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu",
|
zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu",
|
||||||
(unsigned long) length);
|
(unsigned long) length);
|
||||||
|
/* basic checks */
|
||||||
/* double check that length does not exceed stream */
|
if ((STREAM_READABLE(s) < length)
|
||||||
if (STREAM_READABLE(s) < length)
|
|| (STREAM_READABLE(s) < AS_HEADER_SIZE)
|
||||||
return NULL;
|
|| (length % AS16_VALUE_SIZE ))
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* deal with each segment in turn */
|
while (bytes < length)
|
||||||
while (length > 0)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
size_t seg_size;
|
size_t seg_size;
|
||||||
|
|
||||||
/* softly softly, get the header first on its own */
|
if ((length - bytes) <= AS_HEADER_SIZE)
|
||||||
if (length < AS_HEADER_SIZE)
|
|
||||||
{
|
{
|
||||||
assegment_free_all (head);
|
if (head)
|
||||||
return NULL;
|
assegment_free_all (head);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* softly softly, get the header first on its own */
|
||||||
segh.type = stream_getc (s);
|
segh.type = stream_getc (s);
|
||||||
segh.length = stream_getc (s);
|
segh.length = stream_getc (s);
|
||||||
|
|
||||||
seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
|
seg_size = ASSEGMENT_SIZE(segh.length, use32bit);
|
||||||
/* includes the header bytes */
|
|
||||||
|
|
||||||
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d",
|
zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d",
|
||||||
segh.type, segh.length);
|
segh.type, segh.length);
|
||||||
|
|
||||||
|
/* check it.. */
|
||||||
|
if ( ((bytes + seg_size) > length)
|
||||||
|
/* 1771bis 4.3b: seg length contains one or more */
|
||||||
|
|| (segh.length == 0)
|
||||||
|
/* Paranoia in case someone changes type of segment length.
|
||||||
|
* Shift both values by 0x10 to make the comparison operate
|
||||||
|
* on more, than 8 bits (otherwise it's a warning, bug #564).
|
||||||
|
*/
|
||||||
|
|| ((sizeof segh.length > 1)
|
||||||
|
&& (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX)))
|
||||||
|
{
|
||||||
|
if (head)
|
||||||
|
assegment_free_all (head);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (segh.type)
|
switch (segh.type)
|
||||||
{
|
{
|
||||||
case AS_SEQUENCE:
|
case AS_SEQUENCE:
|
||||||
case AS_SET:
|
case AS_SET:
|
||||||
break ;
|
|
||||||
|
|
||||||
case AS_CONFED_SEQUENCE:
|
case AS_CONFED_SEQUENCE:
|
||||||
case AS_CONFED_SET:
|
case AS_CONFED_SET:
|
||||||
if (!as4_path)
|
break;
|
||||||
break ;
|
default:
|
||||||
/* RFC4893 3: "invalid for the AS4_PATH attribute" */
|
if (head)
|
||||||
/* fall through */
|
assegment_free_all (head);
|
||||||
|
return -1;
|
||||||
default: /* reject unknown or invalid AS_PATH segment types */
|
|
||||||
seg_size = 0 ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop now if segment is not valid (discarding anything collected to date)
|
|
||||||
*
|
|
||||||
* RFC4271 4.3, Path Attributes, b) AS_PATH:
|
|
||||||
*
|
|
||||||
* "path segment value field contains one or more AS numbers"
|
|
||||||
*/
|
|
||||||
if ((seg_size == 0) || (seg_size > length) || (segh.length == 0))
|
|
||||||
{
|
|
||||||
assegment_free_all (head);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
length -= seg_size ;
|
|
||||||
|
|
||||||
/* now its safe to trust lengths */
|
/* now its safe to trust lengths */
|
||||||
seg = assegment_new (segh.type, segh.length);
|
seg = assegment_new (segh.type, segh.length);
|
||||||
@ -756,52 +757,47 @@ assegments_parse (struct stream *s, size_t length, int use32bit, int as4_path)
|
|||||||
for (i = 0; i < segh.length; i++)
|
for (i = 0; i < segh.length; i++)
|
||||||
seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s);
|
seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s);
|
||||||
|
|
||||||
|
bytes += seg_size;
|
||||||
|
|
||||||
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
if (BGP_DEBUG (as4, AS4_SEGMENT))
|
||||||
zlog_debug ("[AS4SEG] Parse aspath segment: length left: %lu",
|
zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu",
|
||||||
(unsigned long) length);
|
(unsigned long) bytes);
|
||||||
|
|
||||||
prev = seg;
|
prev = seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return assegment_normalise (head);
|
*result = assegment_normalise (head);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AS path parse function -- parses AS_PATH and AS4_PATH attributes
|
/* AS path parse function. pnt is a pointer to byte stream and length
|
||||||
*
|
is length of byte stream. If there is same AS path in the the AS
|
||||||
* Requires: s -- stream, currently positioned before first segment
|
path hash then return it else make new AS path structure.
|
||||||
* of AS_PATH or AS4_PATH (ie after attribute header)
|
|
||||||
* length -- length of the value of the AS_PATH or AS4_PATH
|
On error NULL is returned.
|
||||||
* use32bit -- true <=> 4Byte ASN, otherwise 2Byte ASN
|
|
||||||
* as4_path -- true <=> AS4_PATH, otherwise AS_PATH
|
|
||||||
*
|
|
||||||
* Returns: if valid: address of struct aspath in the hash of known aspaths,
|
|
||||||
* with reference count incremented.
|
|
||||||
* else: NULL
|
|
||||||
*
|
|
||||||
* NB: empty AS path (length == 0) is valid. The returned struct aspath will
|
|
||||||
* have segments == NULL and str == zero length string (unique).
|
|
||||||
*/
|
*/
|
||||||
struct aspath *
|
struct aspath *
|
||||||
aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
|
aspath_parse (struct stream *s, size_t length, int use32bit)
|
||||||
{
|
{
|
||||||
struct aspath as;
|
struct aspath as;
|
||||||
struct aspath *find;
|
struct aspath *find;
|
||||||
|
|
||||||
/* Parse each segment and construct normalised list of struct assegment */
|
/* If length is odd it's malformed AS path. */
|
||||||
memset (&as, 0, sizeof (struct aspath));
|
/* Nit-picking: if (use32bit == 0) it is malformed if odd,
|
||||||
if (length != 0)
|
* otherwise its malformed when length is larger than 2 and (length-2)
|
||||||
{
|
* is not dividable by 4.
|
||||||
as.segments = assegments_parse (s, length, use32bit, as4_path);
|
* But... this time we're lazy
|
||||||
|
*/
|
||||||
|
if (length % AS16_VALUE_SIZE )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (as.segments == NULL)
|
memset (&as, 0, sizeof (struct aspath));
|
||||||
return NULL ; /* Invalid AS_PATH or AS4_PATH */
|
if (assegments_parse (s, length, &as.segments, use32bit) < 0)
|
||||||
} ;
|
return NULL;
|
||||||
|
|
||||||
/* If already same aspath exist then return it. */
|
/* If already same aspath exist then return it. */
|
||||||
find = hash_get (ashash, &as, aspath_hash_alloc);
|
find = hash_get (ashash, &as, aspath_hash_alloc);
|
||||||
|
|
||||||
assert(find) ; /* valid aspath, so must find or create */
|
|
||||||
|
|
||||||
/* aspath_hash_alloc dupes segments too. that probably could be
|
/* aspath_hash_alloc dupes segments too. that probably could be
|
||||||
* optimised out.
|
* optimised out.
|
||||||
*/
|
*/
|
||||||
@ -809,12 +805,14 @@ aspath_parse (struct stream *s, size_t length, int use32bit, int as4_path)
|
|||||||
if (as.str)
|
if (as.str)
|
||||||
XFREE (MTYPE_AS_STR, as.str);
|
XFREE (MTYPE_AS_STR, as.str);
|
||||||
|
|
||||||
|
if (! find)
|
||||||
|
return NULL;
|
||||||
find->refcnt++;
|
find->refcnt++;
|
||||||
|
|
||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
|
assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -832,7 +830,7 @@ assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static size_t
|
||||||
assegment_header_put (struct stream *s, u_char type, int length)
|
assegment_header_put (struct stream *s, u_char type, int length)
|
||||||
{
|
{
|
||||||
size_t lenp;
|
size_t lenp;
|
||||||
@ -1632,7 +1630,7 @@ aspath_segment_add (struct aspath *as, int type)
|
|||||||
struct aspath *
|
struct aspath *
|
||||||
aspath_empty (void)
|
aspath_empty (void)
|
||||||
{
|
{
|
||||||
return aspath_parse (NULL, 0, 1, 0); /* 32Bit ;-) not AS4_PATH */
|
return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aspath *
|
struct aspath *
|
||||||
|
@ -65,7 +65,7 @@ struct aspath
|
|||||||
/* Prototypes. */
|
/* Prototypes. */
|
||||||
extern void aspath_init (void);
|
extern void aspath_init (void);
|
||||||
extern void aspath_finish (void);
|
extern void aspath_finish (void);
|
||||||
extern struct aspath *aspath_parse (struct stream *, size_t, int, int);
|
extern struct aspath *aspath_parse (struct stream *, size_t, int);
|
||||||
extern struct aspath *aspath_dup (struct aspath *);
|
extern struct aspath *aspath_dup (struct aspath *);
|
||||||
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
|
extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
|
||||||
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
|
extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
|
||||||
@ -80,7 +80,7 @@ extern struct aspath *aspath_empty_get (void);
|
|||||||
extern struct aspath *aspath_str2aspath (const char *);
|
extern struct aspath *aspath_str2aspath (const char *);
|
||||||
extern void aspath_free (struct aspath *);
|
extern void aspath_free (struct aspath *);
|
||||||
extern struct aspath *aspath_intern (struct aspath *);
|
extern struct aspath *aspath_intern (struct aspath *);
|
||||||
extern void aspath_unintern (struct aspath *);
|
extern void aspath_unintern (struct aspath **);
|
||||||
extern const char *aspath_print (struct aspath *);
|
extern const char *aspath_print (struct aspath *);
|
||||||
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
|
extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *);
|
||||||
extern void aspath_print_all_vty (struct vty *);
|
extern void aspath_print_all_vty (struct vty *);
|
||||||
|
1020
bgpd/bgp_attr.c
1020
bgpd/bgp_attr.c
File diff suppressed because it is too large
Load Diff
@ -132,17 +132,25 @@ struct transit
|
|||||||
|
|
||||||
#define ATTR_FLAG_BIT(X) (1 << ((X) - 1))
|
#define ATTR_FLAG_BIT(X) (1 << ((X) - 1))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BGP_ATTR_PARSE_PROCEED = 0,
|
||||||
|
BGP_ATTR_PARSE_ERROR = -1,
|
||||||
|
BGP_ATTR_PARSE_WITHDRAW = -2,
|
||||||
|
} bgp_attr_parse_ret_t;
|
||||||
|
|
||||||
/* Prototypes. */
|
/* Prototypes. */
|
||||||
extern void bgp_attr_init (void);
|
extern void bgp_attr_init (void);
|
||||||
extern void bgp_attr_finish (void);
|
extern void bgp_attr_finish (void);
|
||||||
extern int bgp_attr_parse (struct peer *, struct attr *, bgp_size_t,
|
extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *,
|
||||||
struct bgp_nlri *, struct bgp_nlri *);
|
bgp_size_t, struct bgp_nlri *,
|
||||||
|
struct bgp_nlri *);
|
||||||
extern int bgp_attr_check (struct peer *, struct attr *);
|
extern int bgp_attr_check (struct peer *, struct attr *);
|
||||||
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
|
extern struct attr_extra *bgp_attr_extra_get (struct attr *);
|
||||||
extern void bgp_attr_extra_free (struct attr *);
|
extern void bgp_attr_extra_free (struct attr *);
|
||||||
extern void bgp_attr_dup (struct attr *, struct attr *);
|
extern void bgp_attr_dup (struct attr *, struct attr *);
|
||||||
extern struct attr *bgp_attr_intern (struct attr *attr);
|
extern struct attr *bgp_attr_intern (struct attr *attr);
|
||||||
extern void bgp_attr_unintern (struct attr *);
|
extern void bgp_attr_unintern_sub (struct attr *);
|
||||||
|
extern void bgp_attr_unintern (struct attr **);
|
||||||
extern void bgp_attr_flush (struct attr *);
|
extern void bgp_attr_flush (struct attr *);
|
||||||
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
|
extern struct attr *bgp_attr_default_set (struct attr *attr, u_char);
|
||||||
extern struct attr *bgp_attr_default_intern (u_char);
|
extern struct attr *bgp_attr_default_intern (u_char);
|
||||||
@ -171,9 +179,19 @@ extern void cluster_unintern (struct cluster_list *);
|
|||||||
/* Transit attribute prototypes. */
|
/* Transit attribute prototypes. */
|
||||||
void transit_unintern (struct transit *);
|
void transit_unintern (struct transit *);
|
||||||
|
|
||||||
/* Exported for unit-test purposes only */
|
/* Below exported for unit-test purposes only */
|
||||||
extern int bgp_mp_reach_parse (struct peer *, bgp_size_t, struct attr *,
|
struct bgp_attr_parser_args {
|
||||||
|
struct peer *peer;
|
||||||
|
bgp_size_t length; /* attribute data length; */
|
||||||
|
bgp_size_t total; /* total length, inc header */
|
||||||
|
struct attr *attr;
|
||||||
|
u_int8_t type;
|
||||||
|
u_int8_t flags;
|
||||||
|
u_char *startp;
|
||||||
|
};
|
||||||
|
extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||||
struct bgp_nlri *);
|
struct bgp_nlri *);
|
||||||
extern int bgp_mp_unreach_parse (struct peer *, bgp_size_t, struct bgp_nlri *);
|
extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
|
||||||
|
struct bgp_nlri *);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_ATTR_H */
|
#endif /* _QUAGGA_BGP_ATTR_H */
|
||||||
|
@ -70,7 +70,7 @@ community_entry_free (struct community_entry *entry)
|
|||||||
if (entry->config)
|
if (entry->config)
|
||||||
XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
|
XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
|
||||||
if (entry->u.ecom)
|
if (entry->u.ecom)
|
||||||
ecommunity_free (entry->u.ecom);
|
ecommunity_free (&entry->u.ecom);
|
||||||
break;
|
break;
|
||||||
case COMMUNITY_LIST_EXPANDED:
|
case COMMUNITY_LIST_EXPANDED:
|
||||||
case EXTCOMMUNITY_LIST_EXPANDED:
|
case EXTCOMMUNITY_LIST_EXPANDED:
|
||||||
@ -806,7 +806,7 @@ extcommunity_list_unset (struct community_list_handler *ch,
|
|||||||
entry = community_list_entry_lookup (list, str, direct);
|
entry = community_list_entry_lookup (list, str, direct);
|
||||||
|
|
||||||
if (ecom)
|
if (ecom)
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (&ecom);
|
||||||
if (regex)
|
if (regex)
|
||||||
bgp_regex_free (regex);
|
bgp_regex_free (regex);
|
||||||
|
|
||||||
|
@ -321,21 +321,22 @@ community_intern (struct community *com)
|
|||||||
|
|
||||||
/* Free community attribute. */
|
/* Free community attribute. */
|
||||||
void
|
void
|
||||||
community_unintern (struct community *com)
|
community_unintern (struct community **com)
|
||||||
{
|
{
|
||||||
struct community *ret;
|
struct community *ret;
|
||||||
|
|
||||||
if (com->refcnt)
|
if ((*com)->refcnt)
|
||||||
com->refcnt--;
|
(*com)->refcnt--;
|
||||||
|
|
||||||
/* Pull off from hash. */
|
/* Pull off from hash. */
|
||||||
if (com->refcnt == 0)
|
if ((*com)->refcnt == 0)
|
||||||
{
|
{
|
||||||
/* Community value com must exist in hash. */
|
/* Community value com must exist in hash. */
|
||||||
ret = (struct community *) hash_release (comhash, com);
|
ret = (struct community *) hash_release (comhash, *com);
|
||||||
assert (ret != NULL);
|
assert (ret != NULL);
|
||||||
|
|
||||||
community_free (com);
|
community_free (*com);
|
||||||
|
*com = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ extern void community_free (struct community *);
|
|||||||
extern struct community *community_uniq_sort (struct community *);
|
extern struct community *community_uniq_sort (struct community *);
|
||||||
extern struct community *community_parse (u_int32_t *, u_short);
|
extern struct community *community_parse (u_int32_t *, u_short);
|
||||||
extern struct community *community_intern (struct community *);
|
extern struct community *community_intern (struct community *);
|
||||||
extern void community_unintern (struct community *);
|
extern void community_unintern (struct community **);
|
||||||
extern char *community_str (struct community *);
|
extern char *community_str (struct community *);
|
||||||
extern unsigned int community_hash_make (struct community *);
|
extern unsigned int community_hash_make (struct community *);
|
||||||
extern struct community *community_str2com (const char *);
|
extern struct community *community_str2com (const char *);
|
||||||
|
@ -105,6 +105,7 @@ static const int bgp_notify_head_msg_max = BGP_NOTIFY_HEADER_MAX;
|
|||||||
|
|
||||||
static const struct message bgp_notify_open_msg[] =
|
static const struct message bgp_notify_open_msg[] =
|
||||||
{
|
{
|
||||||
|
{ BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
|
||||||
{ BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number" },
|
{ BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number" },
|
||||||
{ BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"},
|
{ BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"},
|
||||||
{ BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"},
|
{ BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"},
|
||||||
@ -117,6 +118,7 @@ static const int bgp_notify_open_msg_max = BGP_NOTIFY_OPEN_MAX;
|
|||||||
|
|
||||||
static const struct message bgp_notify_update_msg[] =
|
static const struct message bgp_notify_update_msg[] =
|
||||||
{
|
{
|
||||||
|
{ BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
|
||||||
{ BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"},
|
{ BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"},
|
||||||
{ BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"},
|
{ BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"},
|
||||||
{ BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"},
|
{ BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"},
|
||||||
@ -133,6 +135,7 @@ static const int bgp_notify_update_msg_max = BGP_NOTIFY_UPDATE_MAX;
|
|||||||
|
|
||||||
static const struct message bgp_notify_cease_msg[] =
|
static const struct message bgp_notify_cease_msg[] =
|
||||||
{
|
{
|
||||||
|
{ BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
|
||||||
{ BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"},
|
{ BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"},
|
||||||
{ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown"},
|
{ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown"},
|
||||||
{ BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured"},
|
{ BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured"},
|
||||||
@ -146,6 +149,7 @@ static const int bgp_notify_cease_msg_max = BGP_NOTIFY_CEASE_MAX;
|
|||||||
|
|
||||||
static const struct message bgp_notify_capability_msg[] =
|
static const struct message bgp_notify_capability_msg[] =
|
||||||
{
|
{
|
||||||
|
{ BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"},
|
||||||
{ BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value" },
|
{ BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value" },
|
||||||
{ BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"},
|
{ BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"},
|
||||||
{ BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"},
|
{ BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"},
|
||||||
|
@ -42,13 +42,14 @@ ecommunity_new (void)
|
|||||||
|
|
||||||
/* Allocate ecommunities. */
|
/* Allocate ecommunities. */
|
||||||
void
|
void
|
||||||
ecommunity_free (struct ecommunity *ecom)
|
ecommunity_free (struct ecommunity **ecom)
|
||||||
{
|
{
|
||||||
if (ecom->val)
|
if ((*ecom)->val)
|
||||||
XFREE (MTYPE_ECOMMUNITY_VAL, ecom->val);
|
XFREE (MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
|
||||||
if (ecom->str)
|
if ((*ecom)->str)
|
||||||
XFREE (MTYPE_ECOMMUNITY_STR, ecom->str);
|
XFREE (MTYPE_ECOMMUNITY_STR, (*ecom)->str);
|
||||||
XFREE (MTYPE_ECOMMUNITY, ecom);
|
XFREE (MTYPE_ECOMMUNITY, *ecom);
|
||||||
|
ecom = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a new Extended Communities value to Extended Communities
|
/* Add a new Extended Communities value to Extended Communities
|
||||||
@ -197,7 +198,7 @@ ecommunity_intern (struct ecommunity *ecom)
|
|||||||
find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
|
find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
|
||||||
|
|
||||||
if (find != ecom)
|
if (find != ecom)
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (&ecom);
|
||||||
|
|
||||||
find->refcnt++;
|
find->refcnt++;
|
||||||
|
|
||||||
@ -209,18 +210,18 @@ ecommunity_intern (struct ecommunity *ecom)
|
|||||||
|
|
||||||
/* Unintern Extended Communities Attribute. */
|
/* Unintern Extended Communities Attribute. */
|
||||||
void
|
void
|
||||||
ecommunity_unintern (struct ecommunity *ecom)
|
ecommunity_unintern (struct ecommunity **ecom)
|
||||||
{
|
{
|
||||||
struct ecommunity *ret;
|
struct ecommunity *ret;
|
||||||
|
|
||||||
if (ecom->refcnt)
|
if ((*ecom)->refcnt)
|
||||||
ecom->refcnt--;
|
(*ecom)->refcnt--;
|
||||||
|
|
||||||
/* Pull off from hash. */
|
/* Pull off from hash. */
|
||||||
if (ecom->refcnt == 0)
|
if ((*ecom)->refcnt == 0)
|
||||||
{
|
{
|
||||||
/* Extended community must be in the hash. */
|
/* Extended community must be in the hash. */
|
||||||
ret = (struct ecommunity *) hash_release (ecomhash, ecom);
|
ret = (struct ecommunity *) hash_release (ecomhash, *ecom);
|
||||||
assert (ret != NULL);
|
assert (ret != NULL);
|
||||||
|
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (ecom);
|
||||||
@ -516,7 +517,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
|
|||||||
if (! keyword_included || keyword)
|
if (! keyword_included || keyword)
|
||||||
{
|
{
|
||||||
if (ecom)
|
if (ecom)
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (&ecom);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
keyword = 1;
|
keyword = 1;
|
||||||
@ -536,7 +537,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
|
|||||||
if (! keyword)
|
if (! keyword)
|
||||||
{
|
{
|
||||||
if (ecom)
|
if (ecom)
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (&ecom);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
keyword = 0;
|
keyword = 0;
|
||||||
@ -549,7 +550,7 @@ ecommunity_str2com (const char *str, int type, int keyword_included)
|
|||||||
case ecommunity_token_unknown:
|
case ecommunity_token_unknown:
|
||||||
default:
|
default:
|
||||||
if (ecom)
|
if (ecom)
|
||||||
ecommunity_free (ecom);
|
ecommunity_free (&ecom);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,6 +620,13 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
|
|||||||
|
|
||||||
for (i = 0; i < ecom->size; i++)
|
for (i = 0; i < ecom->size; i++)
|
||||||
{
|
{
|
||||||
|
/* Make it sure size is enough. */
|
||||||
|
while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size)
|
||||||
|
{
|
||||||
|
str_size *= 2;
|
||||||
|
str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Space between each value. */
|
/* Space between each value. */
|
||||||
if (! first)
|
if (! first)
|
||||||
str_buf[str_pnt++] = ' ';
|
str_buf[str_pnt++] = ' ';
|
||||||
@ -662,13 +670,6 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make it sure size is enough. */
|
|
||||||
while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size)
|
|
||||||
{
|
|
||||||
str_size *= 2;
|
|
||||||
str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put string into buffer. */
|
/* Put string into buffer. */
|
||||||
if (encode == ECOMMUNITY_ENCODE_AS4)
|
if (encode == ECOMMUNITY_ENCODE_AS4)
|
||||||
{
|
{
|
||||||
|
@ -67,13 +67,13 @@ struct ecommunity_val
|
|||||||
|
|
||||||
extern void ecommunity_init (void);
|
extern void ecommunity_init (void);
|
||||||
extern void ecommunity_finish (void);
|
extern void ecommunity_finish (void);
|
||||||
extern void ecommunity_free (struct ecommunity *);
|
extern void ecommunity_free (struct ecommunity **);
|
||||||
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
|
extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short);
|
||||||
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
|
extern struct ecommunity *ecommunity_dup (struct ecommunity *);
|
||||||
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
|
extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
|
||||||
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
|
extern struct ecommunity *ecommunity_intern (struct ecommunity *);
|
||||||
extern int ecommunity_cmp (const void *, const void *);
|
extern int ecommunity_cmp (const void *, const void *);
|
||||||
extern void ecommunity_unintern (struct ecommunity *);
|
extern void ecommunity_unintern (struct ecommunity **);
|
||||||
extern unsigned int ecommunity_hash_make (void *);
|
extern unsigned int ecommunity_hash_make (void *);
|
||||||
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
|
extern struct ecommunity *ecommunity_str2com (const char *, int, int);
|
||||||
extern char *ecommunity_ecom2str (struct ecommunity *, int);
|
extern char *ecommunity_ecom2str (struct ecommunity *, int);
|
||||||
|
@ -355,7 +355,7 @@ bgp_graceful_restart_timer_expire (struct thread *thread)
|
|||||||
|
|
||||||
/* NSF delete stale route */
|
/* NSF delete stale route */
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
|
||||||
if (peer->nsf[afi][safi])
|
if (peer->nsf[afi][safi])
|
||||||
bgp_clear_stale_route (peer, afi, safi);
|
bgp_clear_stale_route (peer, afi, safi);
|
||||||
|
|
||||||
@ -388,7 +388,7 @@ bgp_graceful_stale_timer_expire (struct thread *thread)
|
|||||||
|
|
||||||
/* NSF delete stale route */
|
/* NSF delete stale route */
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
|
||||||
if (peer->nsf[afi][safi])
|
if (peer->nsf[afi][safi])
|
||||||
bgp_clear_stale_route (peer, afi, safi);
|
bgp_clear_stale_route (peer, afi, safi);
|
||||||
|
|
||||||
@ -481,7 +481,7 @@ bgp_stop (struct peer *peer)
|
|||||||
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
|
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
|
||||||
|
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
|
||||||
peer->nsf[afi][safi] = 0;
|
peer->nsf[afi][safi] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,7 +799,7 @@ bgp_establish (struct peer *peer)
|
|||||||
/* graceful restart */
|
/* graceful restart */
|
||||||
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
|
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
|
||||||
{
|
{
|
||||||
if (peer->afc_nego[afi][safi]
|
if (peer->afc_nego[afi][safi]
|
||||||
&& CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
|
&& CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV)
|
||||||
|
@ -54,6 +54,7 @@ static const struct option longopts[] =
|
|||||||
{ "daemon", no_argument, NULL, 'd'},
|
{ "daemon", no_argument, NULL, 'd'},
|
||||||
{ "config_file", required_argument, NULL, 'f'},
|
{ "config_file", required_argument, NULL, 'f'},
|
||||||
{ "pid_file", required_argument, NULL, 'i'},
|
{ "pid_file", required_argument, NULL, 'i'},
|
||||||
|
{ "socket", required_argument, NULL, 'z'},
|
||||||
{ "bgp_port", required_argument, NULL, 'p'},
|
{ "bgp_port", required_argument, NULL, 'p'},
|
||||||
{ "listenon", required_argument, NULL, 'l'},
|
{ "listenon", required_argument, NULL, 'l'},
|
||||||
{ "vty_addr", required_argument, NULL, 'A'},
|
{ "vty_addr", required_argument, NULL, 'A'},
|
||||||
@ -119,6 +120,7 @@ static zebra_capabilities_t _caps_p [] =
|
|||||||
{
|
{
|
||||||
ZCAP_BIND,
|
ZCAP_BIND,
|
||||||
ZCAP_NET_RAW,
|
ZCAP_NET_RAW,
|
||||||
|
ZCAP_NET_ADMIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zebra_privs_t bgpd_privs =
|
struct zebra_privs_t bgpd_privs =
|
||||||
@ -149,6 +151,7 @@ redistribution between different routing protocols.\n\n\
|
|||||||
-d, --daemon Runs in daemon mode\n\
|
-d, --daemon Runs in daemon mode\n\
|
||||||
-f, --config_file Set configuration file name\n\
|
-f, --config_file Set configuration file name\n\
|
||||||
-i, --pid_file Set process identifier file name\n\
|
-i, --pid_file Set process identifier file name\n\
|
||||||
|
-z, --socket Set path of zebra socket\n\
|
||||||
-p, --bgp_port Set bgp protocol's port number\n\
|
-p, --bgp_port Set bgp protocol's port number\n\
|
||||||
-l, --listenon Listen on specified address (implies -n)\n\
|
-l, --listenon Listen on specified address (implies -n)\n\
|
||||||
-A, --vty_addr Set vty's bind address\n\
|
-A, --vty_addr Set vty's bind address\n\
|
||||||
@ -196,6 +199,7 @@ sigint (void)
|
|||||||
if (! retain_mode)
|
if (! retain_mode)
|
||||||
bgp_terminate ();
|
bgp_terminate ();
|
||||||
|
|
||||||
|
zprivs_terminate (&bgpd_privs);
|
||||||
bgp_exit (0);
|
bgp_exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +339,7 @@ main (int argc, char **argv)
|
|||||||
/* Command line argument treatment. */
|
/* Command line argument treatment. */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
opt = getopt_long (argc, argv, "df:i:hp:l:A:P:rnu:g:vC", longopts, 0);
|
opt = getopt_long (argc, argv, "df:i:z:hp:l:A:P:rnu:g:vC", longopts, 0);
|
||||||
|
|
||||||
if (opt == EOF)
|
if (opt == EOF)
|
||||||
break;
|
break;
|
||||||
@ -353,6 +357,9 @@ main (int argc, char **argv)
|
|||||||
case 'i':
|
case 'i':
|
||||||
pid_file = optarg;
|
pid_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'z':
|
||||||
|
zclient_serv_path_set (optarg);
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
tmp_port = atoi (optarg);
|
tmp_port = atoi (optarg);
|
||||||
if (tmp_port <= 0 || tmp_port > 0xffff)
|
if (tmp_port <= 0 || tmp_port > 0xffff)
|
||||||
|
@ -233,9 +233,13 @@ str2tag (const char *str, u_char *tag)
|
|||||||
char *endptr;
|
char *endptr;
|
||||||
u_int32_t t;
|
u_int32_t t;
|
||||||
|
|
||||||
l = strtoul (str, &endptr, 10);
|
if (*str == '-')
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (*endptr == '\0' || l == ULONG_MAX || l > UINT32_MAX)
|
errno = 0;
|
||||||
|
l = strtoul (str, &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr != '\0' || errno || l > UINT32_MAX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
t = (u_int32_t) l;
|
t = (u_int32_t) l;
|
||||||
|
@ -238,46 +238,36 @@ bgp_bind (struct peer *peer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bgp_bind_address (int sock, struct in_addr *addr)
|
bgp_update_address (struct interface *ifp, const union sockunion *dst,
|
||||||
|
union sockunion *addr)
|
||||||
{
|
{
|
||||||
int ret;
|
struct prefix *p, *sel, *d;
|
||||||
struct sockaddr_in local;
|
|
||||||
|
|
||||||
memset (&local, 0, sizeof (struct sockaddr_in));
|
|
||||||
local.sin_family = AF_INET;
|
|
||||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
|
||||||
local.sin_len = sizeof(struct sockaddr_in);
|
|
||||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
|
||||||
memcpy (&local.sin_addr, addr, sizeof (struct in_addr));
|
|
||||||
|
|
||||||
if ( bgpd_privs.change (ZPRIVS_RAISE) )
|
|
||||||
zlog_err ("bgp_bind_address: could not raise privs");
|
|
||||||
|
|
||||||
ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
|
|
||||||
if (ret < 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
if (bgpd_privs.change (ZPRIVS_LOWER) )
|
|
||||||
zlog_err ("bgp_bind_address: could not lower privs");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct in_addr *
|
|
||||||
bgp_update_address (struct interface *ifp)
|
|
||||||
{
|
|
||||||
struct prefix_ipv4 *p;
|
|
||||||
struct connected *connected;
|
struct connected *connected;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
int common;
|
||||||
|
|
||||||
|
d = sockunion2hostprefix (dst);
|
||||||
|
sel = NULL;
|
||||||
|
common = -1;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
|
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
|
||||||
{
|
{
|
||||||
p = (struct prefix_ipv4 *) connected->address;
|
p = connected->address;
|
||||||
|
if (p->family != d->family)
|
||||||
if (p->family == AF_INET)
|
continue;
|
||||||
return &p->prefix;
|
if (prefix_common_bits (p, d) > common)
|
||||||
|
{
|
||||||
|
sel = p;
|
||||||
|
common = prefix_common_bits (sel, d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
|
prefix_free (d);
|
||||||
|
if (!sel)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
prefix2sockunion (sel, addr);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update source selection. */
|
/* Update source selection. */
|
||||||
@ -285,7 +275,7 @@ static void
|
|||||||
bgp_update_source (struct peer *peer)
|
bgp_update_source (struct peer *peer)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct in_addr *addr;
|
union sockunion addr;
|
||||||
|
|
||||||
/* Source is specified with interface name. */
|
/* Source is specified with interface name. */
|
||||||
if (peer->update_if)
|
if (peer->update_if)
|
||||||
@ -294,11 +284,10 @@ bgp_update_source (struct peer *peer)
|
|||||||
if (! ifp)
|
if (! ifp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addr = bgp_update_address (ifp);
|
if (bgp_update_address (ifp, &peer->su, &addr))
|
||||||
if (! addr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bgp_bind_address (peer->fd, addr);
|
sockunion_bind (peer->fd, &addr, 0, &addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Source is specified with IP address. */
|
/* Source is specified with IP address. */
|
||||||
@ -328,8 +317,16 @@ bgp_connect (struct peer *peer)
|
|||||||
sockopt_reuseport (peer->fd);
|
sockopt_reuseport (peer->fd);
|
||||||
|
|
||||||
#ifdef IPTOS_PREC_INTERNETCONTROL
|
#ifdef IPTOS_PREC_INTERNETCONTROL
|
||||||
|
if (bgpd_privs.change (ZPRIVS_RAISE))
|
||||||
|
zlog_err ("%s: could not raise privs", __func__);
|
||||||
if (sockunion_family (&peer->su) == AF_INET)
|
if (sockunion_family (&peer->su) == AF_INET)
|
||||||
setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
|
setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
|
||||||
|
# ifdef HAVE_IPV6
|
||||||
|
else if (sockunion_family (&peer->su) == AF_INET6)
|
||||||
|
setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
|
||||||
|
# endif
|
||||||
|
if (bgpd_privs.change (ZPRIVS_LOWER))
|
||||||
|
zlog_err ("%s: could not lower privs", __func__);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (peer->password)
|
if (peer->password)
|
||||||
@ -386,27 +383,24 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
|
|||||||
sockopt_reuseaddr (sock);
|
sockopt_reuseaddr (sock);
|
||||||
sockopt_reuseport (sock);
|
sockopt_reuseport (sock);
|
||||||
|
|
||||||
|
if (bgpd_privs.change (ZPRIVS_RAISE))
|
||||||
|
zlog_err ("%s: could not raise privs", __func__);
|
||||||
|
|
||||||
#ifdef IPTOS_PREC_INTERNETCONTROL
|
#ifdef IPTOS_PREC_INTERNETCONTROL
|
||||||
if (sa->sa_family == AF_INET)
|
if (sa->sa_family == AF_INET)
|
||||||
setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
|
setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
|
||||||
|
# ifdef HAVE_IPV6
|
||||||
|
else if (sa->sa_family == AF_INET6)
|
||||||
|
setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IPV6_V6ONLY
|
sockopt_v6only (sa->sa_family, sock);
|
||||||
/* Want only IPV6 on ipv6 socket (not mapped addresses) */
|
|
||||||
if (sa->sa_family == AF_INET6) {
|
|
||||||
int on = 1;
|
|
||||||
setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
|
||||||
(void *) &on, sizeof (on));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bgpd_privs.change (ZPRIVS_RAISE) )
|
|
||||||
zlog_err ("bgp_socket: could not raise privs");
|
|
||||||
|
|
||||||
ret = bind (sock, sa, salen);
|
ret = bind (sock, sa, salen);
|
||||||
en = errno;
|
en = errno;
|
||||||
if (bgpd_privs.change (ZPRIVS_LOWER) )
|
if (bgpd_privs.change (ZPRIVS_LOWER))
|
||||||
zlog_err ("bgp_bind_address: could not lower privs");
|
zlog_err ("%s: could not lower privs", __func__);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
@ -146,7 +146,7 @@ bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bgp_nexthop_cache_changed (struct bgp_nexthop_cache *bnc1,
|
bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
|
||||||
struct bgp_nexthop_cache *bnc2)
|
struct bgp_nexthop_cache *bnc2)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -171,14 +171,14 @@ bgp_nexthop_cache_changed (struct bgp_nexthop_cache *bnc1,
|
|||||||
|
|
||||||
/* If nexthop exists on connected network return 1. */
|
/* If nexthop exists on connected network return 1. */
|
||||||
int
|
int
|
||||||
bgp_nexthop_check_ebgp (afi_t afi, struct attr *attr)
|
bgp_nexthop_onlink (afi_t afi, struct attr *attr)
|
||||||
{
|
{
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
|
|
||||||
/* If zebra is not enabled return */
|
/* If zebra is not enabled return */
|
||||||
if (zlookup->sock < 0)
|
if (zlookup->sock < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Lookup the address is onlink or not. */
|
/* Lookup the address is onlink or not. */
|
||||||
if (afi == AFI_IP)
|
if (afi == AFI_IP)
|
||||||
{
|
{
|
||||||
@ -222,7 +222,7 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|||||||
struct prefix p;
|
struct prefix p;
|
||||||
struct bgp_nexthop_cache *bnc;
|
struct bgp_nexthop_cache *bnc;
|
||||||
struct attr *attr;
|
struct attr *attr;
|
||||||
|
|
||||||
/* If lookup is not enabled, return valid. */
|
/* If lookup is not enabled, return valid. */
|
||||||
if (zlookup->sock < 0)
|
if (zlookup->sock < 0)
|
||||||
{
|
{
|
||||||
@ -230,7 +230,7 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|||||||
ri->extra->igpmetric = 0;
|
ri->extra->igpmetric = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only check IPv6 global address only nexthop. */
|
/* Only check IPv6 global address only nexthop. */
|
||||||
attr = ri->attr;
|
attr = ri->attr;
|
||||||
|
|
||||||
@ -253,15 +253,15 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global);
|
if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
|
||||||
if (bnc)
|
bnc = bnc_new ();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
struct bgp_table *old;
|
|
||||||
struct bgp_node *oldrn;
|
|
||||||
struct bgp_nexthop_cache *oldbnc;
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
|
struct bgp_table *old;
|
||||||
|
struct bgp_node *oldrn;
|
||||||
|
|
||||||
if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
|
if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
|
||||||
old = cache2_table[AFI_IP6];
|
old = cache2_table[AFI_IP6];
|
||||||
else
|
else
|
||||||
@ -270,9 +270,9 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|||||||
oldrn = bgp_node_lookup (old, &p);
|
oldrn = bgp_node_lookup (old, &p);
|
||||||
if (oldrn)
|
if (oldrn)
|
||||||
{
|
{
|
||||||
oldbnc = oldrn->info;
|
struct bgp_nexthop_cache *oldbnc = oldrn->info;
|
||||||
|
|
||||||
bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);
|
bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
|
||||||
|
|
||||||
if (bnc->metric != oldbnc->metric)
|
if (bnc->metric != oldbnc->metric)
|
||||||
bnc->metricchanged = 1;
|
bnc->metricchanged = 1;
|
||||||
@ -281,11 +281,6 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
bnc = bnc_new ();
|
|
||||||
bnc->valid = 0;
|
|
||||||
}
|
|
||||||
rn->info = bnc;
|
rn->info = bnc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +308,7 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|||||||
struct prefix p;
|
struct prefix p;
|
||||||
struct bgp_nexthop_cache *bnc;
|
struct bgp_nexthop_cache *bnc;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
|
|
||||||
/* If lookup is not enabled, return valid. */
|
/* If lookup is not enabled, return valid. */
|
||||||
if (zlookup->sock < 0)
|
if (zlookup->sock < 0)
|
||||||
{
|
{
|
||||||
@ -321,7 +316,7 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|||||||
ri->extra->igpmetric = 0;
|
ri->extra->igpmetric = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (afi == AFI_IP6)
|
if (afi == AFI_IP6)
|
||||||
return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
|
return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
|
||||||
@ -344,15 +339,15 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bnc = zlookup_query (addr);
|
if (NULL == (bnc = zlookup_query (addr)))
|
||||||
if (bnc)
|
bnc = bnc_new ();
|
||||||
|
else
|
||||||
{
|
{
|
||||||
struct bgp_table *old;
|
|
||||||
struct bgp_node *oldrn;
|
|
||||||
struct bgp_nexthop_cache *oldbnc;
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
|
struct bgp_table *old;
|
||||||
|
struct bgp_node *oldrn;
|
||||||
|
|
||||||
if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
|
if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
|
||||||
old = cache2_table[AFI_IP];
|
old = cache2_table[AFI_IP];
|
||||||
else
|
else
|
||||||
@ -361,9 +356,9 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|||||||
oldrn = bgp_node_lookup (old, &p);
|
oldrn = bgp_node_lookup (old, &p);
|
||||||
if (oldrn)
|
if (oldrn)
|
||||||
{
|
{
|
||||||
oldbnc = oldrn->info;
|
struct bgp_nexthop_cache *oldbnc = oldrn->info;
|
||||||
|
|
||||||
bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);
|
bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
|
||||||
|
|
||||||
if (bnc->metric != oldbnc->metric)
|
if (bnc->metric != oldbnc->metric)
|
||||||
bnc->metricchanged = 1;
|
bnc->metricchanged = 1;
|
||||||
@ -372,11 +367,6 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
bnc = bnc_new ();
|
|
||||||
bnc->valid = 0;
|
|
||||||
}
|
|
||||||
rn->info = bnc;
|
rn->info = bnc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +452,7 @@ bgp_scan (afi_t afi, safi_t safi)
|
|||||||
metricchanged = 0;
|
metricchanged = 0;
|
||||||
|
|
||||||
if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
|
if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
|
||||||
valid = bgp_nexthop_check_ebgp (afi, bi->attr);
|
valid = bgp_nexthop_onlink (afi, bi->attr);
|
||||||
else
|
else
|
||||||
valid = bgp_nexthop_lookup (afi, bi->peer, bi,
|
valid = bgp_nexthop_lookup (afi, bi->peer, bi,
|
||||||
&changed, &metricchanged);
|
&changed, &metricchanged);
|
||||||
@ -1098,12 +1088,7 @@ zlookup_connect (struct thread *t)
|
|||||||
if (zlookup->sock != -1)
|
if (zlookup->sock != -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_TCP_ZEBRA
|
if (zclient_socket_connect (zlookup) < 0)
|
||||||
zlookup->sock = zclient_socket ();
|
|
||||||
#else
|
|
||||||
zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH);
|
|
||||||
#endif /* HAVE_TCP_ZEBRA */
|
|
||||||
if (zlookup->sock < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1201,16 +1186,13 @@ ALIAS (no_bgp_scan_time,
|
|||||||
"Configure background scanner interval\n"
|
"Configure background scanner interval\n"
|
||||||
"Scanner interval (seconds)\n")
|
"Scanner interval (seconds)\n")
|
||||||
|
|
||||||
DEFUN (show_ip_bgp_scan,
|
static int
|
||||||
show_ip_bgp_scan_cmd,
|
show_ip_bgp_scan_tables (struct vty *vty, const char detail)
|
||||||
"show ip bgp scan",
|
|
||||||
SHOW_STR
|
|
||||||
IP_STR
|
|
||||||
BGP_STR
|
|
||||||
"BGP scan status\n")
|
|
||||||
{
|
{
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
struct bgp_nexthop_cache *bnc;
|
struct bgp_nexthop_cache *bnc;
|
||||||
|
char buf[INET6_ADDRSTRLEN];
|
||||||
|
u_char i;
|
||||||
|
|
||||||
if (bgp_scan_thread)
|
if (bgp_scan_thread)
|
||||||
vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
|
vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
|
||||||
@ -1223,28 +1205,57 @@ DEFUN (show_ip_bgp_scan,
|
|||||||
if ((bnc = rn->info) != NULL)
|
if ((bnc = rn->info) != NULL)
|
||||||
{
|
{
|
||||||
if (bnc->valid)
|
if (bnc->valid)
|
||||||
|
{
|
||||||
vty_out (vty, " %s valid [IGP metric %d]%s",
|
vty_out (vty, " %s valid [IGP metric %d]%s",
|
||||||
inet_ntoa (rn->p.u.prefix4), bnc->metric, VTY_NEWLINE);
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
|
||||||
|
if (detail)
|
||||||
|
for (i = 0; i < bnc->nexthop_num; i++)
|
||||||
|
switch (bnc->nexthop[i].type)
|
||||||
|
{
|
||||||
|
case NEXTHOP_TYPE_IPV4:
|
||||||
|
vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
||||||
|
break;
|
||||||
|
case NEXTHOP_TYPE_IFINDEX:
|
||||||
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
vty_out (vty, " %s invalid%s",
|
vty_out (vty, " %s invalid%s",
|
||||||
inet_ntoa (rn->p.u.prefix4), VTY_NEWLINE);
|
inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
{
|
{
|
||||||
char buf[BUFSIZ];
|
|
||||||
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
|
for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
|
||||||
rn;
|
rn;
|
||||||
rn = bgp_route_next (rn))
|
rn = bgp_route_next (rn))
|
||||||
if ((bnc = rn->info) != NULL)
|
if ((bnc = rn->info) != NULL)
|
||||||
{
|
{
|
||||||
if (bnc->valid)
|
if (bnc->valid)
|
||||||
|
{
|
||||||
vty_out (vty, " %s valid [IGP metric %d]%s",
|
vty_out (vty, " %s valid [IGP metric %d]%s",
|
||||||
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
||||||
bnc->metric, VTY_NEWLINE);
|
bnc->metric, VTY_NEWLINE);
|
||||||
|
if (detail)
|
||||||
|
for (i = 0; i < bnc->nexthop_num; i++)
|
||||||
|
switch (bnc->nexthop[i].type)
|
||||||
|
{
|
||||||
|
case NEXTHOP_TYPE_IPV6:
|
||||||
|
vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
|
||||||
|
break;
|
||||||
|
case NEXTHOP_TYPE_IFINDEX:
|
||||||
|
vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
vty_out (vty, " %s invalid%s",
|
vty_out (vty, " %s invalid%s",
|
||||||
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1260,14 +1271,12 @@ DEFUN (show_ip_bgp_scan,
|
|||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
{
|
{
|
||||||
char buf[BUFSIZ];
|
|
||||||
|
|
||||||
for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
|
for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
|
||||||
rn;
|
rn;
|
||||||
rn = bgp_route_next (rn))
|
rn = bgp_route_next (rn))
|
||||||
if (rn->info != NULL)
|
if (rn->info != NULL)
|
||||||
vty_out (vty, " %s/%d%s",
|
vty_out (vty, " %s/%d%s",
|
||||||
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
|
inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
|
||||||
rn->p.prefixlen,
|
rn->p.prefixlen,
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
@ -1276,6 +1285,29 @@ DEFUN (show_ip_bgp_scan,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (show_ip_bgp_scan,
|
||||||
|
show_ip_bgp_scan_cmd,
|
||||||
|
"show ip bgp scan",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP scan status\n")
|
||||||
|
{
|
||||||
|
return show_ip_bgp_scan_tables (vty, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (show_ip_bgp_scan_detail,
|
||||||
|
show_ip_bgp_scan_detail_cmd,
|
||||||
|
"show ip bgp scan detail",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
BGP_STR
|
||||||
|
"BGP scan status\n"
|
||||||
|
"More detailed output\n")
|
||||||
|
{
|
||||||
|
return show_ip_bgp_scan_tables (vty, 1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_config_write_scan_time (struct vty *vty)
|
bgp_config_write_scan_time (struct vty *vty)
|
||||||
{
|
{
|
||||||
@ -1317,8 +1349,10 @@ bgp_scan_init (void)
|
|||||||
install_element (BGP_NODE, &no_bgp_scan_time_cmd);
|
install_element (BGP_NODE, &no_bgp_scan_time_cmd);
|
||||||
install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
|
install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
|
||||||
install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
|
install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
|
||||||
|
install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
|
install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
|
||||||
install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
|
install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
|
||||||
|
install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -54,7 +54,7 @@ extern void bgp_connected_add (struct connected *c);
|
|||||||
extern void bgp_connected_delete (struct connected *c);
|
extern void bgp_connected_delete (struct connected *c);
|
||||||
extern int bgp_multiaccess_check_v4 (struct in_addr, char *);
|
extern int bgp_multiaccess_check_v4 (struct in_addr, char *);
|
||||||
extern int bgp_config_write_scan_time (struct vty *);
|
extern int bgp_config_write_scan_time (struct vty *);
|
||||||
extern int bgp_nexthop_check_ebgp (afi_t, struct attr *);
|
extern int bgp_nexthop_onlink (afi_t, struct attr *);
|
||||||
extern int bgp_nexthop_self (afi_t, struct attr *);
|
extern int bgp_nexthop_self (afi_t, struct attr *);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_NEXTHOP_H */
|
#endif /* _QUAGGA_BGP_NEXTHOP_H */
|
||||||
|
@ -93,11 +93,8 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
|
|||||||
case SAFI_MULTICAST:
|
case SAFI_MULTICAST:
|
||||||
vty_out (vty, "SAFI Multicast");
|
vty_out (vty, "SAFI Multicast");
|
||||||
break;
|
break;
|
||||||
case SAFI_UNICAST_MULTICAST:
|
case SAFI_MPLS_LABELED_VPN:
|
||||||
vty_out (vty, "SAFI Unicast Multicast");
|
vty_out (vty, "SAFI MPLS-labeled VPN");
|
||||||
break;
|
|
||||||
case BGP_SAFI_VPNV4:
|
|
||||||
vty_out (vty, "SAFI MPLS-VPN");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vty_out (vty, "SAFI Unknown %d ", mpc.safi);
|
vty_out (vty, "SAFI Unknown %d ", mpc.safi);
|
||||||
@ -127,14 +124,6 @@ bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
|
|||||||
int
|
int
|
||||||
bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
|
bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
|
||||||
{
|
{
|
||||||
/* VPNvX are AFI specific */
|
|
||||||
if ((afi == AFI_IP6 && *safi == BGP_SAFI_VPNV4)
|
|
||||||
|| (afi == AFI_IP && *safi == BGP_SAFI_VPNV6))
|
|
||||||
{
|
|
||||||
zlog_warn ("Invalid afi/safi combination (%u/%u)", afi, *safi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (afi)
|
switch (afi)
|
||||||
{
|
{
|
||||||
case AFI_IP:
|
case AFI_IP:
|
||||||
@ -143,9 +132,8 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
|
|||||||
#endif
|
#endif
|
||||||
switch (*safi)
|
switch (*safi)
|
||||||
{
|
{
|
||||||
/* BGP VPNvX SAFI isn't contigious with others, remap */
|
/* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
|
||||||
case BGP_SAFI_VPNV4:
|
case SAFI_MPLS_LABELED_VPN:
|
||||||
case BGP_SAFI_VPNV6:
|
|
||||||
*safi = SAFI_MPLS_VPN;
|
*safi = SAFI_MPLS_VPN;
|
||||||
case SAFI_UNICAST:
|
case SAFI_UNICAST:
|
||||||
case SAFI_MULTICAST:
|
case SAFI_MULTICAST:
|
||||||
@ -392,7 +380,7 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
|
|||||||
peer->v_gr_restart);
|
peer->v_gr_restart);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (stream_get_getp (s) + 4 < end)
|
while (stream_get_getp (s) + 4 <= end)
|
||||||
{
|
{
|
||||||
afi_t afi = stream_getw (s);
|
afi_t afi = stream_getw (s);
|
||||||
safi_t safi = stream_getc (s);
|
safi_t safi = stream_getc (s);
|
||||||
@ -433,13 +421,20 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
|
|||||||
static as_t
|
static as_t
|
||||||
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
|
bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
|
||||||
{
|
{
|
||||||
|
SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
|
||||||
|
|
||||||
|
if (hdr->length != CAPABILITY_CODE_AS4_LEN)
|
||||||
|
{
|
||||||
|
zlog_err ("%s AS4 capability has incorrect data length %d",
|
||||||
|
peer->host, hdr->length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
as_t as4 = stream_getl (BGP_INPUT(peer));
|
as_t as4 = stream_getl (BGP_INPUT(peer));
|
||||||
|
|
||||||
if (BGP_DEBUG (as4, AS4))
|
if (BGP_DEBUG (as4, AS4))
|
||||||
zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
|
zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
|
||||||
peer->host, as4);
|
peer->host, as4);
|
||||||
SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
|
|
||||||
|
|
||||||
return as4;
|
return as4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,9 +696,6 @@ peek_for_as4_capability (struct peer *peer, u_char length)
|
|||||||
|
|
||||||
if (hdr.code == CAPABILITY_CODE_AS4)
|
if (hdr.code == CAPABILITY_CODE_AS4)
|
||||||
{
|
{
|
||||||
if (hdr.length != CAPABILITY_CODE_AS4_LEN)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (BGP_DEBUG (as4, AS4))
|
if (BGP_DEBUG (as4, AS4))
|
||||||
zlog_info ("[AS4] found AS4 capability, about to parse");
|
zlog_info ("[AS4] found AS4 capability, about to parse");
|
||||||
as4 = bgp_capability_as4 (peer, &hdr);
|
as4 = bgp_capability_as4 (peer, &hdr);
|
||||||
@ -859,7 +851,7 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer,
|
|||||||
int number_of_orfs = 0;
|
int number_of_orfs = 0;
|
||||||
|
|
||||||
if (safi == SAFI_MPLS_VPN)
|
if (safi == SAFI_MPLS_VPN)
|
||||||
safi = BGP_SAFI_VPNV4;
|
safi = SAFI_MPLS_LABELED_VPN;
|
||||||
|
|
||||||
stream_putc (s, BGP_OPEN_OPT_CAP);
|
stream_putc (s, BGP_OPEN_OPT_CAP);
|
||||||
capp = stream_get_endp (s); /* Set Capability Len Pointer */
|
capp = stream_get_endp (s); /* Set Capability Len Pointer */
|
||||||
@ -967,7 +959,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
|||||||
stream_putc (s, CAPABILITY_CODE_MP_LEN);
|
stream_putc (s, CAPABILITY_CODE_MP_LEN);
|
||||||
stream_putw (s, AFI_IP);
|
stream_putw (s, AFI_IP);
|
||||||
stream_putc (s, 0);
|
stream_putc (s, 0);
|
||||||
stream_putc (s, BGP_SAFI_VPNV4);
|
stream_putc (s, SAFI_MPLS_LABELED_VPN);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
/* IPv6 unicast. */
|
/* IPv6 unicast. */
|
||||||
|
@ -206,7 +206,7 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
|
|||||||
|
|
||||||
/* Synchnorize attribute. */
|
/* Synchnorize attribute. */
|
||||||
if (adj->attr)
|
if (adj->attr)
|
||||||
bgp_attr_unintern (adj->attr);
|
bgp_attr_unintern (&adj->attr);
|
||||||
else
|
else
|
||||||
peer->scount[afi][safi]++;
|
peer->scount[afi][safi]++;
|
||||||
|
|
||||||
@ -895,14 +895,27 @@ bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
|
|||||||
if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
|
if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
|
||||||
{
|
{
|
||||||
if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
|
if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
|
||||||
peer->last_reset = PEER_DOWN_USER_RESET;
|
{
|
||||||
|
peer->last_reset = PEER_DOWN_USER_RESET;
|
||||||
|
zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
|
||||||
|
}
|
||||||
else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
|
else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
|
||||||
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
|
{
|
||||||
|
peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
|
||||||
|
zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
|
{
|
||||||
|
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
|
||||||
|
zlog_info ("Notification sent to neighbor %s: type %u/%u",
|
||||||
|
peer->host, code, sub_code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
zlog_info ("Notification sent to neighbor %s: configuration change",
|
||||||
|
peer->host);
|
||||||
|
|
||||||
/* Call imidiately. */
|
/* Call immediately. */
|
||||||
BGP_WRITE_OFF (peer->t_write);
|
BGP_WRITE_OFF (peer->t_write);
|
||||||
|
|
||||||
bgp_write_notify (peer);
|
bgp_write_notify (peer);
|
||||||
@ -933,7 +946,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
|
|
||||||
/* Adjust safi code. */
|
/* Adjust safi code. */
|
||||||
if (safi == SAFI_MPLS_VPN)
|
if (safi == SAFI_MPLS_VPN)
|
||||||
safi = BGP_SAFI_VPNV4;
|
safi = SAFI_MPLS_LABELED_VPN;
|
||||||
|
|
||||||
s = stream_new (BGP_MAX_PACKET_SIZE);
|
s = stream_new (BGP_MAX_PACKET_SIZE);
|
||||||
|
|
||||||
@ -1023,7 +1036,7 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
|
|
||||||
/* Adjust safi code. */
|
/* Adjust safi code. */
|
||||||
if (safi == SAFI_MPLS_VPN)
|
if (safi == SAFI_MPLS_VPN)
|
||||||
safi = BGP_SAFI_VPNV4;
|
safi = SAFI_MPLS_LABELED_VPN;
|
||||||
|
|
||||||
s = stream_new (BGP_MAX_PACKET_SIZE);
|
s = stream_new (BGP_MAX_PACKET_SIZE);
|
||||||
|
|
||||||
@ -1368,7 +1381,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||||||
|
|
||||||
/* remote router-id check. */
|
/* remote router-id check. */
|
||||||
if (remote_id.s_addr == 0
|
if (remote_id.s_addr == 0
|
||||||
|| ntohl (remote_id.s_addr) >= 0xe0000000
|
|| IPV4_CLASS_DE (ntohl (remote_id.s_addr))
|
||||||
|| ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
|
|| ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
|
||||||
{
|
{
|
||||||
if (BGP_DEBUG (normal, NORMAL))
|
if (BGP_DEBUG (normal, NORMAL))
|
||||||
@ -1446,9 +1459,13 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||||||
/* Open option part parse. */
|
/* Open option part parse. */
|
||||||
if (optlen != 0)
|
if (optlen != 0)
|
||||||
{
|
{
|
||||||
ret = bgp_open_option_parse (peer, optlen, &capability);
|
if ((ret = bgp_open_option_parse (peer, optlen, &capability)) < 0)
|
||||||
if (ret < 0)
|
{
|
||||||
return ret;
|
bgp_notify_send (peer,
|
||||||
|
BGP_NOTIFY_OPEN_ERR,
|
||||||
|
BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1583,26 +1600,47 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
BGP_NOTIFY_UPDATE_MAL_ATTR);
|
BGP_NOTIFY_UPDATE_MAL_ATTR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Certain attribute parsing errors should not be considered bad enough
|
||||||
|
* to reset the session for, most particularly any partial/optional
|
||||||
|
* attributes that have 'tunneled' over speakers that don't understand
|
||||||
|
* them. Instead we withdraw only the prefix concerned.
|
||||||
|
*
|
||||||
|
* Complicates the flow a little though..
|
||||||
|
*/
|
||||||
|
bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
|
||||||
|
/* This define morphs the update case into a withdraw when lower levels
|
||||||
|
* have signalled an error condition where this is best.
|
||||||
|
*/
|
||||||
|
#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
|
||||||
|
|
||||||
/* Parse attribute when it exists. */
|
/* Parse attribute when it exists. */
|
||||||
if (attribute_len)
|
if (attribute_len)
|
||||||
{
|
{
|
||||||
ret = bgp_attr_parse (peer, &attr, attribute_len,
|
attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
|
||||||
&mp_update, &mp_withdraw);
|
&mp_update, &mp_withdraw);
|
||||||
if (ret < 0)
|
if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logging the attribute. */
|
/* Logging the attribute. */
|
||||||
if (BGP_DEBUG (update, UPDATE_IN))
|
if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
|
||||||
|
|| BGP_DEBUG (update, UPDATE_IN))
|
||||||
{
|
{
|
||||||
ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
|
ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
|
||||||
|
int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
|
||||||
|
? LOG_ERR : LOG_DEBUG;
|
||||||
|
|
||||||
|
if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
|
||||||
|
zlog (peer->log, LOG_ERR,
|
||||||
|
"%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
|
||||||
|
peer->host);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE w/ attr: %s",
|
zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
|
||||||
peer->host, attrstr);
|
peer->host, attrstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Network Layer Reachability Information. */
|
/* Network Layer Reachability Information. */
|
||||||
update_len = end - stream_pnt (s);
|
update_len = end - stream_pnt (s);
|
||||||
|
|
||||||
@ -1611,7 +1649,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
/* Check NLRI packet format and prefix length. */
|
/* Check NLRI packet format and prefix length. */
|
||||||
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
|
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
{
|
||||||
|
bgp_attr_unintern_sub (&attr);
|
||||||
|
if (attr.extra)
|
||||||
|
bgp_attr_extra_free (&attr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set NLRI portion to structure. */
|
/* Set NLRI portion to structure. */
|
||||||
update.afi = AFI_IP;
|
update.afi = AFI_IP;
|
||||||
@ -1634,15 +1677,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
update. */
|
update. */
|
||||||
ret = bgp_attr_check (peer, &attr);
|
ret = bgp_attr_check (peer, &attr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
{
|
||||||
|
bgp_attr_unintern_sub (&attr);
|
||||||
|
if (attr.extra)
|
||||||
|
bgp_attr_extra_free (&attr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bgp_nlri_parse (peer, &attr, &update);
|
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP
|
&& mp_update.afi == AFI_IP
|
||||||
&& mp_update.safi == SAFI_UNICAST)
|
&& mp_update.safi == SAFI_UNICAST)
|
||||||
bgp_nlri_parse (peer, &attr, &mp_update);
|
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
@ -1669,7 +1717,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP
|
&& mp_update.afi == AFI_IP
|
||||||
&& mp_update.safi == SAFI_MULTICAST)
|
&& mp_update.safi == SAFI_MULTICAST)
|
||||||
bgp_nlri_parse (peer, &attr, &mp_update);
|
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
@ -1699,7 +1747,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP6
|
&& mp_update.afi == AFI_IP6
|
||||||
&& mp_update.safi == SAFI_UNICAST)
|
&& mp_update.safi == SAFI_UNICAST)
|
||||||
bgp_nlri_parse (peer, &attr, &mp_update);
|
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP6
|
&& mp_withdraw.afi == AFI_IP6
|
||||||
@ -1728,7 +1776,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP6
|
&& mp_update.afi == AFI_IP6
|
||||||
&& mp_update.safi == SAFI_MULTICAST)
|
&& mp_update.safi == SAFI_MULTICAST)
|
||||||
bgp_nlri_parse (peer, &attr, &mp_update);
|
bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP6
|
&& mp_withdraw.afi == AFI_IP6
|
||||||
@ -1755,17 +1803,17 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
{
|
{
|
||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP
|
&& mp_update.afi == AFI_IP
|
||||||
&& mp_update.safi == BGP_SAFI_VPNV4)
|
&& mp_update.safi == SAFI_MPLS_LABELED_VPN)
|
||||||
bgp_nlri_parse_vpnv4 (peer, &attr, &mp_update);
|
bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
&& mp_withdraw.safi == BGP_SAFI_VPNV4)
|
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
|
||||||
bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
|
bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
|
||||||
|
|
||||||
if (! withdraw_len
|
if (! withdraw_len
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
&& mp_withdraw.safi == BGP_SAFI_VPNV4
|
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
|
||||||
&& mp_withdraw.length == 0)
|
&& mp_withdraw.length == 0)
|
||||||
{
|
{
|
||||||
/* End-of-RIB received */
|
/* End-of-RIB received */
|
||||||
@ -1778,21 +1826,10 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
|||||||
|
|
||||||
/* Everything is done. We unintern temporary structures which
|
/* Everything is done. We unintern temporary structures which
|
||||||
interned in bgp_attr_parse(). */
|
interned in bgp_attr_parse(). */
|
||||||
if (attr.aspath)
|
bgp_attr_unintern_sub (&attr);
|
||||||
aspath_unintern (attr.aspath);
|
|
||||||
if (attr.community)
|
|
||||||
community_unintern (attr.community);
|
|
||||||
if (attr.extra)
|
if (attr.extra)
|
||||||
{
|
bgp_attr_extra_free (&attr);
|
||||||
if (attr.extra->ecommunity)
|
|
||||||
ecommunity_unintern (attr.extra->ecommunity);
|
|
||||||
if (attr.extra->cluster)
|
|
||||||
cluster_unintern (attr.extra->cluster);
|
|
||||||
if (attr.extra->transit)
|
|
||||||
transit_unintern (attr.extra->transit);
|
|
||||||
bgp_attr_extra_free (&attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If peering is stopped due to some reason, do not generate BGP
|
/* If peering is stopped due to some reason, do not generate BGP
|
||||||
event. */
|
event. */
|
||||||
if (peer->status != Established)
|
if (peer->status != Established)
|
||||||
@ -1936,7 +1973,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|
|||||||
/* Check AFI and SAFI. */
|
/* Check AFI and SAFI. */
|
||||||
if ((afi != AFI_IP && afi != AFI_IP6)
|
if ((afi != AFI_IP && afi != AFI_IP6)
|
||||||
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
|
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
|
||||||
&& safi != BGP_SAFI_VPNV4))
|
&& safi != SAFI_MPLS_LABELED_VPN))
|
||||||
{
|
{
|
||||||
if (BGP_DEBUG (normal, NORMAL))
|
if (BGP_DEBUG (normal, NORMAL))
|
||||||
{
|
{
|
||||||
@ -1947,7 +1984,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust safi code. */
|
/* Adjust safi code. */
|
||||||
if (safi == BGP_SAFI_VPNV4)
|
if (safi == SAFI_MPLS_LABELED_VPN)
|
||||||
safi = SAFI_MPLS_VPN;
|
safi = SAFI_MPLS_VPN;
|
||||||
|
|
||||||
if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
|
if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
|
||||||
@ -2021,7 +2058,7 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
|
ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
|
||||||
if (!ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
memcpy (&seq, p_pnt, sizeof (u_int32_t));
|
memcpy (&seq, p_pnt, sizeof (u_int32_t));
|
||||||
p_pnt += sizeof (u_int32_t);
|
p_pnt += sizeof (u_int32_t);
|
||||||
|
122
bgpd/bgp_route.c
122
bgpd/bgp_route.c
@ -137,7 +137,7 @@ static void
|
|||||||
bgp_info_free (struct bgp_info *binfo)
|
bgp_info_free (struct bgp_info *binfo)
|
||||||
{
|
{
|
||||||
if (binfo->attr)
|
if (binfo->attr)
|
||||||
bgp_attr_unintern (binfo->attr);
|
bgp_attr_unintern (&binfo->attr);
|
||||||
|
|
||||||
bgp_info_extra_free (&binfo->extra);
|
bgp_info_extra_free (&binfo->extra);
|
||||||
|
|
||||||
@ -1069,11 +1069,9 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
|
|||||||
struct bgp_filter *filter;
|
struct bgp_filter *filter;
|
||||||
struct bgp_info info;
|
struct bgp_info info;
|
||||||
struct peer *from;
|
struct peer *from;
|
||||||
struct bgp *bgp;
|
|
||||||
|
|
||||||
from = ri->peer;
|
from = ri->peer;
|
||||||
filter = &rsclient->filter[afi][safi];
|
filter = &rsclient->filter[afi][safi];
|
||||||
bgp = rsclient->bgp;
|
|
||||||
|
|
||||||
if (DISABLE_BGP_ANNOUNCE)
|
if (DISABLE_BGP_ANNOUNCE)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1493,7 +1491,7 @@ bgp_process_main (struct work_queue *wq, void *data)
|
|||||||
if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
|
if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
|
||||||
{
|
{
|
||||||
if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
|
if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
|
||||||
bgp_zebra_announce (p, old_select, bgp);
|
bgp_zebra_announce (p, old_select, bgp, safi);
|
||||||
|
|
||||||
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
|
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
|
||||||
return WQ_SUCCESS;
|
return WQ_SUCCESS;
|
||||||
@ -1516,20 +1514,20 @@ bgp_process_main (struct work_queue *wq, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIB update. */
|
/* FIB update. */
|
||||||
if (safi == SAFI_UNICAST && ! bgp->name &&
|
if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp->name &&
|
||||||
! bgp_option_check (BGP_OPT_NO_FIB))
|
! bgp_option_check (BGP_OPT_NO_FIB)))
|
||||||
{
|
{
|
||||||
if (new_select
|
if (new_select
|
||||||
&& new_select->type == ZEBRA_ROUTE_BGP
|
&& new_select->type == ZEBRA_ROUTE_BGP
|
||||||
&& new_select->sub_type == BGP_ROUTE_NORMAL)
|
&& new_select->sub_type == BGP_ROUTE_NORMAL)
|
||||||
bgp_zebra_announce (p, new_select, bgp);
|
bgp_zebra_announce (p, new_select, bgp, safi);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Withdraw the route from the kernel. */
|
/* Withdraw the route from the kernel. */
|
||||||
if (old_select
|
if (old_select
|
||||||
&& old_select->type == ZEBRA_ROUTE_BGP
|
&& old_select->type == ZEBRA_ROUTE_BGP
|
||||||
&& old_select->sub_type == BGP_ROUTE_NORMAL)
|
&& old_select->sub_type == BGP_ROUTE_NORMAL)
|
||||||
bgp_zebra_withdraw (p, old_select);
|
bgp_zebra_withdraw (p, old_select, safi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1659,7 +1657,7 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
|
|||||||
u_int8_t ndata[7];
|
u_int8_t ndata[7];
|
||||||
|
|
||||||
if (safi == SAFI_MPLS_VPN)
|
if (safi == SAFI_MPLS_VPN)
|
||||||
safi = BGP_SAFI_VPNV4;
|
safi = SAFI_MPLS_LABELED_VPN;
|
||||||
|
|
||||||
ndata[0] = (afi >> 8);
|
ndata[0] = (afi >> 8);
|
||||||
ndata[1] = afi;
|
ndata[1] = afi;
|
||||||
@ -1802,23 +1800,23 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
|
|||||||
/* Apply import policy. */
|
/* Apply import policy. */
|
||||||
if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
|
if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
|
||||||
{
|
{
|
||||||
bgp_attr_unintern (attr_new2);
|
bgp_attr_unintern (&attr_new2);
|
||||||
|
|
||||||
reason = "import-policy;";
|
reason = "import-policy;";
|
||||||
goto filtered;
|
goto filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_new = bgp_attr_intern (&new_attr);
|
attr_new = bgp_attr_intern (&new_attr);
|
||||||
bgp_attr_unintern (attr_new2);
|
bgp_attr_unintern (&attr_new2);
|
||||||
|
|
||||||
/* IPv4 unicast next hop check. */
|
/* IPv4 unicast next hop check. */
|
||||||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
if ((afi == AFI_IP) && ((safi == SAFI_UNICAST) || safi == SAFI_MULTICAST))
|
||||||
{
|
{
|
||||||
/* Next hop must not be 0.0.0.0 nor Class E address. */
|
/* Next hop must not be 0.0.0.0 nor Class D/E address. */
|
||||||
if (new_attr.nexthop.s_addr == 0
|
if (new_attr.nexthop.s_addr == 0
|
||||||
|| ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
|
|| IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
|
||||||
{
|
{
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
|
|
||||||
reason = "martian next-hop;";
|
reason = "martian next-hop;";
|
||||||
goto filtered;
|
goto filtered;
|
||||||
@ -1848,7 +1846,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
|
|||||||
p->prefixlen, rsclient->host);
|
p->prefixlen, rsclient->host);
|
||||||
|
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1868,7 +1866,7 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
|
|||||||
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
|
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
|
||||||
|
|
||||||
/* Update to new attribute. */
|
/* Update to new attribute. */
|
||||||
bgp_attr_unintern (ri->attr);
|
bgp_attr_unintern (&ri->attr);
|
||||||
ri->attr = attr_new;
|
ri->attr = attr_new;
|
||||||
|
|
||||||
/* Update MPLS tag. */
|
/* Update MPLS tag. */
|
||||||
@ -2063,18 +2061,18 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
|
|||||||
/* If the peer is EBGP and nexthop is not on connected route,
|
/* If the peer is EBGP and nexthop is not on connected route,
|
||||||
discard it. */
|
discard it. */
|
||||||
if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1
|
if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1
|
||||||
&& ! bgp_nexthop_check_ebgp (afi, &new_attr)
|
&& ! bgp_nexthop_onlink (afi, &new_attr)
|
||||||
&& ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
|
&& ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
|
||||||
{
|
{
|
||||||
reason = "non-connected next-hop;";
|
reason = "non-connected next-hop;";
|
||||||
goto filtered;
|
goto filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next hop must not be 0.0.0.0 nor Class E address. Next hop
|
/* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
|
||||||
must not be my own address. */
|
must not be my own address. */
|
||||||
if (bgp_nexthop_self (afi, &new_attr)
|
if (bgp_nexthop_self (afi, &new_attr)
|
||||||
|| new_attr.nexthop.s_addr == 0
|
|| new_attr.nexthop.s_addr == 0
|
||||||
|| ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
|
|| IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
|
||||||
{
|
{
|
||||||
reason = "martian next-hop;";
|
reason = "martian next-hop;";
|
||||||
goto filtered;
|
goto filtered;
|
||||||
@ -2128,7 +2126,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
bgp_attr_extra_free (&new_attr);
|
bgp_attr_extra_free (&new_attr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2175,7 +2173,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update to new attribute. */
|
/* Update to new attribute. */
|
||||||
bgp_attr_unintern (ri->attr);
|
bgp_attr_unintern (&ri->attr);
|
||||||
ri->attr = attr_new;
|
ri->attr = attr_new;
|
||||||
|
|
||||||
/* Update MPLS tag. */
|
/* Update MPLS tag. */
|
||||||
@ -2467,7 +2465,7 @@ bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
aspath_unintern (aspath);
|
aspath_unintern (&aspath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2936,7 +2934,7 @@ bgp_cleanup_routes (void)
|
|||||||
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
|
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
|
||||||
&& ri->type == ZEBRA_ROUTE_BGP
|
&& ri->type == ZEBRA_ROUTE_BGP
|
||||||
&& ri->sub_type == BGP_ROUTE_NORMAL)
|
&& ri->sub_type == BGP_ROUTE_NORMAL)
|
||||||
bgp_zebra_withdraw (&rn->p, ri);
|
bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
|
||||||
|
|
||||||
table = bgp->rib[AFI_IP6][SAFI_UNICAST];
|
table = bgp->rib[AFI_IP6][SAFI_UNICAST];
|
||||||
|
|
||||||
@ -2945,7 +2943,7 @@ bgp_cleanup_routes (void)
|
|||||||
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
|
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
|
||||||
&& ri->type == ZEBRA_ROUTE_BGP
|
&& ri->type == ZEBRA_ROUTE_BGP
|
||||||
&& ri->sub_type == BGP_ROUTE_NORMAL)
|
&& ri->sub_type == BGP_ROUTE_NORMAL)
|
||||||
bgp_zebra_withdraw (&rn->p, ri);
|
bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3215,7 +3213,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
bgp_attr_flush (&attr_tmp);
|
bgp_attr_flush (&attr_tmp);
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
|
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
|
|
||||||
@ -3242,8 +3240,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
|
|
||||||
bgp->peer_self->rmap_type = 0;
|
bgp->peer_self->rmap_type = 0;
|
||||||
|
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
|
|
||||||
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
|
bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
|
||||||
@ -3253,7 +3251,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
|
|
||||||
bgp->peer_self->rmap_type = 0;
|
bgp->peer_self->rmap_type = 0;
|
||||||
|
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
attr_new = bgp_attr_intern (&new_attr);
|
attr_new = bgp_attr_intern (&new_attr);
|
||||||
bgp_attr_extra_free (&new_attr);
|
bgp_attr_extra_free (&new_attr);
|
||||||
|
|
||||||
@ -3268,8 +3266,8 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
||||||
{
|
{
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3281,14 +3279,14 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
/* Rewrite BGP route information. */
|
/* Rewrite BGP route information. */
|
||||||
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
||||||
bgp_info_restore(rn, ri);
|
bgp_info_restore(rn, ri);
|
||||||
bgp_attr_unintern (ri->attr);
|
bgp_attr_unintern (&ri->attr);
|
||||||
ri->attr = attr_new;
|
ri->attr = attr_new;
|
||||||
ri->uptime = bgp_clock ();
|
ri->uptime = bgp_clock ();
|
||||||
|
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_process (bgp, rn, afi, safi);
|
bgp_process (bgp, rn, afi, safi);
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3313,7 +3311,7 @@ bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
|
|||||||
bgp_process (bgp, rn, afi, safi);
|
bgp_process (bgp, rn, afi, safi);
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3363,7 +3361,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
|||||||
bgp_attr_flush (&attr_tmp);
|
bgp_attr_flush (&attr_tmp);
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
bgp_static_withdraw (bgp, p, afi, safi);
|
bgp_static_withdraw (bgp, p, afi, safi);
|
||||||
return;
|
return;
|
||||||
@ -3384,8 +3382,8 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
|||||||
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
||||||
{
|
{
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
bgp_attr_unintern (attr_new);
|
bgp_attr_unintern (&attr_new);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3399,7 +3397,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
|||||||
bgp_info_restore(rn, ri);
|
bgp_info_restore(rn, ri);
|
||||||
else
|
else
|
||||||
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
|
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
|
||||||
bgp_attr_unintern (ri->attr);
|
bgp_attr_unintern (&ri->attr);
|
||||||
ri->attr = attr_new;
|
ri->attr = attr_new;
|
||||||
ri->uptime = bgp_clock ();
|
ri->uptime = bgp_clock ();
|
||||||
|
|
||||||
@ -3407,7 +3405,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
|||||||
bgp_aggregate_increment (bgp, p, ri, afi, safi);
|
bgp_aggregate_increment (bgp, p, ri, afi, safi);
|
||||||
bgp_process (bgp, rn, afi, safi);
|
bgp_process (bgp, rn, afi, safi);
|
||||||
bgp_unlock_node (rn);
|
bgp_unlock_node (rn);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3435,7 +3433,7 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
|||||||
bgp_process (bgp, rn, afi, safi);
|
bgp_process (bgp, rn, afi, safi);
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4169,7 +4167,7 @@ DEFUN (ipv6_bgp_network,
|
|||||||
"Specify a network to announce via BGP\n"
|
"Specify a network to announce via BGP\n"
|
||||||
"IPv6 prefix <network>/<length>\n")
|
"IPv6 prefix <network>/<length>\n")
|
||||||
{
|
{
|
||||||
return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST,
|
return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty),
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4192,7 +4190,7 @@ DEFUN (no_ipv6_bgp_network,
|
|||||||
"Specify a network to announce via BGP\n"
|
"Specify a network to announce via BGP\n"
|
||||||
"IPv6 prefix <network>/<length>\n")
|
"IPv6 prefix <network>/<length>\n")
|
||||||
{
|
{
|
||||||
return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST);
|
return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty));
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (no_ipv6_bgp_network,
|
ALIAS (no_ipv6_bgp_network,
|
||||||
@ -5244,7 +5242,8 @@ ALIAS (no_ipv6_aggregate_address_summary_only,
|
|||||||
|
|
||||||
/* Redistribute route treatment. */
|
/* Redistribute route treatment. */
|
||||||
void
|
void
|
||||||
bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
|
||||||
|
const struct in6_addr *nexthop6,
|
||||||
u_int32_t metric, u_char type)
|
u_int32_t metric, u_char type)
|
||||||
{
|
{
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
@ -5264,6 +5263,15 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
if (nexthop)
|
if (nexthop)
|
||||||
attr.nexthop = *nexthop;
|
attr.nexthop = *nexthop;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (nexthop6)
|
||||||
|
{
|
||||||
|
struct attr_extra *extra = bgp_attr_extra_get(&attr);
|
||||||
|
extra->mp_nexthop_global = *nexthop6;
|
||||||
|
extra->mp_nexthop_len = 16;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
attr.med = metric;
|
attr.med = metric;
|
||||||
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
|
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
|
||||||
|
|
||||||
@ -5299,7 +5307,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
bgp_attr_extra_free (&attr_new);
|
bgp_attr_extra_free (&attr_new);
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
bgp_redistribute_delete (p, type);
|
bgp_redistribute_delete (p, type);
|
||||||
return;
|
return;
|
||||||
@ -5322,8 +5330,8 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
if (attrhash_cmp (bi->attr, new_attr) &&
|
if (attrhash_cmp (bi->attr, new_attr) &&
|
||||||
!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
|
||||||
{
|
{
|
||||||
bgp_attr_unintern (new_attr);
|
bgp_attr_unintern (&new_attr);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
bgp_unlock_node (bn);
|
bgp_unlock_node (bn);
|
||||||
return;
|
return;
|
||||||
@ -5338,7 +5346,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
bgp_info_restore(bn, bi);
|
bgp_info_restore(bn, bi);
|
||||||
else
|
else
|
||||||
bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
|
bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
|
||||||
bgp_attr_unintern (bi->attr);
|
bgp_attr_unintern (&bi->attr);
|
||||||
bi->attr = new_attr;
|
bi->attr = new_attr;
|
||||||
bi->uptime = bgp_clock ();
|
bi->uptime = bgp_clock ();
|
||||||
|
|
||||||
@ -5346,7 +5354,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
|
bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
|
||||||
bgp_process (bgp, bn, afi, SAFI_UNICAST);
|
bgp_process (bgp, bn, afi, SAFI_UNICAST);
|
||||||
bgp_unlock_node (bn);
|
bgp_unlock_node (bn);
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -5368,7 +5376,7 @@ bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern (attr.aspath);
|
aspath_unintern (&attr.aspath);
|
||||||
bgp_attr_extra_free (&attr);
|
bgp_attr_extra_free (&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9379,10 +9387,8 @@ bgp_table_stats_vty (struct vty *vty, const char *name,
|
|||||||
safi = SAFI_MULTICAST;
|
safi = SAFI_MULTICAST;
|
||||||
else if (strncmp (safi_str, "u", 1) == 0)
|
else if (strncmp (safi_str, "u", 1) == 0)
|
||||||
safi = SAFI_UNICAST;
|
safi = SAFI_UNICAST;
|
||||||
else if (strncmp (safi_str, "vpnv4", 5) == 0)
|
else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0)
|
||||||
safi = BGP_SAFI_VPNV4;
|
safi = SAFI_MPLS_LABELED_VPN;
|
||||||
else if (strncmp (safi_str, "vpnv6", 6) == 0)
|
|
||||||
safi = BGP_SAFI_VPNV6;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid subsequent address family %s%s",
|
vty_out (vty, "%% Invalid subsequent address family %s%s",
|
||||||
@ -9397,13 +9403,6 @@ bgp_table_stats_vty (struct vty *vty, const char *name,
|
|||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((afi == AFI_IP && safi == BGP_SAFI_VPNV6)
|
|
||||||
|| (afi == AFI_IP6 && safi == BGP_SAFI_VPNV4))
|
|
||||||
{
|
|
||||||
vty_out (vty, "%% Invalid subsequent address family %s for %s%s",
|
|
||||||
afi_str, safi_str, VTY_NEWLINE);
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
return bgp_table_stats (vty, bgp, afi, safi);
|
return bgp_table_stats (vty, bgp, afi, safi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12581,6 +12580,9 @@ bgp_route_init (void)
|
|||||||
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
|
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
|
||||||
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd);
|
install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd);
|
||||||
|
|
||||||
|
install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
|
||||||
|
install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
|
||||||
|
|
||||||
/* Old config IPv6 BGP commands. */
|
/* Old config IPv6 BGP commands. */
|
||||||
install_element (BGP_NODE, &old_ipv6_bgp_network_cmd);
|
install_element (BGP_NODE, &old_ipv6_bgp_network_cmd);
|
||||||
install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd);
|
install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd);
|
||||||
|
@ -192,7 +192,9 @@ extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
|
|||||||
|
|
||||||
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
|
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
|
||||||
|
|
||||||
extern void bgp_redistribute_add (struct prefix *, struct in_addr *, u_int32_t, u_char);
|
extern void bgp_redistribute_add (struct prefix *, const struct in_addr *,
|
||||||
|
const struct in6_addr *,
|
||||||
|
u_int32_t, u_char);
|
||||||
extern void bgp_redistribute_delete (struct prefix *, u_char);
|
extern void bgp_redistribute_delete (struct prefix *, u_char);
|
||||||
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
|
extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
|
||||||
|
|
||||||
|
@ -525,8 +525,13 @@ route_match_metric_compile (const char *arg)
|
|||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
unsigned long tmpval;
|
unsigned long tmpval;
|
||||||
|
|
||||||
|
/* Metric value shoud be integer. */
|
||||||
|
if (! all_digit (arg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
tmpval = strtoul (arg, &endptr, 10);
|
tmpval = strtoul (arg, &endptr, 10);
|
||||||
if (*endptr != '\0' || tmpval == ULONG_MAX || tmpval > UINT32_MAX)
|
if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
||||||
@ -790,6 +795,75 @@ struct route_map_rule_cmd route_match_origin_cmd =
|
|||||||
route_match_origin_compile,
|
route_match_origin_compile,
|
||||||
route_match_origin_free
|
route_match_origin_free
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* match probability { */
|
||||||
|
|
||||||
|
static route_map_result_t
|
||||||
|
route_match_probability (void *rule, struct prefix *prefix,
|
||||||
|
route_map_object_t type, void *object)
|
||||||
|
{
|
||||||
|
long r;
|
||||||
|
#if _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500
|
||||||
|
r = random();
|
||||||
|
#else
|
||||||
|
r = (long) rand();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (*(unsigned *) rule)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case RAND_MAX: return RMAP_MATCH;
|
||||||
|
default:
|
||||||
|
if (r < *(unsigned *) rule)
|
||||||
|
{
|
||||||
|
return RMAP_MATCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
route_match_probability_compile (const char *arg)
|
||||||
|
{
|
||||||
|
unsigned *lobule;
|
||||||
|
unsigned perc;
|
||||||
|
|
||||||
|
#if _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500
|
||||||
|
srandom (time (NULL));
|
||||||
|
#else
|
||||||
|
srand (time (NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
perc = atoi (arg);
|
||||||
|
lobule = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (unsigned));
|
||||||
|
|
||||||
|
switch (perc)
|
||||||
|
{
|
||||||
|
case 0: *lobule = 0; break;
|
||||||
|
case 100: *lobule = RAND_MAX; break;
|
||||||
|
default: *lobule = RAND_MAX / 100 * perc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lobule;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_match_probability_free (void *rule)
|
||||||
|
{
|
||||||
|
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct route_map_rule_cmd route_match_probability_cmd =
|
||||||
|
{
|
||||||
|
"probability",
|
||||||
|
route_match_probability,
|
||||||
|
route_match_probability_compile,
|
||||||
|
route_match_probability_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* } */
|
||||||
|
|
||||||
/* `set ip next-hop IP_ADDRESS' */
|
/* `set ip next-hop IP_ADDRESS' */
|
||||||
|
|
||||||
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
||||||
@ -933,8 +1007,9 @@ route_set_local_pref_compile (const char *arg)
|
|||||||
if (! all_digit (arg))
|
if (! all_digit (arg))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
tmp = strtoul (arg, &endptr, 10);
|
tmp = strtoul (arg, &endptr, 10);
|
||||||
if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)
|
if (*endptr != '\0' || errno || tmp > UINT32_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
||||||
@ -1001,9 +1076,9 @@ route_set_weight_compile (const char *arg)
|
|||||||
if (! all_digit (arg))
|
if (! all_digit (arg))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
tmp = strtoul (arg, &endptr, 10);
|
tmp = strtoul (arg, &endptr, 10);
|
||||||
if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)
|
if (*endptr != '\0' || errno || tmp > UINT32_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
|
||||||
@ -1092,8 +1167,9 @@ route_set_metric_compile (const char *arg)
|
|||||||
if (all_digit (arg))
|
if (all_digit (arg))
|
||||||
{
|
{
|
||||||
/* set metric value check*/
|
/* set metric value check*/
|
||||||
|
errno = 0;
|
||||||
larg = strtoul (arg, &endptr, 10);
|
larg = strtoul (arg, &endptr, 10);
|
||||||
if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)
|
if (*endptr != '\0' || errno || larg > UINT32_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
metric = larg;
|
metric = larg;
|
||||||
}
|
}
|
||||||
@ -1105,8 +1181,9 @@ route_set_metric_compile (const char *arg)
|
|||||||
|| (! all_digit (arg+1)))
|
|| (! all_digit (arg+1)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
larg = strtoul (arg+1, &endptr, 10);
|
larg = strtoul (arg+1, &endptr, 10);
|
||||||
if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)
|
if (*endptr != '\0' || errno || larg > UINT32_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
metric = larg;
|
metric = larg;
|
||||||
}
|
}
|
||||||
@ -1482,10 +1559,10 @@ route_set_ecommunity_rt (void *rule, struct prefix *prefix,
|
|||||||
else
|
else
|
||||||
new_ecom = ecommunity_dup (ecom);
|
new_ecom = ecommunity_dup (ecom);
|
||||||
|
|
||||||
bgp_info->attr->extra->ecommunity = new_ecom;
|
bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
|
||||||
|
|
||||||
if (old_ecom)
|
if (old_ecom)
|
||||||
ecommunity_free (old_ecom);
|
ecommunity_unintern (&old_ecom);
|
||||||
|
|
||||||
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
|
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
|
||||||
}
|
}
|
||||||
@ -1501,7 +1578,7 @@ route_set_ecommunity_rt_compile (const char *arg)
|
|||||||
ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
|
ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
|
||||||
if (! ecom)
|
if (! ecom)
|
||||||
return NULL;
|
return NULL;
|
||||||
return ecom;
|
return ecommunity_intern (ecom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free function for set community. */
|
/* Free function for set community. */
|
||||||
@ -1509,7 +1586,7 @@ static void
|
|||||||
route_set_ecommunity_rt_free (void *rule)
|
route_set_ecommunity_rt_free (void *rule)
|
||||||
{
|
{
|
||||||
struct ecommunity *ecom = rule;
|
struct ecommunity *ecom = rule;
|
||||||
ecommunity_free (ecom);
|
ecommunity_unintern (&ecom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set community rule structure. */
|
/* Set community rule structure. */
|
||||||
@ -1528,7 +1605,7 @@ static route_map_result_t
|
|||||||
route_set_ecommunity_soo (void *rule, struct prefix *prefix,
|
route_set_ecommunity_soo (void *rule, struct prefix *prefix,
|
||||||
route_map_object_t type, void *object)
|
route_map_object_t type, void *object)
|
||||||
{
|
{
|
||||||
struct ecommunity *ecom;
|
struct ecommunity *ecom, *old_ecom, *new_ecom;
|
||||||
struct bgp_info *bgp_info;
|
struct bgp_info *bgp_info;
|
||||||
|
|
||||||
if (type == RMAP_BGP)
|
if (type == RMAP_BGP)
|
||||||
@ -1539,8 +1616,19 @@ route_set_ecommunity_soo (void *rule, struct prefix *prefix,
|
|||||||
if (! ecom)
|
if (! ecom)
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
|
|
||||||
|
old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
|
||||||
|
|
||||||
|
if (old_ecom)
|
||||||
|
new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
|
||||||
|
else
|
||||||
|
new_ecom = ecommunity_dup (ecom);
|
||||||
|
|
||||||
|
bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
|
||||||
|
|
||||||
|
if (old_ecom)
|
||||||
|
ecommunity_unintern (&old_ecom);
|
||||||
|
|
||||||
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
|
bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
|
||||||
(bgp_attr_extra_get (bgp_info->attr))->ecommunity = ecommunity_dup (ecom);
|
|
||||||
}
|
}
|
||||||
return RMAP_OKAY;
|
return RMAP_OKAY;
|
||||||
}
|
}
|
||||||
@ -1555,7 +1643,7 @@ route_set_ecommunity_soo_compile (const char *arg)
|
|||||||
if (! ecom)
|
if (! ecom)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ecom;
|
return ecommunity_intern (ecom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free function for set community. */
|
/* Free function for set community. */
|
||||||
@ -1563,7 +1651,7 @@ static void
|
|||||||
route_set_ecommunity_soo_free (void *rule)
|
route_set_ecommunity_soo_free (void *rule)
|
||||||
{
|
{
|
||||||
struct ecommunity *ecom = rule;
|
struct ecommunity *ecom = rule;
|
||||||
ecommunity_free (ecom);
|
ecommunity_unintern (&ecom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set community rule structure. */
|
/* Set community rule structure. */
|
||||||
@ -2451,6 +2539,38 @@ ALIAS (no_match_ip_next_hop,
|
|||||||
"IP access-list number (expanded range)\n"
|
"IP access-list number (expanded range)\n"
|
||||||
"IP Access-list name\n")
|
"IP Access-list name\n")
|
||||||
|
|
||||||
|
/* match probability { */
|
||||||
|
|
||||||
|
DEFUN (match_probability,
|
||||||
|
match_probability_cmd,
|
||||||
|
"match probability <0-100>",
|
||||||
|
MATCH_STR
|
||||||
|
"Match portion of routes defined by percentage value\n"
|
||||||
|
"Percentage of routes\n")
|
||||||
|
{
|
||||||
|
return bgp_route_match_add (vty, vty->index, "probability", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_match_probability,
|
||||||
|
no_match_probability_cmd,
|
||||||
|
"no match probability",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
"Match portion of routes defined by percentage value\n")
|
||||||
|
{
|
||||||
|
return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS (no_match_probability,
|
||||||
|
no_match_probability_val_cmd,
|
||||||
|
"no match probability <1-99>",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
"Match portion of routes defined by percentage value\n"
|
||||||
|
"Percentage of routes\n")
|
||||||
|
|
||||||
|
/* } */
|
||||||
|
|
||||||
DEFUN (match_ip_route_source,
|
DEFUN (match_ip_route_source,
|
||||||
match_ip_route_source_cmd,
|
match_ip_route_source_cmd,
|
||||||
"match ip route-source (<1-199>|<1300-2699>|WORD)",
|
"match ip route-source (<1-199>|<1300-2699>|WORD)",
|
||||||
@ -3738,6 +3858,7 @@ bgp_route_map_init (void)
|
|||||||
route_map_install_match (&route_match_ecommunity_cmd);
|
route_map_install_match (&route_match_ecommunity_cmd);
|
||||||
route_map_install_match (&route_match_metric_cmd);
|
route_map_install_match (&route_match_metric_cmd);
|
||||||
route_map_install_match (&route_match_origin_cmd);
|
route_map_install_match (&route_match_origin_cmd);
|
||||||
|
route_map_install_match (&route_match_probability_cmd);
|
||||||
|
|
||||||
route_map_install_set (&route_set_ip_nexthop_cmd);
|
route_map_install_set (&route_set_ip_nexthop_cmd);
|
||||||
route_map_install_set (&route_set_local_pref_cmd);
|
route_map_install_set (&route_set_local_pref_cmd);
|
||||||
@ -3769,7 +3890,6 @@ bgp_route_map_init (void)
|
|||||||
install_element (RMAP_NODE, &match_ip_route_source_cmd);
|
install_element (RMAP_NODE, &match_ip_route_source_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
|
install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
|
install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
|
||||||
|
|
||||||
install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
|
install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
|
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
|
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
|
||||||
@ -3797,6 +3917,9 @@ bgp_route_map_init (void)
|
|||||||
install_element (RMAP_NODE, &match_origin_cmd);
|
install_element (RMAP_NODE, &match_origin_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_origin_cmd);
|
install_element (RMAP_NODE, &no_match_origin_cmd);
|
||||||
install_element (RMAP_NODE, &no_match_origin_val_cmd);
|
install_element (RMAP_NODE, &no_match_origin_val_cmd);
|
||||||
|
install_element (RMAP_NODE, &match_probability_cmd);
|
||||||
|
install_element (RMAP_NODE, &no_match_probability_cmd);
|
||||||
|
install_element (RMAP_NODE, &no_match_probability_val_cmd);
|
||||||
|
|
||||||
install_element (RMAP_NODE, &set_ip_nexthop_cmd);
|
install_element (RMAP_NODE, &set_ip_nexthop_cmd);
|
||||||
install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
|
install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
|
||||||
|
281
bgpd/bgp_vty.c
281
bgpd/bgp_vty.c
@ -3707,7 +3707,7 @@ peer_maximum_prefix_set_vty (struct vty *vty, const char *ip_str, afi_t afi,
|
|||||||
if (! peer)
|
if (! peer)
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
VTY_GET_INTEGER ("maxmum number", max, num_str);
|
VTY_GET_INTEGER ("maximum number", max, num_str);
|
||||||
if (threshold_str)
|
if (threshold_str)
|
||||||
threshold = atoi (threshold_str);
|
threshold = atoi (threshold_str);
|
||||||
else
|
else
|
||||||
@ -4215,18 +4215,10 @@ bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
|
|||||||
if (sort == clear_as)
|
if (sort == clear_as)
|
||||||
{
|
{
|
||||||
as_t as;
|
as_t as;
|
||||||
unsigned long as_ul;
|
|
||||||
int find = 0;
|
int find = 0;
|
||||||
|
|
||||||
VTY_GET_LONG ("AS", as_ul, arg);
|
VTY_GET_INTEGER_RANGE ("AS", as, arg, 1, BGP_AS4_MAX);
|
||||||
|
|
||||||
if (!as_ul)
|
|
||||||
{
|
|
||||||
vty_out (vty, "Invalid AS number%s", VTY_NEWLINE);
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
as = (as_t) as_ul;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
||||||
{
|
{
|
||||||
if (peer->as != as)
|
if (peer->as != as)
|
||||||
@ -8381,57 +8373,16 @@ ALIAS (show_bgp_instance_ipv6_safi_rsclient_summary,
|
|||||||
|
|
||||||
/* Redistribute VTY commands. */
|
/* Redistribute VTY commands. */
|
||||||
|
|
||||||
/* Utility function to convert user input route type string to route
|
|
||||||
type. */
|
|
||||||
static int
|
|
||||||
bgp_str2route_type (int afi, const char *str)
|
|
||||||
{
|
|
||||||
if (! str)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (afi == AFI_IP)
|
|
||||||
{
|
|
||||||
if (strncmp (str, "k", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_KERNEL;
|
|
||||||
else if (strncmp (str, "c", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_CONNECT;
|
|
||||||
else if (strncmp (str, "s", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_STATIC;
|
|
||||||
else if (strncmp (str, "r", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_RIP;
|
|
||||||
else if (strncmp (str, "o", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_OSPF;
|
|
||||||
}
|
|
||||||
if (afi == AFI_IP6)
|
|
||||||
{
|
|
||||||
if (strncmp (str, "k", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_KERNEL;
|
|
||||||
else if (strncmp (str, "c", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_CONNECT;
|
|
||||||
else if (strncmp (str, "s", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_STATIC;
|
|
||||||
else if (strncmp (str, "r", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_RIPNG;
|
|
||||||
else if (strncmp (str, "o", 1) == 0)
|
|
||||||
return ZEBRA_ROUTE_OSPF6;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv4,
|
DEFUN (bgp_redistribute_ipv4,
|
||||||
bgp_redistribute_ipv4_cmd,
|
bgp_redistribute_ipv4_cmd,
|
||||||
"redistribute (connected|kernel|ospf|rip|static)",
|
"redistribute " QUAGGA_IP_REDIST_STR_BGPD,
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD)
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n")
|
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8441,20 +8392,16 @@ DEFUN (bgp_redistribute_ipv4,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv4_rmap,
|
DEFUN (bgp_redistribute_ipv4_rmap,
|
||||||
bgp_redistribute_ipv4_rmap_cmd,
|
bgp_redistribute_ipv4_rmap_cmd,
|
||||||
"redistribute (connected|kernel|ospf|rip|static) route-map WORD",
|
"redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n")
|
"Pointer to route-map entries\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8466,21 +8413,17 @@ DEFUN (bgp_redistribute_ipv4_rmap,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv4_metric,
|
DEFUN (bgp_redistribute_ipv4_metric,
|
||||||
bgp_redistribute_ipv4_metric_cmd,
|
bgp_redistribute_ipv4_metric_cmd,
|
||||||
"redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
|
"redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295>",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n")
|
"Default metric\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8493,13 +8436,9 @@ DEFUN (bgp_redistribute_ipv4_metric,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
||||||
bgp_redistribute_ipv4_rmap_metric_cmd,
|
bgp_redistribute_ipv4_rmap_metric_cmd,
|
||||||
"redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
|
"redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n"
|
"Pointer to route-map entries\n"
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
@ -8508,8 +8447,8 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
|||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8523,13 +8462,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
||||||
bgp_redistribute_ipv4_metric_rmap_cmd,
|
bgp_redistribute_ipv4_metric_rmap_cmd,
|
||||||
"redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
|
"redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n"
|
"Default metric\n"
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
@ -8538,8 +8473,8 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
|||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8553,19 +8488,15 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv4,
|
DEFUN (no_bgp_redistribute_ipv4,
|
||||||
no_bgp_redistribute_ipv4_cmd,
|
no_bgp_redistribute_ipv4_cmd,
|
||||||
"no redistribute (connected|kernel|ospf|rip|static)",
|
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD,
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD)
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n")
|
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8576,21 +8507,17 @@ DEFUN (no_bgp_redistribute_ipv4,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv4_rmap,
|
DEFUN (no_bgp_redistribute_ipv4_rmap,
|
||||||
no_bgp_redistribute_ipv4_rmap_cmd,
|
no_bgp_redistribute_ipv4_rmap_cmd,
|
||||||
"no redistribute (connected|kernel|ospf|rip|static) route-map WORD",
|
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n")
|
"Pointer to route-map entries\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8602,21 +8529,17 @@ DEFUN (no_bgp_redistribute_ipv4_rmap,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv4_metric,
|
DEFUN (no_bgp_redistribute_ipv4_metric,
|
||||||
no_bgp_redistribute_ipv4_metric_cmd,
|
no_bgp_redistribute_ipv4_metric_cmd,
|
||||||
"no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
|
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295>",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n")
|
"Default metric\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8628,14 +8551,10 @@ DEFUN (no_bgp_redistribute_ipv4_metric,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
|
DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
|
||||||
no_bgp_redistribute_ipv4_rmap_metric_cmd,
|
no_bgp_redistribute_ipv4_rmap_metric_cmd,
|
||||||
"no redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
|
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n"
|
"Pointer to route-map entries\n"
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
@ -8643,8 +8562,8 @@ DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP, argv[0]);
|
type = proto_redistnum (AFI_IP, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8657,14 +8576,10 @@ DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
|
|||||||
|
|
||||||
ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
|
ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
|
||||||
no_bgp_redistribute_ipv4_metric_rmap_cmd,
|
no_bgp_redistribute_ipv4_metric_rmap_cmd,
|
||||||
"no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
|
"no redistribute " QUAGGA_IP_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPF)\n"
|
|
||||||
"Routing Information Protocol (RIP)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n"
|
"Default metric\n"
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
@ -8673,18 +8588,14 @@ ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
|
|||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
DEFUN (bgp_redistribute_ipv6,
|
DEFUN (bgp_redistribute_ipv6,
|
||||||
bgp_redistribute_ipv6_cmd,
|
bgp_redistribute_ipv6_cmd,
|
||||||
"redistribute (connected|kernel|ospf6|ripng|static)",
|
"redistribute " QUAGGA_IP6_REDIST_STR_BGPD,
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD)
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n")
|
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8695,20 +8606,16 @@ DEFUN (bgp_redistribute_ipv6,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_rmap,
|
DEFUN (bgp_redistribute_ipv6_rmap,
|
||||||
bgp_redistribute_ipv6_rmap_cmd,
|
bgp_redistribute_ipv6_rmap_cmd,
|
||||||
"redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
|
"redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n")
|
"Pointer to route-map entries\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8720,21 +8627,17 @@ DEFUN (bgp_redistribute_ipv6_rmap,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_metric,
|
DEFUN (bgp_redistribute_ipv6_metric,
|
||||||
bgp_redistribute_ipv6_metric_cmd,
|
bgp_redistribute_ipv6_metric_cmd,
|
||||||
"redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
|
"redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295>",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n")
|
"Default metric\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8747,13 +8650,9 @@ DEFUN (bgp_redistribute_ipv6_metric,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
||||||
bgp_redistribute_ipv6_rmap_metric_cmd,
|
bgp_redistribute_ipv6_rmap_metric_cmd,
|
||||||
"redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
|
"redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n"
|
"Pointer to route-map entries\n"
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
@ -8762,8 +8661,8 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
|||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8777,13 +8676,9 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
|||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
||||||
bgp_redistribute_ipv6_metric_rmap_cmd,
|
bgp_redistribute_ipv6_metric_rmap_cmd,
|
||||||
"redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
|
"redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n"
|
"Default metric\n"
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
@ -8792,8 +8687,8 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
|||||||
int type;
|
int type;
|
||||||
u_int32_t metric;
|
u_int32_t metric;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8807,19 +8702,15 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv6,
|
DEFUN (no_bgp_redistribute_ipv6,
|
||||||
no_bgp_redistribute_ipv6_cmd,
|
no_bgp_redistribute_ipv6_cmd,
|
||||||
"no redistribute (connected|kernel|ospf6|ripng|static)",
|
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD,
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD)
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n")
|
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8830,21 +8721,17 @@ DEFUN (no_bgp_redistribute_ipv6,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv6_rmap,
|
DEFUN (no_bgp_redistribute_ipv6_rmap,
|
||||||
no_bgp_redistribute_ipv6_rmap_cmd,
|
no_bgp_redistribute_ipv6_rmap_cmd,
|
||||||
"no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
|
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n")
|
"Pointer to route-map entries\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8856,21 +8743,17 @@ DEFUN (no_bgp_redistribute_ipv6_rmap,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv6_metric,
|
DEFUN (no_bgp_redistribute_ipv6_metric,
|
||||||
no_bgp_redistribute_ipv6_metric_cmd,
|
no_bgp_redistribute_ipv6_metric_cmd,
|
||||||
"no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
|
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295>",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n")
|
"Default metric\n")
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8882,14 +8765,10 @@ DEFUN (no_bgp_redistribute_ipv6_metric,
|
|||||||
|
|
||||||
DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
|
DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
|
||||||
no_bgp_redistribute_ipv6_rmap_metric_cmd,
|
no_bgp_redistribute_ipv6_rmap_metric_cmd,
|
||||||
"no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
|
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " route-map WORD metric <0-4294967295>",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
"Pointer to route-map entries\n"
|
"Pointer to route-map entries\n"
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
@ -8897,8 +8776,8 @@ DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
|
|||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
type = bgp_str2route_type (AFI_IP6, argv[0]);
|
type = proto_redistnum (AFI_IP6, argv[0]);
|
||||||
if (! type)
|
if (type < 0 || type == ZEBRA_ROUTE_BGP)
|
||||||
{
|
{
|
||||||
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@ -8911,14 +8790,10 @@ DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
|
|||||||
|
|
||||||
ALIAS (no_bgp_redistribute_ipv6_rmap_metric,
|
ALIAS (no_bgp_redistribute_ipv6_rmap_metric,
|
||||||
no_bgp_redistribute_ipv6_metric_rmap_cmd,
|
no_bgp_redistribute_ipv6_metric_rmap_cmd,
|
||||||
"no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
|
"no redistribute " QUAGGA_IP6_REDIST_STR_BGPD " metric <0-4294967295> route-map WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Redistribute information from another routing protocol\n"
|
"Redistribute information from another routing protocol\n"
|
||||||
"Connected\n"
|
QUAGGA_IP6_REDIST_HELP_STR_BGPD
|
||||||
"Kernel routes\n"
|
|
||||||
"Open Shurtest Path First (OSPFv3)\n"
|
|
||||||
"Routing Information Protocol (RIPng)\n"
|
|
||||||
"Static routes\n"
|
|
||||||
"Metric for redistributed routes\n"
|
"Metric for redistributed routes\n"
|
||||||
"Default metric\n"
|
"Default metric\n"
|
||||||
"Route map reference\n"
|
"Route map reference\n"
|
||||||
|
@ -232,12 +232,10 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
struct zapi_ipv4 api;
|
struct zapi_ipv4 api;
|
||||||
unsigned long ifindex;
|
|
||||||
struct in_addr nexthop;
|
struct in_addr nexthop;
|
||||||
struct prefix_ipv4 p;
|
struct prefix_ipv4 p;
|
||||||
|
|
||||||
s = zclient->ibuf;
|
s = zclient->ibuf;
|
||||||
ifindex = 0;
|
|
||||||
nexthop.s_addr = 0;
|
nexthop.s_addr = 0;
|
||||||
|
|
||||||
/* Type, flags, message. */
|
/* Type, flags, message. */
|
||||||
@ -260,7 +258,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
|
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
|
||||||
{
|
{
|
||||||
api.ifindex_num = stream_getc (s);
|
api.ifindex_num = stream_getc (s);
|
||||||
ifindex = stream_getl (s);
|
stream_getl (s); /* ifindex, unused */
|
||||||
}
|
}
|
||||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
|
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
|
||||||
api.distance = stream_getc (s);
|
api.distance = stream_getc (s);
|
||||||
@ -281,7 +279,8 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
|
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
|
||||||
api.metric);
|
api.metric);
|
||||||
}
|
}
|
||||||
bgp_redistribute_add((struct prefix *)&p, &nexthop, api.metric, api.type);
|
bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
|
||||||
|
api.metric, api.type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -309,12 +308,10 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
struct zapi_ipv6 api;
|
struct zapi_ipv6 api;
|
||||||
unsigned long ifindex;
|
|
||||||
struct in6_addr nexthop;
|
struct in6_addr nexthop;
|
||||||
struct prefix_ipv6 p;
|
struct prefix_ipv6 p;
|
||||||
|
|
||||||
s = zclient->ibuf;
|
s = zclient->ibuf;
|
||||||
ifindex = 0;
|
|
||||||
memset (&nexthop, 0, sizeof (struct in6_addr));
|
memset (&nexthop, 0, sizeof (struct in6_addr));
|
||||||
|
|
||||||
/* Type, flags, message. */
|
/* Type, flags, message. */
|
||||||
@ -337,7 +334,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
|
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
|
||||||
{
|
{
|
||||||
api.ifindex_num = stream_getc (s);
|
api.ifindex_num = stream_getc (s);
|
||||||
ifindex = stream_getl (s);
|
stream_getl (s); /* ifindex, unused */
|
||||||
}
|
}
|
||||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
|
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
|
||||||
api.distance = stream_getc (s);
|
api.distance = stream_getc (s);
|
||||||
@ -356,23 +353,29 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
{
|
{
|
||||||
if (BGP_DEBUG(zebra, ZEBRA))
|
if (BGP_DEBUG(zebra, ZEBRA))
|
||||||
{
|
{
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[2][INET6_ADDRSTRLEN];
|
||||||
zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d metric %u",
|
zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u",
|
||||||
zebra_route_string(api.type),
|
zebra_route_string(api.type),
|
||||||
inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
|
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
|
||||||
p.prefixlen, api.metric);
|
p.prefixlen,
|
||||||
|
inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
|
||||||
|
api.metric);
|
||||||
}
|
}
|
||||||
bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
|
bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
|
||||||
|
api.metric, api.type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (BGP_DEBUG(zebra, ZEBRA))
|
if (BGP_DEBUG(zebra, ZEBRA))
|
||||||
{
|
{
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[2][INET6_ADDRSTRLEN];
|
||||||
zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d metric %u",
|
zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d "
|
||||||
|
"nexthop %s metric %u",
|
||||||
zebra_route_string(api.type),
|
zebra_route_string(api.type),
|
||||||
inet_ntop(AF_INET6, &p.prefix, buf, sizeof(buf)),
|
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
|
||||||
p.prefixlen, api.metric);
|
p.prefixlen,
|
||||||
|
inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])),
|
||||||
|
api.metric);
|
||||||
}
|
}
|
||||||
bgp_redistribute_delete ((struct prefix *) &p, api.type);
|
bgp_redistribute_delete ((struct prefix *) &p, api.type);
|
||||||
}
|
}
|
||||||
@ -640,7 +643,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
|
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
u_char distance;
|
u_char distance;
|
||||||
@ -675,6 +678,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
|
|||||||
|
|
||||||
api.type = ZEBRA_ROUTE_BGP;
|
api.type = ZEBRA_ROUTE_BGP;
|
||||||
api.message = 0;
|
api.message = 0;
|
||||||
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1;
|
||||||
api.nexthop = &nexthop;
|
api.nexthop = &nexthop;
|
||||||
@ -749,6 +753,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
|
|||||||
api.flags = flags;
|
api.flags = flags;
|
||||||
api.type = ZEBRA_ROUTE_BGP;
|
api.type = ZEBRA_ROUTE_BGP;
|
||||||
api.message = 0;
|
api.message = 0;
|
||||||
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1;
|
||||||
api.nexthop = &nexthop;
|
api.nexthop = &nexthop;
|
||||||
@ -775,7 +780,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
|
bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
@ -809,6 +814,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
|
|||||||
|
|
||||||
api.type = ZEBRA_ROUTE_BGP;
|
api.type = ZEBRA_ROUTE_BGP;
|
||||||
api.message = 0;
|
api.message = 0;
|
||||||
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1;
|
||||||
api.nexthop = &nexthop;
|
api.nexthop = &nexthop;
|
||||||
@ -864,6 +870,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
|
|||||||
api.flags = flags;
|
api.flags = flags;
|
||||||
api.type = ZEBRA_ROUTE_BGP;
|
api.type = ZEBRA_ROUTE_BGP;
|
||||||
api.message = 0;
|
api.message = 0;
|
||||||
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1;
|
||||||
api.nexthop = &nexthop;
|
api.nexthop = &nexthop;
|
||||||
|
@ -25,8 +25,8 @@ extern void bgp_zebra_init (void);
|
|||||||
extern int bgp_if_update_all (void);
|
extern int bgp_if_update_all (void);
|
||||||
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
|
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
|
||||||
int *);
|
int *);
|
||||||
extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *);
|
extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *, safi_t);
|
||||||
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *);
|
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);
|
||||||
|
|
||||||
extern int bgp_redistribute_set (struct bgp *, afi_t, int);
|
extern int bgp_redistribute_set (struct bgp *, afi_t, int);
|
||||||
extern int bgp_redistribute_rmap_set (struct bgp *, afi_t, int, const char *);
|
extern int bgp_redistribute_rmap_set (struct bgp *, afi_t, int, const char *);
|
||||||
|
18
bgpd/bgpd.c
18
bgpd/bgpd.c
@ -695,7 +695,7 @@ peer_sort (struct peer *peer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
peer_free (struct peer *peer)
|
peer_free (struct peer *peer)
|
||||||
{
|
{
|
||||||
assert (peer->status == Deleted);
|
assert (peer->status == Deleted);
|
||||||
@ -1147,7 +1147,7 @@ peer_nsf_stop (struct peer *peer)
|
|||||||
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
|
UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
|
||||||
|
|
||||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||||
for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
|
for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
|
||||||
peer->nsf[afi][safi] = 0;
|
peer->nsf[afi][safi] = 0;
|
||||||
|
|
||||||
if (peer->t_gr_restart)
|
if (peer->t_gr_restart)
|
||||||
@ -2048,6 +2048,10 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bgp = bgp_create (as, name);
|
||||||
|
bgp_router_id_set(bgp, &router_id_zebra);
|
||||||
|
*bgp_val = bgp;
|
||||||
|
|
||||||
/* Create BGP server socket, if first instance. */
|
/* Create BGP server socket, if first instance. */
|
||||||
if (list_isempty(bm->bgp))
|
if (list_isempty(bm->bgp))
|
||||||
{
|
{
|
||||||
@ -2055,10 +2059,7 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
|
|||||||
return BGP_ERR_INVALID_VALUE;
|
return BGP_ERR_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp = bgp_create (as, name);
|
|
||||||
listnode_add (bm->bgp, bgp);
|
listnode_add (bm->bgp, bgp);
|
||||||
bgp_router_id_set(bgp, &router_id_zebra);
|
|
||||||
*bgp_val = bgp;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -4720,12 +4721,10 @@ static void
|
|||||||
bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
|
bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
|
||||||
struct peer *peer, afi_t afi, safi_t safi)
|
struct peer *peer, afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
struct bgp_filter *filter;
|
|
||||||
struct peer *g_peer = NULL;
|
struct peer *g_peer = NULL;
|
||||||
char buf[SU_ADDRSTRLEN];
|
char buf[SU_ADDRSTRLEN];
|
||||||
char *addr;
|
char *addr;
|
||||||
|
|
||||||
filter = &peer->filter[afi][safi];
|
|
||||||
addr = peer->host;
|
addr = peer->host;
|
||||||
if (peer_group_active (peer))
|
if (peer_group_active (peer))
|
||||||
g_peer = peer->group->conf;
|
g_peer = peer->group->conf;
|
||||||
@ -5014,6 +5013,11 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
|
|||||||
&& ! peer->af_group[afi][safi])
|
&& ! peer->af_group[afi][safi])
|
||||||
vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
|
vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
|
||||||
|
|
||||||
|
/* Nexthop-local unchanged. */
|
||||||
|
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
|
||||||
|
&& ! peer->af_group[afi][safi])
|
||||||
|
vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
|
||||||
|
|
||||||
/* Allow AS in. */
|
/* Allow AS in. */
|
||||||
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
|
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
|
||||||
if (! peer_group_active (peer)
|
if (! peer_group_active (peer)
|
||||||
|
@ -632,6 +632,8 @@ struct bgp_nlri
|
|||||||
#define BGP_NOTIFY_CAPABILITY_ERR 7
|
#define BGP_NOTIFY_CAPABILITY_ERR 7
|
||||||
#define BGP_NOTIFY_MAX 8
|
#define BGP_NOTIFY_MAX 8
|
||||||
|
|
||||||
|
#define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0
|
||||||
|
|
||||||
/* BGP_NOTIFY_HEADER_ERR sub codes. */
|
/* BGP_NOTIFY_HEADER_ERR sub codes. */
|
||||||
#define BGP_NOTIFY_HEADER_NOT_SYNC 1
|
#define BGP_NOTIFY_HEADER_NOT_SYNC 1
|
||||||
#define BGP_NOTIFY_HEADER_BAD_MESLEN 2
|
#define BGP_NOTIFY_HEADER_BAD_MESLEN 2
|
||||||
@ -662,7 +664,7 @@ struct bgp_nlri
|
|||||||
#define BGP_NOTIFY_UPDATE_MAL_AS_PATH 11
|
#define BGP_NOTIFY_UPDATE_MAL_AS_PATH 11
|
||||||
#define BGP_NOTIFY_UPDATE_MAX 12
|
#define BGP_NOTIFY_UPDATE_MAX 12
|
||||||
|
|
||||||
/* BGP_NOTIFY_CEASE sub codes (draft-ietf-idr-cease-subcode-05). */
|
/* BGP_NOTIFY_CEASE sub codes (RFC 4486). */
|
||||||
#define BGP_NOTIFY_CEASE_MAX_PREFIX 1
|
#define BGP_NOTIFY_CEASE_MAX_PREFIX 1
|
||||||
#define BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN 2
|
#define BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN 2
|
||||||
#define BGP_NOTIFY_CEASE_PEER_UNCONFIG 3
|
#define BGP_NOTIFY_CEASE_PEER_UNCONFIG 3
|
||||||
@ -725,9 +727,8 @@ struct bgp_nlri
|
|||||||
#define BGP_DEFAULT_RESTART_TIME 120
|
#define BGP_DEFAULT_RESTART_TIME 120
|
||||||
#define BGP_DEFAULT_STALEPATH_TIME 360
|
#define BGP_DEFAULT_STALEPATH_TIME 360
|
||||||
|
|
||||||
/* SAFI which used in open capability negotiation. */
|
/* RFC4364 */
|
||||||
#define BGP_SAFI_VPNV4 128
|
#define SAFI_MPLS_LABELED_VPN 128
|
||||||
#define BGP_SAFI_VPNV6 129
|
|
||||||
|
|
||||||
/* Max TTL value. */
|
/* Max TTL value. */
|
||||||
#define TTL_MAX 255
|
#define TTL_MAX 255
|
||||||
|
120
configure.ac
120
configure.ac
@ -5,10 +5,9 @@
|
|||||||
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
|
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||||
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
|
## Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
|
||||||
##
|
##
|
||||||
## $Id$
|
|
||||||
AC_PREREQ(2.53)
|
AC_PREREQ(2.53)
|
||||||
|
|
||||||
AC_INIT(Quagga, 0.99.18, [https://bugzilla.quagga.net])
|
AC_INIT(Quagga, 0.99.20, [https://bugzilla.quagga.net])
|
||||||
AC_CONFIG_SRCDIR(lib/zebra.h)
|
AC_CONFIG_SRCDIR(lib/zebra.h)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
@ -73,6 +72,16 @@ dnl autoconf 2.59 appears not to support AC_PROG_SED
|
|||||||
dnl AC_PROG_SED
|
dnl AC_PROG_SED
|
||||||
AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
|
AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
|
||||||
|
|
||||||
|
dnl pdflatex and latexmk are needed to build HACKING.pdf
|
||||||
|
AC_CHECK_PROG([PDFLATEX],[pdflatex],[pdflatex],[/bin/false])
|
||||||
|
AC_CHECK_PROG([LATEXMK],[latexmk],[latexmk],[/bin/false])
|
||||||
|
if test "x$PDFLATEX" = "x/bin/false" -o "x$LATEXMK" = "x/bin/false"; then
|
||||||
|
AC_MSG_WARN([Will not be able to make PDF versions of TeX documents])
|
||||||
|
else
|
||||||
|
HAVE_LATEX=true
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([HAVE_LATEX], [test "x$HAVE_LATEX" = "xtrue"])
|
||||||
|
|
||||||
dnl ------------------------------------------------------------------
|
dnl ------------------------------------------------------------------
|
||||||
dnl Intel compiler check. Although Intel tries really hard to make icc
|
dnl Intel compiler check. Although Intel tries really hard to make icc
|
||||||
dnl look like gcc, there are some differences. It's very verbose with
|
dnl look like gcc, there are some differences. It's very verbose with
|
||||||
@ -198,6 +207,8 @@ AC_ARG_ENABLE(ospfd,
|
|||||||
[ --disable-ospfd do not build ospfd])
|
[ --disable-ospfd do not build ospfd])
|
||||||
AC_ARG_ENABLE(ospf6d,
|
AC_ARG_ENABLE(ospf6d,
|
||||||
[ --disable-ospf6d do not build ospf6d])
|
[ --disable-ospf6d do not build ospf6d])
|
||||||
|
AC_ARG_ENABLE(babeld,
|
||||||
|
[ --disable-babeld do not build babeld])
|
||||||
AC_ARG_ENABLE(watchquagga,
|
AC_ARG_ENABLE(watchquagga,
|
||||||
[ --disable-watchquagga do not build watchquagga])
|
[ --disable-watchquagga do not build watchquagga])
|
||||||
AC_ARG_ENABLE(isisd,
|
AC_ARG_ENABLE(isisd,
|
||||||
@ -395,7 +406,7 @@ dnl Check other header files.
|
|||||||
dnl -------------------------
|
dnl -------------------------
|
||||||
AC_CHECK_HEADERS([stropts.h sys/ksym.h sys/times.h sys/select.h \
|
AC_CHECK_HEADERS([stropts.h sys/ksym.h sys/times.h sys/select.h \
|
||||||
sys/types.h linux/version.h netdb.h asm/types.h \
|
sys/types.h linux/version.h netdb.h asm/types.h \
|
||||||
sys/param.h limits.h signal.h libutil.h \
|
sys/param.h limits.h signal.h \
|
||||||
sys/socket.h netinet/in.h time.h sys/time.h])
|
sys/socket.h netinet/in.h time.h sys/time.h])
|
||||||
|
|
||||||
dnl Utility macro to avoid retyping includes all the time
|
dnl Utility macro to avoid retyping includes all the time
|
||||||
@ -442,8 +453,35 @@ m4_define([QUAGGA_INCLUDES],
|
|||||||
#endif /* TIME_WITH_SYS_TIME */
|
#endif /* TIME_WITH_SYS_TIME */
|
||||||
])dnl
|
])dnl
|
||||||
|
|
||||||
AC_CHECK_HEADERS([sys/un.h net/if.h netinet/in_systm.h netinet/in_var.h \
|
dnl HAVE_NET_IF_H must be discovered by the time the longer AC_CHECK_HEADERS
|
||||||
net/if_dl.h net/if_var.h net/netopt.h net/route.h \
|
dnl round below execution begins, otherwise it doesn't properly detect
|
||||||
|
dnl HAVE_NETINET6_IN6_VAR_H, HAVE_NET_IF_VAR_H and HAVE_STRUCT_IN6_ALIASREQ
|
||||||
|
dnl on FreeBSD (BZ#408).
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([net/if.h], [], [], QUAGGA_INCLUDES)
|
||||||
|
|
||||||
|
m4_define([QUAGGA_INCLUDES],
|
||||||
|
QUAGGA_INCLUDES
|
||||||
|
[#if HAVE_NET_IF_H
|
||||||
|
# include <net/if.h>
|
||||||
|
#endif
|
||||||
|
])dnl
|
||||||
|
|
||||||
|
dnl Same applies for HAVE_NET_IF_VAR_H, which HAVE_NETINET6_ND6_H and
|
||||||
|
dnl HAVE_NETINET_IN_VAR_H depend upon. But if_var.h depends on if.h, hence
|
||||||
|
dnl an additional round for it.
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([net/if_var.h], [], [], QUAGGA_INCLUDES)
|
||||||
|
|
||||||
|
m4_define([QUAGGA_INCLUDES],
|
||||||
|
QUAGGA_INCLUDES
|
||||||
|
[#if HAVE_NET_IF_VAR_H
|
||||||
|
# include <net/if_var.h>
|
||||||
|
#endif
|
||||||
|
])dnl
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([sys/un.h netinet/in_systm.h netinet/in_var.h \
|
||||||
|
net/if_dl.h net/netopt.h net/route.h \
|
||||||
inet/nd.h arpa/inet.h netinet/ip_icmp.h \
|
inet/nd.h arpa/inet.h netinet/ip_icmp.h \
|
||||||
fcntl.h stddef.h sys/ioctl.h syslog.h wchar.h wctype.h \
|
fcntl.h stddef.h sys/ioctl.h syslog.h wchar.h wctype.h \
|
||||||
sys/sysctl.h sys/sockio.h kvm.h sys/conf.h],
|
sys/sysctl.h sys/sockio.h kvm.h sys/conf.h],
|
||||||
@ -458,10 +496,7 @@ QUAGGA_INCLUDES
|
|||||||
|
|
||||||
m4_define([QUAGGA_INCLUDES],
|
m4_define([QUAGGA_INCLUDES],
|
||||||
QUAGGA_INCLUDES
|
QUAGGA_INCLUDES
|
||||||
[#if HAVE_NET_IF_H
|
[#if HAVE_SYS_UN_H
|
||||||
# include <net/if.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_UN_H
|
|
||||||
# include <sys/un.h>
|
# include <sys/un.h>
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_NETINET_IN_SYSTM_H
|
#if HAVE_NETINET_IN_SYSTM_H
|
||||||
@ -473,9 +508,6 @@ QUAGGA_INCLUDES
|
|||||||
#if HAVE_NET_IF_DL_H
|
#if HAVE_NET_IF_DL_H
|
||||||
# include <net/if_dl.h>
|
# include <net/if_dl.h>
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_NET_IF_VAR_H
|
|
||||||
# include <net/if_var.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_NET_NETOPT_H
|
#if HAVE_NET_NETOPT_H
|
||||||
# include <net/netopt.h>
|
# include <net/netopt.h>
|
||||||
#endif
|
#endif
|
||||||
@ -595,6 +627,13 @@ AC_SUBST(LIBREADLINE)
|
|||||||
|
|
||||||
dnl ----------
|
dnl ----------
|
||||||
dnl PAM module
|
dnl PAM module
|
||||||
|
dnl
|
||||||
|
dnl Quagga detects the PAM library it is built against by checking for a
|
||||||
|
dnl functional pam_misc.h (Linux-PAM) or openpam.h (OpenPAM) header. pam_misc.h
|
||||||
|
dnl is known to #include pam_appl.h, the standard header of a PAM library, and
|
||||||
|
dnl openpam.h doesn't do that, although depends on the header too. Hence a
|
||||||
|
dnl little assistance to AC_CHECK_HEADER is necessary for the proper detection
|
||||||
|
dnl of OpenPAM.
|
||||||
dnl ----------
|
dnl ----------
|
||||||
if test "$with_libpam" = "yes"; then
|
if test "$with_libpam" = "yes"; then
|
||||||
AC_CHECK_HEADER([security/pam_misc.h],
|
AC_CHECK_HEADER([security/pam_misc.h],
|
||||||
@ -608,7 +647,7 @@ if test "$with_libpam" = "yes"; then
|
|||||||
AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
|
AC_DEFINE(PAM_CONV_FUNC,openpam_ttyconv,Have openpam_ttyconv)
|
||||||
pam_conv_func="openpam_ttyconv"
|
pam_conv_func="openpam_ttyconv"
|
||||||
],
|
],
|
||||||
[], QUAGGA_INCLUDES)
|
[], QUAGGA_INCLUDES[#include <security/pam_appl.h>])
|
||||||
if test -z "$ac_cv_header_security_pam_misc_h$ac_cv_header_security_openpam_h" ; then
|
if test -z "$ac_cv_header_security_pam_misc_h$ac_cv_header_security_openpam_h" ; then
|
||||||
AC_MSG_WARN([*** pam support will not be built ***])
|
AC_MSG_WARN([*** pam support will not be built ***])
|
||||||
with_libpam="no"
|
with_libpam="no"
|
||||||
@ -665,11 +704,9 @@ dnl ----------------------------
|
|||||||
AC_FUNC_CHOWN
|
AC_FUNC_CHOWN
|
||||||
AC_FUNC_FNMATCH
|
AC_FUNC_FNMATCH
|
||||||
AC_FUNC_FORK
|
AC_FUNC_FORK
|
||||||
AC_FUNC_MALLOC
|
|
||||||
AC_FUNC_MEMCMP
|
AC_FUNC_MEMCMP
|
||||||
AC_FUNC_MKTIME
|
AC_FUNC_MKTIME
|
||||||
AC_FUNC_STRFTIME
|
AC_FUNC_STRFTIME
|
||||||
AC_FUNC_REALLOC
|
|
||||||
AC_FUNC_STAT
|
AC_FUNC_STAT
|
||||||
AC_FUNC_SELECT_ARGTYPES
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
AC_FUNC_STRFTIME
|
AC_FUNC_STRFTIME
|
||||||
@ -916,6 +953,15 @@ AC_TRY_COMPILE([#ifdef HAVE_SYS_PARAM_H
|
|||||||
AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])],
|
AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])],
|
||||||
AC_MSG_RESULT(no))
|
AC_MSG_RESULT(no))
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for RFC3678 protocol-independed API])
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
], [struct group_req gr; int sock; setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void*)&gr, sizeof(gr));
|
||||||
|
], [AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_RFC3678,1,[Have RFC3678 protocol-independed API])],
|
||||||
|
AC_MSG_RESULT(no))
|
||||||
|
|
||||||
dnl ---------------------------------------------------------------
|
dnl ---------------------------------------------------------------
|
||||||
dnl figure out how to check link-state
|
dnl figure out how to check link-state
|
||||||
dnl ---------------------------------------------------------------
|
dnl ---------------------------------------------------------------
|
||||||
@ -972,10 +1018,18 @@ dnl -----------------------------
|
|||||||
dnl check ipforward detect method
|
dnl check ipforward detect method
|
||||||
dnl -----------------------------
|
dnl -----------------------------
|
||||||
AC_CACHE_CHECK([ipforward method], [quagga_cv_ipforward_method],
|
AC_CACHE_CHECK([ipforward method], [quagga_cv_ipforward_method],
|
||||||
[for quagga_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
|
[if test x$cross_compiling = xyes; then
|
||||||
do
|
if test x"$opsys" = x"gnu-linux"; then
|
||||||
test x`ls $quagga_cv_ipforward_method 2>/dev/null` = x"$quagga_cv_ipforward_method" && break
|
quagga_cv_ipforward_method=/proc/net/snmp
|
||||||
done
|
else
|
||||||
|
quagga_cv_ipforward_method=/dev/ip
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
for quagga_cv_ipforward_method in /proc/net/snmp /dev/ip /dev/null;
|
||||||
|
do
|
||||||
|
test x`ls $quagga_cv_ipforward_method 2>/dev/null` = x"$quagga_cv_ipforward_method" && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
case $quagga_cv_ipforward_method in
|
case $quagga_cv_ipforward_method in
|
||||||
"/proc/net/snmp") quagga_cv_ipforward_method="proc";;
|
"/proc/net/snmp") quagga_cv_ipforward_method="proc";;
|
||||||
"/dev/ip")
|
"/dev/ip")
|
||||||
@ -1193,6 +1247,12 @@ else
|
|||||||
OSPFD="ospfd"
|
OSPFD="ospfd"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "${enable_babeld}" = "no";then
|
||||||
|
BABELD=""
|
||||||
|
else
|
||||||
|
BABELD="babeld"
|
||||||
|
fi
|
||||||
|
|
||||||
if test "${enable_watchquagga}" = "no";then
|
if test "${enable_watchquagga}" = "no";then
|
||||||
WATCHQUAGGA=""
|
WATCHQUAGGA=""
|
||||||
else
|
else
|
||||||
@ -1249,6 +1309,7 @@ AC_SUBST(RIPD)
|
|||||||
AC_SUBST(RIPNGD)
|
AC_SUBST(RIPNGD)
|
||||||
AC_SUBST(OSPFD)
|
AC_SUBST(OSPFD)
|
||||||
AC_SUBST(OSPF6D)
|
AC_SUBST(OSPF6D)
|
||||||
|
AC_SUBST(BABELD)
|
||||||
AC_SUBST(WATCHQUAGGA)
|
AC_SUBST(WATCHQUAGGA)
|
||||||
AC_SUBST(ISISD)
|
AC_SUBST(ISISD)
|
||||||
AC_SUBST(SOLARIS)
|
AC_SUBST(SOLARIS)
|
||||||
@ -1403,14 +1464,12 @@ AC_SUBST(LIBCAP)
|
|||||||
dnl ---------------------------
|
dnl ---------------------------
|
||||||
dnl check for glibc 'backtrace'
|
dnl check for glibc 'backtrace'
|
||||||
dnl ---------------------------
|
dnl ---------------------------
|
||||||
if test "${glibc}" = "yes"; then
|
AC_CHECK_HEADER([execinfo.h],
|
||||||
AC_CHECK_HEADER([execinfo.h],
|
[AC_CHECK_FUNC([backtrace],
|
||||||
[AC_CHECK_FUNC([backtrace],
|
[AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace])
|
||||||
[AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace])
|
AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding])
|
||||||
AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding])
|
])
|
||||||
])
|
])
|
||||||
])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl -----------------------------------------
|
dnl -----------------------------------------
|
||||||
dnl check for malloc mallinfo struct and call
|
dnl check for malloc mallinfo struct and call
|
||||||
@ -1494,6 +1553,7 @@ AC_DEFINE_UNQUOTED(PATH_RIPNGD_PID, "$quagga_statedir/ripngd.pid",ripngd PID)
|
|||||||
AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$quagga_statedir/bgpd.pid",bgpd PID)
|
AC_DEFINE_UNQUOTED(PATH_BGPD_PID, "$quagga_statedir/bgpd.pid",bgpd PID)
|
||||||
AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$quagga_statedir/ospfd.pid",ospfd PID)
|
AC_DEFINE_UNQUOTED(PATH_OSPFD_PID, "$quagga_statedir/ospfd.pid",ospfd PID)
|
||||||
AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$quagga_statedir/ospf6d.pid",ospf6d PID)
|
AC_DEFINE_UNQUOTED(PATH_OSPF6D_PID, "$quagga_statedir/ospf6d.pid",ospf6d PID)
|
||||||
|
AC_DEFINE_UNQUOTED(PATH_BABELD_PID, "$quagga_statedir/babeld.pid",babeld PID)
|
||||||
AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$quagga_statedir/isisd.pid",isisd PID)
|
AC_DEFINE_UNQUOTED(PATH_ISISD_PID, "$quagga_statedir/isisd.pid",isisd PID)
|
||||||
AC_DEFINE_UNQUOTED(PATH_WATCHQUAGGA_PID, "$quagga_statedir/watchquagga.pid",watchquagga PID)
|
AC_DEFINE_UNQUOTED(PATH_WATCHQUAGGA_PID, "$quagga_statedir/watchquagga.pid",watchquagga PID)
|
||||||
AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$quagga_statedir/zserv.api",zebra api socket)
|
AC_DEFINE_UNQUOTED(ZEBRA_SERV_PATH, "$quagga_statedir/zserv.api",zebra api socket)
|
||||||
@ -1503,6 +1563,7 @@ AC_DEFINE_UNQUOTED(RIPNG_VTYSH_PATH, "$quagga_statedir/ripngd.vty",ripng vty soc
|
|||||||
AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$quagga_statedir/bgpd.vty",bgpd vty socket)
|
AC_DEFINE_UNQUOTED(BGP_VTYSH_PATH, "$quagga_statedir/bgpd.vty",bgpd vty socket)
|
||||||
AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$quagga_statedir/ospfd.vty",ospfd vty socket)
|
AC_DEFINE_UNQUOTED(OSPF_VTYSH_PATH, "$quagga_statedir/ospfd.vty",ospfd vty socket)
|
||||||
AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$quagga_statedir/ospf6d.vty",ospf6d vty socket)
|
AC_DEFINE_UNQUOTED(OSPF6_VTYSH_PATH, "$quagga_statedir/ospf6d.vty",ospf6d vty socket)
|
||||||
|
AC_DEFINE_UNQUOTED(BABEL_VTYSH_PATH, "$quagga_statedir/babeld.vty",babeld vty socket)
|
||||||
AC_DEFINE_UNQUOTED(ISIS_VTYSH_PATH, "$quagga_statedir/isisd.vty",isisd vty socket)
|
AC_DEFINE_UNQUOTED(ISIS_VTYSH_PATH, "$quagga_statedir/isisd.vty",isisd vty socket)
|
||||||
AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$quagga_statedir",daemon vty directory)
|
AC_DEFINE_UNQUOTED(DAEMON_VTY_DIR, "$quagga_statedir",daemon vty directory)
|
||||||
|
|
||||||
@ -1527,8 +1588,9 @@ AC_MSG_RESULT($ac_cv_htonl_works)
|
|||||||
|
|
||||||
AC_CONFIG_FILES([Makefile lib/Makefile zebra/Makefile ripd/Makefile
|
AC_CONFIG_FILES([Makefile lib/Makefile zebra/Makefile ripd/Makefile
|
||||||
ripngd/Makefile bgpd/Makefile ospfd/Makefile watchquagga/Makefile
|
ripngd/Makefile bgpd/Makefile ospfd/Makefile watchquagga/Makefile
|
||||||
ospf6d/Makefile isisd/Makefile vtysh/Makefile doc/Makefile
|
ospf6d/Makefile isisd/Makefile babeld/Makefile vtysh/Makefile
|
||||||
ospfclient/Makefile tests/Makefile m4/Makefile redhat/Makefile
|
doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
|
||||||
|
redhat/Makefile
|
||||||
pkgsrc/Makefile
|
pkgsrc/Makefile
|
||||||
redhat/quagga.spec
|
redhat/quagga.spec
|
||||||
lib/version.h
|
lib/version.h
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
mdate-sh
|
|
||||||
draft-zebra-00.txt
|
|
||||||
zebra.info-*
|
|
||||||
zebra.html
|
|
||||||
defines.texi
|
|
||||||
version.texi
|
|
||||||
quagga.html
|
|
||||||
quagga.info
|
|
||||||
*.pdf
|
|
||||||
*.eps
|
|
||||||
quagga.ps
|
|
||||||
quagga.dvi
|
|
||||||
stamp-vti
|
|
||||||
.nfs*
|
|
||||||
*.aux
|
|
||||||
*.cp
|
|
||||||
*.cps
|
|
||||||
*.fn
|
|
||||||
*.fns
|
|
||||||
*.ky
|
|
||||||
*.kys
|
|
||||||
*.log
|
|
||||||
*.op
|
|
||||||
*.pg
|
|
||||||
*.toc
|
|
||||||
*.tp
|
|
||||||
*.vr
|
|
||||||
.arch-inventory
|
|
||||||
.arch-ids
|
|
@ -3,24 +3,22 @@
|
|||||||
|
|
||||||
Value Attribute References
|
Value Attribute References
|
||||||
=========================================================================
|
=========================================================================
|
||||||
1 ORIGIN [RFC 1771]
|
1 ORIGIN [RFC 4271]
|
||||||
2 AS_PATH [RFC 1771]
|
2 AS_PATH [RFC 4271]
|
||||||
3 NEXT_HOP [RFC 1771]
|
3 NEXT_HOP [RFC 4271]
|
||||||
4 MULTI_EXIT_DISC [RFC 1771]
|
4 MULTI_EXIT_DISC [RFC 4271]
|
||||||
5 LOCAL_PREF [RFC 1771]
|
5 LOCAL_PREF [RFC 4271]
|
||||||
6 ATOMIC_AGGREGATE [RFC 1771]
|
6 ATOMIC_AGGREGATE [RFC 4271]
|
||||||
7 AGGREGATOR [RFC 1771]
|
7 AGGREGATOR [RFC 4271]
|
||||||
8 COMMUNITIES [RFC 1997]
|
8 COMMUNITIES [RFC 1997]
|
||||||
9 ORIGINATOR_ID [RFC 1966]
|
9 ORIGINATOR_ID [RFC 4456]
|
||||||
10 CLUSTER_LIST [RFC 1966]
|
10 CLUSTER_LIST [RFC 4456]
|
||||||
11 DPA [draft-ietf-idr-bgp-dpa-05.txt(expired)]
|
11 DPA [draft-ietf-idr-bgp-dpa-05.txt(expired)]
|
||||||
12 ADVERTISER [Changed from RFC 1863 bgp@ans.net ML?]
|
12 ADVERTISER [RFC 1863]
|
||||||
13 RCID_PATH [Changed from RFC 1863 bgp@ans.net ML?]
|
13 RCID_PATH [RFC 1863]
|
||||||
14 MP_REACH_NLRI [RFC 2283]
|
14 MP_REACH_NLRI [RFC 4760]
|
||||||
15 MP_UNREACH_NLRI [RFC 2283]
|
15 MP_UNREACH_NLRI [RFC 4760]
|
||||||
16 EXT_COMMUNITIES [draft-ramachandra-bgp-ext-communities-09.txt]
|
16 EXT_COMMUNITIES [RFC 4360]
|
||||||
17 AS4_PATH [RFC 4893]
|
17 AS4_PATH [RFC 4893]
|
||||||
18 AS4_AGGREGATOR [RFC 4893]
|
18 AS4_AGGREGATOR [RFC 4893]
|
||||||
254 RCID_PATH [RFC 1863]
|
|
||||||
255 ADVERTISER [RFC 1863]
|
|
||||||
=========================================================================
|
=========================================================================
|
||||||
|
@ -46,11 +46,11 @@ info_TEXINFOS = quagga.texi
|
|||||||
quagga.pdf: $(info_TEXINFOS) $(figures_pdf) $(quagga_TEXINFOS)
|
quagga.pdf: $(info_TEXINFOS) $(figures_pdf) $(quagga_TEXINFOS)
|
||||||
$(TEXI2PDF) -o "$@" $<
|
$(TEXI2PDF) -o "$@" $<
|
||||||
|
|
||||||
quagga_TEXINFOS = appendix.texi basic.texi bgpd.texi filter.texi install.texi \
|
quagga_TEXINFOS = appendix.texi babeld.texi basic.texi bgpd.texi filter.texi \
|
||||||
ipv6.texi kernel.texi main.texi ospf6d.texi ospfd.texi overview.texi \
|
install.texi ipv6.texi kernel.texi main.texi ospf6d.texi ospfd.texi \
|
||||||
protocol.texi ripd.texi ripngd.texi routemap.texi snmp.texi \
|
overview.texi protocol.texi ripd.texi ripngd.texi routemap.texi \
|
||||||
vtysh.texi routeserver.texi defines.texi $(figures_png) snmptrap.texi \
|
snmp.texi vtysh.texi routeserver.texi defines.texi $(figures_png) \
|
||||||
$(figures_txt)
|
snmptrap.texi $(figures_txt)
|
||||||
|
|
||||||
.png.eps:
|
.png.eps:
|
||||||
$(PNGTOEPS) $< "$@"
|
$(PNGTOEPS) $< "$@"
|
||||||
|
118
doc/babeld.texi
Normal file
118
doc/babeld.texi
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
@c -*-texinfo-*-
|
||||||
|
@c This is part of the Quagga Manual.
|
||||||
|
@c @value{COPYRIGHT_STR}
|
||||||
|
@c See file quagga.texi for copying conditions.
|
||||||
|
@node Babel
|
||||||
|
@chapter Babel
|
||||||
|
|
||||||
|
Babel is an interior gateway protocol that is suitable both for wired
|
||||||
|
networks and for wireless mesh networks. Babel has been described as
|
||||||
|
``RIP on speed'' --- it is based on the same principles as RIP, but
|
||||||
|
includes a number of refinements that make it react much faster to
|
||||||
|
topology changes without ever counting to infinity, and allow it to
|
||||||
|
perform reliable link quality estimation on wireless links. Babel is
|
||||||
|
a double-stack routing protocol, meaning that a single Babel instance
|
||||||
|
is able to perform routing for both IPv4 and IPv6.
|
||||||
|
|
||||||
|
Quagga implements Babel as described in RFC6126.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Configuring babeld::
|
||||||
|
* Babel configuration::
|
||||||
|
* Babel redistribution::
|
||||||
|
* Show Babel information::
|
||||||
|
* Babel debugging commands::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Configuring babeld, Babel configuration, Babel, Babel
|
||||||
|
@section Configuring babeld
|
||||||
|
|
||||||
|
The @command{babeld} daemon can be invoked with any of the common
|
||||||
|
options (@pxref{Common Invocation Options}).
|
||||||
|
|
||||||
|
The @command{zebra} daemon must be running before @command{babeld} is
|
||||||
|
invoked. Also, if @command{zebra} is restarted then @command{babeld}
|
||||||
|
must be too.
|
||||||
|
|
||||||
|
Configuration of @command{babeld} is done in its configuration file
|
||||||
|
@file{babeld.conf}.
|
||||||
|
|
||||||
|
@node Babel configuration, Babel redistribution, Configuring babeld, Babel
|
||||||
|
@section Babel configuration
|
||||||
|
|
||||||
|
@deffn Command {router babel} {}
|
||||||
|
@deffnx Command {no router babel} {}
|
||||||
|
Enable or disable Babel routing.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Babel Command} {network @var{ifname}} {}
|
||||||
|
@deffnx {Babel Command} {no network @var{ifname}} {}
|
||||||
|
Enable or disable Babel on the given interface.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Interface Command} {babel wired} {}
|
||||||
|
@deffnx {Interface Command} {babel wireless} {}
|
||||||
|
Specifies whether this interface is wireless, which disables a number
|
||||||
|
of optimisations that are only correct on wired interfaces.
|
||||||
|
Specifying @code{wireless} (the default) is always correct, but may
|
||||||
|
cause slower convergence and extra routing traffic.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Interface Command} {babel split-horizon}
|
||||||
|
@deffnx {Interface Command} {no babel split-horizon}
|
||||||
|
Specifies whether to perform split-horizon on the interface.
|
||||||
|
Specifying @code{no babel split-horizon} (the default) is always
|
||||||
|
correct, while @code{babel split-horizon} is an optimisation that
|
||||||
|
should only be used on symmetric and transitive (wired) networks.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Interface Command} {babel hello-interval <20-655340>}
|
||||||
|
Specifies the time in milliseconds between two scheduled hellos. On
|
||||||
|
wired links, Babel notices a link failure within two hello intervals;
|
||||||
|
on wireless links, the link quality value is reestimated at every
|
||||||
|
hello interval. The default is 4000@dmn{ms}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Interface Command} {babel update-interval <20-655340>}
|
||||||
|
Specifies the time in milliseconds between two scheduled updates.
|
||||||
|
Since Babel makes extensive use of triggered updates, this can be set
|
||||||
|
to fairly high values on links with little packet loss. The default
|
||||||
|
is 20000@dmn{ms}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Babel Command} {babel resend-delay <20-655340>}
|
||||||
|
Specifies the time in milliseconds after which an ``important''
|
||||||
|
request or update will be resent. The default is 2000@dmn{ms}. You
|
||||||
|
probably don't want to tweak this value.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@node Babel redistribution, Show Babel information, Babel configuration, Babel
|
||||||
|
@section Babel redistribution
|
||||||
|
|
||||||
|
@deffn {Babel command} {redistribute @var{kind}}
|
||||||
|
@deffnx {Babel command} {no redistribute @var{kind}}
|
||||||
|
Specify which kind of routes should be redistributed into Babel.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@node Show Babel information, Babel debugging commands, Babel redistribution, Babel
|
||||||
|
@section Show Babel information
|
||||||
|
|
||||||
|
@deffn {Command} {show babel database} {}
|
||||||
|
@deffnx {Command} {show babel interface} {}
|
||||||
|
@deffnx {Command} {show babel neighbour} {}
|
||||||
|
@deffnx {Command} {show babel parameters} {}
|
||||||
|
These commands dump various parts of @command{babeld}'s internal
|
||||||
|
state. They are mostly useful for troubleshooting.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@node Babel debugging commands, , Show Babel information, Babel
|
||||||
|
@section Babel debugging commands
|
||||||
|
|
||||||
|
@deffn {Babel Command} {debug babel @var{kind}} {}
|
||||||
|
@deffnx {Babel Command} {no debug babel @var{kind}} {}
|
||||||
|
Enable or disable debugging messages of a given kind. @var{kind} can
|
||||||
|
be one of @samp{common}, @samp{kernel}, @samp{filter}, @samp{timeout},
|
||||||
|
@samp{interface}, @samp{route} or @samp{all}. Note that if you have
|
||||||
|
compiled with the NO_DEBUG flag, then these commands aren't available.
|
||||||
|
@end deffn
|
||||||
|
|
@ -46,14 +46,14 @@ starting.
|
|||||||
|
|
||||||
Config files are generally found in:
|
Config files are generally found in:
|
||||||
|
|
||||||
@itemize @asis
|
@itemize @w{}
|
||||||
@item @file{@value{INSTALL_PREFIX_ETC}/*.conf}
|
@item @file{@value{INSTALL_PREFIX_ETC}/*.conf}
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
Each of the daemons has its own
|
Each of the daemons has its own
|
||||||
config file. For example, zebra's default config file name is:
|
config file. For example, zebra's default config file name is:
|
||||||
|
|
||||||
@itemize @asis
|
@itemize @w{}
|
||||||
@item @file{@value{INSTALL_PREFIX_ETC}/zebra.conf}
|
@item @file{@value{INSTALL_PREFIX_ETC}/zebra.conf}
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ so @code{router-id} is set to 0.0.0.0. So please set router-id by hand.
|
|||||||
@menu
|
@menu
|
||||||
* BGP distance::
|
* BGP distance::
|
||||||
* BGP decision process::
|
* BGP decision process::
|
||||||
|
* BGP route flap dampening::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node BGP distance
|
@node BGP distance
|
||||||
@ -123,6 +124,27 @@ sequences should should be taken into account during the BGP best path
|
|||||||
decision process.
|
decision process.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@node BGP route flap dampening
|
||||||
|
@subsection BGP route flap dampening
|
||||||
|
|
||||||
|
@deffn {BGP} {bgp dampening @var{<1-45>} @var{<1-20000>} @var{<1-20000>} @var{<1-255>}} {}
|
||||||
|
This command enables BGP route-flap dampening and specifies dampening parameters.
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item @asis{half-life}
|
||||||
|
Half-life time for the penalty
|
||||||
|
@item @asis{reuse-threshold}
|
||||||
|
Value to start reusing a route
|
||||||
|
@item @asis{suppress-threshold}
|
||||||
|
Value to start suppressing a route
|
||||||
|
@item @asis{max-suppress}
|
||||||
|
Maximum duration to suppress a stable route
|
||||||
|
@end table
|
||||||
|
|
||||||
|
The route-flap damping algorithm is compatible with @cite{RFC2439}. The use of this command
|
||||||
|
is not recommended nowadays, see @uref{http://www.ripe.net/ripe/docs/ripe-378,,RIPE-378}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@node BGP network
|
@node BGP network
|
||||||
@section BGP network
|
@section BGP network
|
||||||
|
|
||||||
@ -930,6 +952,14 @@ Clear peers which have addresses of X.X.X.X
|
|||||||
Clear peer using soft reconfiguration.
|
Clear peer using soft reconfiguration.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Command} {show ip bgp dampened-paths} {}
|
||||||
|
Display paths suppressed due to dampening
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Command} {show ip bgp flap-statistics} {}
|
||||||
|
Display flap statistics of routes
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {show debug} {}
|
@deffn {Command} {show debug} {}
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
@chapter IPv6 Support
|
@chapter IPv6 Support
|
||||||
|
|
||||||
Quagga fully supports IPv6 routing. As described so far, Quagga supports
|
Quagga fully supports IPv6 routing. As described so far, Quagga supports
|
||||||
RIPng, OSPFv3 and BGP-4+. You can give IPv6 addresses to an interface
|
RIPng, OSPFv3, Babel and BGP-4+. You can give IPv6 addresses to an interface
|
||||||
and configure static IPv6 routing information. Quagga IPv6 also provides
|
and configure static IPv6 routing information. Quagga IPv6 also provides
|
||||||
automatic address configuration via a feature called @code{address
|
automatic address configuration via a feature called @code{address
|
||||||
auto configuration}. To do it, the router must send router advertisement
|
auto configuration}. To do it, the router must send router advertisement
|
||||||
@ -62,23 +62,24 @@ Default: not set, i.e. hosts do not assume a complete IP address is placed.
|
|||||||
@end itemize
|
@end itemize
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd ra-interval SECONDS} {}
|
@deffn {Interface Command} {ipv6 nd ra-interval <1-1800>} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd ra-interval} {}
|
@deffnx {Interface Command} {no ipv6 nd ra-interval [<1-1800>]} {}
|
||||||
The maximum time allowed between sending unsolicited multicast router
|
The maximum time allowed between sending unsolicited multicast router
|
||||||
advertisements from the interface, in seconds. Must be no less than 3 seconds.
|
advertisements from the interface, in seconds.
|
||||||
|
|
||||||
Default: @code{600}
|
Default: @code{600}
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd ra-interval msec MILLISECONDS} {}
|
@deffn {Interface Command} {ipv6 nd ra-interval msec <70-1800000>} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd ra-interval msec} {}
|
@deffnx {Interface Command} {no ipv6 nd ra-interval [msec <70-1800000>]} {}
|
||||||
The maximum time allowed between sending unsolicited multicast router
|
The maximum time allowed between sending unsolicited multicast router
|
||||||
advertisements from the interface, in milliseconds. Must be no less than 30 milliseconds.
|
advertisements from the interface, in milliseconds.
|
||||||
|
|
||||||
Default: @code{600000}
|
Default: @code{600000}
|
||||||
@end deffn
|
@end deffn
|
||||||
@deffn {Interface Command} {ipv6 nd ra-lifetime SECONDS} {}
|
|
||||||
@deffnx {Interface Command} {no ipv6 nd ra-lifetime} {}
|
@deffn {Interface Command} {ipv6 nd ra-lifetime <0-9000>} {}
|
||||||
|
@deffnx {Interface Command} {no ipv6 nd ra-lifetime [<0-9000>]} {}
|
||||||
The value to be placed in the Router Lifetime field of router advertisements
|
The value to be placed in the Router Lifetime field of router advertisements
|
||||||
sent from the interface, in seconds. Indicates the usefulness of the router
|
sent from the interface, in seconds. Indicates the usefulness of the router
|
||||||
as a default router on this interface. Setting the value to zero indicates
|
as a default router on this interface. Setting the value to zero indicates
|
||||||
@ -89,12 +90,12 @@ Must be either zero or between value specified with @var{ipv6 nd ra-interval}
|
|||||||
Default: @code{1800}
|
Default: @code{1800}
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd reachable-time MILLISECONDS} {}
|
@deffn {Interface Command} {ipv6 nd reachable-time <1-3600000>} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd reachable-time} {}
|
@deffnx {Interface Command} {no ipv6 nd reachable-time [<1-3600000>]} {}
|
||||||
The value to be placed in the Reachable Time field in the Router Advertisement
|
The value to be placed in the Reachable Time field in the Router Advertisement
|
||||||
messages sent by the router, in milliseconds. The configured time enables the
|
messages sent by the router, in milliseconds. The configured time enables the
|
||||||
router to detect unavailable neighbors. The value zero means unspecified (by
|
router to detect unavailable neighbors. The value zero means unspecified (by
|
||||||
this router). Must be no greater than @code{3,600,000} milliseconds (1 hour).
|
this router).
|
||||||
|
|
||||||
Default: @code{0}
|
Default: @code{0}
|
||||||
@end deffn
|
@end deffn
|
||||||
@ -126,18 +127,20 @@ the router acts as a Home Agent and includes a Home Agent Option.
|
|||||||
Default: not set
|
Default: not set
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd home-agent-preference} {}
|
@deffn {Interface Command} {ipv6 nd home-agent-preference <0-65535>} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd home-agent-preference} {}
|
@deffnx {Interface Command} {no ipv6 nd home-agent-preference [<0-65535>]} {}
|
||||||
The value to be placed in Home Agent Option, when Home Agent config flag is set,
|
The value to be placed in Home Agent Option, when Home Agent config flag is set,
|
||||||
which indicates to hosts Home Agent preference.
|
which indicates to hosts Home Agent preference. The default value of 0 stands
|
||||||
|
for the lowest preference possible.
|
||||||
|
|
||||||
Default: 0
|
Default: 0
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd home-agent-lifetime} {}
|
+@deffn {Interface Command} {ipv6 nd home-agent-lifetime <0-65520>} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd home-agent-lifetime} {}
|
+@deffnx {Interface Command} {no ipv6 nd home-agent-lifetime [<0-65520>]} {}
|
||||||
The value to be placed in Home Agent Option, when Home Agent config flag is set,
|
The value to be placed in Home Agent Option, when Home Agent config flag is set,
|
||||||
which indicates to hosts Home Agent Lifetime. A value of 0 means to place Router Lifetime value.
|
which indicates to hosts Home Agent Lifetime. The default value of 0 means to
|
||||||
|
place the current Router Lifetime value.
|
||||||
|
|
||||||
Default: 0
|
Default: 0
|
||||||
@end deffn
|
@end deffn
|
||||||
@ -151,12 +154,21 @@ Default: not set
|
|||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Interface Command} {ipv6 nd router-preference (high|medium|low)} {}
|
@deffn {Interface Command} {ipv6 nd router-preference (high|medium|low)} {}
|
||||||
@deffnx {Interface Command} {no ipv6 nd router-preference} {}
|
@deffnx {Interface Command} {no ipv6 nd router-preference [(high|medium|low)]} {}
|
||||||
Set default router preference in IPv6 router advertisements per RFC4191.
|
Set default router preference in IPv6 router advertisements per RFC4191.
|
||||||
|
|
||||||
Default: medium
|
Default: medium
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Interface Command} {ipv6 nd mtu <1-65535>} {}
|
||||||
|
@deffnx {Interface Command} {no ipv6 nd mtu [<1-65535>]} {}
|
||||||
|
Include an MTU (type 5) option in each RA packet to assist the attached hosts
|
||||||
|
in proper interface configuration. The announced value is not verified to be
|
||||||
|
consistent with router interface MTU.
|
||||||
|
|
||||||
|
Default: don't advertise any MTU option
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@group
|
@group
|
||||||
interface eth0
|
interface eth0
|
||||||
@ -166,6 +178,6 @@ interface eth0
|
|||||||
@end example
|
@end example
|
||||||
|
|
||||||
For more information see @cite{RFC2462 (IPv6 Stateless Address Autoconfiguration)}
|
For more information see @cite{RFC2462 (IPv6 Stateless Address Autoconfiguration)}
|
||||||
, @cite{RFC2461 (Neighbor Discovery for IP Version 6 (IPv6))}
|
, @cite{RFC4861 (Neighbor Discovery for IP Version 6 (IPv6))}
|
||||||
, @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))}
|
, @cite{RFC6275 (Mobility Support in IPv6)}
|
||||||
and @cite{RFC4191 (Default Router Preferences and More-Specific Routes)}.
|
and @cite{RFC4191 (Default Router Preferences and More-Specific Routes)}.
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
.arch-ids
|
|
||||||
.arch-inventory
|
|
@ -99,7 +99,7 @@ behaviors implemented in Cisco and IBM routers."
|
|||||||
to section G.2 (changes) in section 16.4 a change to the path
|
to section G.2 (changes) in section 16.4 a change to the path
|
||||||
preference algorithm that prevents possible routing loops that were
|
preference algorithm that prevents possible routing loops that were
|
||||||
possible in the old version of OSPFv2. More specifically it demands
|
possible in the old version of OSPFv2. More specifically it demands
|
||||||
that inter-area paths and intra-area path are now of equal preference
|
that inter-area paths and intra-area backbone path are now of equal preference
|
||||||
but still both preferred to external paths.
|
but still both preferred to external paths.
|
||||||
|
|
||||||
This command should NOT be set normally.
|
This command should NOT be set normally.
|
||||||
@ -568,10 +568,6 @@ redistributed into OSPF (@pxref{OSPF redistribute}).
|
|||||||
@deffnx {OSPF Command} {no distance ospf} {}
|
@deffnx {OSPF Command} {no distance ospf} {}
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {router zebra} {}
|
|
||||||
@deffnx {Command} {no router zebra} {}
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@node Showing OSPF information
|
@node Showing OSPF information
|
||||||
@section Showing OSPF information
|
@section Showing OSPF information
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of
|
|||||||
* RIPng::
|
* RIPng::
|
||||||
* OSPFv2::
|
* OSPFv2::
|
||||||
* OSPFv3::
|
* OSPFv3::
|
||||||
|
* Babel::
|
||||||
* BGP::
|
* BGP::
|
||||||
* Configuring Quagga as a Route Server::
|
* Configuring Quagga as a Route Server::
|
||||||
* VTY shell::
|
* VTY shell::
|
||||||
@ -110,6 +111,7 @@ for @value{PACKAGE_STRING}. @uref{http://www.quagga.net,,Quagga} is a fork of
|
|||||||
@include ripngd.texi
|
@include ripngd.texi
|
||||||
@include ospfd.texi
|
@include ospfd.texi
|
||||||
@include ospf6d.texi
|
@include ospf6d.texi
|
||||||
|
@include babeld.texi
|
||||||
@include bgpd.texi
|
@include bgpd.texi
|
||||||
@include routeserver.texi
|
@include routeserver.texi
|
||||||
@include vtysh.texi
|
@include vtysh.texi
|
||||||
|
@ -424,10 +424,10 @@ must be different. Maybe it'd be better to made new matches - say
|
|||||||
Match if route destination is permitted by access-list.
|
Match if route destination is permitted by access-list.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Route Map} {match ip next-hop A.B.C.D} {}
|
@deffn {Route Map} {match ip next-hop @var{word}} {}
|
||||||
Cisco uses here <access-list>, @command{ripd} IPv4 address. Match if
|
@deffnx {Route Map} {match ip next-hop prefix-list @var{word}} {}
|
||||||
route has this next-hop (meaning next-hop listed in the rip route
|
Match if route next-hop (meaning next-hop listed in the rip route-table
|
||||||
table - "show ip rip")
|
as displayed by "show ip rip") is permitted by access-list.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Route Map} {match metric <0-4294967295>} {}
|
@deffn {Route Map} {match metric <0-4294967295>} {}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
Makefile
|
|
||||||
*.o
|
|
||||||
zebra-guile
|
|
||||||
Makefile.in
|
|
||||||
.nfs*
|
|
||||||
.arch-inventory
|
|
||||||
.arch-ids
|
|
@ -1,3 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
.nfs*
|
|
@ -1,14 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
*.o
|
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
version.c
|
|
||||||
version.h
|
|
||||||
.deps
|
|
||||||
.nfs*
|
|
||||||
.libs
|
|
||||||
.arch-inventory
|
|
||||||
.arch-ids
|
|
||||||
memtypes.h
|
|
||||||
route_types.h
|
|
@ -29,10 +29,10 @@ pkginclude_HEADERS = \
|
|||||||
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
|
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
|
||||||
workqueue.h route_types.h
|
workqueue.h route_types.h
|
||||||
|
|
||||||
EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt
|
EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.pl route_types.txt
|
||||||
|
|
||||||
memtypes.h: $(srcdir)/memtypes.c $(srcdir)/memtypes.awk
|
memtypes.h: $(srcdir)/memtypes.c $(srcdir)/memtypes.awk
|
||||||
($(GAWK) -f $(srcdir)/memtypes.awk $(srcdir)/memtypes.c > $@)
|
($(GAWK) -f $(srcdir)/memtypes.awk $(srcdir)/memtypes.c > $@)
|
||||||
|
|
||||||
route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.awk
|
route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl
|
||||||
($(GAWK) -f $(srcdir)/route_types.awk $(srcdir)/route_types.txt > $@)
|
@PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
$Id$
|
|
||||||
|
|
||||||
Command interpreter routine for virtual terminal [aka TeletYpe]
|
Command interpreter routine for virtual terminal [aka TeletYpe]
|
||||||
Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
|
Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
|
||||||
|
|
||||||
@ -2402,6 +2400,7 @@ DEFUN (config_exit,
|
|||||||
case BGP_NODE:
|
case BGP_NODE:
|
||||||
case RIP_NODE:
|
case RIP_NODE:
|
||||||
case RIPNG_NODE:
|
case RIPNG_NODE:
|
||||||
|
case BABEL_NODE:
|
||||||
case OSPF_NODE:
|
case OSPF_NODE:
|
||||||
case OSPF6_NODE:
|
case OSPF6_NODE:
|
||||||
case ISIS_NODE:
|
case ISIS_NODE:
|
||||||
@ -2451,6 +2450,7 @@ DEFUN (config_end,
|
|||||||
case ZEBRA_NODE:
|
case ZEBRA_NODE:
|
||||||
case RIP_NODE:
|
case RIP_NODE:
|
||||||
case RIPNG_NODE:
|
case RIPNG_NODE:
|
||||||
|
case BABEL_NODE:
|
||||||
case BGP_NODE:
|
case BGP_NODE:
|
||||||
case BGP_VPNV4_NODE:
|
case BGP_VPNV4_NODE:
|
||||||
case BGP_IPV4_NODE:
|
case BGP_IPV4_NODE:
|
||||||
|
@ -78,6 +78,7 @@ enum node_type
|
|||||||
TABLE_NODE, /* rtm_table selection node. */
|
TABLE_NODE, /* rtm_table selection node. */
|
||||||
RIP_NODE, /* RIP protocol mode node. */
|
RIP_NODE, /* RIP protocol mode node. */
|
||||||
RIPNG_NODE, /* RIPng protocol mode node. */
|
RIPNG_NODE, /* RIPng protocol mode node. */
|
||||||
|
BABEL_NODE, /* Babel protocol mode node. */
|
||||||
BGP_NODE, /* BGP protocol mode which includes BGP4+ */
|
BGP_NODE, /* BGP protocol mode which includes BGP4+ */
|
||||||
BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
|
BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
|
||||||
BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
|
BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
|
||||||
|
@ -299,7 +299,6 @@ DEFUN (distribute_list_all,
|
|||||||
"Filter outgoing routing updates\n")
|
"Filter outgoing routing updates\n")
|
||||||
{
|
{
|
||||||
enum distribute_type type;
|
enum distribute_type type;
|
||||||
struct distribute *dist;
|
|
||||||
|
|
||||||
/* Check of distribute list type. */
|
/* Check of distribute list type. */
|
||||||
if (strncmp (argv[1], "i", 1) == 0)
|
if (strncmp (argv[1], "i", 1) == 0)
|
||||||
@ -314,7 +313,7 @@ DEFUN (distribute_list_all,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get interface name corresponding distribute list. */
|
/* Get interface name corresponding distribute list. */
|
||||||
dist = distribute_list_set (NULL, type, argv[0]);
|
distribute_list_set (NULL, type, argv[0]);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -379,7 +378,6 @@ DEFUN (distribute_list,
|
|||||||
"Interface name\n")
|
"Interface name\n")
|
||||||
{
|
{
|
||||||
enum distribute_type type;
|
enum distribute_type type;
|
||||||
struct distribute *dist;
|
|
||||||
|
|
||||||
/* Check of distribute list type. */
|
/* Check of distribute list type. */
|
||||||
if (strncmp (argv[1], "i", 1) == 0)
|
if (strncmp (argv[1], "i", 1) == 0)
|
||||||
@ -393,7 +391,7 @@ DEFUN (distribute_list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get interface name corresponding distribute list. */
|
/* Get interface name corresponding distribute list. */
|
||||||
dist = distribute_list_set (argv[2], type, argv[0]);
|
distribute_list_set (argv[2], type, argv[0]);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -407,7 +405,7 @@ ALIAS (distribute_list,
|
|||||||
"Filter outgoing routing updates\n"
|
"Filter outgoing routing updates\n"
|
||||||
"Interface name\n")
|
"Interface name\n")
|
||||||
|
|
||||||
DEFUN (no_districute_list, no_distribute_list_cmd,
|
DEFUN (no_distribute_list, no_distribute_list_cmd,
|
||||||
"no distribute-list WORD (in|out) WORD",
|
"no distribute-list WORD (in|out) WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -439,7 +437,7 @@ DEFUN (no_districute_list, no_distribute_list_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (no_districute_list, no_ipv6_distribute_list_cmd,
|
ALIAS (no_distribute_list, no_ipv6_distribute_list_cmd,
|
||||||
"no distribute-list WORD (in|out) WORD",
|
"no distribute-list WORD (in|out) WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -448,7 +446,7 @@ ALIAS (no_districute_list, no_ipv6_distribute_list_cmd,
|
|||||||
"Filter outgoing routing updates\n"
|
"Filter outgoing routing updates\n"
|
||||||
"Interface name\n")
|
"Interface name\n")
|
||||||
|
|
||||||
DEFUN (districute_list_prefix_all,
|
DEFUN (distribute_list_prefix_all,
|
||||||
distribute_list_prefix_all_cmd,
|
distribute_list_prefix_all_cmd,
|
||||||
"distribute-list prefix WORD (in|out)",
|
"distribute-list prefix WORD (in|out)",
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -458,7 +456,6 @@ DEFUN (districute_list_prefix_all,
|
|||||||
"Filter outgoing routing updates\n")
|
"Filter outgoing routing updates\n")
|
||||||
{
|
{
|
||||||
enum distribute_type type;
|
enum distribute_type type;
|
||||||
struct distribute *dist;
|
|
||||||
|
|
||||||
/* Check of distribute list type. */
|
/* Check of distribute list type. */
|
||||||
if (strncmp (argv[1], "i", 1) == 0)
|
if (strncmp (argv[1], "i", 1) == 0)
|
||||||
@ -473,12 +470,12 @@ DEFUN (districute_list_prefix_all,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get interface name corresponding distribute list. */
|
/* Get interface name corresponding distribute list. */
|
||||||
dist = distribute_list_prefix_set (NULL, type, argv[0]);
|
distribute_list_prefix_set (NULL, type, argv[0]);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (districute_list_prefix_all,
|
ALIAS (distribute_list_prefix_all,
|
||||||
ipv6_distribute_list_prefix_all_cmd,
|
ipv6_distribute_list_prefix_all_cmd,
|
||||||
"distribute-list prefix WORD (in|out)",
|
"distribute-list prefix WORD (in|out)",
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -487,7 +484,7 @@ ALIAS (districute_list_prefix_all,
|
|||||||
"Filter incoming routing updates\n"
|
"Filter incoming routing updates\n"
|
||||||
"Filter outgoing routing updates\n")
|
"Filter outgoing routing updates\n")
|
||||||
|
|
||||||
DEFUN (no_districute_list_prefix_all,
|
DEFUN (no_distribute_list_prefix_all,
|
||||||
no_distribute_list_prefix_all_cmd,
|
no_distribute_list_prefix_all_cmd,
|
||||||
"no distribute-list prefix WORD (in|out)",
|
"no distribute-list prefix WORD (in|out)",
|
||||||
NO_STR
|
NO_STR
|
||||||
@ -521,7 +518,7 @@ DEFUN (no_districute_list_prefix_all,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (no_districute_list_prefix_all,
|
ALIAS (no_distribute_list_prefix_all,
|
||||||
no_ipv6_distribute_list_prefix_all_cmd,
|
no_ipv6_distribute_list_prefix_all_cmd,
|
||||||
"no distribute-list prefix WORD (in|out)",
|
"no distribute-list prefix WORD (in|out)",
|
||||||
NO_STR
|
NO_STR
|
||||||
@ -531,7 +528,7 @@ ALIAS (no_districute_list_prefix_all,
|
|||||||
"Filter incoming routing updates\n"
|
"Filter incoming routing updates\n"
|
||||||
"Filter outgoing routing updates\n")
|
"Filter outgoing routing updates\n")
|
||||||
|
|
||||||
DEFUN (districute_list_prefix, distribute_list_prefix_cmd,
|
DEFUN (distribute_list_prefix, distribute_list_prefix_cmd,
|
||||||
"distribute-list prefix WORD (in|out) WORD",
|
"distribute-list prefix WORD (in|out) WORD",
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
"Filter prefixes in routing updates\n"
|
"Filter prefixes in routing updates\n"
|
||||||
@ -541,7 +538,6 @@ DEFUN (districute_list_prefix, distribute_list_prefix_cmd,
|
|||||||
"Interface name\n")
|
"Interface name\n")
|
||||||
{
|
{
|
||||||
enum distribute_type type;
|
enum distribute_type type;
|
||||||
struct distribute *dist;
|
|
||||||
|
|
||||||
/* Check of distribute list type. */
|
/* Check of distribute list type. */
|
||||||
if (strncmp (argv[1], "i", 1) == 0)
|
if (strncmp (argv[1], "i", 1) == 0)
|
||||||
@ -556,12 +552,12 @@ DEFUN (districute_list_prefix, distribute_list_prefix_cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get interface name corresponding distribute list. */
|
/* Get interface name corresponding distribute list. */
|
||||||
dist = distribute_list_prefix_set (argv[2], type, argv[0]);
|
distribute_list_prefix_set (argv[2], type, argv[0]);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (districute_list_prefix, ipv6_distribute_list_prefix_cmd,
|
ALIAS (distribute_list_prefix, ipv6_distribute_list_prefix_cmd,
|
||||||
"distribute-list prefix WORD (in|out) WORD",
|
"distribute-list prefix WORD (in|out) WORD",
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
"Filter prefixes in routing updates\n"
|
"Filter prefixes in routing updates\n"
|
||||||
@ -570,7 +566,7 @@ ALIAS (districute_list_prefix, ipv6_distribute_list_prefix_cmd,
|
|||||||
"Filter outgoing routing updates\n"
|
"Filter outgoing routing updates\n"
|
||||||
"Interface name\n")
|
"Interface name\n")
|
||||||
|
|
||||||
DEFUN (no_districute_list_prefix, no_distribute_list_prefix_cmd,
|
DEFUN (no_distribute_list_prefix, no_distribute_list_prefix_cmd,
|
||||||
"no distribute-list prefix WORD (in|out) WORD",
|
"no distribute-list prefix WORD (in|out) WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -604,7 +600,7 @@ DEFUN (no_districute_list_prefix, no_distribute_list_prefix_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS (no_districute_list_prefix, no_ipv6_distribute_list_prefix_cmd,
|
ALIAS (no_distribute_list_prefix, no_ipv6_distribute_list_prefix_cmd,
|
||||||
"no distribute-list prefix WORD (in|out) WORD",
|
"no distribute-list prefix WORD (in|out) WORD",
|
||||||
NO_STR
|
NO_STR
|
||||||
"Filter networks in routing updates\n"
|
"Filter networks in routing updates\n"
|
||||||
@ -762,22 +758,25 @@ distribute_list_init (int node)
|
|||||||
(int (*) (const void *, const void *)) distribute_cmp);
|
(int (*) (const void *, const void *)) distribute_cmp);
|
||||||
|
|
||||||
if(node==RIP_NODE) {
|
if(node==RIP_NODE) {
|
||||||
install_element (RIP_NODE, &distribute_list_all_cmd);
|
install_element (node, &distribute_list_all_cmd);
|
||||||
install_element (RIP_NODE, &no_distribute_list_all_cmd);
|
install_element (node, &no_distribute_list_all_cmd);
|
||||||
install_element (RIP_NODE, &distribute_list_cmd);
|
install_element (node, &distribute_list_cmd);
|
||||||
install_element (RIP_NODE, &no_distribute_list_cmd);
|
install_element (node, &no_distribute_list_cmd);
|
||||||
install_element (RIP_NODE, &distribute_list_prefix_all_cmd);
|
install_element (node, &distribute_list_prefix_all_cmd);
|
||||||
install_element (RIP_NODE, &no_distribute_list_prefix_all_cmd);
|
install_element (node, &no_distribute_list_prefix_all_cmd);
|
||||||
install_element (RIP_NODE, &distribute_list_prefix_cmd);
|
install_element (node, &distribute_list_prefix_cmd);
|
||||||
install_element (RIP_NODE, &no_distribute_list_prefix_cmd);
|
install_element (node, &no_distribute_list_prefix_cmd);
|
||||||
} else {
|
} else if (node == RIPNG_NODE || node == BABEL_NODE) {
|
||||||
install_element (RIPNG_NODE, &ipv6_distribute_list_all_cmd);
|
/* WARNING: two identical commands installed do a crash, so be worry with
|
||||||
install_element (RIPNG_NODE, &no_ipv6_distribute_list_all_cmd);
|
aliases. For this reason, and because all these commands are aliases, Babel
|
||||||
install_element (RIPNG_NODE, &ipv6_distribute_list_cmd);
|
is not set with RIP. */
|
||||||
install_element (RIPNG_NODE, &no_ipv6_distribute_list_cmd);
|
install_element (node, &ipv6_distribute_list_all_cmd);
|
||||||
install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_all_cmd);
|
install_element (node, &no_ipv6_distribute_list_all_cmd);
|
||||||
install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_all_cmd);
|
install_element (node, &ipv6_distribute_list_cmd);
|
||||||
install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_cmd);
|
install_element (node, &no_ipv6_distribute_list_cmd);
|
||||||
install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_cmd);
|
install_element (node, &ipv6_distribute_list_prefix_all_cmd);
|
||||||
|
install_element (node, &no_ipv6_distribute_list_prefix_all_cmd);
|
||||||
|
install_element (node, &ipv6_distribute_list_prefix_cmd);
|
||||||
|
install_element (node, &no_ipv6_distribute_list_prefix_cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
#ifndef _ZEBRA_DISTRIBUTE_H
|
#ifndef _ZEBRA_DISTRIBUTE_H
|
||||||
#define _ZEBRA_DISTRIBUTE_H
|
#define _ZEBRA_DISTRIBUTE_H
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "if.h"
|
||||||
|
|
||||||
/* Disctirubte list types. */
|
/* Disctirubte list types. */
|
||||||
enum distribute_type
|
enum distribute_type
|
||||||
{
|
{
|
||||||
|
12
lib/filter.c
12
lib/filter.c
@ -1337,13 +1337,13 @@ DEFUN (no_access_list_all,
|
|||||||
|
|
||||||
master = access->master;
|
master = access->master;
|
||||||
|
|
||||||
/* Delete all filter from access-list. */
|
|
||||||
access_list_delete (access);
|
|
||||||
|
|
||||||
/* Run hook function. */
|
/* Run hook function. */
|
||||||
if (master->delete_hook)
|
if (master->delete_hook)
|
||||||
(*master->delete_hook) (access);
|
(*master->delete_hook) (access);
|
||||||
|
|
||||||
|
/* Delete all filter from access-list. */
|
||||||
|
access_list_delete (access);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1508,13 +1508,13 @@ DEFUN (no_ipv6_access_list_all,
|
|||||||
|
|
||||||
master = access->master;
|
master = access->master;
|
||||||
|
|
||||||
/* Delete all filter from access-list. */
|
|
||||||
access_list_delete (access);
|
|
||||||
|
|
||||||
/* Run hook function. */
|
/* Run hook function. */
|
||||||
if (master->delete_hook)
|
if (master->delete_hook)
|
||||||
(*master->delete_hook) (access);
|
(*master->delete_hook) (access);
|
||||||
|
|
||||||
|
/* Delete all filter from access-list. */
|
||||||
|
access_list_delete (access);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
lib/if.c
22
lib/if.c
@ -431,19 +431,17 @@ if_dump (const struct interface *ifp)
|
|||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct connected *c;
|
struct connected *c;
|
||||||
|
|
||||||
zlog_info ("Interface %s index %d metric %d mtu %d "
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
"mtu6 %d "
|
|
||||||
#endif /* HAVE_IPV6 */
|
|
||||||
"%s",
|
|
||||||
ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
ifp->mtu6,
|
|
||||||
#endif /* HAVE_IPV6 */
|
|
||||||
if_flag_dump (ifp->flags));
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
|
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
|
||||||
;
|
zlog_info ("Interface %s index %d metric %d mtu %d "
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
"mtu6 %d "
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
"%s",
|
||||||
|
ifp->name, ifp->ifindex, ifp->metric, ifp->mtu,
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
ifp->mtu6,
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
if_flag_dump (ifp->flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interface printing for all interface. */
|
/* Interface printing for all interface. */
|
||||||
|
@ -207,7 +207,6 @@ DEFUN (if_rmap,
|
|||||||
"Route map interface name\n")
|
"Route map interface name\n")
|
||||||
{
|
{
|
||||||
enum if_rmap_type type;
|
enum if_rmap_type type;
|
||||||
struct if_rmap *if_rmap;
|
|
||||||
|
|
||||||
if (strncmp (argv[1], "i", 1) == 0)
|
if (strncmp (argv[1], "i", 1) == 0)
|
||||||
type = IF_RMAP_IN;
|
type = IF_RMAP_IN;
|
||||||
@ -219,7 +218,7 @@ DEFUN (if_rmap,
|
|||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
if_rmap = if_rmap_set (argv[2], type, argv[0]);
|
if_rmap_set (argv[2], type, argv[0]);
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
86
lib/log.c
86
lib/log.c
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* Logging of zebra
|
* Logging of zebra
|
||||||
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
|
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
|
||||||
*
|
*
|
||||||
@ -22,6 +20,8 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define QUAGGA_DEFINE_DESC_TABLE
|
||||||
|
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -48,6 +48,7 @@ const char *zlog_proto_names[] =
|
|||||||
"BGP",
|
"BGP",
|
||||||
"OSPF",
|
"OSPF",
|
||||||
"RIPNG",
|
"RIPNG",
|
||||||
|
"BABEL",
|
||||||
"OSPF6",
|
"OSPF6",
|
||||||
"ISIS",
|
"ISIS",
|
||||||
"MASC",
|
"MASC",
|
||||||
@ -776,7 +777,8 @@ lookup (const struct message *mes, int key)
|
|||||||
* provided otherwise.
|
* provided otherwise.
|
||||||
*/
|
*/
|
||||||
const char *
|
const char *
|
||||||
mes_lookup (const struct message *meslist, int max, int index, const char *none)
|
mes_lookup (const struct message *meslist, int max, int index,
|
||||||
|
const char *none, const char *mesname)
|
||||||
{
|
{
|
||||||
int pos = index - meslist[0].key;
|
int pos = index - meslist[0].key;
|
||||||
|
|
||||||
@ -799,13 +801,13 @@ mes_lookup (const struct message *meslist, int max, int index, const char *none)
|
|||||||
{
|
{
|
||||||
const char *str = (meslist->str ? meslist->str : none);
|
const char *str = (meslist->str ? meslist->str : none);
|
||||||
|
|
||||||
zlog_debug ("message index %d [%s] found in position %d (max is %d)",
|
zlog_debug ("message index %d [%s] found in %s at position %d (max is %d)",
|
||||||
index, str, i, max);
|
index, str, mesname, i, max);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zlog_err("message index %d not found (max is %d)", index, max);
|
zlog_err("message index %d not found in %s (max is %d)", index, mesname, max);
|
||||||
assert (none);
|
assert (none);
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
@ -818,29 +820,6 @@ safe_strerror(int errnum)
|
|||||||
return (s != NULL) ? s : "Unknown error";
|
return (s != NULL) ? s : "Unknown error";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zebra_desc_table
|
|
||||||
{
|
|
||||||
unsigned int type;
|
|
||||||
const char *string;
|
|
||||||
char chr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) }
|
|
||||||
static const struct zebra_desc_table route_types[] = {
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_SYSTEM, "system", 'X' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_KERNEL, "kernel", 'K' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_CONNECT, "connected", 'C' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_STATIC, "static", 'S' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_RIP, "rip", 'R' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_RIPNG, "ripng", 'R' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_OSPF, "ospf", 'O' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_OSPF6, "ospf6", 'O' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_ISIS, "isis", 'I' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_BGP, "bgp", 'B' ),
|
|
||||||
DESC_ENTRY (ZEBRA_ROUTE_HSLS, "hsls", 'H' ),
|
|
||||||
};
|
|
||||||
#undef DESC_ENTRY
|
|
||||||
|
|
||||||
#define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
|
#define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
|
||||||
static const struct zebra_desc_table command_types[] = {
|
static const struct zebra_desc_table command_types[] = {
|
||||||
DESC_ENTRY (ZEBRA_INTERFACE_ADD),
|
DESC_ENTRY (ZEBRA_INTERFACE_ADD),
|
||||||
@ -865,6 +844,7 @@ static const struct zebra_desc_table command_types[] = {
|
|||||||
DESC_ENTRY (ZEBRA_ROUTER_ID_ADD),
|
DESC_ENTRY (ZEBRA_ROUTER_ID_ADD),
|
||||||
DESC_ENTRY (ZEBRA_ROUTER_ID_DELETE),
|
DESC_ENTRY (ZEBRA_ROUTER_ID_DELETE),
|
||||||
DESC_ENTRY (ZEBRA_ROUTER_ID_UPDATE),
|
DESC_ENTRY (ZEBRA_ROUTER_ID_UPDATE),
|
||||||
|
DESC_ENTRY (ZEBRA_HELLO),
|
||||||
};
|
};
|
||||||
#undef DESC_ENTRY
|
#undef DESC_ENTRY
|
||||||
|
|
||||||
@ -930,4 +910,52 @@ proto_name2num(const char *s)
|
|||||||
return route_types[i].type;
|
return route_types[i].type;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef RTSIZE
|
#undef RTSIZE
|
||||||
|
|
||||||
|
int
|
||||||
|
proto_redistnum(int afi, const char *s)
|
||||||
|
{
|
||||||
|
if (! s)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (afi == AFI_IP)
|
||||||
|
{
|
||||||
|
if (strncmp (s, "k", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_KERNEL;
|
||||||
|
else if (strncmp (s, "c", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_CONNECT;
|
||||||
|
else if (strncmp (s, "s", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_STATIC;
|
||||||
|
else if (strncmp (s, "r", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_RIP;
|
||||||
|
else if (strncmp (s, "o", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_OSPF;
|
||||||
|
else if (strncmp (s, "i", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_ISIS;
|
||||||
|
else if (strncmp (s, "bg", 2) == 0)
|
||||||
|
return ZEBRA_ROUTE_BGP;
|
||||||
|
else if (strncmp (s, "ba", 2) == 0)
|
||||||
|
return ZEBRA_ROUTE_BABEL;
|
||||||
|
}
|
||||||
|
if (afi == AFI_IP6)
|
||||||
|
{
|
||||||
|
if (strncmp (s, "k", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_KERNEL;
|
||||||
|
else if (strncmp (s, "c", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_CONNECT;
|
||||||
|
else if (strncmp (s, "s", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_STATIC;
|
||||||
|
else if (strncmp (s, "r", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_RIPNG;
|
||||||
|
else if (strncmp (s, "o", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_OSPF6;
|
||||||
|
else if (strncmp (s, "i", 1) == 0)
|
||||||
|
return ZEBRA_ROUTE_ISIS;
|
||||||
|
else if (strncmp (s, "bg", 2) == 0)
|
||||||
|
return ZEBRA_ROUTE_BGP;
|
||||||
|
else if (strncmp (s, "ba", 2) == 0)
|
||||||
|
return ZEBRA_ROUTE_BABEL;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* Zebra logging funcions.
|
* Zebra logging funcions.
|
||||||
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
|
* Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
|
||||||
*
|
*
|
||||||
@ -51,7 +49,8 @@ typedef enum
|
|||||||
ZLOG_RIP,
|
ZLOG_RIP,
|
||||||
ZLOG_BGP,
|
ZLOG_BGP,
|
||||||
ZLOG_OSPF,
|
ZLOG_OSPF,
|
||||||
ZLOG_RIPNG,
|
ZLOG_RIPNG,
|
||||||
|
ZLOG_BABEL,
|
||||||
ZLOG_OSPF6,
|
ZLOG_OSPF6,
|
||||||
ZLOG_ISIS,
|
ZLOG_ISIS,
|
||||||
ZLOG_MASC
|
ZLOG_MASC
|
||||||
@ -148,12 +147,12 @@ extern int zlog_reset_file (struct zlog *zl);
|
|||||||
extern int zlog_rotate (struct zlog *);
|
extern int zlog_rotate (struct zlog *);
|
||||||
|
|
||||||
/* For hackey massage lookup and check */
|
/* For hackey massage lookup and check */
|
||||||
#define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)")
|
#define LOOKUP(x, y) mes_lookup(x, x ## _max, y, "(no item found)", #x)
|
||||||
|
|
||||||
extern const char *lookup (const struct message *, int);
|
extern const char *lookup (const struct message *, int);
|
||||||
extern const char *mes_lookup (const struct message *meslist,
|
extern const char *mes_lookup (const struct message *meslist,
|
||||||
int max, int index,
|
int max, int index,
|
||||||
const char *no_item);
|
const char *no_item, const char *mesname);
|
||||||
|
|
||||||
extern const char *zlog_priority[];
|
extern const char *zlog_priority[];
|
||||||
extern const char *zlog_proto_names[];
|
extern const char *zlog_proto_names[];
|
||||||
|
14
lib/memory.c
14
lib/memory.c
@ -466,6 +466,17 @@ DEFUN (show_memory_ripng,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (show_memory_babel,
|
||||||
|
show_memory_babel_cmd,
|
||||||
|
"show memory babel",
|
||||||
|
SHOW_STR
|
||||||
|
"Memory statistics\n"
|
||||||
|
"Babel memory\n")
|
||||||
|
{
|
||||||
|
show_memory_vty (vty, memory_list_babel);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (show_memory_bgp,
|
DEFUN (show_memory_bgp,
|
||||||
show_memory_bgp_cmd,
|
show_memory_bgp_cmd,
|
||||||
"show memory bgp",
|
"show memory bgp",
|
||||||
@ -518,6 +529,7 @@ memory_init (void)
|
|||||||
install_element (RESTRICTED_NODE, &show_memory_lib_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_lib_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_memory_rip_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_rip_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_memory_ripng_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_ripng_cmd);
|
||||||
|
install_element (RESTRICTED_NODE, &show_memory_babel_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_memory_bgp_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_bgp_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_memory_ospf_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_ospf_cmd);
|
||||||
install_element (RESTRICTED_NODE, &show_memory_ospf6_cmd);
|
install_element (RESTRICTED_NODE, &show_memory_ospf6_cmd);
|
||||||
@ -528,6 +540,7 @@ memory_init (void)
|
|||||||
install_element (VIEW_NODE, &show_memory_lib_cmd);
|
install_element (VIEW_NODE, &show_memory_lib_cmd);
|
||||||
install_element (VIEW_NODE, &show_memory_rip_cmd);
|
install_element (VIEW_NODE, &show_memory_rip_cmd);
|
||||||
install_element (VIEW_NODE, &show_memory_ripng_cmd);
|
install_element (VIEW_NODE, &show_memory_ripng_cmd);
|
||||||
|
install_element (VIEW_NODE, &show_memory_babel_cmd);
|
||||||
install_element (VIEW_NODE, &show_memory_bgp_cmd);
|
install_element (VIEW_NODE, &show_memory_bgp_cmd);
|
||||||
install_element (VIEW_NODE, &show_memory_ospf_cmd);
|
install_element (VIEW_NODE, &show_memory_ospf_cmd);
|
||||||
install_element (VIEW_NODE, &show_memory_ospf6_cmd);
|
install_element (VIEW_NODE, &show_memory_ospf6_cmd);
|
||||||
@ -539,6 +552,7 @@ memory_init (void)
|
|||||||
install_element (ENABLE_NODE, &show_memory_zebra_cmd);
|
install_element (ENABLE_NODE, &show_memory_zebra_cmd);
|
||||||
install_element (ENABLE_NODE, &show_memory_rip_cmd);
|
install_element (ENABLE_NODE, &show_memory_rip_cmd);
|
||||||
install_element (ENABLE_NODE, &show_memory_ripng_cmd);
|
install_element (ENABLE_NODE, &show_memory_ripng_cmd);
|
||||||
|
install_element (ENABLE_NODE, &show_memory_babel_cmd);
|
||||||
install_element (ENABLE_NODE, &show_memory_bgp_cmd);
|
install_element (ENABLE_NODE, &show_memory_bgp_cmd);
|
||||||
install_element (ENABLE_NODE, &show_memory_ospf_cmd);
|
install_element (ENABLE_NODE, &show_memory_ospf_cmd);
|
||||||
install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
|
install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
*
|
*
|
||||||
* The script is sensitive to the format (though not whitespace), see
|
* The script is sensitive to the format (though not whitespace), see
|
||||||
* the top of memtypes.awk for more details.
|
* the top of memtypes.awk for more details.
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "zebra.h"
|
#include "zebra.h"
|
||||||
@ -176,6 +174,13 @@ struct memory_list memory_list_ripng[] =
|
|||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct memory_list memory_list_babel[] =
|
||||||
|
{
|
||||||
|
{ MTYPE_BABEL, "Babel structure" },
|
||||||
|
{ MTYPE_BABEL_IF, "Babel interface" },
|
||||||
|
{ -1, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
struct memory_list memory_list_ospf[] =
|
struct memory_list memory_list_ospf[] =
|
||||||
{
|
{
|
||||||
{ MTYPE_OSPF_TOP, "OSPF top" },
|
{ MTYPE_OSPF_TOP, "OSPF top" },
|
||||||
|
314
lib/prefix.c
314
lib/prefix.c
@ -32,6 +32,139 @@
|
|||||||
static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
|
static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
|
||||||
0xf8, 0xfc, 0xfe, 0xff};
|
0xf8, 0xfc, 0xfe, 0xff};
|
||||||
|
|
||||||
|
static const struct in6_addr maskbytes6[] =
|
||||||
|
{
|
||||||
|
/* /0 */ { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /1 */ { { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /2 */ { { { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /3 */ { { { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /4 */ { { { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /5 */ { { { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /6 */ { { { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /7 */ { { { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /8 */ { { { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /9 */ { { { 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /10 */ { { { 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /11 */ { { { 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /12 */ { { { 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /13 */ { { { 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /14 */ { { { 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /15 */ { { { 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /16 */ { { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /17 */ { { { 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /18 */ { { { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /19 */ { { { 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /20 */ { { { 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /21 */ { { { 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /22 */ { { { 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /23 */ { { { 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /24 */ { { { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /25 */ { { { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /26 */ { { { 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /27 */ { { { 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /28 */ { { { 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /29 */ { { { 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /30 */ { { { 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /31 */ { { { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /32 */ { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /33 */ { { { 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /34 */ { { { 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /35 */ { { { 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /36 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /37 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /38 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /39 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /40 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /41 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /42 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /43 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /44 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /45 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /46 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /47 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /48 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /49 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /50 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /51 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /52 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /53 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /54 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /55 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /56 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /57 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /58 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /59 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /60 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /61 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /62 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /63 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /64 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /65 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /66 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /67 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /68 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /69 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /70 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /71 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /72 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /73 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /74 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /75 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /76 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /77 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /78 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /79 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /80 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /81 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /82 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /83 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /84 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /85 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /86 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /87 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /88 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /89 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /90 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /91 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /92 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /93 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /94 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /95 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /96 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /97 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /98 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /99 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /100 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /101 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /102 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /103 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /104 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 } } },
|
||||||
|
/* /105 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 } } },
|
||||||
|
/* /106 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00 } } },
|
||||||
|
/* /107 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00 } } },
|
||||||
|
/* /108 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00 } } },
|
||||||
|
/* /109 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00 } } },
|
||||||
|
/* /110 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00 } } },
|
||||||
|
/* /111 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00 } } },
|
||||||
|
/* /112 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } },
|
||||||
|
/* /113 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00 } } },
|
||||||
|
/* /114 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 } } },
|
||||||
|
/* /115 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00 } } },
|
||||||
|
/* /116 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00 } } },
|
||||||
|
/* /117 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00 } } },
|
||||||
|
/* /118 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00 } } },
|
||||||
|
/* /119 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00 } } },
|
||||||
|
/* /120 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 } } },
|
||||||
|
/* /121 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 } } },
|
||||||
|
/* /122 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 } } },
|
||||||
|
/* /123 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0 } } },
|
||||||
|
/* /124 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 } } },
|
||||||
|
/* /125 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8 } } },
|
||||||
|
/* /126 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc } } },
|
||||||
|
/* /127 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe } } },
|
||||||
|
/* /128 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } }
|
||||||
|
};
|
||||||
|
|
||||||
/* Number of bits in prefix type. */
|
/* Number of bits in prefix type. */
|
||||||
#ifndef PNBBY
|
#ifndef PNBBY
|
||||||
#define PNBBY 8
|
#define PNBBY 8
|
||||||
@ -39,6 +172,21 @@ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
|
|||||||
|
|
||||||
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
|
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
prefix_bit (const u_char *prefix, const u_char prefixlen)
|
||||||
|
{
|
||||||
|
unsigned int offset = prefixlen / 8;
|
||||||
|
unsigned int shift = 7 - (prefixlen % 8);
|
||||||
|
|
||||||
|
return (prefix[offset] >> shift) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
|
||||||
|
{
|
||||||
|
return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
|
||||||
|
}
|
||||||
|
|
||||||
/* Address Famiy Identifier to Address Family converter. */
|
/* Address Famiy Identifier to Address Family converter. */
|
||||||
int
|
int
|
||||||
afi2family (afi_t afi)
|
afi2family (afi_t afi)
|
||||||
@ -133,11 +281,11 @@ prefix_same (const struct prefix *p1, const struct prefix *p2)
|
|||||||
if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
|
if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
|
||||||
{
|
{
|
||||||
if (p1->family == AF_INET)
|
if (p1->family == AF_INET)
|
||||||
if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
|
if (IPV4_ADDR_SAME (&p1->u.prefix4.s_addr, &p2->u.prefix4.s_addr))
|
||||||
return 1;
|
return 1;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (p1->family == AF_INET6 )
|
if (p1->family == AF_INET6 )
|
||||||
if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
|
if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr))
|
||||||
return 1;
|
return 1;
|
||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
}
|
}
|
||||||
@ -167,8 +315,8 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2)
|
|||||||
if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
|
if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
offset = p1->prefixlen / 8;
|
offset = p1->prefixlen / PNBBY;
|
||||||
shift = p1->prefixlen % 8;
|
shift = p1->prefixlen % PNBBY;
|
||||||
|
|
||||||
if (shift)
|
if (shift)
|
||||||
if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
|
if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
|
||||||
@ -181,6 +329,46 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Count the number of common bits in 2 prefixes. The prefix length is
|
||||||
|
* ignored for this function; the whole prefix is compared. If the prefix
|
||||||
|
* address families don't match, return -1; otherwise the return value is
|
||||||
|
* in range 0 ... maximum prefix length for the address family.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
|
||||||
|
{
|
||||||
|
int pos, bit;
|
||||||
|
int length = 0;
|
||||||
|
u_char xor;
|
||||||
|
|
||||||
|
/* Set both prefix's head pointer. */
|
||||||
|
const u_char *pp1 = (const u_char *)&p1->u.prefix;
|
||||||
|
const u_char *pp2 = (const u_char *)&p2->u.prefix;
|
||||||
|
|
||||||
|
if (p1->family == AF_INET)
|
||||||
|
length = IPV4_MAX_BYTELEN;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (p1->family == AF_INET6)
|
||||||
|
length = IPV6_MAX_BYTELEN;
|
||||||
|
#endif
|
||||||
|
if (p1->family != p2->family || !length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (pos = 0; pos < length; pos++)
|
||||||
|
if (pp1[pos] != pp2[pos])
|
||||||
|
break;
|
||||||
|
if (pos == length)
|
||||||
|
return pos * 8;
|
||||||
|
|
||||||
|
xor = pp1[pos] ^ pp2[pos];
|
||||||
|
for (bit = 0; bit < 8; bit++)
|
||||||
|
if (xor & (1 << (7 - bit)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
return pos * 8 + bit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return prefix family type string. */
|
/* Return prefix family type string. */
|
||||||
const char *
|
const char *
|
||||||
prefix_family_str (const struct prefix *p)
|
prefix_family_str (const struct prefix *p)
|
||||||
@ -261,25 +449,20 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert masklen into IP address's netmask. */
|
/* Convert masklen into IP address's netmask (network byte order). */
|
||||||
void
|
void
|
||||||
masklen2ip (int masklen, struct in_addr *netmask)
|
masklen2ip (const int masklen, struct in_addr *netmask)
|
||||||
{
|
{
|
||||||
u_char *pnt;
|
assert (masklen >= 0 && masklen <= IPV4_MAX_BITLEN);
|
||||||
int bit;
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
memset (netmask, 0, sizeof (struct in_addr));
|
/* left shift is only defined for less than the size of the type.
|
||||||
pnt = (unsigned char *) netmask;
|
* we unconditionally use long long in case the target platform
|
||||||
|
* has defined behaviour for << 32 (or has a 64-bit left shift) */
|
||||||
|
|
||||||
offset = masklen / 8;
|
if (sizeof(unsigned long long) > 4)
|
||||||
bit = masklen % 8;
|
netmask->s_addr = htonl(0xffffffffULL << (32 - masklen));
|
||||||
|
else
|
||||||
while (offset--)
|
netmask->s_addr = htonl(masklen ? 0xffffffffU << (32 - masklen) : 0);
|
||||||
*pnt++ = 0xff;
|
|
||||||
|
|
||||||
if (bit)
|
|
||||||
*pnt = maskbit[bit];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert IP address's netmask into integer. We assume netmask is
|
/* Convert IP address's netmask into integer. We assume netmask is
|
||||||
@ -287,54 +470,22 @@ masklen2ip (int masklen, struct in_addr *netmask)
|
|||||||
u_char
|
u_char
|
||||||
ip_masklen (struct in_addr netmask)
|
ip_masklen (struct in_addr netmask)
|
||||||
{
|
{
|
||||||
u_char len;
|
uint32_t tmp = ~ntohl(netmask.s_addr);
|
||||||
u_char *pnt;
|
if (tmp)
|
||||||
u_char *end;
|
/* clz: count leading zeroes. sadly, the behaviour of this builtin
|
||||||
u_char val;
|
* is undefined for a 0 argument, even though most CPUs give 32 */
|
||||||
|
return __builtin_clz(tmp);
|
||||||
len = 0;
|
else
|
||||||
pnt = (u_char *) &netmask;
|
return 32;
|
||||||
end = pnt + 4;
|
|
||||||
|
|
||||||
while ((pnt < end) && (*pnt == 0xff))
|
|
||||||
{
|
|
||||||
len+= 8;
|
|
||||||
pnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pnt < end)
|
|
||||||
{
|
|
||||||
val = *pnt;
|
|
||||||
while (val)
|
|
||||||
{
|
|
||||||
len++;
|
|
||||||
val <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply mask to IPv4 prefix. */
|
/* Apply mask to IPv4 prefix (network byte order). */
|
||||||
void
|
void
|
||||||
apply_mask_ipv4 (struct prefix_ipv4 *p)
|
apply_mask_ipv4 (struct prefix_ipv4 *p)
|
||||||
{
|
{
|
||||||
u_char *pnt;
|
struct in_addr mask;
|
||||||
int index;
|
masklen2ip(p->prefixlen, &mask);
|
||||||
int offset;
|
p->prefix.s_addr &= mask.s_addr;
|
||||||
|
|
||||||
index = p->prefixlen / 8;
|
|
||||||
|
|
||||||
if (index < 4)
|
|
||||||
{
|
|
||||||
pnt = (u_char *) &p->prefix;
|
|
||||||
offset = p->prefixlen % 8;
|
|
||||||
|
|
||||||
pnt[index] &= maskbit[offset];
|
|
||||||
index++;
|
|
||||||
|
|
||||||
while (index < 4)
|
|
||||||
pnt[index++] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
|
/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
|
||||||
@ -396,7 +547,7 @@ str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
plen = (u_char) atoi (++pnt);
|
plen = (u_char) atoi (++pnt);
|
||||||
if (plen > 128)
|
if (plen > IPV6_MAX_BITLEN)
|
||||||
return 0;
|
return 0;
|
||||||
p->prefixlen = plen;
|
p->prefixlen = plen;
|
||||||
}
|
}
|
||||||
@ -416,13 +567,13 @@ ip6_masklen (struct in6_addr netmask)
|
|||||||
|
|
||||||
pnt = (unsigned char *) & netmask;
|
pnt = (unsigned char *) & netmask;
|
||||||
|
|
||||||
while ((*pnt == 0xff) && len < 128)
|
while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN)
|
||||||
{
|
{
|
||||||
len += 8;
|
len += 8;
|
||||||
pnt++;
|
pnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 128)
|
if (len < IPV6_MAX_BITLEN)
|
||||||
{
|
{
|
||||||
val = *pnt;
|
val = *pnt;
|
||||||
while (val)
|
while (val)
|
||||||
@ -435,23 +586,10 @@ ip6_masklen (struct in6_addr netmask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
masklen2ip6 (int masklen, struct in6_addr *netmask)
|
masklen2ip6 (const int masklen, struct in6_addr *netmask)
|
||||||
{
|
{
|
||||||
unsigned char *pnt;
|
assert (masklen >= 0 && masklen <= IPV6_MAX_BITLEN);
|
||||||
int bit;
|
memcpy (netmask, maskbytes6 + masklen, sizeof (struct in6_addr));
|
||||||
int offset;
|
|
||||||
|
|
||||||
memset (netmask, 0, sizeof (struct in6_addr));
|
|
||||||
pnt = (unsigned char *) netmask;
|
|
||||||
|
|
||||||
offset = masklen / 8;
|
|
||||||
bit = masklen % 8;
|
|
||||||
|
|
||||||
while (offset--)
|
|
||||||
*pnt++ = 0xff;
|
|
||||||
|
|
||||||
if (bit)
|
|
||||||
*pnt = maskbit[bit];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -570,6 +708,20 @@ sockunion2hostprefix (const union sockunion *su)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
prefix2sockunion (const struct prefix *p, union sockunion *su)
|
||||||
|
{
|
||||||
|
memset (su, 0, sizeof (*su));
|
||||||
|
|
||||||
|
su->sa.sa_family = p->family;
|
||||||
|
if (p->family == AF_INET)
|
||||||
|
su->sin.sin_addr = p->u.prefix4;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (p->family == AF_INET6)
|
||||||
|
memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
prefix_blen (const struct prefix *p)
|
prefix_blen (const struct prefix *p)
|
||||||
{
|
{
|
||||||
|
27
lib/prefix.h
27
lib/prefix.h
@ -112,6 +112,7 @@ struct prefix_rd
|
|||||||
#define IPV4_NET0(a) ((((u_int32_t) (a)) & 0xff000000) == 0x00000000)
|
#define IPV4_NET0(a) ((((u_int32_t) (a)) & 0xff000000) == 0x00000000)
|
||||||
#define IPV4_NET127(a) ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000)
|
#define IPV4_NET127(a) ((((u_int32_t) (a)) & 0xff000000) == 0x7f000000)
|
||||||
#define IPV4_LINKLOCAL(a) ((((u_int32_t) (a)) & 0xffff0000) == 0xa9fe0000)
|
#define IPV4_LINKLOCAL(a) ((((u_int32_t) (a)) & 0xffff0000) == 0xa9fe0000)
|
||||||
|
#define IPV4_CLASS_DE(a) ((((u_int32_t) (a)) & 0xe0000000) == 0xe0000000)
|
||||||
|
|
||||||
/* Max bit/byte length of IPv6 address. */
|
/* Max bit/byte length of IPv6 address. */
|
||||||
#define IPV6_MAX_BYTELEN 16
|
#define IPV6_MAX_BYTELEN 16
|
||||||
@ -127,26 +128,14 @@ struct prefix_rd
|
|||||||
/* Prefix's family member. */
|
/* Prefix's family member. */
|
||||||
#define PREFIX_FAMILY(p) ((p)->family)
|
#define PREFIX_FAMILY(p) ((p)->family)
|
||||||
|
|
||||||
/* Check bit of the prefix. */
|
|
||||||
static inline unsigned int
|
|
||||||
prefix_bit (const u_char *prefix, const u_char prefixlen)
|
|
||||||
{
|
|
||||||
unsigned int offset = prefixlen / 8;
|
|
||||||
unsigned int shift = 7 - (prefixlen % 8);
|
|
||||||
|
|
||||||
return (prefix[offset] >> shift) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int
|
|
||||||
prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
|
|
||||||
{
|
|
||||||
return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prototypes. */
|
/* Prototypes. */
|
||||||
extern int afi2family (afi_t);
|
extern int afi2family (afi_t);
|
||||||
extern afi_t family2afi (int);
|
extern afi_t family2afi (int);
|
||||||
|
|
||||||
|
/* Check bit of the prefix. */
|
||||||
|
extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen);
|
||||||
|
extern unsigned int prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen);
|
||||||
|
|
||||||
extern struct prefix *prefix_new (void);
|
extern struct prefix *prefix_new (void);
|
||||||
extern void prefix_free (struct prefix *);
|
extern void prefix_free (struct prefix *);
|
||||||
extern const char *prefix_family_str (const struct prefix *);
|
extern const char *prefix_family_str (const struct prefix *);
|
||||||
@ -156,12 +145,14 @@ extern int prefix2str (const struct prefix *, char *, int);
|
|||||||
extern int prefix_match (const struct prefix *, const struct prefix *);
|
extern int prefix_match (const struct prefix *, const struct prefix *);
|
||||||
extern int prefix_same (const struct prefix *, const struct prefix *);
|
extern int prefix_same (const struct prefix *, const struct prefix *);
|
||||||
extern int prefix_cmp (const struct prefix *, const struct prefix *);
|
extern int prefix_cmp (const struct prefix *, const struct prefix *);
|
||||||
|
extern int prefix_common_bits (const struct prefix *, const struct prefix *);
|
||||||
extern void prefix_copy (struct prefix *dest, const struct prefix *src);
|
extern void prefix_copy (struct prefix *dest, const struct prefix *src);
|
||||||
extern void apply_mask (struct prefix *);
|
extern void apply_mask (struct prefix *);
|
||||||
|
|
||||||
extern struct prefix *sockunion2prefix (const union sockunion *dest,
|
extern struct prefix *sockunion2prefix (const union sockunion *dest,
|
||||||
const union sockunion *mask);
|
const union sockunion *mask);
|
||||||
extern struct prefix *sockunion2hostprefix (const union sockunion *);
|
extern struct prefix *sockunion2hostprefix (const union sockunion *);
|
||||||
|
extern void prefix2sockunion (const struct prefix *, union sockunion *);
|
||||||
|
|
||||||
extern struct prefix_ipv4 *prefix_ipv4_new (void);
|
extern struct prefix_ipv4 *prefix_ipv4_new (void);
|
||||||
extern void prefix_ipv4_free (struct prefix_ipv4 *);
|
extern void prefix_ipv4_free (struct prefix_ipv4 *);
|
||||||
@ -175,7 +166,7 @@ extern int prefix_ipv4_any (const struct prefix_ipv4 *);
|
|||||||
extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
|
extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
|
||||||
|
|
||||||
extern u_char ip_masklen (struct in_addr);
|
extern u_char ip_masklen (struct in_addr);
|
||||||
extern void masklen2ip (int, struct in_addr *);
|
extern void masklen2ip (const int, struct in_addr *);
|
||||||
/* returns the network portion of the host address */
|
/* returns the network portion of the host address */
|
||||||
extern in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen);
|
extern in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen);
|
||||||
/* given the address of a host on a network and the network mask length,
|
/* given the address of a host on a network and the network mask length,
|
||||||
@ -196,7 +187,7 @@ extern void apply_mask_ipv6 (struct prefix_ipv6 *);
|
|||||||
*((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC));
|
*((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC));
|
||||||
|
|
||||||
extern int ip6_masklen (struct in6_addr);
|
extern int ip6_masklen (struct in6_addr);
|
||||||
extern void masklen2ip6 (int, struct in6_addr *);
|
extern void masklen2ip6 (const int, struct in6_addr *);
|
||||||
|
|
||||||
extern void str2in6_addr (const char *, struct in6_addr *);
|
extern void str2in6_addr (const char *, struct in6_addr *);
|
||||||
extern const char *inet6_ntoa (struct in6_addr);
|
extern const char *inet6_ntoa (struct in6_addr);
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Scan a file of route-type definitions (see eg route_types.txt) and
|
|
||||||
# generate a corresponding header file with:
|
|
||||||
#
|
|
||||||
# - enum of Zserv route-types
|
|
||||||
# - redistribute strings for the various Quagga daemons
|
|
||||||
#
|
|
||||||
# See route_types.txt for the format.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
FS="[,]";
|
|
||||||
|
|
||||||
# globals
|
|
||||||
exitret = 0;
|
|
||||||
tcount = 0;
|
|
||||||
|
|
||||||
# formats for output
|
|
||||||
## the define format
|
|
||||||
redist_def_fmt = "#define QUAGGA_REDIST_STR_%s \\\n";
|
|
||||||
## DEFUN/vty route-type argument
|
|
||||||
redist_str_fmt = "\"(%s)\"\n";
|
|
||||||
redist_help_def_fmt = "#define QUAGGA_REDIST_HELP_STR_%s";
|
|
||||||
redist_help_str_fmt = " \\\n \"%s\\n\"";
|
|
||||||
|
|
||||||
# header
|
|
||||||
header = "/* Auto-generated from route_types.txt by " ARGV[0] ". */\n";
|
|
||||||
header = header "/* Do not edit! */\n";
|
|
||||||
header = header "\n#ifndef _QUAGGA_ROUTE_TYPES_H\n";
|
|
||||||
header = header "#define _QUAGGA_ROUTE_TYPES_H\n";
|
|
||||||
footer = "#endif /* _QUAGGA_ROUTE_TYPES_H */\n";
|
|
||||||
printf ("%s\n", header);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Chomp comment lines
|
|
||||||
($0 ~ /^#/) {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# get rid of the commas, leading/trailling whitespace and
|
|
||||||
# quotes
|
|
||||||
{
|
|
||||||
for (i = 1; i <= NF; i++) {
|
|
||||||
#print "before:" $i;
|
|
||||||
$i = gensub(/^[[:blank:]]*(.*)[,]*.*/, "\\1", "g",$i);
|
|
||||||
$i = gensub(/^["](.*)["]$/, "\\1", "g", $i);
|
|
||||||
#print "after :" $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 7 field format:
|
|
||||||
# type cname daemon C 4 6 short help
|
|
||||||
(NF >= 7) {
|
|
||||||
#print "7", $1, $0;
|
|
||||||
|
|
||||||
if ($1 in types) {
|
|
||||||
print "error: attempt to redefine", $1;
|
|
||||||
exitret = 1;
|
|
||||||
exit exitret;
|
|
||||||
}
|
|
||||||
|
|
||||||
typesbynum[tcount] = $1;
|
|
||||||
types[$1,"num"] = tcount++;
|
|
||||||
types[$1,"cname"] = $2;
|
|
||||||
types[$1,"daemon"] = $3;
|
|
||||||
types[$1,"C"] = $4;
|
|
||||||
types[$1,"4"] = strtonum($5);
|
|
||||||
types[$1,"6"] = strtonum($6);
|
|
||||||
types[$1,"shelp"] = $7;
|
|
||||||
|
|
||||||
#print "num :", types[$1,"num"]
|
|
||||||
#print "cname :", types[$1,"cname"]
|
|
||||||
#print "daemon:", types[$1,"daemon"];
|
|
||||||
#print "char :", types[$1,"C"];
|
|
||||||
};
|
|
||||||
|
|
||||||
# 2 field: type "long description"
|
|
||||||
(NF == 2) {
|
|
||||||
#print "2", $1, $2;
|
|
||||||
|
|
||||||
if (!(($1 SUBSEP "num") in types)) {
|
|
||||||
print "error: type", $1, "must be defined before help str";
|
|
||||||
exitret = 2;
|
|
||||||
exit exitret;
|
|
||||||
}
|
|
||||||
|
|
||||||
types[$1,"lhelp"] = $2;
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
if (exitret)
|
|
||||||
exit exitret;
|
|
||||||
|
|
||||||
# The enums
|
|
||||||
# not yet...
|
|
||||||
#printf("enum\n{\n");
|
|
||||||
#for (i = 0; i < tcount; i++) {
|
|
||||||
# type = typesbynum[i];
|
|
||||||
# if (type != "" && types[type,"num"] == i)
|
|
||||||
# printf (" %s,\n", type);
|
|
||||||
#}
|
|
||||||
#printf (" ZEBRA_ROUTE_MAX,\n};\n\n");
|
|
||||||
|
|
||||||
# the redistribute defines
|
|
||||||
for (i = 0; i < tcount; i++) {
|
|
||||||
type = typesbynum[i];
|
|
||||||
|
|
||||||
# must be a type, and must cross-check against recorded type
|
|
||||||
if (type == "" || types[type,"num"] != i)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
# ignore route types that can't be redistributed
|
|
||||||
if (!(types[type,"4"] || types[type,"6"]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
# must have a daemon name
|
|
||||||
if (!((type SUBSEP "daemon") in types))
|
|
||||||
continue;
|
|
||||||
if (!(daemon = types[type,"daemon"]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
# might have done this daemon already?
|
|
||||||
if (daemon in seen_daemons)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cname = types[type,"cname"];
|
|
||||||
all = all "|" cname;
|
|
||||||
rstr = "";
|
|
||||||
hstr = "";
|
|
||||||
|
|
||||||
# add it to the others
|
|
||||||
for (j = 0; j < tcount; j++) {
|
|
||||||
# ignore self
|
|
||||||
if (i == j)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
type2 = typesbynum[j];
|
|
||||||
|
|
||||||
# type2 must be valid, and self-check.
|
|
||||||
if (type2 == "" || types[type2,"num"] != j)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
# ignore different route types for the same daemon
|
|
||||||
# (eg system/kernel/connected)
|
|
||||||
if (types[type2,"daemon"] == daemon)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((types[type2,"4"] && types[type,"4"]) \
|
|
||||||
|| (types[type2,"6"] && types[type,"6"])) {
|
|
||||||
|
|
||||||
if (rstr == "")
|
|
||||||
rstr = types[type2,"cname"];
|
|
||||||
else
|
|
||||||
rstr = rstr "|" types[type2,"cname"];
|
|
||||||
|
|
||||||
if ((type2 SUBSEP "lhelp") in types)
|
|
||||||
hstr2 = types[type2,"lhelp"];
|
|
||||||
else if ((type2 SUBSEP "shelp") in types)
|
|
||||||
hstr2 = types[type2,"shelp"];
|
|
||||||
else
|
|
||||||
hstr2 = types[type2,"cname"];
|
|
||||||
|
|
||||||
hstr = hstr sprintf(redist_help_str_fmt, hstr2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# dont double-process daemons.
|
|
||||||
seen_daemons[daemon] = 1;
|
|
||||||
|
|
||||||
printf("/* %s */\n", daemon);
|
|
||||||
printf(redist_def_fmt, toupper(daemon));
|
|
||||||
printf(redist_str_fmt, rstr);
|
|
||||||
printf(redist_help_def_fmt, toupper(daemon));
|
|
||||||
printf("%s", hstr);
|
|
||||||
printf("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#printf("#define QUAGGA_REDIST_STR_ALL %s\n",all);
|
|
||||||
|
|
||||||
# for (i = 0; i < lcount; i++) {
|
|
||||||
# if (mlists[i] != "")
|
|
||||||
# printf (mlistformat "\n", mlists[i]);
|
|
||||||
# }
|
|
||||||
printf (footer);
|
|
||||||
}
|
|
199
lib/route_types.pl
Executable file
199
lib/route_types.pl
Executable file
@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
##
|
||||||
|
## Scan a file of route-type definitions (see eg route_types.txt) and
|
||||||
|
## generate a corresponding header file with:
|
||||||
|
##
|
||||||
|
## - enum of Zserv route-types
|
||||||
|
## - redistribute strings for the various Quagga daemons
|
||||||
|
##
|
||||||
|
## See route_types.txt for the format.
|
||||||
|
##
|
||||||
|
##
|
||||||
|
## Copyright (C) 2009 David Lamparter.
|
||||||
|
## This file is part of GNU Zebra.
|
||||||
|
##
|
||||||
|
## GNU Zebra is free software; you can redistribute it and/or modify it
|
||||||
|
## under the terms of the GNU General Public License as published by the
|
||||||
|
## Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
## later version.
|
||||||
|
##
|
||||||
|
## GNU Zebra is distributed in the hope that it will be useful, but
|
||||||
|
## WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
## General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License
|
||||||
|
## along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||||
|
## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
## 02111-1307, USA.
|
||||||
|
##
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
# input processing
|
||||||
|
#
|
||||||
|
my @protos;
|
||||||
|
my %protodetail;
|
||||||
|
|
||||||
|
my %daemons;
|
||||||
|
|
||||||
|
while (<STDIN>) {
|
||||||
|
# skip comments and empty lines
|
||||||
|
next if (/^\s*(#|$)/);
|
||||||
|
|
||||||
|
# strip whitespace
|
||||||
|
chomp;
|
||||||
|
$_ =~ s/^\s*//;
|
||||||
|
$_ =~ s/\s*$//;
|
||||||
|
|
||||||
|
# match help strings
|
||||||
|
if (/^(ZEBRA_ROUTE_[^\s]+)\s*,\s*"(.*)"$/) {
|
||||||
|
$protodetail{$1}->{'longhelp'} = $2;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_ =~ s/\s*,\s*/,/g;
|
||||||
|
|
||||||
|
# else: 7-field line
|
||||||
|
my @f = split(/,/, $_);
|
||||||
|
unless (@f == 7) {
|
||||||
|
die "invalid input on route_types line $.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $proto = $f[0];
|
||||||
|
$f[3] = $1 if ($f[3] =~ /^'(.*)'$/);
|
||||||
|
$f[6] = $1 if ($f[6] =~ /^"(.*)"$/);
|
||||||
|
|
||||||
|
$protodetail{$proto} = {
|
||||||
|
"number" => scalar @protos,
|
||||||
|
"type" => $f[0],
|
||||||
|
"cname" => $f[1],
|
||||||
|
"daemon" => $f[2],
|
||||||
|
"char" => $f[3],
|
||||||
|
"ipv4" => int($f[4]),
|
||||||
|
"ipv6" => int($f[5]),
|
||||||
|
"shorthelp" => $f[6],
|
||||||
|
};
|
||||||
|
push @protos, $proto;
|
||||||
|
$daemons{$f[2]} = {
|
||||||
|
"ipv4" => int($f[4]),
|
||||||
|
"ipv6" => int($f[5])
|
||||||
|
} unless ($f[2] eq "NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
# output
|
||||||
|
printf <<EOF, $ARGV[0];
|
||||||
|
/* Auto-generated from route_types.txt by %s. */
|
||||||
|
/* Do not edit! */
|
||||||
|
|
||||||
|
#ifndef _QUAGGA_ROUTE_TYPES_H
|
||||||
|
#define _QUAGGA_ROUTE_TYPES_H
|
||||||
|
|
||||||
|
/* Zebra route's types. */
|
||||||
|
EOF
|
||||||
|
|
||||||
|
push @protos, "ZEBRA_ROUTE_MAX";
|
||||||
|
my (@protosv4, @protosv6) = ((), ());
|
||||||
|
for (my $c = 0; $c < @protos; $c++) {
|
||||||
|
my $p = $protos[$c];
|
||||||
|
printf "#define %-32s %d\n", $p, $c;
|
||||||
|
push @protosv4, $p if ($protodetail{$p}->{"ipv4"});
|
||||||
|
push @protosv6, $p if ($protodetail{$p}->{"ipv6"});
|
||||||
|
}
|
||||||
|
pop @protos;
|
||||||
|
|
||||||
|
sub codelist {
|
||||||
|
my (@protos) = @_;
|
||||||
|
my (@lines) = ();
|
||||||
|
my $str = " \"Codes: ";
|
||||||
|
for my $p (@protos) {
|
||||||
|
my $s = sprintf("%s - %s, ",
|
||||||
|
$protodetail{$p}->{"char"},
|
||||||
|
$protodetail{$p}->{"shorthelp"});
|
||||||
|
if (length($str . $s) > 70) {
|
||||||
|
$str =~ s/ $//;
|
||||||
|
push @lines, $str . "%s\" \\\n";
|
||||||
|
$str = " \" ";
|
||||||
|
}
|
||||||
|
$str .= $s;
|
||||||
|
}
|
||||||
|
$str =~ s/ $//;
|
||||||
|
push @lines, $str . "%s\" \\\n";
|
||||||
|
push @lines, " \" > - selected route, * - FIB route%s%s\", \\\n";
|
||||||
|
my @nl = ();
|
||||||
|
for (my $c = 0; $c < @lines + 1; $c++) {
|
||||||
|
push @nl, "VTY_NEWLINE"
|
||||||
|
}
|
||||||
|
return join("", @lines) ." ". join(", ", @nl);
|
||||||
|
}
|
||||||
|
|
||||||
|
print "\n";
|
||||||
|
printf "#define SHOW_ROUTE_V4_HEADER \\\n%s\n", codelist(@protosv4);
|
||||||
|
printf "#define SHOW_ROUTE_V6_HEADER \\\n%s\n", codelist(@protosv6);
|
||||||
|
print "\n";
|
||||||
|
|
||||||
|
sub collect {
|
||||||
|
my ($daemon, $ipv4, $ipv6) = @_;
|
||||||
|
my (@names, @help) = ((), ());
|
||||||
|
for my $p (@protos) {
|
||||||
|
next if ($protodetail{$p}->{"daemon"} eq $daemon && $daemon ne "zebra");
|
||||||
|
next unless (($ipv4 && $protodetail{$p}->{"ipv4"})
|
||||||
|
|| ($ipv6 && $protodetail{$p}->{"ipv6"}));
|
||||||
|
push @names, $protodetail{$p}->{"cname"};
|
||||||
|
push @help, " \"".$protodetail{$p}->{"longhelp"}."\\n\"";
|
||||||
|
}
|
||||||
|
return ("\"(" . join("|", @names) . ")\"", join(" \\\n", @help));
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $daemon (sort keys %daemons) {
|
||||||
|
next unless ($daemons{$daemon}->{"ipv4"} || $daemons{$daemon}->{"ipv6"});
|
||||||
|
printf "/* %s */\n", $daemon;
|
||||||
|
if ($daemons{$daemon}->{"ipv4"} && $daemons{$daemon}->{"ipv6"}) {
|
||||||
|
my ($names, $help) = collect($daemon, 1, 1);
|
||||||
|
printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
|
||||||
|
printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
|
||||||
|
($names, $help) = collect($daemon, 1, 0);
|
||||||
|
printf "#define QUAGGA_IP_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
|
||||||
|
printf "#define QUAGGA_IP_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
|
||||||
|
($names, $help) = collect($daemon, 0, 1);
|
||||||
|
printf "#define QUAGGA_IP6_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
|
||||||
|
printf "#define QUAGGA_IP6_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
|
||||||
|
} else {
|
||||||
|
my ($names, $help) = collect($daemon,
|
||||||
|
$daemons{$daemon}->{"ipv4"}, $daemons{$daemon}->{"ipv6"});
|
||||||
|
printf "#define QUAGGA_REDIST_STR_%s \\\n %s\n", uc $daemon, $names;
|
||||||
|
printf "#define QUAGGA_REDIST_HELP_STR_%s \\\n%s\n", uc $daemon, $help;
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print <<EOF;
|
||||||
|
|
||||||
|
#ifdef QUAGGA_DEFINE_DESC_TABLE
|
||||||
|
|
||||||
|
struct zebra_desc_table
|
||||||
|
{
|
||||||
|
unsigned int type;
|
||||||
|
const char *string;
|
||||||
|
char chr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) }
|
||||||
|
static const struct zebra_desc_table route_types[] = {
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for (my $c = 0; $c < @protos; $c++) {
|
||||||
|
my $p = $protos[$c];
|
||||||
|
printf " DESC_ENTRY\t(%s\t \"%s\",\t'%s' ),\n",
|
||||||
|
$p.",", $protodetail{$p}->{"cname"}, $protodetail{$p}->{"char"};
|
||||||
|
}
|
||||||
|
|
||||||
|
print <<EOF;
|
||||||
|
};
|
||||||
|
#undef DESC_ENTRY
|
||||||
|
|
||||||
|
#endif /* QUAGGA_DEFINE_DESC_TABLE */
|
||||||
|
|
||||||
|
#endif /* _QUAGGA_ROUTE_TYPES_H */
|
||||||
|
EOF
|
||||||
|
|
@ -42,13 +42,13 @@
|
|||||||
|
|
||||||
## type cname daemon C 4 6 short help
|
## type cname daemon C 4 6 short help
|
||||||
ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, "Reserved"
|
ZEBRA_ROUTE_SYSTEM, system, NULL, 'X', 0, 0, "Reserved"
|
||||||
ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, NULL
|
ZEBRA_ROUTE_KERNEL, kernel, zebra, 'K', 1, 1, "kernel route"
|
||||||
ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, NULL
|
ZEBRA_ROUTE_CONNECT, connected, zebra, 'C', 1, 1, "connected"
|
||||||
ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, NULL
|
ZEBRA_ROUTE_STATIC, static, zebra, 'S', 1, 1, "static"
|
||||||
ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, "RIP"
|
ZEBRA_ROUTE_RIP, rip, ripd, 'R', 1, 0, "RIP"
|
||||||
ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, "RIPng"
|
ZEBRA_ROUTE_RIPNG, ripng, ripngd, 'R', 0, 1, "RIPng"
|
||||||
ZEBRA_ROUTE_OSPF, ospf, ospfd, 'O', 1, 0, "OSPF"
|
ZEBRA_ROUTE_OSPF, ospf, ospfd, 'O', 1, 0, "OSPF"
|
||||||
ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPF"
|
ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPFv6"
|
||||||
ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS"
|
ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS"
|
||||||
ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
|
ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
|
||||||
# HSLS and OLSR both are AFI independent (so: 1, 1), however
|
# HSLS and OLSR both are AFI independent (so: 1, 1), however
|
||||||
@ -57,7 +57,8 @@ ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
|
|||||||
# to 'switch on' redist support (direct numeric entry remaining
|
# to 'switch on' redist support (direct numeric entry remaining
|
||||||
# possible).
|
# possible).
|
||||||
ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, "HSLS"
|
ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, "HSLS"
|
||||||
ZEBRA_ROUTE_OLSR, olsr, oslrd, 'o', 0, 0, "OLSR"
|
ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 0, 0, "OLSR"
|
||||||
|
ZEBRA_ROUTE_BABEL, babel, babeld, 'A', 1, 1, "Babel"
|
||||||
|
|
||||||
## help strings
|
## help strings
|
||||||
ZEBRA_ROUTE_SYSTEM, "Reserved route type, for internal use only"
|
ZEBRA_ROUTE_SYSTEM, "Reserved route type, for internal use only"
|
||||||
@ -72,3 +73,4 @@ ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)"
|
|||||||
ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)"
|
ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)"
|
||||||
ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)"
|
ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)"
|
||||||
ZEBRA_ROUTE_OLSR, "Optimised Link State Routing (OLSR)"
|
ZEBRA_ROUTE_OLSR, "Optimised Link State Routing (OLSR)"
|
||||||
|
ZEBRA_ROUTE_BABEL, "Babel routing protocol (Babel)"
|
||||||
|
@ -43,6 +43,7 @@ typedef enum
|
|||||||
{
|
{
|
||||||
RMAP_RIP,
|
RMAP_RIP,
|
||||||
RMAP_RIPNG,
|
RMAP_RIPNG,
|
||||||
|
RMAP_BABEL,
|
||||||
RMAP_OSPF,
|
RMAP_OSPF,
|
||||||
RMAP_OSPF6,
|
RMAP_OSPF6,
|
||||||
RMAP_BGP,
|
RMAP_BGP,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user