Addition of OSPF-API - Amir Guindehi <nospam.amir@datacore.ch>

This commit is contained in:
paul 2003-03-17 01:10:58 +00:00
parent f9a80b452f
commit 2d33f15789
15 changed files with 6002 additions and 0 deletions

1
ospfclient/AUTHORS Normal file
View file

@ -0,0 +1 @@
Ralph Keller <keller@tik.ee.ethz.ch>

339
ospfclient/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

57
ospfclient/ChangeLog Normal file
View file

@ -0,0 +1,57 @@
2003-01-10 Ralph Keller <keller@tik.ee.ethz.ch>
* New ChangeLog
2003-01-08 Ralph Keller <keller@tik.ee.ethz.ch>
* apiclient message passing bug resolved
* (proposed by Masahiko)
2002-10-09 Ralph Keller <keller@tik.ee.ethz.ch>
* Includes patch in OSPFd for ISM, NSM, neighbor
2002-09-16 Ralph Keller <keller@tik.ee.ethz.ch>
* Current patch vs. Zebra-0.93b
2002-08-22 Ralph Keller <keller@tik.ee.ethz.ch>
* Bugfix: LSA updates are now received only once even
* if multiple opaque types are registered
2002-08-06 Ralph Keller <keller@tik.ee.ethz.ch>
* Upgrade of OSPF API to Zebra-0.93a.
2002-06-13 Ralph Keller <keller@tik.ee.ethz.ch>
* Opaque LSA origination bug fixed by Masahiko.
* This code is based on 0.93-pre
2002-05-03 Ralph Keller <keller@tik.ee.ethz.ch>
* Upgrade to newest Zebra from CVS repository. ospf_flood_through
* function did not work after upgrade. Function
* ospf_apiserver_flood_opaque_lsa added. Also byte order problem
* with port numbers resolved.
2002-05-02 Ralph Keller <keller@tik.ee.ethz.ch>
* new autoconf and automake files, now called configure.in
* instead of configure.ac
2002-04-24 Ralph Keller <keller@tik.ee.ethz.ch>
* reverse channel now works (syncport and syncport+1)
* ospf_apiclient.c: standard includes removed (not needed)
* bzero replaced with memset
2002-04-18 Ralph Keller <keller@tik.ee.ethz.ch>
* 2-way phase connection setup
2002-04-05 Ralph Keller <keller@tik.ee.ethz.ch>
* Changes incorporated as proposed by Masahiko
2002-04-05 Ralph Keller <keller@tik.ee.ethz.ch>
* autoconf and automake-style Makefile
2002-04-04 Ralph Keller <keller@tik.ee.ethz.ch>
* 1st public release of OSPF API

182
ospfclient/INSTALL Normal file
View file

@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

19
ospfclient/Makefile.am Normal file
View file

@ -0,0 +1,19 @@
## Automake.am for OSPF API client
INCLUDES = -I../lib -I../
noinst_LIBRARIES = libospfapiclient.a
sbin_PROGRAMS = ospfclient
libospfapiclient_a_SOURCES = \
ospf_apiclient.c
noinst_HEADERS = \
ospf_apiclient.h
ospfclient_SOURCES = \
ospfclient.c $(libospfapiclient_a_SOURCES)
ospfclient_LDADD = ../ospfd/libospf.a ../lib/libzebra.a

374
ospfclient/Makefile.in Normal file
View file

@ -0,0 +1,374 @@
# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AR = @AR@
BGPD = @BGPD@
CC = @CC@
CPP = @CPP@
CURSES = @CURSES@
IF_METHOD = @IF_METHOD@
IF_PROC = @IF_PROC@
IPFORWARD = @IPFORWARD@
KERNEL_METHOD = @KERNEL_METHOD@
LIBPAM = @LIBPAM@
LIB_IPV6 = @LIB_IPV6@
LIB_REGEX = @LIB_REGEX@
MAKEINFO = @MAKEINFO@
MULTIPATH_NUM = @MULTIPATH_NUM@
OSPF6D = @OSPF6D@
OSPFCLIENT = @OSPFCLIENT@
OSPFD = @OSPFD@
OTHER_METHOD = @OTHER_METHOD@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
RIPD = @RIPD@
RIPNGD = @RIPNGD@
RTREAD_METHOD = @RTREAD_METHOD@
RT_METHOD = @RT_METHOD@
VERSION = @VERSION@
VTYSH = @VTYSH@
ZEBRA = @ZEBRA@
INCLUDES = -I../lib -I../
noinst_LIBRARIES = libospfapiclient.a
sbin_PROGRAMS = ospfclient
libospfapiclient_a_SOURCES = \
ospf_apiclient.c
noinst_HEADERS = \
ospf_apiclient.h
ospfclient_SOURCES = \
ospfclient.c $(libospfapiclient_a_SOURCES)
ospfclient_LDADD = ../ospfd/libospf.a ../lib/libzebra.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I..
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libospfapiclient_a_LIBADD =
libospfapiclient_a_OBJECTS = ospf_apiclient.o
PROGRAMS = $(sbin_PROGRAMS)
ospfclient_OBJECTS = ospfclient.o ospf_apiclient.o
ospfclient_DEPENDENCIES = ../ospfd/libospf.a ../lib/libzebra.a
ospfclient_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
HEADERS = $(noinst_HEADERS)
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
Makefile.in NEWS
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
DEP_FILES = .deps/ospf_apiclient.P .deps/ospfclient.P
SOURCES = $(libospfapiclient_a_SOURCES) $(ospfclient_SOURCES)
OBJECTS = $(libospfapiclient_a_OBJECTS) $(ospfclient_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign ospfclient/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
libospfapiclient.a: $(libospfapiclient_a_OBJECTS) $(libospfapiclient_a_DEPENDENCIES)
-rm -f libospfapiclient.a
$(AR) cru libospfapiclient.a $(libospfapiclient_a_OBJECTS) $(libospfapiclient_a_LIBADD)
$(RANLIB) libospfapiclient.a
mostlyclean-sbinPROGRAMS:
clean-sbinPROGRAMS:
-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
distclean-sbinPROGRAMS:
maintainer-clean-sbinPROGRAMS:
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(sbindir)
@list='$(sbin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
else :; fi; \
done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(sbin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
done
ospfclient: $(ospfclient_OBJECTS) $(ospfclient_DEPENDENCIES)
@rm -f ospfclient
$(LINK) $(ospfclient_LDFLAGS) $(ospfclient_OBJECTS) $(ospfclient_LDADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = ospfclient
distdir: $(DISTFILES)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(top_distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign ospfclient/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-include $(DEP_FILES)
mostlyclean-depend:
clean-depend:
distclean-depend:
-rm -rf .deps
maintainer-clean-depend:
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
%.lo: %.c
@echo '$(LTCOMPILE) -c $<'; \
$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*F).pp > .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm -f .deps/$(*F).pp
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am: install-sbinPROGRAMS
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-sbinPROGRAMS
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(sbindir)
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-sbinPROGRAMS mostlyclean-tags \
mostlyclean-depend mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-sbinPROGRAMS \
clean-tags clean-depend clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-sbinPROGRAMS distclean-tags distclean-depend \
distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-sbinPROGRAMS \
maintainer-clean-tags maintainer-clean-depend \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile mostlyclean-sbinPROGRAMS \
distclean-sbinPROGRAMS clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS \
uninstall-sbinPROGRAMS install-sbinPROGRAMS tags mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir \
mostlyclean-depend distclean-depend clean-depend \
maintainer-clean-depend info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

1
ospfclient/NEWS Normal file
View file

@ -0,0 +1 @@
This file contains news.

4
ospfclient/README Normal file
View file

@ -0,0 +1,4 @@
For more information about this software check out:
http://www.tik.ee.ethz.ch/~keller/ospfapi/

747
ospfclient/ospf_apiclient.c Normal file
View file

@ -0,0 +1,747 @@
/*
* Client side of OSPF API.
* Copyright (C) 2001, 2002, 2003 Ralph Keller
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <zebra.h>
#include "version.h"
#include "getopt.h"
#include "thread.h"
#include "prefix.h"
#include "linklist.h"
#include "if.h"
#include "vector.h"
#include "vty.h"
#include "command.h"
#include "filter.h"
#include "stream.h"
#include "log.h"
#include "memory.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_opaque.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_api.h"
#include "ospf_apiclient.h"
/* Backlog for listen */
#define BACKLOG 5
/* -----------------------------------------------------------
* Forward declarations
* -----------------------------------------------------------
*/
void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient,
struct msg *msg);
void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient,
struct msg *msg);
void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient,
struct msg *msg);
/* -----------------------------------------------------------
* Initialization
* -----------------------------------------------------------
*/
unsigned short
ospf_apiclient_getport (void)
{
struct servent *sp = getservbyname ("ospfapi", "tcp");
return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
}
/* -----------------------------------------------------------
* Followings are functions for connection management
* -----------------------------------------------------------
*/
struct ospf_apiclient *
ospf_apiclient_connect (char *host, int syncport)
{
struct sockaddr_in myaddr_sync;
struct sockaddr_in myaddr_async;
struct sockaddr_in peeraddr;
struct hostent *hp;
struct ospf_apiclient *new;
int size = 0;
int peeraddrlen;
int async_server_sock;
int fd1, fd2;
int ret;
int on = 1;
/* There are two connections between the client and the server.
First the client opens a connection for synchronous requests/replies
to the server. The server will accept this connection and
as a reaction open a reverse connection channel for
asynchronous messages. */
async_server_sock = socket (AF_INET, SOCK_STREAM, 0);
if (async_server_sock < 0)
{
fprintf (stderr,
"ospf_apiclient_connect: creating async socket failed\n");
return NULL;
}
/* Prepare socket for asynchronous messages */
/* Initialize async address structure */
memset (&myaddr_async, 0, sizeof (struct sockaddr_in));
myaddr_async.sin_family = AF_INET;
myaddr_async.sin_addr.s_addr = htonl (INADDR_ANY);
myaddr_async.sin_port = htons (syncport+1);
size = sizeof (struct sockaddr_in);
#ifdef HAVE_SIN_LEN
myaddr_async.sin_len = size;
#endif /* HAVE_SIN_LEN */
/* This is a server socket, reuse addr and port */
ret = setsockopt (async_server_sock, SOL_SOCKET,
SO_REUSEADDR, (void *) &on, sizeof (on));
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
close (async_server_sock);
return NULL;
}
#ifdef SO_REUSEPORT
ret = setsockopt (async_server_sock, SOL_SOCKET, SO_REUSEPORT,
(void *) &on, sizeof (on));
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
close (async_server_sock);
return NULL;
}
#endif /* SO_REUSEPORT */
/* Bind socket to address structure */
ret = bind (async_server_sock, (struct sockaddr *) &myaddr_async, size);
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: bind async socket failed\n");
close (async_server_sock);
return NULL;
}
/* Wait for reverse channel connection establishment from server */
ret = listen (async_server_sock, BACKLOG);
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: listen: %s\n", strerror (errno));
close (async_server_sock);
return NULL;
}
/* Make connection for synchronous requests and connect to server */
/* Resolve address of server */
hp = gethostbyname (host);
if (!hp)
{
fprintf (stderr, "ospf_apiclient_connect: no such host %s\n", host);
close (async_server_sock);
return NULL;
}
fd1 = socket (AF_INET, SOCK_STREAM, 0);
if (fd1 < 0)
{
fprintf (stderr,
"ospf_apiclient_connect: creating sync socket failed\n");
return NULL;
}
/* Reuse addr and port */
ret = setsockopt (fd1, SOL_SOCKET,
SO_REUSEADDR, (void *) &on, sizeof (on));
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
close (fd1);
return NULL;
}
#ifdef SO_REUSEPORT
ret = setsockopt (fd1, SOL_SOCKET, SO_REUSEPORT,
(void *) &on, sizeof (on));
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
close (fd1);
return NULL;
}
#endif /* SO_REUSEPORT */
/* Bind sync socket to address structure. This is needed since we
want the sync port number on a fixed port number. The reverse
async channel will be at this port+1 */
memset (&myaddr_sync, 0, sizeof (struct sockaddr_in));
myaddr_sync.sin_family = AF_INET;
myaddr_sync.sin_port = htons (syncport);
#ifdef HAVE_SIN_LEN
myaddr_sync.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */
ret = bind (fd1, (struct sockaddr *) &myaddr_sync, size);
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: bind sync socket failed\n");
close (fd1);
return NULL;
}
/* Prepare address structure for connect */
memcpy (&myaddr_sync.sin_addr, hp->h_addr, hp->h_length);
myaddr_sync.sin_family = AF_INET;
myaddr_sync.sin_port = htons(ospf_apiclient_getport ());
#ifdef HAVE_SIN_LEN
myaddr_sync.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */
/* Now establish synchronous channel with OSPF daemon */
ret = connect (fd1, (struct sockaddr *) &myaddr_sync,
sizeof (struct sockaddr_in));
if (ret < 0)
{
fprintf (stderr, "ospf_apiclient_connect: sync connect failed\n");
close (async_server_sock);
close (fd1);
return NULL;
}
/* Accept reverse connection */
peeraddrlen = sizeof (struct sockaddr_in);
memset (&peeraddr, 0, peeraddrlen);
fd2 =
accept (async_server_sock, (struct sockaddr *) &peeraddr, &peeraddrlen);
if (fd2 < 0)
{
fprintf (stderr, "ospf_apiclient_connect: accept async failed\n");
close (async_server_sock);
close (fd1);
return NULL;
}
/* Server socket is not needed anymore since we are not accepting more
connections */
close (async_server_sock);
/* Create new client-side instance */
new = XMALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient));
memset (new, 0, sizeof (struct ospf_apiclient));
/* Initialize socket descriptors for sync and async channels */
new->fd_sync = fd1;
new->fd_async = fd2;
return new;
}
int
ospf_apiclient_close (struct ospf_apiclient *oclient)
{
if (oclient->fd_sync >= 0)
{
close (oclient->fd_sync);
}
if (oclient->fd_async >= 0)
{
close (oclient->fd_async);
}
/* Free client structure */
XFREE (MTYPE_OSPF_APICLIENT, oclient);
return 0;
}
/* -----------------------------------------------------------
* Followings are functions to send a request to OSPFd
* -----------------------------------------------------------
*/
/* Send synchronous request, wait for reply */
int
ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg)
{
u_int32_t reqseq;
struct msg_reply *msgreply;
int rc;
/* NB: Given "msg" is freed inside this function. */
/* Remember the sequence number of the request */
reqseq = ntohl (msg->hdr.msgseq);
/* Write message to OSPFd */
rc = msg_write (oclient->fd_sync, msg);
msg_free (msg);
if (rc < 0)
{
return -1;
}
/* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */
msg = msg_read (oclient->fd_sync);
if (!msg)
return -1;
assert (msg->hdr.msgtype == MSG_REPLY);
assert (ntohl (msg->hdr.msgseq) == reqseq);
msgreply = (struct msg_reply *) STREAM_DATA (msg->s);
rc = msgreply->errcode;
msg_free (msg);
return rc;
}
/* -----------------------------------------------------------
* Helper functions
* -----------------------------------------------------------
*/
static u_int32_t
ospf_apiclient_get_seqnr (void)
{
static u_int32_t seqnr = MIN_SEQ;
u_int32_t tmp;
tmp = seqnr;
/* Increment sequence number */
if (seqnr < MAX_SEQ)
{
seqnr++;
}
else
{
seqnr = MIN_SEQ;
}
return tmp;
}
/* -----------------------------------------------------------
* API to access OSPF daemon by client applications.
* -----------------------------------------------------------
*/
/*
* Synchronous request to register opaque type.
*/
int
ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl,
u_char ltype, u_char otype)
{
struct msg *msg;
int rc;
/* just put 1 as a sequence number. */
msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (),
ltype, otype);
if (!msg)
{
fprintf (stderr, "new_msg_register_opaque_type failed\n");
return -1;
}
rc = ospf_apiclient_send_request (cl, msg);
return rc;
}
/*
* Synchronous request to synchronize with OSPF's LSDB.
* Two steps required: register_event in order to get
* dynamic updates and LSDB_Sync.
*/
int
ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient)
{
struct msg *msg;
int rc;
struct lsa_filter_type filter;
filter.typemask = 0xFFFF; /* all LSAs */
filter.origin = ANY_ORIGIN;
filter.num_areas = 0; /* all Areas. */
msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter);
if (!msg)
{
fprintf (stderr, "new_msg_register_event failed\n");
return -1;
}
rc = ospf_apiclient_send_request (oclient, msg);
if (rc != 0)
goto out;
msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter);
if (!msg)
{
fprintf (stderr, "new_msg_sync_lsdb failed\n");
return -1;
}
rc = ospf_apiclient_send_request (oclient, msg);
out:
return rc;
}
/*
* Synchronous request to originate or update an LSA.
*/
int
ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient,
struct in_addr ifaddr,
struct in_addr area_id,
u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id,
void *opaquedata, int opaquelen)
{
struct msg *msg;
int rc;
u_char buf[OSPF_MAX_LSA_SIZE];
struct lsa_header *lsah;
u_int32_t tmp;
/* We can only originate opaque LSAs */
if (!IS_OPAQUE_LSA (lsa_type))
{
fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type);
return OSPF_API_ILLEGALLSATYPE;
}
/* Make a new LSA from parameters */
lsah = (struct lsa_header *) buf;
lsah->ls_age = 0;
lsah->options = 0;
lsah->type = lsa_type;
tmp = SET_OPAQUE_LSID (opaque_type, opaque_id);
lsah->id.s_addr = htonl (tmp);
lsah->adv_router.s_addr = 0;
lsah->ls_seqnum = 0;
lsah->checksum = 0;
lsah->length = htons (sizeof (struct lsa_header) + opaquelen);
memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata,
opaquelen);
msg = new_msg_originate_request (ospf_apiclient_get_seqnr (),
ifaddr, area_id, lsah);
if (!msg)
{
fprintf (stderr, "new_msg_originate_request failed\n");
return OSPF_API_NOMEMORY;
}
rc = ospf_apiclient_send_request (oclient, msg);
return rc;
}
int
ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient,
struct in_addr area_id, u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id)
{
struct msg *msg;
int rc;
/* Only opaque LSA can be deleted */
if (!IS_OPAQUE_LSA (lsa_type))
{
fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type);
return OSPF_API_ILLEGALLSATYPE;
}
/* opaque_id is in host byte order and will be converted
* to network byte order by new_msg_delete_request */
msg = new_msg_delete_request (ospf_apiclient_get_seqnr (),
area_id, lsa_type, opaque_type, opaque_id);
rc = ospf_apiclient_send_request (oclient, msg);
return rc;
}
/* -----------------------------------------------------------
* Followings are handlers for messages from OSPF daemon
* -----------------------------------------------------------
*/
void
ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg)
{
struct msg_ready_notify *r;
r = (struct msg_ready_notify *) STREAM_DATA (msg->s);
/* Invoke registered callback function. */
if (oclient->ready_notify)
{
(oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr);
}
}
void
ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg)
{
struct msg_new_if *n;
n = (struct msg_new_if *) STREAM_DATA (msg->s);
/* Invoke registered callback function. */
if (oclient->new_if)
{
(oclient->new_if) (n->ifaddr, n->area_id);
}
}
void
ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg)
{
struct msg_del_if *d;
d = (struct msg_del_if *) STREAM_DATA (msg->s);
/* Invoke registered callback function. */
if (oclient->del_if)
{
(oclient->del_if) (d->ifaddr);
}
}
void
ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient,
struct msg *msg)
{
struct msg_ism_change *m;
m = (struct msg_ism_change *) STREAM_DATA (msg->s);
/* Invoke registered callback function. */
if (oclient->ism_change)
{
(oclient->ism_change) (m->ifaddr, m->area_id, m->status);
}
}
void
ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient,
struct msg *msg)
{
struct msg_nsm_change *m;
m = (struct msg_nsm_change *) STREAM_DATA (msg->s);
/* Invoke registered callback function. */
if (oclient->nsm_change)
{
(oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status);
}
}
void
ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient,
struct msg *msg)
{
struct msg_lsa_change_notify *cn;
struct lsa_header *lsa;
int lsalen;
cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
/* Extract LSA from message */
lsalen = ntohs (cn->data.length);
lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
if (!lsa)
{
fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n");
return;
}
memcpy (lsa, &(cn->data), lsalen);
/* Invoke registered update callback function */
if (oclient->update_notify)
{
(oclient->update_notify) (cn->ifaddr, cn->area_id,
cn->is_self_originated, lsa);
}
/* free memory allocated by ospf apiclient library */
XFREE (MTYPE_OSPF_APICLIENT, lsa);
}
void
ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient,
struct msg *msg)
{
struct msg_lsa_change_notify *cn;
struct lsa_header *lsa;
int lsalen;
cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
/* Extract LSA from message */
lsalen = ntohs (cn->data.length);
lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
if (!lsa)
{
fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n");
return;
}
memcpy (lsa, &(cn->data), lsalen);
/* Invoke registered update callback function */
if (oclient->delete_notify)
{
(oclient->delete_notify) (cn->ifaddr, cn->area_id,
cn->is_self_originated, lsa);
}
/* free memory allocated by ospf apiclient library */
XFREE (MTYPE_OSPF_APICLIENT, lsa);
}
void
ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg)
{
/* Call message handler function. */
switch (msg->hdr.msgtype)
{
case MSG_READY_NOTIFY:
ospf_apiclient_handle_ready (oclient, msg);
break;
case MSG_NEW_IF:
ospf_apiclient_handle_new_if (oclient, msg);
break;
case MSG_DEL_IF:
ospf_apiclient_handle_del_if (oclient, msg);
break;
case MSG_ISM_CHANGE:
ospf_apiclient_handle_ism_change (oclient, msg);
break;
case MSG_NSM_CHANGE:
ospf_apiclient_handle_nsm_change (oclient, msg);
break;
case MSG_LSA_UPDATE_NOTIFY:
ospf_apiclient_handle_lsa_update (oclient, msg);
break;
case MSG_LSA_DELETE_NOTIFY:
ospf_apiclient_handle_lsa_delete (oclient, msg);
break;
default:
fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n",
msg->hdr.msgtype);
break;
}
}
/* -----------------------------------------------------------
* Callback handler registration
* -----------------------------------------------------------
*/
void
ospf_apiclient_register_callback (struct ospf_apiclient *oclient,
void (*ready_notify) (u_char lsa_type,
u_char opaque_type,
struct in_addr addr),
void (*new_if) (struct in_addr ifaddr,
struct in_addr area_id),
void (*del_if) (struct in_addr ifaddr),
void (*ism_change) (struct in_addr ifaddr,
struct in_addr area_id,
u_char status),
void (*nsm_change) (struct in_addr ifaddr,
struct in_addr nbraddr,
struct in_addr
router_id,
u_char status),
void (*update_notify) (struct in_addr
ifaddr,
struct in_addr
area_id,
u_char self_origin,
struct lsa_header *
lsa),
void (*delete_notify) (struct in_addr
ifaddr,
struct in_addr
area_id,
u_char self_origin,
struct lsa_header *
lsa))
{
assert (oclient);
assert (update_notify);
/* Register callback function */
oclient->ready_notify = ready_notify;
oclient->new_if = new_if;
oclient->del_if = del_if;
oclient->ism_change = ism_change;
oclient->nsm_change = nsm_change;
oclient->update_notify = update_notify;
oclient->delete_notify = delete_notify;
}
/* -----------------------------------------------------------
* Asynchronous message handling
* -----------------------------------------------------------
*/
int
ospf_apiclient_handle_async (struct ospf_apiclient *oclient)
{
struct msg *msg;
/* Get a message */
msg = msg_read (oclient->fd_async);
if (!msg)
{
/* Connection broke down */
return -1;
}
/* Handle message */
ospf_apiclient_msghandle (oclient, msg);
/* Don't forget to free this message */
msg_free (msg);
return 0;
}

135
ospfclient/ospf_apiclient.h Normal file
View file

@ -0,0 +1,135 @@
/*
* Client side of OSPF API.
* Copyright (C) 2001, 2002, 2003 Ralph Keller
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _OSPF_APICLIENT_H
#define _OSPF_APICLIENT_H
#define MTYPE_OSPF_APICLIENT 0
/* Structure for the OSPF API client */
struct ospf_apiclient
{
/* Sockets for sync requests and async notifications */
int fd_sync;
int fd_async;
/* Pointer to callback functions */
void (*ready_notify) (u_char lsa_type, u_char opaque_type,
struct in_addr addr);
void (*new_if) (struct in_addr ifaddr, struct in_addr area_id);
void (*del_if) (struct in_addr ifaddr);
void (*ism_change) (struct in_addr ifaddr, struct in_addr area_id,
u_char status);
void (*nsm_change) (struct in_addr ifaddr, struct in_addr nbraddr,
struct in_addr router_id, u_char status);
void (*update_notify) (struct in_addr ifaddr, struct in_addr area_id,
u_char self_origin,
struct lsa_header * lsa);
void (*delete_notify) (struct in_addr ifaddr, struct in_addr area_id,
u_char self_origin,
struct lsa_header * lsa);
};
/* ---------------------------------------------------------
* API function prototypes.
* --------------------------------------------------------- */
/* Open connection to OSPF daemon. Two ports will be allocated on
client, sync channel at syncport and reverse channel at syncport+1 */
struct ospf_apiclient *ospf_apiclient_connect (char *host, int syncport);
/* Shutdown connection to OSPF daemon. */
int ospf_apiclient_close (struct ospf_apiclient *oclient);
/* Synchronous request to register opaque type. */
int ospf_apiclient_register_opaque_type (struct ospf_apiclient *oclient,
u_char ltype, u_char otype);
/* Synchronous request to register event mask. */
int ospf_apiclient_register_events (struct ospf_apiclient *oclient,
u_int32_t mask);
/* Register callback functions.*/
void ospf_apiclient_register_callback (struct ospf_apiclient *oclient,
void (*ready_notify) (u_char lsa_type,
u_char
opaque_type,
struct in_addr
addr),
void (*new_if) (struct in_addr ifaddr,
struct in_addr
area_id),
void (*del_if) (struct in_addr ifaddr),
void (*ism_change) (struct in_addr
ifaddr,
struct in_addr
area_id,
u_char status),
void (*nsm_change) (struct in_addr
ifaddr,
struct in_addr
nbraddr,
struct in_addr
router_id,
u_char status),
void (*update_notify) (struct in_addr
ifaddr,
struct in_addr
area_id,
u_char selforig,
struct
lsa_header *
lsa),
void (*delete_notify) (struct in_addr
ifaddr,
struct in_addr
area_id,
u_char selforig,
struct
lsa_header *
lsa));
/* Synchronous request to synchronize LSDB. */
int ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient);
/* Synchronous request to originate or update opaque LSA. */
int
ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
struct in_addr ifaddr,
struct in_addr area_id,
u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id,
void *opaquedata, int opaquelen);
/* Synchronous request to delete opaque LSA. Parameter opaque_id is in
host byte order */
int ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient,
struct in_addr area_id, u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id);
/* Fetch async message and handle it */
int ospf_apiclient_handle_async (struct ospf_apiclient *oclient);
#endif /* _OSPF_APICLIENT_H */

291
ospfclient/ospfclient.c Normal file
View file

@ -0,0 +1,291 @@
/*
* Simple main program to demonstrate how OSPF API can be used.
*/
/* The following includes are needed in all OSPF API client
applications */
#include <zebra.h>
#include "prefix.h" /* for ospf_asbr.h */
#include "ospfd/ospfd.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_opaque.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_api.h"
#include "ospf_apiclient.h"
/* The following includes are specific to this main application. Here
main uses the thread functionality from libzebra (however an
application can use any thread library like pthreads) */
#include "thread.h"
#include "log.h"
/* local portnumber for async channel */
#define ASYNCPORT 4000
/* Master thread */
struct thread_master *master;
/* Global variables */
struct ospf_apiclient *oclient;
char **args;
/* Our opaque LSAs have the following format */
struct my_opaque_lsa
{
struct lsa_header hdr;
u_char data[4];
};
/* ---------------------------------------------------------
* Threads for asynchronous messages and LSA update/delete
* ---------------------------------------------------------
*/
int
lsa_delete (struct thread *t)
{
struct ospf_apiclient *oclient;
struct in_addr area_id;
int rc;
oclient = THREAD_ARG (t);
inet_aton (args[6], &area_id);
printf ("Deleting LSA... ");
rc = ospf_apiclient_lsa_delete (oclient,
area_id,
atoi (args[2]), /* lsa type */
atoi (args[3]), /* opaque type */
atoi (args[4])); /* opaque ID */
printf ("done, return code is = %d\n", rc);
return rc;
}
int
lsa_inject (struct thread *t)
{
struct ospf_apiclient *cl;
struct in_addr ifaddr;
struct in_addr area_id;
u_char lsa_type;
u_char opaque_type;
u_int32_t opaque_id;
void *opaquedata;
int opaquelen;
static u_int32_t counter = 1; /* Incremented each time */
int rc;
cl = THREAD_ARG (t);
inet_aton (args[5], &ifaddr);
inet_aton (args[6], &area_id);
lsa_type = atoi (args[2]);
opaque_type = atoi (args[3]);
opaque_id = atoi (args[4]);
opaquedata = &counter;
opaquelen = sizeof (u_int32_t);
printf ("Originating/updating LSA with counter=%d... ", counter);
rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
lsa_type,
opaque_type, opaque_id,
opaquedata, opaquelen);
printf ("done, return code is %d\n", rc);
counter++;
return 0;
};
/* This thread handles asynchronous messages coming in from the OSPF
API server */
int
lsa_read (struct thread *thread)
{
struct ospf_apiclient *oclient;
int fd;
int ret;
printf ("lsa_read called\n");
oclient = THREAD_ARG (thread);
fd = THREAD_FD (thread);
/* Handle asynchronous message */
ret = ospf_apiclient_handle_async (oclient);
if (ret < 0) {
printf ("Connection closed, exiting...");
exit(0);
}
/* Reschedule read thread */
thread_add_read (master, lsa_read, oclient, fd);
return 0;
}
/* ---------------------------------------------------------
* Callback functions for asynchronous events
* ---------------------------------------------------------
*/
void
lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char is_self_originated,
struct lsa_header *lsa)
{
printf ("lsa_update_callback: ");
printf ("ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area: %s\n", inet_ntoa (area_id));
printf ("is_self_origin: %u\n", is_self_originated);
ospf_lsa_header_dump (lsa);
}
void
lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char is_self_originated,
struct lsa_header *lsa)
{
printf ("lsa_delete_callback: ");
printf ("ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area: %s\n", inet_ntoa (area_id));
printf ("is_self_origin: %u\n", is_self_originated);
ospf_lsa_header_dump (lsa);
}
void
ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
{
printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
lsa_type, opaque_type, inet_ntoa (addr));
/* Schedule opaque LSA originate in 5 secs */
thread_add_timer (master, lsa_inject, oclient, 5);
/* Schedule opaque LSA update with new value */
thread_add_timer (master, lsa_inject, oclient, 10);
/* Schedule delete */
thread_add_timer (master, lsa_delete, oclient, 30);
}
void
new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
{
printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area_id: %s\n", inet_ntoa (area_id));
}
void
del_if_callback (struct in_addr ifaddr)
{
printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
}
void
ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char state)
{
printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area_id: %s\n", inet_ntoa (area_id));
printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
}
void
nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
struct in_addr router_id, u_char state)
{
printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
printf ("router_id: %s\n", inet_ntoa (router_id));
printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
}
/* ---------------------------------------------------------
* Main program
* ---------------------------------------------------------
*/
int
main (int argc, char *argv[])
{
struct thread thread;
args = argv;
/* Main should be started with the following arguments:
*
* (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
* (6) area_id
*
* host: name or IP of host where ospfd is running
* lsa_type: 9, 10, or 11
* opaque_type: 0-255 (e.g., 140 for experimental Active Networking)
* opaque_id: arbitrary application instance (24 bits)
* if_addr: interface IP address (for type 9) otherwise ignored
* area_id: area in IP address format (for type 10) otherwise ignored
*/
if (argc != 7)
{
printf ("main: wrong number of arguments!\n");
exit (1);
}
/* Initialization */
master = thread_master_create ();
/* Open connection to OSPF daemon */
oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
if (!oclient)
{
printf ("main: connect failed!\n");
exit (1);
}
/* Register callback functions. */
ospf_apiclient_register_callback (oclient,
ready_callback,
new_if_callback,
del_if_callback,
ism_change_callback,
nsm_change_callback,
lsa_update_callback,
lsa_delete_callback);
/* Register LSA type and opaque type. */
ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
atoi (args[3]));
/* Synchronize database with OSPF daemon. */
ospf_apiclient_sync_lsdb (oclient);
/* Schedule thread that handles asynchronous messages */
thread_add_read (master, lsa_read, oclient, oclient->fd_async);
/* Now connection is established, run loop */
while (1)
{
thread_fetch (master, &thread);
thread_call (&thread);
}
/* Never reached */
return 0;
}

647
ospfd/ospf_api.c Normal file
View file

@ -0,0 +1,647 @@
/*
* API message handling module for OSPF daemon and client.
* Copyright (C) 2001, 2002 Ralph Keller
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <zebra.h>
#ifdef SUPPORT_OSPF_API
#ifndef HAVE_OPAQUE_LSA
#error "Core Opaque-LSA module must be configured."
#endif /* HAVE_OPAQUE_LSA */
#include "linklist.h"
#include "prefix.h"
#include "if.h"
#include "table.h"
#include "memory.h"
#include "command.h"
#include "vty.h"
#include "stream.h"
#include "log.h"
#include "thread.h"
#include "hash.h"
#include "sockunion.h" /* for inet_aton() */
#include "buffer.h"
#include "network.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_packet.h"
#include "ospfd/ospf_spf.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_ase.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_api.h"
/* For debugging only, will be removed */
void
api_opaque_lsa_print (struct lsa_header *data)
{
struct opaque_lsa
{
struct lsa_header header;
u_char mydata[0];
};
struct opaque_lsa *olsa;
int opaquelen;
int i;
ospf_lsa_header_dump (data);
olsa = (struct opaque_lsa *) data;
opaquelen = ntohs (data->length) - OSPF_LSA_HEADER_SIZE;
zlog_warn ("apiserver_lsa_print: opaquelen=%d\n", opaquelen);
for (i = 0; i < opaquelen; i++)
{
zlog_warn ("0x%x ", olsa->mydata[i]);
}
zlog_warn ("\n");
}
/* -----------------------------------------------------------
* Generic messages
* -----------------------------------------------------------
*/
struct msg *
msg_new (u_char msgtype, void *msgbody, u_int32_t seqnum, u_int16_t msglen)
{
struct msg *new;
new = XMALLOC (MTYPE_OSPF_API_MSG, sizeof (struct msg));
memset (new, 0, sizeof (struct msg));
new->hdr.version = OSPF_API_VERSION;
new->hdr.msgtype = msgtype;
new->hdr.msglen = htons (msglen);
new->hdr.msgseq = htonl (seqnum);
new->s = stream_new (msglen);
assert (new->s);
stream_put (new->s, msgbody, msglen);
return new;
}
/* Duplicate a message by copying content. */
struct msg *
msg_dup (struct msg *msg)
{
struct msg *new;
assert (msg);
new = msg_new (msg->hdr.msgtype, STREAM_DATA (msg->s),
ntohl (msg->hdr.msgseq), ntohs (msg->hdr.msglen));
return new;
}
/* XXX only for testing, will be removed */
struct nametab {
int value;
const char *name;
};
const char *
ospf_api_typename (int msgtype)
{
struct nametab NameTab[] = {
{ MSG_REGISTER_OPAQUETYPE, "Register opaque-type", },
{ MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type", },
{ MSG_REGISTER_EVENT, "Register event", },
{ MSG_SYNC_LSDB, "Sync LSDB", },
{ MSG_ORIGINATE_REQUEST, "Originate request", },
{ MSG_DELETE_REQUEST, "Delete request", },
{ MSG_REPLY, "Reply", },
{ MSG_READY_NOTIFY, "Ready notify", },
{ MSG_LSA_UPDATE_NOTIFY, "LSA update notify", },
{ MSG_LSA_DELETE_NOTIFY, "LSA delete notify", },
{ MSG_NEW_IF, "New interface", },
{ MSG_DEL_IF, "Del interface", },
{ MSG_ISM_CHANGE, "ISM change", },
{ MSG_NSM_CHANGE, "NSM change", },
};
int i, n = sizeof (NameTab) / sizeof (NameTab[0]);
const char *name = NULL;
for (i = 0; i < n; i++)
{
if (NameTab[i].value == msgtype)
{
name = NameTab[i].name;
break;
}
}
return name ? name : "?";
}
const char *
ospf_api_errname (int errcode)
{
struct nametab NameTab[] = {
{ OSPF_API_OK, "OK", },
{ OSPF_API_NOSUCHINTERFACE, "No such interface", },
{ OSPF_API_NOSUCHAREA, "No such area", },
{ OSPF_API_NOSUCHLSA, "No such LSA", },
{ OSPF_API_ILLEGALLSATYPE, "Illegal LSA type", },
{ OSPF_API_OPAQUETYPEINUSE, "Opaque type in use", },
{ OSPF_API_OPAQUETYPENOTREGISTERED, "Opaque type not registered", },
{ OSPF_API_NOTREADY, "Not ready", },
{ OSPF_API_NOMEMORY, "No memory", },
{ OSPF_API_ERROR, "Other error", },
{ OSPF_API_UNDEF, "Undefined", },
};
int i, n = sizeof (NameTab) / sizeof (NameTab[0]);
const char *name = NULL;
for (i = 0; i < n; i++)
{
if (NameTab[i].value == errcode)
{
name = NameTab[i].name;
break;
}
}
return name ? name : "?";
}
void
msg_print (struct msg *msg)
{
if (!msg)
{
zlog_warn ("msg_print msg=NULL!\n");
return;
}
#ifdef ORIGINAL_CODING
zlog_warn
("msg=%p msgtype=%d msglen=%d msgseq=%d streamdata=%p streamsize=%lu\n",
msg, msg->hdr.msgtype, ntohs (msg->hdr.msglen), ntohl (msg->hdr.msgseq),
STREAM_DATA (msg->s), STREAM_SIZE (msg->s));
#else /* ORIGINAL_CODING */
/* API message common header part. */
zlog_info
("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%lu)",
ospf_api_typename (msg->hdr.msgtype), msg->hdr.msgtype,
ntohs (msg->hdr.msglen), (unsigned long) ntohl (msg->hdr.msgseq),
STREAM_DATA (msg->s), STREAM_SIZE (msg->s));
/* API message body part. */
#ifdef ndef
/* Generic Hex/Ascii dump */
DumpBuf (STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); /* Sorry, deleted! */
#else /* ndef */
/* Message-type dependent dump function. */
#endif /* ndef */
return;
#endif /* ORIGINAL_CODING */
}
void
msg_free (struct msg *msg)
{
if (msg->s)
stream_free (msg->s);
XFREE (MTYPE_OSPF_API_MSG, msg);
}
/* Set sequence number of message */
void
msg_set_seq (struct msg *msg, u_int32_t seqnr)
{
assert (msg);
msg->hdr.msgseq = htonl (seqnr);
}
/* Get sequence number of message */
u_int32_t
msg_get_seq (struct msg *msg)
{
assert (msg);
return ntohl (msg->hdr.msgseq);
}
/* -----------------------------------------------------------
* Message fifo queues
* -----------------------------------------------------------
*/
struct msg_fifo *
msg_fifo_new ()
{
struct msg_fifo *new;
new = XMALLOC (MTYPE_OSPF_API_FIFO, sizeof (struct msg_fifo));
memset (new, 0, sizeof (struct msg_fifo));
return new;
}
/* Add new message to fifo. */
void
msg_fifo_push (struct msg_fifo *fifo, struct msg *msg)
{
if (fifo->tail)
fifo->tail->next = msg;
else
fifo->head = msg;
fifo->tail = msg;
fifo->count++;
}
/* Remove first message from fifo. */
struct msg *
msg_fifo_pop (struct msg_fifo *fifo)
{
struct msg *msg;
msg = fifo->head;
if (msg)
{
fifo->head = msg->next;
if (fifo->head == NULL)
fifo->tail = NULL;
fifo->count--;
}
return msg;
}
/* Return first fifo entry but do not remove it. */
struct msg *
msg_fifo_head (struct msg_fifo *fifo)
{
return fifo->head;
}
/* Flush message fifo. */
void
msg_fifo_flush (struct msg_fifo *fifo)
{
struct msg *op;
struct msg *next;
for (op = fifo->head; op; op = next)
{
next = op->next;
msg_free (op);
}
fifo->head = fifo->tail = NULL;
fifo->count = 0;
}
/* Free API message fifo. */
void
msg_fifo_free (struct msg_fifo *fifo)
{
msg_fifo_flush (fifo);
XFREE (MTYPE_OSPF_API_FIFO, fifo);
}
struct msg *
msg_read (int fd)
{
struct msg *msg;
struct apimsghdr hdr;
char buf[OSPF_API_MAX_MSG_SIZE];
int bodylen;
int rlen;
/* Read message header */
rlen = readn (fd, (char *) &hdr, sizeof (struct apimsghdr));
if (rlen < 0)
{
zlog_warn ("msg_read: readn %s", strerror (errno));
return NULL;
}
else if (rlen == 0)
{
zlog_warn ("msg_read: Connection closed by peer");
return NULL;
}
else if (rlen != sizeof (struct apimsghdr))
{
zlog_warn ("msg_read: Cannot read message header!");
return NULL;
}
/* Check version of API protocol */
if (hdr.version != OSPF_API_VERSION)
{
zlog_warn ("msg_read: OSPF API protocol version mismatch");
return NULL;
}
/* Determine body length. */
bodylen = ntohs (hdr.msglen);
if (bodylen > 0)
{
/* Read message body */
rlen = readn (fd, buf, bodylen);
if (rlen < 0)
{
zlog_warn ("msg_read: readn %s", strerror (errno));
return NULL;
}
else if (rlen == 0)
{
zlog_warn ("msg_read: Connection closed by peer");
return NULL;
}
else if (rlen != bodylen)
{
zlog_warn ("msg_read: Cannot read message body!");
return NULL;
}
}
/* Allocate new message */
msg = msg_new (hdr.msgtype, buf, ntohl (hdr.msgseq), ntohs (hdr.msglen));
return msg;
}
int
msg_write (int fd, struct msg *msg)
{
u_char buf[OSPF_API_MAX_MSG_SIZE];
int l;
int wlen;
assert (msg);
assert (msg->s);
/* Length of message including header */
l = sizeof (struct apimsghdr) + ntohs (msg->hdr.msglen);
/* Make contiguous memory buffer for message */
memcpy (buf, &msg->hdr, sizeof (struct apimsghdr));
memcpy (buf + sizeof (struct apimsghdr), STREAM_DATA (msg->s),
ntohs (msg->hdr.msglen));
wlen = writen (fd, buf, l);
if (wlen < 0)
{
zlog_warn ("msg_write: writen %s", strerror (errno));
return -1;
}
else if (wlen == 0)
{
zlog_warn ("msg_write: Connection closed by peer");
return -1;
}
else if (wlen != l)
{
zlog_warn ("msg_write: Cannot write API message");
return -1;
}
return 0;
}
/* -----------------------------------------------------------
* Specific messages
* -----------------------------------------------------------
*/
struct msg *
new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype, u_char otype)
{
struct msg_register_opaque_type rmsg;
rmsg.lsatype = ltype;
rmsg.opaquetype = otype;
memset (&rmsg.pad, 0, sizeof (rmsg.pad));
return msg_new (MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum,
sizeof (struct msg_register_opaque_type));
}
struct msg *
new_msg_register_event (u_int32_t seqnum, struct lsa_filter_type *filter)
{
u_char buf[OSPF_API_MAX_MSG_SIZE];
struct msg_register_event *emsg;
int len;
emsg = (struct msg_register_event *) buf;
len = sizeof (struct msg_register_event) +
filter->num_areas * sizeof (struct in_addr);
emsg->filter.typemask = htons (filter->typemask);
emsg->filter.origin = filter->origin;
emsg->filter.num_areas = filter->num_areas;
return msg_new (MSG_REGISTER_EVENT, emsg, seqnum, len);
}
struct msg *
new_msg_sync_lsdb (u_int32_t seqnum, struct lsa_filter_type *filter)
{
u_char buf[OSPF_API_MAX_MSG_SIZE];
struct msg_sync_lsdb *smsg;
int len;
smsg = (struct msg_sync_lsdb *) buf;
len = sizeof (struct msg_sync_lsdb) +
filter->num_areas * sizeof (struct in_addr);
smsg->filter.typemask = htons (filter->typemask);
smsg->filter.origin = filter->origin;
smsg->filter.num_areas = filter->num_areas;
return msg_new (MSG_SYNC_LSDB, smsg, seqnum, len);
}
struct msg *
new_msg_originate_request (u_int32_t seqnum,
struct in_addr ifaddr,
struct in_addr area_id, struct lsa_header *data)
{
struct msg_originate_request *omsg;
int omsglen;
char buf[OSPF_API_MAX_MSG_SIZE];
omsglen = sizeof (struct msg_originate_request) - sizeof (struct lsa_header)
+ ntohs (data->length);
omsg = (struct msg_originate_request *) buf;
omsg->ifaddr = ifaddr;
omsg->area_id = area_id;
memcpy (&omsg->data, data, ntohs (data->length));
return msg_new (MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen);
}
struct msg *
new_msg_delete_request (u_int32_t seqnum,
struct in_addr area_id, u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id)
{
struct msg_delete_request dmsg;
dmsg.area_id = area_id;
dmsg.lsa_type = lsa_type;
dmsg.opaque_type = opaque_type;
dmsg.opaque_id = htonl (opaque_id);
memset (&dmsg.pad, 0, sizeof (dmsg.pad));
return msg_new (MSG_DELETE_REQUEST, &dmsg, seqnum,
sizeof (struct msg_delete_request));
}
struct msg *
new_msg_reply (u_int32_t seqnr, u_char rc)
{
struct msg *msg;
struct msg_reply rmsg;
/* Set return code */
rmsg.errcode = rc;
memset (&rmsg.pad, 0, sizeof (rmsg.pad));
msg = msg_new (MSG_REPLY, &rmsg, seqnr, sizeof (struct msg_reply));
return msg;
}
struct msg *
new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type,
u_char opaque_type, struct in_addr addr)
{
struct msg_ready_notify rmsg;
rmsg.lsa_type = lsa_type;
rmsg.opaque_type = opaque_type;
memset (&rmsg.pad, 0, sizeof (rmsg.pad));
rmsg.addr = addr;
return msg_new (MSG_READY_NOTIFY, &rmsg, seqnr,
sizeof (struct msg_ready_notify));
}
struct msg *
new_msg_new_if (u_int32_t seqnr,
struct in_addr ifaddr, struct in_addr area_id)
{
struct msg_new_if nmsg;
nmsg.ifaddr = ifaddr;
nmsg.area_id = area_id;
return msg_new (MSG_NEW_IF, &nmsg, seqnr, sizeof (struct msg_new_if));
}
struct msg *
new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr)
{
struct msg_del_if dmsg;
dmsg.ifaddr = ifaddr;
return msg_new (MSG_DEL_IF, &dmsg, seqnr, sizeof (struct msg_del_if));
}
struct msg *
new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr,
struct in_addr area_id, u_char status)
{
struct msg_ism_change imsg;
imsg.ifaddr = ifaddr;
imsg.area_id = area_id;
imsg.status = status;
memset (&imsg.pad, 0, sizeof (imsg.pad));
return msg_new (MSG_ISM_CHANGE, &imsg, seqnr,
sizeof (struct msg_ism_change));
}
struct msg *
new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr,
struct in_addr nbraddr,
struct in_addr router_id, u_char status)
{
struct msg_nsm_change nmsg;
nmsg.ifaddr = ifaddr;
nmsg.nbraddr = nbraddr;
nmsg.router_id = router_id;
nmsg.status = status;
memset (&nmsg.pad, 0, sizeof (nmsg.pad));
return msg_new (MSG_NSM_CHANGE, &nmsg, seqnr,
sizeof (struct msg_nsm_change));
}
struct msg *
new_msg_lsa_change_notify (u_char msgtype,
u_int32_t seqnum,
struct in_addr ifaddr,
struct in_addr area_id,
u_char is_self_originated, struct lsa_header *data)
{
u_char buf[OSPF_API_MAX_MSG_SIZE];
struct msg_lsa_change_notify *nmsg;
int len;
assert (data);
nmsg = (struct msg_lsa_change_notify *) buf;
len = ntohs (data->length) + sizeof (struct msg_lsa_change_notify)
- sizeof (struct lsa_header);
nmsg->ifaddr = ifaddr;
nmsg->area_id = area_id;
nmsg->is_self_originated = is_self_originated;
memset (&nmsg->pad, 0, sizeof (nmsg->pad));
memcpy (&nmsg->data, data, ntohs (data->length));
return msg_new (msgtype, nmsg, seqnum, len);
}
#endif /* SUPPORT_OSPF_API */

357
ospfd/ospf_api.h Normal file
View file

@ -0,0 +1,357 @@
/*
* API message handling module for OSPF daemon and client.
* Copyright (C) 2001, 2002 Ralph Keller
*
* 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.
*/
/* This file is used both by the OSPFd and client applications to
define message formats used for communication. */
#ifndef _OSPF_API_H
#define _OSPF_API_H
#define OSPF_API_VERSION 1
/* MTYPE definition is not reflected to "memory.h". */
#define MTYPE_OSPF_API_MSG MTYPE_TMP
#define MTYPE_OSPF_API_FIFO MTYPE_TMP
/* Default API server port to accept connection request from client-side. */
/* This value could be overridden by "ospfapi" entry in "/etc/services". */
#define OSPF_API_SYNC_PORT 2607
/* -----------------------------------------------------------
* Generic messages
* -----------------------------------------------------------
*/
/* Message header structure, fields are in network byte order and
aligned to four octets. */
struct apimsghdr
{
u_char version; /* OSPF API protocol version */
u_char msgtype; /* Type of message */
u_int16_t msglen; /* Length of message w/o header */
u_int32_t msgseq; /* Sequence number */
};
/* Message representation with header and body */
struct msg
{
struct msg *next; /* to link into fifo */
/* Message header */
struct apimsghdr hdr;
/* Message body */
struct stream *s;
};
/* Prototypes for generic messages. */
struct msg *msg_new (u_char msgtype, void *msgbody,
u_int32_t seqnum, u_int16_t msglen);
struct msg *msg_dup (struct msg *msg);
void msg_print (struct msg *msg); /* XXX debug only */
void msg_free (struct msg *msg);
struct msg *msg_read (int fd);
int msg_write (int fd, struct msg *msg);
/* For requests, the message sequence number is between MIN_SEQ and
MAX_SEQ. For notifications, the sequence number is 0. */
#define MIN_SEQ 1
#define MAX_SEQ 2147483647
void msg_set_seq (struct msg *msg, u_int32_t seqnr);
u_int32_t msg_get_seq (struct msg *msg);
/* -----------------------------------------------------------
* Message fifo queues
* -----------------------------------------------------------
*/
/* Message queue structure. */
struct msg_fifo
{
unsigned long count;
struct msg *head;
struct msg *tail;
};
/* Prototype for message fifo queues. */
struct msg_fifo *msg_fifo_new ();
void msg_fifo_push (struct msg_fifo *, struct msg *msg);
struct msg *msg_fifo_pop (struct msg_fifo *fifo);
struct msg *msg_fifo_head (struct msg_fifo *fifo);
void msg_fifo_flush (struct msg_fifo *fifo);
void msg_fifo_free (struct msg_fifo *fifo);
/* -----------------------------------------------------------
* Specific message type and format definitions
* -----------------------------------------------------------
*/
/* Messages to OSPF daemon. */
#define MSG_REGISTER_OPAQUETYPE 1
#define MSG_UNREGISTER_OPAQUETYPE 2
#define MSG_REGISTER_EVENT 3
#define MSG_SYNC_LSDB 4
#define MSG_ORIGINATE_REQUEST 5
#define MSG_DELETE_REQUEST 6
/* Messages from OSPF daemon. */
#define MSG_REPLY 10
#define MSG_READY_NOTIFY 11
#define MSG_LSA_UPDATE_NOTIFY 12
#define MSG_LSA_DELETE_NOTIFY 13
#define MSG_NEW_IF 14
#define MSG_DEL_IF 15
#define MSG_ISM_CHANGE 16
#define MSG_NSM_CHANGE 17
struct msg_register_opaque_type
{
u_char lsatype;
u_char opaquetype;
u_char pad[2]; /* padding */
};
struct msg_unregister_opaque_type
{
u_char lsatype;
u_char opaquetype;
u_char pad[2]; /* padding */
};
/* Power2 is needed to convert LSA types into bit positions,
* see typemask below. Type definition starts at 1, so
* Power2[0] is not used. */
#ifdef ORIGINAL_CODING
static const u_int16_t
Power2[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000
};
#else
static const u_int16_t
Power2[] = { 0, (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4),
(1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9),
(1 << 10), (1 << 11), (1 << 12), (1 << 13), (1 << 14),
(1 << 15)
};
#endif /* ORIGINAL_CODING */
struct lsa_filter_type
{
u_int16_t typemask; /* bitmask for selecting LSA types (1..16) */
u_char origin; /* selects according to origin. */
#define NON_SELF_ORIGINATED 0
#define SELF_ORIGINATED (OSPF_LSA_SELF)
#define ANY_ORIGIN 2
u_char num_areas; /* number of areas in the filter. */
/* areas, if any, go here. */
};
struct msg_register_event
{
struct lsa_filter_type filter;
};
struct msg_sync_lsdb
{
struct lsa_filter_type filter;
};
struct msg_originate_request
{
/* Used for LSA type 9 otherwise ignored */
struct in_addr ifaddr;
/* Used for LSA type 10 otherwise ignored */
struct in_addr area_id;
/* LSA header and LSA-specific part */
struct lsa_header data;
};
struct msg_delete_request
{
struct in_addr area_id; /* "0.0.0.0" for AS-external opaque LSAs */
u_char lsa_type;
u_char opaque_type;
u_char pad[2]; /* padding */
u_int32_t opaque_id;
};
struct msg_reply
{
char errcode;
#define OSPF_API_OK 0
#define OSPF_API_NOSUCHINTERFACE (-1)
#define OSPF_API_NOSUCHAREA (-2)
#define OSPF_API_NOSUCHLSA (-3)
#define OSPF_API_ILLEGALLSATYPE (-4)
#define OSPF_API_OPAQUETYPEINUSE (-5)
#define OSPF_API_OPAQUETYPENOTREGISTERED (-6)
#define OSPF_API_NOTREADY (-7)
#define OSPF_API_NOMEMORY (-8)
#define OSPF_API_ERROR (-9)
#define OSPF_API_UNDEF (-10)
u_char pad[3]; /* padding to four byte alignment */
};
/* Message to tell client application that it ospf daemon is
* ready to accept opaque LSAs for a given interface or area. */
struct msg_ready_notify
{
u_char lsa_type;
u_char opaque_type;
u_char pad[2]; /* padding */
struct in_addr addr; /* interface address or area address */
};
/* These messages have a dynamic length depending on the embodied LSA.
They are aligned to four octets. msg_lsa_change_notify is used for
both LSA update and LSAs delete. */
struct msg_lsa_change_notify
{
/* Used for LSA type 9 otherwise ignored */
struct in_addr ifaddr;
/* Area ID. Not valid for AS-External and Opaque11 LSAs. */
struct in_addr area_id;
u_char is_self_originated; /* 1 if self originated. */
u_char pad[3];
struct lsa_header data;
};
struct msg_new_if
{
struct in_addr ifaddr; /* interface IP address */
struct in_addr area_id; /* area this interface belongs to */
};
struct msg_del_if
{
struct in_addr ifaddr; /* interface IP address */
};
struct msg_ism_change
{
struct in_addr ifaddr; /* interface IP address */
struct in_addr area_id; /* area this interface belongs to */
u_char status; /* interface status (up/down) */
u_char pad[3]; /* not used */
};
struct msg_nsm_change
{
struct in_addr ifaddr; /* attached interface */
struct in_addr nbraddr; /* Neighbor interface address */
struct in_addr router_id; /* Router ID of neighbor */
u_char status; /* NSM status */
u_char pad[3];
};
/* We make use of a union to define a structure that covers all
possible API messages. This allows us to find out how much memory
needs to be reserved for the largest API message. */
struct apimsg
{
struct apimsghdr hdr;
union
{
struct msg_register_opaque_type register_opaque_type;
struct msg_register_event register_event;
struct msg_sync_lsdb sync_lsdb;
struct msg_originate_request originate_request;
struct msg_delete_request delete_request;
struct msg_reply reply;
struct msg_ready_notify ready_notify;
struct msg_new_if new_if;
struct msg_del_if del_if;
struct msg_ism_change ism_change;
struct msg_nsm_change nsm_change;
struct msg_lsa_change_notify lsa_change_notify;
}
u;
};
#define OSPF_API_MAX_MSG_SIZE (sizeof(struct apimsg) + OSPF_MAX_LSA_SIZE)
/* -----------------------------------------------------------
* Prototypes for specific messages
* -----------------------------------------------------------
*/
/* For debugging only. */
void api_opaque_lsa_print (struct lsa_header *data);
/* Messages sent by client */
struct msg *new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype,
u_char otype);
struct msg *new_msg_register_event (u_int32_t seqnum,
struct lsa_filter_type *filter);
struct msg *new_msg_sync_lsdb (u_int32_t seqnum,
struct lsa_filter_type *filter);
struct msg *new_msg_originate_request (u_int32_t seqnum,
struct in_addr ifaddr,
struct in_addr area_id,
struct lsa_header *data);
struct msg *new_msg_delete_request (u_int32_t seqnum,
struct in_addr area_id,
u_char lsa_type,
u_char opaque_type, u_int32_t opaque_id);
/* Messages sent by OSPF daemon */
struct msg *new_msg_reply (u_int32_t seqnum, u_char rc);
struct msg *new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type,
u_char opaque_type, struct in_addr addr);
struct msg *new_msg_new_if (u_int32_t seqnr,
struct in_addr ifaddr, struct in_addr area);
struct msg *new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr);
struct msg *new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr,
struct in_addr area, u_char status);
struct msg *new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr,
struct in_addr nbraddr,
struct in_addr router_id, u_char status);
/* msgtype is MSG_LSA_UPDATE_NOTIFY or MSG_LSA_DELETE_NOTIFY */
struct msg *new_msg_lsa_change_notify (u_char msgtype,
u_int32_t seqnum,
struct in_addr ifaddr,
struct in_addr area_id,
u_char is_self_originated,
struct lsa_header *data);
/* string printing functions */
const char *ospf_api_errname (int errcode);
const char *ospf_api_typename (int msgtype);
#endif /* _OSPF_API_H */

2647
ospfd/ospf_apiserver.c Normal file

File diff suppressed because it is too large Load diff

201
ospfd/ospf_apiserver.h Normal file
View file

@ -0,0 +1,201 @@
/*
* Server side of OSPF API.
* Copyright (C) 2001, 2002 Ralph Keller
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _OSPF_APISERVER_H
#define _OSPF_APISERVER_H
/* MTYPE definition is not reflected to "memory.h". */
#define MTYPE_OSPF_APISERVER MTYPE_TMP
#define MTYPE_OSPF_APISERVER_MSGFILTER MTYPE_TMP
/* List of opaque types that application registered */
struct registered_opaque_type
{
u_char lsa_type;
u_char opaque_type;
};
/* Server instance for each accepted client connection. */
struct ospf_apiserver
{
/* Socket connections for synchronous commands and asynchronous
notifications */
int fd_sync; /* synchronous requests */
struct sockaddr_in peer_sync;
int fd_async; /* asynchronous notifications */
struct sockaddr_in peer_async;
/* List of all opaque types that application registers to use. Using
a single connection with the OSPF daemon, multiple
<lsa,opaque_type> pairs can be registered. However, each
combination can only be registered once by all applications. */
list opaque_types; /* of type registered_opaque_type */
/* Temporary storage for LSA instances to be refreshed. */
struct ospf_lsdb reserve;
/* filter for LSA update/delete notifies */
struct lsa_filter_type *filter;
/* Fifo buffers for outgoing messages */
struct msg_fifo *out_sync_fifo;
struct msg_fifo *out_async_fifo;
/* Read and write threads */
struct thread *t_sync_read;
#ifdef USE_ASYNC_READ
struct thread *t_async_read;
#endif /* USE_ASYNC_READ */
struct thread *t_sync_write;
struct thread *t_async_write;
};
enum event
{
OSPF_APISERVER_ACCEPT,
OSPF_APISERVER_SYNC_READ,
#ifdef USE_ASYNC_READ
OSPF_APISERVER_ASYNC_READ,
#endif /* USE_ASYNC_READ */
OSPF_APISERVER_SYNC_WRITE,
OSPF_APISERVER_ASYNC_WRITE
};
/* -----------------------------------------------------------
* Followings are functions to manage client connections.
* -----------------------------------------------------------
*/
unsigned short ospf_apiserver_getport (void);
int ospf_apiserver_init (void);
void ospf_apiserver_term (void);
struct ospf_apiserver *ospf_apiserver_new (int fd_sync, int fd_async);
void ospf_apiserver_free (struct ospf_apiserver *apiserv);
void ospf_apiserver_event (enum event event, int fd,
struct ospf_apiserver *apiserv);
int ospf_apiserver_serv_sock_family (unsigned short port, int family);
int ospf_apiserver_accept (struct thread *thread);
int ospf_apiserver_read (struct thread *thread);
int ospf_apiserver_sync_write (struct thread *thread);
int ospf_apiserver_async_write (struct thread *thread);
int ospf_apiserver_send_reply (struct ospf_apiserver *apiserv,
u_int32_t seqnr, u_char rc);
/* -----------------------------------------------------------
* Followings are message handler functions
* -----------------------------------------------------------
*/
int ospf_apiserver_lsa9_originator (void *arg);
int ospf_apiserver_lsa10_originator (void *arg);
int ospf_apiserver_lsa11_originator (void *arg);
void ospf_apiserver_clients_notify_all (struct msg *msg);
void ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi);
void ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area);
void ospf_apiserver_clients_notify_ready_type11 (struct ospf *top);
void ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi);
void ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi);
void ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi);
void ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr);
int ospf_apiserver_is_ready_type9 (struct ospf_interface *oi);
int ospf_apiserver_is_ready_type10 (struct ospf_area *area);
int ospf_apiserver_is_ready_type11 (struct ospf *ospf);
void ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv);
void ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv);
void ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv);
int ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv,
struct msg *msg);
int ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver
*apiserv, struct msg *msg);
int ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver
*apiserv, struct msg *msg);
int ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv,
struct msg *msg);
int ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv,
struct msg *msg);
int ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv,
struct msg *msg);
int ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv,
struct msg *msg);
/* -----------------------------------------------------------
* Followings are functions for LSA origination/deletion
* -----------------------------------------------------------
*/
int ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserver,
u_char lsa_type, u_char opaque_type);
int ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserver,
u_char lsa_type,
u_char opaque_type);
struct ospf_lsa *ospf_apiserver_opaque_lsa_new (struct ospf_area *area,
struct ospf_interface *oi,
struct lsa_header *protolsa);
struct ospf_interface *ospf_apiserver_if_lookup_by_addr (struct in_addr
address);
struct ospf_interface *ospf_apiserver_if_lookup_by_ifp (struct interface
*ifp);
int ospf_apiserver_originate1 (struct ospf_lsa *lsa);
void ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa);
/* -----------------------------------------------------------
* Followings are callback functions to handle opaque types
* -----------------------------------------------------------
*/
int ospf_apiserver_new_if (struct interface *ifp);
int ospf_apiserver_del_if (struct interface *ifp);
void ospf_apiserver_ism_change (struct ospf_interface *oi, int old_status);
void ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status);
void ospf_apiserver_config_write_router (struct vty *vty);
void ospf_apiserver_config_write_if (struct vty *vty, struct interface *ifp);
void ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa);
int ospf_ospf_apiserver_lsa_originator (void *arg);
void ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa);
void ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv,
u_char lsa_type, u_char opaque_type);
/* -----------------------------------------------------------
* Followings are hooks when LSAs are updated or deleted
* -----------------------------------------------------------
*/
/* Hooks that are invoked from ospf opaque module */
int ospf_apiserver_lsa_update (struct ospf_lsa *lsa);
int ospf_apiserver_lsa_delete (struct ospf_lsa *lsa);
void ospf_apiserver_clients_lsa_change_notify (u_char msgtype,
struct ospf_lsa *lsa);
#endif /* _OSPF_APISERVER_H */