Initial import

This commit is contained in:
Thomas Graf 2007-09-15 01:28:01 +02:00
commit 44d362409d
188 changed files with 44556 additions and 0 deletions

461
COPYING Normal file
View file

@ -0,0 +1,461 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
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 and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, 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 library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete 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 distribute a copy of this License along with the
Library.
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 Library or any portion
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
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 Library, 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 Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you 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.
If distribution of 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 satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be 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.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library 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.
9. 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 Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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 with
this License.
11. 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 Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library 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 Library.
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.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library 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.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser 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 Library
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 Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
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
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "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
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. 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 LIBRARY 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
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

333
ChangeLog Normal file
View file

@ -0,0 +1,333 @@
Summary of Changes from 1.0-pre6 to HEAD
================================================
Thomas Graf <tgraf@suug.ch>
o Generic netlink support
o Route Addition/Deletion
o Added nl_cache_subset()
o Have nl_object_clone() make real clones without
sharing any data.
o Remove old nl_object_alloc() not based on a object
operations to avoid bugs due to missing init.
o Added nl-list-caches utility
o Removed nlmsg_build_no_hdr(), duplicate
o Reworked message interface
o Fixed nlmsg_put() and genlmsg_put() to correctly reserve
tail room for user specific headers.
o Added nl_cache_move()
o Renamed nl_cache_delete() to nl_cache_remove() (no API break)
o Fixed reference counting while objects stay in caches.
o Object marking
o Moved attribute mask for objects into generic structure
o nl-list-caches: List available dump procedures
o Use PAGE_SIZE as initial buffer size when reading from
netlink socket
o Double buffer size when recv() returns MSG_TRUNC
o Replaced filter object operation with new compare operation
capable of listing differences between two objects
o Added nl_object_identical() to check if two objects are
identical from a uniqueness point of view
o Added nl_object_diff() returning a bitmask of differences in
attributes
o Added nl_object_attr_list() generating a list of attribute
name the object has assigned
o Cache updates based on event notifications, code based on
Patrick McHardy's patches
o Cache Manager
o Added NL_AUTO_PID, NL_AUTO_SEQ for convenience
o Disable MSG_PEEK by default and provide nl_socket_enable_msg_peek()
o Fixed nl_recvmsgs() to return 0 when interrupted via NL_STOP or
NL_SKIP
o Fixed nl_recvmsgs() to stop reading after parsing if not in the
middle of a multipart message.
o Fixed nl_recvmsgs() to not stop after receving an ACK
o Fixed nl_recvmsgs() to not blindly discard remaining messages
if a NLMSG_DONE message is received.
Petr Gotthard <petr.gotthard@siemens.com>
Siemens AG Oesterreich
o Fix u32 to properly handle multiple keys
o rtnl_htb_set_(r|c)buffer()
o Fixed MTU handling in HTB class, problem pointed out
by Edouard Thuleau
Zilvinas Valinskas <zilvinas@wilibox.com>
o Fix wrong msg_namelen in nl_recv()
o Fix memory leak in flnl_request_put()
Helmut Schaa <hschaa@suse.de>
o Fix for using libnl from within C++
Patrick McHardy <kaber@trash.net>
o *_alloc_cache(): Only refill cache if handle is provided
James Oakley <jfunk@funktronics.ca>
o Fix rtnl_link_set_arptype() typo
Philip Craig <philipc@snapgear.com>
o Change address family type from char to int
o Fix the error handling when the build fails.
o add nl_cache_mngr_get_fd()
o add netfilter support
o add netfilter conntrack support
o add netfilter log support
Summary of Changes from 1.0-pre5 to 1.0-pre6
================================================
Christopher Aillon <caillon@redhat.com>
o Use $(libdir) instead of $(prefix)/lib for 64bit awesomeness.
Thomas Graf <tgraf@suug.ch>
o Extend nl_msg to include source address, destination address
and the protocol being used.
o Make nl_send*() take a nl_msg instead of a nlmsghdr (API BREAK)
o Change callbacks to take a nl_msg instead of source address
and nlmsghdr (API BREAK)
o caches must specify the protocol they're hooked up from now on
if they intend to be associated with message types.
o cache_mngt_associate now takes the protocol besides the message
type to allow for multiple protocols to be supported (API BREAK)
o overwrite destination address in nl_send() when specified in the
message itself, allows for unbound addressing.
o Support for netlink based fib_lookup()
o Documentation fixes
o Fix double nlmsg_free() in nl_recvmsgs() while receiving
a multipart message and the read was interrupted.
o Change cache operations to store names for message types.
o Provide interface to convert message type to character string.
o Add dp_dump_msgtype to prefix each dumped element with a
pretty printed message type.
o netlink fib lookup support
o nl_recvmsgs() debugging
o use nl_cachemngt_type2name() when pretty printing netlink header
o Routing protocol translations.
o Routing metric translations.
o Revised route dumping
o Nexthop flag translations.
o Add support for IFF_DORMANT
Petr Gotthard <petr.gotthard@siemens.com>
Siemens AG Oesterreich
o Fix access to obj after freeing it
o Fix u32 selector access after realloc()
o Fix missing out-of-memory error handling in various places
o Enhance nl-monitor to have group selection selectable and
demonstrate usage of select()
o Don't ignore IFF_RUNNING any longer
o fw classifier support
Patrick McHardy <kaber@trash.net>
o Fix conflicting types for __u64
o Fix printf format string warnings
o Fix object cloning
o Deal with structure padding in nl_object_clone
o Fix nl_addr leak
o Set ce_msgtype in all parsed objects
o Fix addr flag filter
o Fix RTNLGRP definitions (was based on broken kernel version)
o Export nl_get_errno()
o Add function to get/set peer pid
o Add IFF_LOWER_UP
o Add/export some missing accessor functions
o print /0 prefix in nl_addr2str()
o Fix invalid free in nl_addr_parse for AF_UNSPEC addresses
o Use __str2flags instead of __str2type in rtnl_link_str2flags()
o Make sure object and filter types match in nl_object_match()
o Add support for credential passing over netlink sockets (API BREAK)
o Add support for custom dump callbacks
o Add NL_DUMP_ENV format
Michael Biebl <biebl@teco.edu>
"Alex V. Myltsev" <avm@altlinux.ru>
o Makefile fixes
Summary of Changes from 1.0-pre4 to 1.0-pre5
================================================
Thomas Graf <tgraf@suug.ch>
o Use minimized local copies for <linux/if.h>, <linux/if_arp.h>,
and <linux/if_ether.h> to avoid compile troubles with
applications including <net/if*.h>
Reported by Christopher Aillon.
Summary of Changes from 1.0-pre3 to 1.0-pre4
================================================
Thomas Graf <tgraf@suug.ch>
o Fix wrong rtnl_addr_set_prefixlen() external declaration,
reported by Dan Williams.
o Fix nl_addr_parse() to not change the original string
for prefixes.
o Do not build documentation per default, but have the user
issue 'make gendoc'
o Assume neighbours to be permanent, set NUD_PERMANENT if not
specified otherwise.
Summary of Changes from 1.0-pre2 to 1.0-pre3
================================================
Thomas Graf <tgraf@suug.ch>
o Fix SFQ parser to allocate qdisc options.
o Fix rule statistics dumping to not call itself.
o Complete Netem qdisc interface.
o Add rtnl_*_put() and rtnl_*_free() to increase readability.
o Cleanup of nl-* tools
o Fix inclusion guards of route/neightbl.h
o Fix nl_connect() to only modify rx/tx socket buffers if not
already modified by the user.
o Fix wrong nl_handle_alloc() prototype.
o Fix typo in route/addr.c causing label to be marked as
local address.
o Use ~0UL as default prefix length instead of 0.
o Fix neighbour message parser to correctly store core.
attributes and provide them again.
o Fix neighbour message parser to correctly guess address family.
to make it compatible with nl_addr_parse() and ether llc
addresses.
o Add rtnl_route_table2str(), rtnl_route_str2table().
o Add nl_cache_nitems_filter() to find out if a filter produces
any matches.
o Remove rtnl_rule_set_(dst|src)_str() (obsolete).
o Remove scope and protocol field of routing rule.
o Complete routing rules module.
o Move realms translations from route to rtnl module.
Summary of Changes from 1.0-pre1 to 1.0-pre2
================================================
Thomas Graf <tgraf@suug.ch>
o More API documentation
o Added flags argument to rtnl_addr_(add|build_add_request)().
o Added rtnl_addr_(set|get)_multicast().
o Moved scope translations routines from route/route.c to
route/rtnl.c, required by other modules as well.
o Removed old rtattr bits from rtnetlink-kernel.h
o Customized libnl.css for doxygen documentation
o Removed non-reentrant translation routines, only bloating
the code and too risky.
o Fixed wrong version number from 1.0-pre1.
o Reenabled unfinished policer module.
o Reworked TBF module, automatic caluclation of transmit times,
limit setable via latency, automatic cell size calculation,
options TLV generation. (untested)
o Renamed nl_xmittime() to rtnl_tc_calc_txtime().
o Renamde nl_build_rtable() to rtnl_tc_build_rate_table()
Petr Gotthard <petr.gotthard@siemens.com>,
Siemens AG Oesterreich
o Fix symlinks to libnl library files to be moveable
o Fix extern struct prototypes meant to be static.
o Add empty install target to src/Makefile
Simon Stelling <blubb@gentoo.org>
o Use LIBDIR instead of $(prefix)/lib for users to alllow librariers
into $(prefix)/lib64.
Summary of Changes from 0.5.0 to 1.0-pre1
================================================
Thomas Graf <tgraf@suug.ch>
o Uncountable number of changes, rewrite of certain modules,
several major API breakages
Petr Gotthard <petr.gotthard@siemens.com>,
Siemens AG Oesterreich
o added class_build, rtnl_class_build_add_request, rtnl_class_add
o added HTB (Hierachical Token Bucket) class support
o added nl_xmittime, nl_build_rtable
o added nl_data_append to realloc a nl_data structure
o added rtnl_rcopy_ratespec as reverse to rtnl_copy_ratespec
o fixed byte order conversion of rtnl_filter.protocol
o SuSE and Fedora Linux compile fixes
o fixed u32 classifier support
o added rtnl_u32_set_handle, rtnl_u32_set_classid, rtnl_u32_set_flags
and several rtnl_u32_add_key_... operations to u32 classifier
Summary of Changes from 0.4.4 to 0.5.0
================================================
Thomas Graf <tgraf@suug.ch>
o API documentation
o nl_cache_filter to manually filter on a object
o partial routing support
o routing rules support
o Propely set address family when setting addresses
o debug flag and some rare messages, more to come
o make error mesage verboseness configureable
o tc fixes to wait for ack
o cleanup and adaption of address code to latest internal API
o various cleanups
o dozens of API breakages (better now than later)
Daniel Hottinger <hotti@hotti.ch>
o arch 64bit printf length modifier fixes
Baruch Even <baruch@ev-en.org>,
Mediatrix Telecom, inc. <ericb@mediatrix.com>
o address support
Summary of changes from 0.4.3 to 0.4.4
================================================
Thomas Graf <tgraf@suug.ch>:
o overall cleanups for better code quality
o replace dump_(brief|full|with_stats) ops with
dump[NL_DUMP_MAX] array to allow further additions without
breaking the ABI.
o add of send_ack callback, called whenever when oppenent
asks for an ACK.
o make nl_parse_rtattr initialize the tb buffer like in the
kernel, caller must no longer take care of it.
o remove nl_addrnattr (obsolete)
o fixed nl_msg_append_raw to correctly calculate length
for raw data not aligned to NLMSG_ALIGN
o fix memory leak in nl_recv in case of errors
o correctly check sequence numbers if more than one message
was sent out before the answer is being received.
o add workaround for buggy netlink applications not properly
setting NLM_F_MULTI.
Summary of changes from 0.4.2 to 0.4.3
================================================
Thomas Graf <tgraf@suug.ch>:
o use parser_param in nl_cache_parse
o EGP: dump nfilters attribute
o allow retrieving of filters attached to classes via
FILTER_CACHE_PARENT(C) cache argument
o filter message building API
Summary of changes from 0.4.1 to 0.4.2
================================================
Baruch Even <baruch@ev-en.org>:
o memory leak fix in nl_parse_rtattr
o reset padding to 0 when appending raw data to a nl_msg
o avoid overwriting nlmsg ptr when buffer extending fails
o typo fixes
o create symlinks libnl.so.0 and libnl.so
Thomas Graf <tgraf@suug.ch>:
o EGP classifier support
o avoid null pointer in printf call
o added nl_cache_parse to put nl_msg's into a cache
o added rtnl_filter_build to build a nl_msg filter message
o correctly install header files
o nl_msg_payload/nl_msg_payloadlen to access nl_msg payload
o nl_parse_nested macro to simplify nested TLV parsing
o NL_ERROR_ASSERT compile flag to assert(0) on errors
o rta alignment fix in nl_msg_append_tlv
o added nl_msg_parse_rtattr as shortcut for nl_parse_rtattr
for nl_msg API
o added nl_parse_nested for nested TLVs
o added RTA_ARRAY_ELEMS macro to calculate array length
for array TLVs
o added nl_wait_for_ack to wait for the next ack
o added rtnl_link_build_change_request(...)
o added rtnl_neigh_build_*_request
o converted neighbour code to use nl_wait_for_ack
o cb_recvmsgs_ow callback to overwrite internal calls to
nl_recvmsgs_def
o cb_seq_check callback to overwrite default sequence checking
o added nl_parser_param as argument for message parsers including
a callback to be called upon successful parsing of a message.
Removes the requirement of having all parsed messages to be added
to a cache.
o added cb_recv_ow and nl_send_ow callbacks to overwrite internal
calls to nl_recv and nl_send.
Jamal Hadi Salim <hadi@cyberus.ca>
o Linux 2.4 compile fixes

64
Makefile Normal file
View file

@ -0,0 +1,64 @@
#
# Makefile
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
ifeq ($(shell [ ! -r Makefile.opts ] && echo 1),)
include Makefile.opts
endif
SUBDIRS := lib include doc src tests
.PHONY: all clean distclean install gendoc $(SUBDIRS)
all: Makefile.opts
@for dir in $(SUBDIRS); do \
echo "Entering $$dir" && $(MAKE) -C $$dir || exit $$?; \
done
clean: Makefile.opts
rm -f cscope.*
@for dir in $(SUBDIRS); do \
echo "Entering $$dir" && $(MAKE) -C $$dir clean || exit $$?; \
done
distclean: clean
@$(RM) -rf Makefile.opts autom4te.cache config.log config.status
@for dir in $(SUBDIRS); do \
echo "Entering $$dir" && $(MAKE) -C $$dir distclean || exit $$?; \
done
install: Makefile.opts
@for dir in $(SUBDIRS); do \
echo "Entering $$dir" && cd $$dir && $(MAKE) install && cd ..; \
done
mkdir -p $(DESTDIR)$(libdir)/pkgconfig/
install -m 0644 libnl-1.pc $(DESTDIR)$(libdir)/pkgconfig/
gendoc:
$(MAKE) -C doc gendoc
show: Makefile.opts
@echo "CC: $(CC)"
@echo "RM: $(RM)"
@echo "CFLAGS: $(CFLAGS)"
@echo "DEPFLAGS: $(DEPFLAGS)"
@echo "LDFLAGS: $(LDFLAGS)"
@echo "DESTDIR: $(DESTDIR)"
@echo "prefix: $(prefix)"
@echo "libdir: $(libdir)"
@echo "includedir: $(includedir)"
cscope:
cscope -b -q -R -Iinclude -slib -ssrc
$(SUBDIRS):
cd $@ && $(MAKE)
-include Makefile.rules

39
Makefile.opts.in Normal file
View file

@ -0,0 +1,39 @@
#
# Makefile.opts.in
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
CC := @CC@
CFLAGS := @CFLAGS@
LDFLAGS := @LDFLAGS@
CPPFLAGS := @CPPFLAGS@
PACKAGE_NAME := @PACKAGE_NAME@
PACKAGE_VERSION := @PACKAGE_VERSION@
LIBNL_LIB := @LIBNL_LIB@
prefix := @prefix@
exec_prefix := @exec_prefix@
libdir := @libdir@
includedir := @includedir@
mandir := @mandir@
sysconfdir := @sysconfdir@
AR := ar
RM := rm
LN := ln
DEPFLAGS += -M -I../include/ -I. $(CPPFLAGS)
CFLAGS += -g -I./include -I../include -I. $(CPPFLAGS) -D_GNU_SOURCE
MAKEFLAGS += --no-print-directory
ifeq ($(CC),gcc)
CFLAGS += -Wall -ggdb
endif

37
Makefile.rules Normal file
View file

@ -0,0 +1,37 @@
#
# Makefile.rules
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
.SUFFIXES:
.SUFFIXES: .d .c
%.o: %.c
@echo " CC $<"; \
$(CC) $(CFLAGS) -c -o $@ $<
%.d: %.c
@echo " DEP $<"; \
$(CC) $(DEPFLAGS) $< > $@.tmp; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.tmp > $@; \
rm -f $@.tmp
Makefile.opts:
@echo "***"
@echo "*** No configuration found, please run ./configure"
@echo "***"
@exit 1
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
ifneq ($(DEPS),)
-include $(DEPS)
endif
endif
endif

831
aclocal.m4 vendored Normal file
View file

@ -0,0 +1,831 @@
dnl aclocal.m4 generated automatically by aclocal 1.4-p6
dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# lib-prefix.m4 serial 4 (gettext-0.14.2)
dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
dnl require excessive bracketing.
ifdef([AC_HELP_STRING],
[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
dnl to access previously installed libraries. The basic assumption is that
dnl a user will want packages to use other packages he previously installed
dnl with the same --prefix option.
dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
dnl libraries, but is otherwise very convenient.
AC_DEFUN([AC_LIB_PREFIX],
[
AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
dnl By default, look in $includedir and $libdir.
use_additional=yes
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
AC_LIB_ARG_WITH([lib-prefix],
[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
--without-lib-prefix don't search for libraries in includedir and libdir],
[
if test "X$withval" = "Xno"; then
use_additional=no
else
if test "X$withval" = "X"; then
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
else
additional_includedir="$withval/include"
additional_libdir="$withval/lib"
fi
fi
])
if test $use_additional = yes; then
dnl Potentially add $additional_includedir to $CPPFLAGS.
dnl But don't add it
dnl 1. if it's the standard /usr/include,
dnl 2. if it's already present in $CPPFLAGS,
dnl 3. if it's /usr/local/include and we are using GCC on Linux,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_includedir" != "X/usr/include"; then
haveit=
for x in $CPPFLAGS; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-I$additional_includedir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test "X$additional_includedir" = "X/usr/local/include"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
if test -d "$additional_includedir"; then
dnl Really add $additional_includedir to $CPPFLAGS.
CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
fi
fi
fi
fi
dnl Potentially add $additional_libdir to $LDFLAGS.
dnl But don't add it
dnl 1. if it's the standard /usr/lib,
dnl 2. if it's already present in $LDFLAGS,
dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_libdir" != "X/usr/lib"; then
haveit=
for x in $LDFLAGS; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test "X$additional_libdir" = "X/usr/local/lib"; then
if test -n "$GCC"; then
case $host_os in
linux*) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LDFLAGS.
LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
fi
fi
fi
fi
fi
])
dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
dnl acl_final_exec_prefix, containing the values to which $prefix and
dnl $exec_prefix will expand at the end of the configure script.
AC_DEFUN([AC_LIB_PREPARE_PREFIX],
[
dnl Unfortunately, prefix and exec_prefix get only finally determined
dnl at the end of configure.
if test "X$prefix" = "XNONE"; then
acl_final_prefix="$ac_default_prefix"
else
acl_final_prefix="$prefix"
fi
if test "X$exec_prefix" = "XNONE"; then
acl_final_exec_prefix='${prefix}'
else
acl_final_exec_prefix="$exec_prefix"
fi
acl_save_prefix="$prefix"
prefix="$acl_final_prefix"
eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
prefix="$acl_save_prefix"
])
dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
dnl variables prefix and exec_prefix bound to the values they will have
dnl at the end of the configure script.
AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
[
acl_save_prefix="$prefix"
prefix="$acl_final_prefix"
acl_save_exec_prefix="$exec_prefix"
exec_prefix="$acl_final_exec_prefix"
$1
exec_prefix="$acl_save_exec_prefix"
prefix="$acl_save_prefix"
])
# lib-link.m4 serial 6 (gettext-0.14.3)
dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
AC_PREREQ(2.50)
dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
dnl the libraries corresponding to explicit and implicit dependencies.
dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
dnl augments the CPPFLAGS variable.
AC_DEFUN([AC_LIB_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
define([Name],[translit([$1],[./-], [___])])
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
AC_LIB_LINKFLAGS_BODY([$1], [$2])
ac_cv_lib[]Name[]_libs="$LIB[]NAME"
ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
])
LIB[]NAME="$ac_cv_lib[]Name[]_libs"
LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
dnl results of this search when this library appears as a dependency.
HAVE_LIB[]NAME=yes
undefine([Name])
undefine([NAME])
])
dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
dnl searches for libname and the libraries corresponding to explicit and
dnl implicit dependencies, together with the specified include files and
dnl the ability to compile and link the specified testcode. If found, it
dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
define([Name],[translit([$1],[./-], [___])])
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
dnl accordingly.
AC_LIB_LINKFLAGS_BODY([$1], [$2])
dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
dnl because if the user has installed lib[]Name and not disabled its use
dnl via --without-lib[]Name-prefix, he wants to use it.
ac_save_CPPFLAGS="$CPPFLAGS"
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
ac_save_LIBS="$LIBS"
LIBS="$LIBS $LIB[]NAME"
AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
LIBS="$ac_save_LIBS"
])
if test "$ac_cv_lib[]Name" = yes; then
HAVE_LIB[]NAME=yes
AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
AC_MSG_CHECKING([how to link with lib[]$1])
AC_MSG_RESULT([$LIB[]NAME])
else
HAVE_LIB[]NAME=no
dnl If $LIB[]NAME didn't lead to a usable library, we don't need
dnl $INC[]NAME either.
CPPFLAGS="$ac_save_CPPFLAGS"
LIB[]NAME=
LTLIB[]NAME=
fi
AC_SUBST([HAVE_LIB]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
undefine([Name])
undefine([NAME])
])
dnl Determine the platform dependent parameters needed to use rpath:
dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator,
dnl hardcode_direct, hardcode_minus_L.
AC_DEFUN([AC_LIB_RPATH],
[
dnl Tell automake >= 1.10 to complain if config.rpath is missing.
m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
. ./conftest.sh
rm -f ./conftest.sh
acl_cv_rpath=done
])
wl="$acl_cv_wl"
libext="$acl_cv_libext"
shlibext="$acl_cv_shlibext"
hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
hardcode_direct="$acl_cv_hardcode_direct"
hardcode_minus_L="$acl_cv_hardcode_minus_L"
dnl Determine whether the user wants rpath handling at all.
AC_ARG_ENABLE(rpath,
[ --disable-rpath do not hardcode runtime library paths],
:, enable_rpath=yes)
])
dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
dnl the libraries corresponding to explicit and implicit dependencies.
dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
[
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
dnl By default, look in $includedir and $libdir.
use_additional=yes
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
AC_LIB_ARG_WITH([lib$1-prefix],
[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
--without-lib$1-prefix don't search for lib$1 in includedir and libdir],
[
if test "X$withval" = "Xno"; then
use_additional=no
else
if test "X$withval" = "X"; then
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
else
additional_includedir="$withval/include"
additional_libdir="$withval/lib"
fi
fi
])
dnl Search the library and its dependencies in $additional_libdir and
dnl $LDFLAGS. Using breadth-first-seach.
LIB[]NAME=
LTLIB[]NAME=
INC[]NAME=
rpathdirs=
ltrpathdirs=
names_already_handled=
names_next_round='$1 $2'
while test -n "$names_next_round"; do
names_this_round="$names_next_round"
names_next_round=
for name in $names_this_round; do
already_handled=
for n in $names_already_handled; do
if test "$n" = "$name"; then
already_handled=yes
break
fi
done
if test -z "$already_handled"; then
names_already_handled="$names_already_handled $name"
dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
dnl or AC_LIB_HAVE_LINKFLAGS call.
uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
eval value=\"\$HAVE_LIB$uppername\"
if test -n "$value"; then
if test "$value" = yes; then
eval value=\"\$LIB$uppername\"
test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
eval value=\"\$LTLIB$uppername\"
test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
else
dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
dnl that this library doesn't exist. So just drop it.
:
fi
else
dnl Search the library lib$name in $additional_libdir and $LDFLAGS
dnl and the already constructed $LIBNAME/$LTLIBNAME.
found_dir=
found_la=
found_so=
found_a=
if test $use_additional = yes; then
if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
found_dir="$additional_libdir"
found_so="$additional_libdir/lib$name.$shlibext"
if test -f "$additional_libdir/lib$name.la"; then
found_la="$additional_libdir/lib$name.la"
fi
else
if test -f "$additional_libdir/lib$name.$libext"; then
found_dir="$additional_libdir"
found_a="$additional_libdir/lib$name.$libext"
if test -f "$additional_libdir/lib$name.la"; then
found_la="$additional_libdir/lib$name.la"
fi
fi
fi
fi
if test "X$found_dir" = "X"; then
for x in $LDFLAGS $LTLIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
case "$x" in
-L*)
dir=`echo "X$x" | sed -e 's/^X-L//'`
if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
found_dir="$dir"
found_so="$dir/lib$name.$shlibext"
if test -f "$dir/lib$name.la"; then
found_la="$dir/lib$name.la"
fi
else
if test -f "$dir/lib$name.$libext"; then
found_dir="$dir"
found_a="$dir/lib$name.$libext"
if test -f "$dir/lib$name.la"; then
found_la="$dir/lib$name.la"
fi
fi
fi
;;
esac
if test "X$found_dir" != "X"; then
break
fi
done
fi
if test "X$found_dir" != "X"; then
dnl Found the library.
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
if test "X$found_so" != "X"; then
dnl Linking with a shared library. We attempt to hardcode its
dnl directory into the executable's runpath, unless it's the
dnl standard /usr/lib.
if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
dnl No hardcoding is needed.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
dnl Use an explicit option to hardcode DIR into the resulting
dnl binary.
dnl Potentially add DIR to ltrpathdirs.
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
haveit=
for x in $ltrpathdirs; do
if test "X$x" = "X$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
ltrpathdirs="$ltrpathdirs $found_dir"
fi
dnl The hardcoding into $LIBNAME is system dependent.
if test "$hardcode_direct" = yes; then
dnl Using DIR/libNAME.so during linking hardcodes DIR into the
dnl resulting binary.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
dnl Use an explicit option to hardcode DIR into the resulting
dnl binary.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
dnl Potentially add DIR to rpathdirs.
dnl The rpathdirs will be appended to $LIBNAME at the end.
haveit=
for x in $rpathdirs; do
if test "X$x" = "X$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
rpathdirs="$rpathdirs $found_dir"
fi
else
dnl Rely on "-L$found_dir".
dnl But don't add it if it's already contained in the LDFLAGS
dnl or the already constructed $LIBNAME
haveit=
for x in $LDFLAGS $LIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
fi
if test "$hardcode_minus_L" != no; then
dnl FIXME: Not sure whether we should use
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
dnl here.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH
dnl here, because this doesn't fit in flags passed to the
dnl compiler. So give up. No hardcoding. This affects only
dnl very old systems.
dnl FIXME: Not sure whether we should use
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
dnl here.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
fi
fi
fi
fi
else
if test "X$found_a" != "X"; then
dnl Linking with a static library.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
else
dnl We shouldn't come here, but anyway it's good to have a
dnl fallback.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
fi
fi
dnl Assume the include files are nearby.
additional_includedir=
case "$found_dir" in
*/lib | */lib/)
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
additional_includedir="$basedir/include"
;;
esac
if test "X$additional_includedir" != "X"; then
dnl Potentially add $additional_includedir to $INCNAME.
dnl But don't add it
dnl 1. if it's the standard /usr/include,
dnl 2. if it's /usr/local/include and we are using GCC on Linux,
dnl 3. if it's already present in $CPPFLAGS or the already
dnl constructed $INCNAME,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_includedir" != "X/usr/include"; then
haveit=
if test "X$additional_includedir" = "X/usr/local/include"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
for x in $CPPFLAGS $INC[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-I$additional_includedir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_includedir"; then
dnl Really add $additional_includedir to $INCNAME.
INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
fi
fi
fi
fi
fi
dnl Look for dependencies.
if test -n "$found_la"; then
dnl Read the .la file. It defines the variables
dnl dlname, library_names, old_library, dependency_libs, current,
dnl age, revision, installed, dlopen, dlpreopen, libdir.
save_libdir="$libdir"
case "$found_la" in
*/* | *\\*) . "$found_la" ;;
*) . "./$found_la" ;;
esac
libdir="$save_libdir"
dnl We use only dependency_libs.
for dep in $dependency_libs; do
case "$dep" in
-L*)
additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
dnl But don't add it
dnl 1. if it's the standard /usr/lib,
dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
dnl 3. if it's already present in $LDFLAGS or the already
dnl constructed $LIBNAME,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_libdir" != "X/usr/lib"; then
haveit=
if test "X$additional_libdir" = "X/usr/local/lib"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
haveit=
for x in $LDFLAGS $LIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LIBNAME.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
fi
fi
haveit=
for x in $LDFLAGS $LTLIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LTLIBNAME.
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
fi
fi
fi
fi
;;
-R*)
dir=`echo "X$dep" | sed -e 's/^X-R//'`
if test "$enable_rpath" != no; then
dnl Potentially add DIR to rpathdirs.
dnl The rpathdirs will be appended to $LIBNAME at the end.
haveit=
for x in $rpathdirs; do
if test "X$x" = "X$dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
rpathdirs="$rpathdirs $dir"
fi
dnl Potentially add DIR to ltrpathdirs.
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
haveit=
for x in $ltrpathdirs; do
if test "X$x" = "X$dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
ltrpathdirs="$ltrpathdirs $dir"
fi
fi
;;
-l*)
dnl Handle this in the next round.
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
;;
*.la)
dnl Handle this in the next round. Throw away the .la's
dnl directory; it is already contained in a preceding -L
dnl option.
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
;;
*)
dnl Most likely an immediate library name.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
;;
esac
done
fi
else
dnl Didn't find the library; assume it is in the system directories
dnl known to the linker and runtime loader. (All the system
dnl directories known to the linker should also be known to the
dnl runtime loader, otherwise the system is severely misconfigured.)
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
fi
fi
fi
done
done
if test "X$rpathdirs" != "X"; then
if test -n "$hardcode_libdir_separator"; then
dnl Weird platform: only the last -rpath option counts, the user must
dnl pass all path elements in one option. We can arrange that for a
dnl single library, but not when more than one $LIBNAMEs are used.
alldirs=
for found_dir in $rpathdirs; do
alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
done
dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl.
acl_save_libdir="$libdir"
libdir="$alldirs"
eval flag=\"$hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
else
dnl The -rpath options are cumulative.
for found_dir in $rpathdirs; do
acl_save_libdir="$libdir"
libdir="$found_dir"
eval flag=\"$hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
done
fi
fi
if test "X$ltrpathdirs" != "X"; then
dnl When using libtool, the option that works for both libraries and
dnl executables is -R. The -R options are cumulative.
for found_dir in $ltrpathdirs; do
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
done
fi
])
dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
dnl unless already present in VAR.
dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
dnl contains two or three consecutive elements that belong together.
AC_DEFUN([AC_LIB_APPENDTOVAR],
[
for element in [$2]; do
haveit=
for x in $[$1]; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X$element"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
[$1]="${[$1]}${[$1]:+ }$element"
fi
done
])
# lib-ld.m4 serial 3 (gettext-0.13)
dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl Subroutines of libtool.m4,
dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
dnl with libtool.m4.
dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
AC_DEFUN([AC_LIB_PROG_LD_GNU],
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
case `$LD -v 2>&1 </dev/null` in
*GNU* | *'with BFD'*)
acl_cv_prog_gnu_ld=yes ;;
*)
acl_cv_prog_gnu_ld=no ;;
esac])
with_gnu_ld=$acl_cv_prog_gnu_ld
])
dnl From libtool-1.4. Sets the variable LD.
AC_DEFUN([AC_LIB_PROG_LD],
[AC_ARG_WITH(gnu-ld,
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
# Prepare PATH_SEPARATOR.
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
echo "#! /bin/sh" >conf$$.sh
echo "exit 0" >>conf$$.sh
chmod +x conf$$.sh
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
PATH_SEPARATOR=';'
else
PATH_SEPARATOR=:
fi
rm -f conf$$.sh
fi
ac_prog=ld
if test "$GCC" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by GCC])
case $host in
*-*-mingw*)
# gcc leaves a trailing carriage return which upsets mingw
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
*)
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
esac
case $ac_prog in
# Accept absolute paths.
[[\\/]* | [A-Za-z]:[\\/]*)]
[re_direlt='/[^/][^/]*/\.\./']
# Canonicalize the path of ld
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
done
test -z "$LD" && LD="$ac_prog"
;;
"")
# If it fails, then pretend we aren't using GCC.
ac_prog=ld
;;
*)
# If it is relative, then search for the first ld in PATH.
with_gnu_ld=unknown
;;
esac
elif test "$with_gnu_ld" = yes; then
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(acl_cv_path_LD,
[if test -z "$LD"; then
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
acl_cv_path_LD="$ac_dir/$ac_prog"
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some GNU ld's only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
*GNU* | *'with BFD'*)
test "$with_gnu_ld" != no && break ;;
*)
test "$with_gnu_ld" != yes && break ;;
esac
fi
done
IFS="$ac_save_ifs"
else
acl_cv_path_LD="$LD" # Let the user override the test with a path.
fi])
LD="$acl_cv_path_LD"
if test -n "$LD"; then
AC_MSG_RESULT($LD)
else
AC_MSG_RESULT(no)
fi
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
AC_LIB_PROG_LD_GNU
])

3724
configure vendored Executable file

File diff suppressed because it is too large Load diff

80
configure.in Normal file
View file

@ -0,0 +1,80 @@
#
# configure.in
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
AC_INIT(libnl, 1.0-pre6, tgraf@suug.ch)
AC_CONFIG_HEADER(lib/defs.h)
save_CFLAGS="${CFLAGS}"
save_LDFLAGS="${LDFLAGS}"
save_CPPFLAGS="${CPPFLAGS}"
AC_PROG_CC
AC_PROG_INSTALL
AC_C_CONST
AC_C_INLINE
#####################################################################
##
## libm check
##
#####################################################################
M="No "
AC_CHECK_LIB(m, pow,
[
LIBM="-lm"
M="Yes"
],[
echo
echo "*** Error: libm required ***"
echo
exit
])
#####################################################################
##
## verbose error strings
##
#####################################################################
AC_ARG_ENABLE(verbose-errors,
[ --enable-verbose-errors enable verbose errors (debugging)],[
if test x$enableval = xyes; then
AC_DEFINE_UNQUOTED(VERBOSE_ERRORS,"1",[verbose errors])
fi
])
#####################################################################
##
## compile decisions
##
#####################################################################
COMPILE_LIBNL="Yes "
LIBNL_LIB="$LIBM"
AC_SUBST(LIBNL_LIB)
AC_OUTPUT([Makefile.opts libnl-1.pc])
#####################################################################
##
## status report
##
#####################################################################
echo "
----------------------------------------------------------------------
SUMMARY:
Included in Compilation:
libnl: $COMPILE_LIBNL $LIBNL_LIB
Dependencies:
bmon:
libm $M (required)"

1259
doc/Doxyfile Normal file

File diff suppressed because it is too large Load diff

35
doc/Makefile Normal file
View file

@ -0,0 +1,35 @@
#
# doc/Makefile
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
include ../Makefile.opts
endif
export
.PHONY: all gendoc clean distclean install
all:
@true
gendoc:
doxygen Doxyfile
clean:
@true
distclean:
$(RM) -f html/*
install:
@true
$(DEPS): ../Makefile.opts

310
doc/libnl.css Normal file
View file

@ -0,0 +1,310 @@
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
font-family: Geneva, Arial, Helvetica, sans-serif;
}
BODY,TD {
font-size: 90%;
}
H1 {
text-align: center;
font-size: 160%;
}
H2 {
font-size: 120%;
}
H3 {
font-size: 100%;
}
CAPTION { font-weight: bold }
DIV.qindex {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.nav {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.navtab {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
TD.navtab {
font-size: 70%;
}
A.qindex {
text-decoration: none;
font-weight: bold;
color: #1A419D;
}
A.qindex:visited {
text-decoration: none;
font-weight: bold;
color: #1A419D
}
A.qindex:hover {
text-decoration: none;
background-color: #ddddff;
}
A.qindexHL {
text-decoration: none;
font-weight: bold;
background-color: #6666cc;
color: #ffffff;
border: 1px double #9295C2;
}
A.qindexHL:hover {
text-decoration: none;
background-color: #6666cc;
color: #ffffff;
}
A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
A.codeRef:link { font-weight: normal; color: #0000FF}
A.codeRef:visited { font-weight: normal; color: #0000FF}
A:hover { text-decoration: none; background-color: #f2f2ff }
DL.el { margin-left: -1cm }
.fragment {
font-family: Fixed, monospace;
font-size: 95%;
}
PRE.fragment {
border: 1px solid #CCCCCC;
background-color: #f5f5f5;
margin-top: 4px;
margin-bottom: 4px;
margin-left: 2px;
margin-right: 8px;
padding-left: 6px;
padding-right: 6px;
padding-top: 4px;
padding-bottom: 4px;
}
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
TD.md { background-color: #F4F4FB; font-weight: bold; }
TD.mdPrefix {
background-color: #F4F4FB;
color: #606060;
font-size: 80%;
}
TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
DIV.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
BODY {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}
TD.indexkey {
background-color: #eeeeff;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TD.indexvalue {
background-color: #eeeeff;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TR.memlist {
background-color: #f0f0f0;
}
P.formulaDsp { text-align: center; }
IMG.formulaDsp { }
IMG.formulaInl { vertical-align: middle; }
SPAN.keyword { color: #008000 }
SPAN.keywordtype { color: #604020 }
SPAN.keywordflow { color: #e08000 }
SPAN.comment { color: #800000 }
SPAN.preprocessor { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral { color: #008080 }
.mdTable {
border: 1px solid #868686;
background-color: #F4F4FB;
width: 100%;
}
.mdRow {
padding: 8px 10px;
}
.mdescLeft {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.mdescRight {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplParams {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
color: #606060;
background-color: #FAFAFA;
font-size: 80%;
}
.search { color: #003399;
font-weight: bold;
}
FORM.search {
margin-bottom: 0px;
margin-top: 0px;
}
INPUT.search { font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #eeeeff;
}
TD.tiny { font-size: 75%;
}
a {
color: #252E78;
}
a:visited {
color: #3D2185;
}
.dirtab { padding: 4px;
border-collapse: collapse;
border: 1px solid #b0b0b0;
}
TH.dirtab { background: #eeeeff;
font-weight: bold;
}
HR { height: 1px;
border: none;
border-top: 1px solid black;
}

38
include/Makefile Normal file
View file

@ -0,0 +1,38 @@
#
# include/Makefile
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
include ../Makefile.opts
endif
.PHONY: all clean install
all:
@true
clean:
@true
distclean:
@true
install:
mkdir -p $(DESTDIR)$(includedir)/netlink/route/sch/
mkdir -p $(DESTDIR)$(includedir)/netlink/route/cls/
mkdir -p $(DESTDIR)$(includedir)/netlink/genl/
mkdir -p $(DESTDIR)$(includedir)/netlink/fib_lookup/
install -m 0644 netlink/*.h $(DESTDIR)$(includedir)/netlink/
install -m 0644 netlink/route/*.h $(DESTDIR)$(includedir)/netlink/route/
install -m 0644 netlink/route/sch/*.h $(DESTDIR)$(includedir)/netlink/route/sch/
install -m 0644 netlink/route/cls/*.h $(DESTDIR)$(includedir)/netlink/route/cls/
install -m 0644 netlink/genl/*.h $(DESTDIR)$(includedir)/netlink/genl/
install -m 0644 netlink/fib_lookup/*.h $(DESTDIR)$(includedir)/netlink/fib_lookup/

60
include/linux/gen_stats.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef __LINUX_GEN_STATS_H
#define __LINUX_GEN_STATS_H
enum {
TCA_STATS_UNSPEC,
TCA_STATS_BASIC,
TCA_STATS_RATE_EST,
TCA_STATS_QUEUE,
TCA_STATS_APP,
__TCA_STATS_MAX,
};
#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
/**
* @bytes: number of seen bytes
* @packets: number of seen packets
*/
struct gnet_stats_basic
{
__u64 bytes;
__u32 packets;
};
/**
* @bps: current byte rate
* @pps: current packet rate
*/
struct gnet_stats_rate_est
{
__u32 bps;
__u32 pps;
};
/**
* @qlen: queue length
* @backlog: backlog size of queue
* @drops: number of dropped packets
* @requeues: number of requeues
*/
struct gnet_stats_queue
{
__u32 qlen;
__u32 backlog;
__u32 drops;
__u32 requeues;
__u32 overlimits;
};
/**
* @interval: sampling period
* @ewma_log: the log of measurement window weight
*/
struct gnet_estimator
{
signed char interval;
unsigned char ewma_log;
};
#endif /* __LINUX_GEN_STATS_H */

69
include/linux/genetlink.h Normal file
View file

@ -0,0 +1,69 @@
#ifndef __LINUX_GENERIC_NETLINK_H
#define __LINUX_GENERIC_NETLINK_H
#include <linux/netlink.h>
#define GENL_NAMSIZ 16 /* length of family name */
#define GENL_MIN_ID NLMSG_MIN_TYPE
#define GENL_MAX_ID 1023
struct genlmsghdr {
__u8 cmd;
__u8 version;
__u16 reserved;
};
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
#define GENL_ADMIN_PERM 0x01
#define GENL_CMD_CAP_DO 0x02
#define GENL_CMD_CAP_DUMP 0x04
#define GENL_CMD_CAP_HASPOL 0x08
/*
* List of reserved static generic netlink identifiers:
*/
#define GENL_ID_GENERATE 0
#define GENL_ID_CTRL NLMSG_MIN_TYPE
/**************************************************************************
* Controller
**************************************************************************/
enum {
CTRL_CMD_UNSPEC,
CTRL_CMD_NEWFAMILY,
CTRL_CMD_DELFAMILY,
CTRL_CMD_GETFAMILY,
CTRL_CMD_NEWOPS,
CTRL_CMD_DELOPS,
CTRL_CMD_GETOPS,
__CTRL_CMD_MAX,
};
#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
enum {
CTRL_ATTR_UNSPEC,
CTRL_ATTR_FAMILY_ID,
CTRL_ATTR_FAMILY_NAME,
CTRL_ATTR_VERSION,
CTRL_ATTR_HDRSIZE,
CTRL_ATTR_MAXATTR,
CTRL_ATTR_OPS,
__CTRL_ATTR_MAX,
};
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
enum {
CTRL_ATTR_OP_UNSPEC,
CTRL_ATTR_OP_ID,
CTRL_ATTR_OP_FLAGS,
__CTRL_ATTR_OP_MAX,
};
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
#endif /* __LINUX_GENERIC_NETLINK_H */

102
include/linux/if.h Normal file
View file

@ -0,0 +1,102 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Global definitions for the INET interface module.
*
* Version: @(#)if.h 1.0.2 04/18/93
*
* Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
* Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* 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.
*/
#ifndef _LINUX_IF_H
#define _LINUX_IF_H
#define IFNAMSIZ 16
/* Standard interface flags (netdevice->flags). */
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* interface running and carrier ok */
#define IFF_NOARP 0x80 /* no ARP protocol */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
#define IFF_MASTER 0x400 /* master of a load balancer */
#define IFF_SLAVE 0x800 /* slave of a load balancer */
#define IFF_MULTICAST 0x1000 /* Supports multicast */
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
#define IFF_PORTSEL 0x2000 /* can set media type */
#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
#define IFF_DORMANT 0x20000 /* driver signals dormant */
/* Private (from user) interface flags (netdevice->priv_flags). */
#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */
#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */
#define IF_GET_IFACE 0x0001 /* for querying only */
#define IF_GET_PROTO 0x0002
/* For definitions see hdlc.h */
#define IF_IFACE_V35 0x1000 /* V.35 serial interface */
#define IF_IFACE_V24 0x1001 /* V.24 serial interface */
#define IF_IFACE_X21 0x1002 /* X.21 serial interface */
#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */
#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */
#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */
#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */
/* For definitions see hdlc.h */
#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */
#define IF_PROTO_PPP 0x2001 /* PPP protocol */
#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */
#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */
#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */
#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */
#define IF_PROTO_X25 0x2006 /* X.25 */
#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */
#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */
#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */
#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */
#define IF_PROTO_FR_ETH_PVC 0x200B
#define IF_PROTO_RAW 0x200C /* RAW Socket */
/*
* Device mapping structure. I'd just gone off and designed a
* beautiful scheme using only loadable modules with arguments
* for driver options and along come the PCMCIA people 8)
*
* Ah well. The get() side of this is good for WDSETUP, and it'll
* be handy for debugging things. The set side is fine for now and
* being very small might be worth keeping for clean configuration.
*/
struct ifmap
{
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
/* 3 bytes spare */
};
#endif /* _LINUX_IF_H */

62
include/linux/if_addr.h Normal file
View file

@ -0,0 +1,62 @@
#ifndef __LINUX_IF_ADDR_H
#define __LINUX_IF_ADDR_H
#include <linux/netlink.h>
struct ifaddrmsg
{
__u8 ifa_family;
__u8 ifa_prefixlen; /* The prefix length */
__u8 ifa_flags; /* Flags */
__u8 ifa_scope; /* Address scope */
__u32 ifa_index; /* Link index */
};
/*
* Important comment:
* IFA_ADDRESS is prefix address, rather than local interface address.
* It makes no difference for normally configured broadcast interfaces,
* but for point-to-point IFA_ADDRESS is DESTINATION address,
* local address is supplied in IFA_LOCAL attribute.
*/
enum
{
IFA_UNSPEC,
IFA_ADDRESS,
IFA_LOCAL,
IFA_LABEL,
IFA_BROADCAST,
IFA_ANYCAST,
IFA_CACHEINFO,
IFA_MULTICAST,
__IFA_MAX,
};
#define IFA_MAX (__IFA_MAX - 1)
/* ifa_flags */
#define IFA_F_SECONDARY 0x01
#define IFA_F_TEMPORARY IFA_F_SECONDARY
#define IFA_F_NODAD 0x02
#define IFA_F_OPTIMISTIC 0x04
#define IFA_F_HOMEADDRESS 0x10
#define IFA_F_DEPRECATED 0x20
#define IFA_F_TENTATIVE 0x40
#define IFA_F_PERMANENT 0x80
struct ifa_cacheinfo
{
__u32 ifa_prefered;
__u32 ifa_valid;
__u32 cstamp; /* created timestamp, hundredths of seconds */
__u32 tstamp; /* updated timestamp, hundredths of seconds */
};
/* backwards compatibility for userspace */
#ifndef __KERNEL__
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
#endif
#endif

149
include/linux/if_arp.h Normal file
View file

@ -0,0 +1,149 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Global definitions for the ARP (RFC 826) protocol.
*
* Version: @(#)if_arp.h 1.0.1 04/16/93
*
* Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
* Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source.
* Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Florian La Roche,
* Jonathan Layes <layes@loran.com>
* Arnaldo Carvalho de Melo <acme@conectiva.com.br> ARPHRD_HWX25
*
* 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.
*/
#ifndef _LINUX_IF_ARP_H
#define _LINUX_IF_ARP_H
/* ARP protocol HARDWARE identifiers. */
#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
#define ARPHRD_EETHER 2 /* Experimental Ethernet */
#define ARPHRD_AX25 3 /* AX.25 Level 2 */
#define ARPHRD_PRONET 4 /* PROnet token ring */
#define ARPHRD_CHAOS 5 /* Chaosnet */
#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
#define ARPHRD_ARCNET 7 /* ARCnet */
#define ARPHRD_APPLETLK 8 /* APPLEtalk */
#define ARPHRD_DLCI 15 /* Frame Relay DLCI */
#define ARPHRD_ATM 19 /* ATM */
#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */
#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */
#define ARPHRD_EUI64 27 /* EUI-64 */
#define ARPHRD_INFINIBAND 32 /* InfiniBand */
/* Dummy types for non ARP hardware */
#define ARPHRD_SLIP 256
#define ARPHRD_CSLIP 257
#define ARPHRD_SLIP6 258
#define ARPHRD_CSLIP6 259
#define ARPHRD_RSRVD 260 /* Notional KISS type */
#define ARPHRD_ADAPT 264
#define ARPHRD_ROSE 270
#define ARPHRD_X25 271 /* CCITT X.25 */
#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */
#define ARPHRD_PPP 512
#define ARPHRD_CISCO 513 /* Cisco HDLC */
#define ARPHRD_HDLC ARPHRD_CISCO
#define ARPHRD_LAPB 516 /* LAPB */
#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */
#define ARPHRD_RAWHDLC 518 /* Raw HDLC */
#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
#define ARPHRD_FRAD 770 /* Frame Relay Access Device */
#define ARPHRD_SKIP 771 /* SKIP vif */
#define ARPHRD_LOOPBACK 772 /* Loopback device */
#define ARPHRD_LOCALTLK 773 /* Localtalk device */
#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface */
#define ARPHRD_BIF 775 /* AP1000 BIF */
#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4 */
#define ARPHRD_IPDDP 777 /* IP over DDP tunneller */
#define ARPHRD_IPGRE 778 /* GRE over IP */
#define ARPHRD_PIMREG 779 /* PIMSM register interface */
#define ARPHRD_HIPPI 780 /* High Performance Parallel Interface */
#define ARPHRD_ASH 781 /* Nexus 64Mbps Ash */
#define ARPHRD_ECONET 782 /* Acorn Econet */
#define ARPHRD_IRDA 783 /* Linux-IrDA */
/* ARP works differently on different FC media .. so */
#define ARPHRD_FCPP 784 /* Point to point fibrechannel */
#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */
#define ARPHRD_FCPL 786 /* Fibrechannel public loop */
#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */
/* 787->799 reserved for fibrechannel media types */
#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */
#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */
#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
#define ARPHRD_NONE 0xFFFE /* zero header length */
/* ARP protocol opcodes. */
#define ARPOP_REQUEST 1 /* ARP request */
#define ARPOP_REPLY 2 /* ARP reply */
#define ARPOP_RREQUEST 3 /* RARP request */
#define ARPOP_RREPLY 4 /* RARP reply */
#define ARPOP_InREQUEST 8 /* InARP request */
#define ARPOP_InREPLY 9 /* InARP reply */
#define ARPOP_NAK 10 /* (ATM)ARP NAK */
/* ARP ioctl request. */
struct arpreq {
struct sockaddr arp_pa; /* protocol address */
struct sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */
struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
char arp_dev[16];
};
struct arpreq_old {
struct sockaddr arp_pa; /* protocol address */
struct sockaddr arp_ha; /* hardware address */
int arp_flags; /* flags */
struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
};
/* ARP Flag values. */
#define ATF_COM 0x02 /* completed entry (ha valid) */
#define ATF_PERM 0x04 /* permanent entry */
#define ATF_PUBL 0x08 /* publish entry */
#define ATF_USETRAILERS 0x10 /* has requested trailers */
#define ATF_NETMASK 0x20 /* want to use a netmask (only
for proxy entries) */
#define ATF_DONTPUB 0x40 /* don't answer this addresses */
/*
* This structure defines an ethernet arp header.
*/
struct arphdr
{
unsigned short ar_hrd; /* format of hardware address */
unsigned short ar_pro; /* format of protocol address */
unsigned char ar_hln; /* length of hardware address */
unsigned char ar_pln; /* length of protocol address */
unsigned short ar_op; /* ARP opcode (command) */
#if 0
/*
* Ethernet looks like this : This bit is variable sized however...
*/
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
unsigned char ar_sip[4]; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
unsigned char ar_tip[4]; /* target IP address */
#endif
};
#endif /* _LINUX_IF_ARP_H */

106
include/linux/if_ether.h Normal file
View file

@ -0,0 +1,106 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Global definitions for the Ethernet IEEE 802.3 interface.
*
* Version: @(#)if_ether.h 1.0.1a 02/08/94
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
* Alan Cox, <alan@redhat.com>
* Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
*
* 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.
*/
#ifndef _LINUX_IF_ETHER_H
#define _LINUX_IF_ETHER_H
/*
* IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble
* and FCS/CRC (frame check sequence).
*/
#define ETH_ALEN 6 /* Octets in one ethernet addr */
#define ETH_HLEN 14 /* Total octets in header. */
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
#define ETH_DATA_LEN 1500 /* Max. octets in payload */
#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
/*
* These are the defined Ethernet Protocol ID's.
*/
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_X25 0x0805 /* CCITT X.25 */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */
#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */
#define ETH_P_DEC 0x6000 /* DEC Assigned proto */
#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */
#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */
#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */
#define ETH_P_LAT 0x6004 /* DEC LAT */
#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */
#define ETH_P_CUST 0x6006 /* DEC Customer use */
#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */
#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */
#define ETH_P_ATALK 0x809B /* Appletalk DDP */
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol
* defined in draft-wilson-wrec-wccp-v2-00.txt */
#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */
#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */
#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport
* over Ethernet
*/
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
/*
* Non DIX types. Won't clash for 1500 types.
*/
#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
#define ETH_P_802_2 0x0004 /* 802.2 frames */
#define ETH_P_SNAP 0x0005 /* Internal only */
#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */
#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
#define ETH_P_CONTROL 0x0016 /* Card specific control frames */
#define ETH_P_IRDA 0x0017 /* Linux-IrDA */
#define ETH_P_ECONET 0x0018 /* Acorn Econet */
#define ETH_P_HDLC 0x0019 /* HDLC frames */
#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */
/*
* This is an Ethernet frame header.
*/
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
} __attribute__((packed));
#endif /* _LINUX_IF_ETHER_H */

143
include/linux/if_link.h Normal file
View file

@ -0,0 +1,143 @@
#ifndef _LINUX_IF_LINK_H
#define _LINUX_IF_LINK_H
#include <linux/netlink.h>
/* The struct should be in sync with struct net_device_stats */
struct rtnl_link_stats
{
__u32 rx_packets; /* total packets received */
__u32 tx_packets; /* total packets transmitted */
__u32 rx_bytes; /* total bytes received */
__u32 tx_bytes; /* total bytes transmitted */
__u32 rx_errors; /* bad packets received */
__u32 tx_errors; /* packet transmit problems */
__u32 rx_dropped; /* no space in linux buffers */
__u32 tx_dropped; /* no space available in linux */
__u32 multicast; /* multicast packets received */
__u32 collisions;
/* detailed rx_errors: */
__u32 rx_length_errors;
__u32 rx_over_errors; /* receiver ring buff overflow */
__u32 rx_crc_errors; /* recved pkt with crc error */
__u32 rx_frame_errors; /* recv'd frame alignment error */
__u32 rx_fifo_errors; /* recv'r fifo overrun */
__u32 rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
__u32 tx_aborted_errors;
__u32 tx_carrier_errors;
__u32 tx_fifo_errors;
__u32 tx_heartbeat_errors;
__u32 tx_window_errors;
/* for cslip etc */
__u32 rx_compressed;
__u32 tx_compressed;
};
/* The struct should be in sync with struct ifmap */
struct rtnl_link_ifmap
{
__u64 mem_start;
__u64 mem_end;
__u64 base_addr;
__u16 irq;
__u8 dma;
__u8 port;
};
enum
{
IFLA_UNSPEC,
IFLA_ADDRESS,
IFLA_BROADCAST,
IFLA_IFNAME,
IFLA_MTU,
IFLA_LINK,
IFLA_QDISC,
IFLA_STATS,
IFLA_COST,
#define IFLA_COST IFLA_COST
IFLA_PRIORITY,
#define IFLA_PRIORITY IFLA_PRIORITY
IFLA_MASTER,
#define IFLA_MASTER IFLA_MASTER
IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
#define IFLA_WIRELESS IFLA_WIRELESS
IFLA_PROTINFO, /* Protocol specific information for a link */
#define IFLA_PROTINFO IFLA_PROTINFO
IFLA_TXQLEN,
#define IFLA_TXQLEN IFLA_TXQLEN
IFLA_MAP,
#define IFLA_MAP IFLA_MAP
IFLA_WEIGHT,
#define IFLA_WEIGHT IFLA_WEIGHT
IFLA_OPERSTATE,
IFLA_LINKMODE,
__IFLA_MAX
};
#define IFLA_MAX (__IFLA_MAX - 1)
/* backwards compatibility for userspace */
#ifndef __KERNEL__
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
#endif
/* ifi_flags.
IFF_* flags.
The only change is:
IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
more not changeable by user. They describe link media
characteristics and set by device driver.
Comments:
- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
- If neither of these three flags are set;
the interface is NBMA.
- IFF_MULTICAST does not mean anything special:
multicasts can be used on all not-NBMA links.
IFF_MULTICAST means that this media uses special encapsulation
for multicast frames. Apparently, all IFF_POINTOPOINT and
IFF_BROADCAST devices are able to use multicasts too.
*/
/* IFLA_LINK.
For usual devices it is equal ifi_index.
If it is a "virtual interface" (f.e. tunnel), ifi_link
can point to real physical interface (f.e. for bandwidth calculations),
or maybe 0, what means, that real media is unknown (usual
for IPIP tunnels, when route to endpoint is allowed to change)
*/
/* Subtype attributes for IFLA_PROTINFO */
enum
{
IFLA_INET6_UNSPEC,
IFLA_INET6_FLAGS, /* link flags */
IFLA_INET6_CONF, /* sysctl parameters */
IFLA_INET6_STATS, /* statistics */
IFLA_INET6_MCAST, /* MC things. What of them? */
IFLA_INET6_CACHEINFO, /* time values and max reasm size */
IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */
__IFLA_INET6_MAX
};
#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
struct ifla_cacheinfo
{
__u32 max_reasm_len;
__u32 tstamp; /* ipv6InterfaceTable updated timestamp */
__u32 reachable_time;
__u32 retrans_time;
};
#endif /* _LINUX_IF_LINK_H */

22
include/linux/ip_mp_alg.h Normal file
View file

@ -0,0 +1,22 @@
/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
*
* Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
* Copyright (C) 2005 David S. Miller <davem@davemloft.net>
*/
#ifndef _LINUX_IP_MP_ALG_H
#define _LINUX_IP_MP_ALG_H
enum ip_mp_alg {
IP_MP_ALG_NONE,
IP_MP_ALG_RR,
IP_MP_ALG_DRR,
IP_MP_ALG_RANDOM,
IP_MP_ALG_WRANDOM,
__IP_MP_ALG_MAX
};
#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
#endif /* _LINUX_IP_MP_ALG_H */

159
include/linux/neighbour.h Normal file
View file

@ -0,0 +1,159 @@
#ifndef __LINUX_NEIGHBOUR_H
#define __LINUX_NEIGHBOUR_H
#include <linux/netlink.h>
struct ndmsg
{
__u8 ndm_family;
__u8 ndm_pad1;
__u16 ndm_pad2;
__s32 ndm_ifindex;
__u16 ndm_state;
__u8 ndm_flags;
__u8 ndm_type;
};
enum
{
NDA_UNSPEC,
NDA_DST,
NDA_LLADDR,
NDA_CACHEINFO,
NDA_PROBES,
__NDA_MAX
};
#define NDA_MAX (__NDA_MAX - 1)
/*
* Neighbor Cache Entry Flags
*/
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_ROUTER 0x80
/*
* Neighbor Cache Entry States.
*/
#define NUD_INCOMPLETE 0x01
#define NUD_REACHABLE 0x02
#define NUD_STALE 0x04
#define NUD_DELAY 0x08
#define NUD_PROBE 0x10
#define NUD_FAILED 0x20
/* Dummy states */
#define NUD_NOARP 0x40
#define NUD_PERMANENT 0x80
#define NUD_NONE 0x00
/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
and make no address resolution or NUD.
NUD_PERMANENT is also cannot be deleted by garbage collectors.
*/
struct nda_cacheinfo
{
__u32 ndm_confirmed;
__u32 ndm_used;
__u32 ndm_updated;
__u32 ndm_refcnt;
};
/*****************************************************************
* Neighbour tables specific messages.
*
* To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
* NLM_F_DUMP flag set. Every neighbour table configuration is
* spread over multiple messages to avoid running into message
* size limits on systems with many interfaces. The first message
* in the sequence transports all not device specific data such as
* statistics, configuration, and the default parameter set.
* This message is followed by 0..n messages carrying device
* specific parameter sets.
* Although the ordering should be sufficient, NDTA_NAME can be
* used to identify sequences. The initial message can be identified
* by checking for NDTA_CONFIG. The device specific messages do
* not contain this TLV but have NDTPA_IFINDEX set to the
* corresponding interface index.
*
* To change neighbour table attributes, send RTM_SETNEIGHTBL
* with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
* NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
* otherwise. Device specific parameter sets can be changed by
* setting NDTPA_IFINDEX to the interface index of the corresponding
* device.
****/
struct ndt_stats
{
__u64 ndts_allocs;
__u64 ndts_destroys;
__u64 ndts_hash_grows;
__u64 ndts_res_failed;
__u64 ndts_lookups;
__u64 ndts_hits;
__u64 ndts_rcv_probes_mcast;
__u64 ndts_rcv_probes_ucast;
__u64 ndts_periodic_gc_runs;
__u64 ndts_forced_gc_runs;
};
enum {
NDTPA_UNSPEC,
NDTPA_IFINDEX, /* u32, unchangeable */
NDTPA_REFCNT, /* u32, read-only */
NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
NDTPA_RETRANS_TIME, /* u64, msecs */
NDTPA_GC_STALETIME, /* u64, msecs */
NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
NDTPA_QUEUE_LEN, /* u32 */
NDTPA_APP_PROBES, /* u32 */
NDTPA_UCAST_PROBES, /* u32 */
NDTPA_MCAST_PROBES, /* u32 */
NDTPA_ANYCAST_DELAY, /* u64, msecs */
NDTPA_PROXY_DELAY, /* u64, msecs */
NDTPA_PROXY_QLEN, /* u32 */
NDTPA_LOCKTIME, /* u64, msecs */
__NDTPA_MAX
};
#define NDTPA_MAX (__NDTPA_MAX - 1)
struct ndtmsg
{
__u8 ndtm_family;
__u8 ndtm_pad1;
__u16 ndtm_pad2;
};
struct ndt_config
{
__u16 ndtc_key_len;
__u16 ndtc_entry_size;
__u32 ndtc_entries;
__u32 ndtc_last_flush; /* delta to now in msecs */
__u32 ndtc_last_rand; /* delta to now in msecs */
__u32 ndtc_hash_rnd;
__u32 ndtc_hash_mask;
__u32 ndtc_hash_chain_gc;
__u32 ndtc_proxy_qlen;
};
enum {
NDTA_UNSPEC,
NDTA_NAME, /* char *, unchangeable */
NDTA_THRESH1, /* u32 */
NDTA_THRESH2, /* u32 */
NDTA_THRESH3, /* u32 */
NDTA_CONFIG, /* struct ndt_config, read-only */
NDTA_PARMS, /* nested TLV NDTPA_* */
NDTA_STATS, /* struct ndt_stats, read-only */
NDTA_GC_INTERVAL, /* u64, msecs */
__NDTA_MAX
};
#define NDTA_MAX (__NDTA_MAX - 1)
#endif

View file

@ -0,0 +1,60 @@
#ifndef _NFNETLINK_H
#define _NFNETLINK_H
#include <linux/types.h>
#ifndef __KERNEL__
/* nfnetlink groups: Up to 32 maximum - backwards compatibility for userspace */
#define NF_NETLINK_CONNTRACK_NEW 0x00000001
#define NF_NETLINK_CONNTRACK_UPDATE 0x00000002
#define NF_NETLINK_CONNTRACK_DESTROY 0x00000004
#define NF_NETLINK_CONNTRACK_EXP_NEW 0x00000008
#define NF_NETLINK_CONNTRACK_EXP_UPDATE 0x00000010
#define NF_NETLINK_CONNTRACK_EXP_DESTROY 0x00000020
#endif
enum nfnetlink_groups {
NFNLGRP_NONE,
#define NFNLGRP_NONE NFNLGRP_NONE
NFNLGRP_CONNTRACK_NEW,
#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW
NFNLGRP_CONNTRACK_UPDATE,
#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE
NFNLGRP_CONNTRACK_DESTROY,
#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY
NFNLGRP_CONNTRACK_EXP_NEW,
#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW
NFNLGRP_CONNTRACK_EXP_UPDATE,
#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE
NFNLGRP_CONNTRACK_EXP_DESTROY,
#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY
__NFNLGRP_MAX,
};
#define NFNLGRP_MAX (__NFNLGRP_MAX - 1)
/* General form of address family dependent message.
*/
struct nfgenmsg {
u_int8_t nfgen_family; /* AF_xxx */
u_int8_t version; /* nfnetlink version */
__be16 res_id; /* resource id */
};
#define NFNETLINK_V0 0
/* netfilter netlink message types are split in two pieces:
* 8 bit subsystem, 8bit operation.
*/
#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8)
#define NFNL_MSG_TYPE(x) (x & 0x00ff)
/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS()
* won't work anymore */
#define NFNL_SUBSYS_NONE 0
#define NFNL_SUBSYS_CTNETLINK 1
#define NFNL_SUBSYS_CTNETLINK_EXP 2
#define NFNL_SUBSYS_QUEUE 3
#define NFNL_SUBSYS_ULOG 4
#define NFNL_SUBSYS_COUNT 5
#endif /* _NFNETLINK_H */

View file

@ -0,0 +1,140 @@
#ifndef _IPCONNTRACK_NETLINK_H
#define _IPCONNTRACK_NETLINK_H
#include <linux/netfilter/nfnetlink.h>
enum cntl_msg_types {
IPCTNL_MSG_CT_NEW,
IPCTNL_MSG_CT_GET,
IPCTNL_MSG_CT_DELETE,
IPCTNL_MSG_CT_GET_CTRZERO,
IPCTNL_MSG_MAX
};
enum ctnl_exp_msg_types {
IPCTNL_MSG_EXP_NEW,
IPCTNL_MSG_EXP_GET,
IPCTNL_MSG_EXP_DELETE,
IPCTNL_MSG_EXP_MAX
};
enum ctattr_type {
CTA_UNSPEC,
CTA_TUPLE_ORIG,
CTA_TUPLE_REPLY,
CTA_STATUS,
CTA_PROTOINFO,
CTA_HELP,
CTA_NAT_SRC,
#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */
CTA_TIMEOUT,
CTA_MARK,
CTA_COUNTERS_ORIG,
CTA_COUNTERS_REPLY,
CTA_USE,
CTA_ID,
CTA_NAT_DST,
__CTA_MAX
};
#define CTA_MAX (__CTA_MAX - 1)
enum ctattr_tuple {
CTA_TUPLE_UNSPEC,
CTA_TUPLE_IP,
CTA_TUPLE_PROTO,
__CTA_TUPLE_MAX
};
#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1)
enum ctattr_ip {
CTA_IP_UNSPEC,
CTA_IP_V4_SRC,
CTA_IP_V4_DST,
CTA_IP_V6_SRC,
CTA_IP_V6_DST,
__CTA_IP_MAX
};
#define CTA_IP_MAX (__CTA_IP_MAX - 1)
enum ctattr_l4proto {
CTA_PROTO_UNSPEC,
CTA_PROTO_NUM,
CTA_PROTO_SRC_PORT,
CTA_PROTO_DST_PORT,
CTA_PROTO_ICMP_ID,
CTA_PROTO_ICMP_TYPE,
CTA_PROTO_ICMP_CODE,
CTA_PROTO_ICMPV6_ID,
CTA_PROTO_ICMPV6_TYPE,
CTA_PROTO_ICMPV6_CODE,
__CTA_PROTO_MAX
};
#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
enum ctattr_protoinfo {
CTA_PROTOINFO_UNSPEC,
CTA_PROTOINFO_TCP,
__CTA_PROTOINFO_MAX
};
#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
enum ctattr_protoinfo_tcp {
CTA_PROTOINFO_TCP_UNSPEC,
CTA_PROTOINFO_TCP_STATE,
CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
CTA_PROTOINFO_TCP_WSCALE_REPLY,
CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
CTA_PROTOINFO_TCP_FLAGS_REPLY,
__CTA_PROTOINFO_TCP_MAX
};
#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
enum ctattr_counters {
CTA_COUNTERS_UNSPEC,
CTA_COUNTERS_PACKETS, /* old 64bit counters */
CTA_COUNTERS_BYTES, /* old 64bit counters */
CTA_COUNTERS32_PACKETS,
CTA_COUNTERS32_BYTES,
__CTA_COUNTERS_MAX
};
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
enum ctattr_nat {
CTA_NAT_UNSPEC,
CTA_NAT_MINIP,
CTA_NAT_MAXIP,
CTA_NAT_PROTO,
__CTA_NAT_MAX
};
#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)
enum ctattr_protonat {
CTA_PROTONAT_UNSPEC,
CTA_PROTONAT_PORT_MIN,
CTA_PROTONAT_PORT_MAX,
__CTA_PROTONAT_MAX
};
#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)
enum ctattr_expect {
CTA_EXPECT_UNSPEC,
CTA_EXPECT_MASTER,
CTA_EXPECT_TUPLE,
CTA_EXPECT_MASK,
CTA_EXPECT_TIMEOUT,
CTA_EXPECT_ID,
CTA_EXPECT_HELP_NAME,
__CTA_EXPECT_MAX
};
#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
enum ctattr_help {
CTA_HELP_UNSPEC,
CTA_HELP_NAME,
__CTA_HELP_MAX
};
#define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
#endif /* _IPCONNTRACK_NETLINK_H */

View file

@ -0,0 +1,96 @@
#ifndef _NFNETLINK_LOG_H
#define _NFNETLINK_LOG_H
/* This file describes the netlink messages (i.e. 'protocol packets'),
* and not any kind of function definitions. It is shared between kernel and
* userspace. Don't put kernel specific stuff in here */
#ifndef aligned_be64
#define aligned_be64 u_int64_t __attribute__((aligned(8)))
#endif
#include <linux/types.h>
#include <linux/netfilter/nfnetlink.h>
enum nfulnl_msg_types {
NFULNL_MSG_PACKET, /* packet from kernel to userspace */
NFULNL_MSG_CONFIG, /* connect to a particular queue */
NFULNL_MSG_MAX
};
struct nfulnl_msg_packet_hdr {
__be16 hw_protocol; /* hw protocol (network order) */
u_int8_t hook; /* netfilter hook */
u_int8_t _pad;
};
struct nfulnl_msg_packet_hw {
__be16 hw_addrlen;
u_int16_t _pad;
u_int8_t hw_addr[8];
};
struct nfulnl_msg_packet_timestamp {
aligned_be64 sec;
aligned_be64 usec;
};
enum nfulnl_attr_type {
NFULA_UNSPEC,
NFULA_PACKET_HDR,
NFULA_MARK, /* u_int32_t nfmark */
NFULA_TIMESTAMP, /* nfulnl_msg_packet_timestamp */
NFULA_IFINDEX_INDEV, /* u_int32_t ifindex */
NFULA_IFINDEX_OUTDEV, /* u_int32_t ifindex */
NFULA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */
NFULA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */
NFULA_HWADDR, /* nfulnl_msg_packet_hw */
NFULA_PAYLOAD, /* opaque data payload */
NFULA_PREFIX, /* string prefix */
NFULA_UID, /* user id of socket */
NFULA_SEQ, /* instance-local sequence number */
NFULA_SEQ_GLOBAL, /* global sequence number */
__NFULA_MAX
};
#define NFULA_MAX (__NFULA_MAX - 1)
enum nfulnl_msg_config_cmds {
NFULNL_CFG_CMD_NONE,
NFULNL_CFG_CMD_BIND,
NFULNL_CFG_CMD_UNBIND,
NFULNL_CFG_CMD_PF_BIND,
NFULNL_CFG_CMD_PF_UNBIND,
};
struct nfulnl_msg_config_cmd {
u_int8_t command; /* nfulnl_msg_config_cmds */
} __attribute__ ((packed));
struct nfulnl_msg_config_mode {
__be32 copy_range;
u_int8_t copy_mode;
u_int8_t _pad;
} __attribute__ ((packed));
enum nfulnl_attr_config {
NFULA_CFG_UNSPEC,
NFULA_CFG_CMD, /* nfulnl_msg_config_cmd */
NFULA_CFG_MODE, /* nfulnl_msg_config_mode */
NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */
NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */
NFULA_CFG_QTHRESH, /* u_int32_t */
NFULA_CFG_FLAGS, /* u_int16_t */
__NFULA_CFG_MAX
};
#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
#define NFULNL_COPY_NONE 0x00
#define NFULNL_COPY_META 0x01
#define NFULNL_COPY_PACKET 0x02
#define NFULNL_CFG_F_SEQ 0x0001
#define NFULNL_CFG_F_SEQ_GLOBAL 0x0002
#endif /* _NFNETLINK_LOG_H */

150
include/linux/netlink.h Normal file
View file

@ -0,0 +1,150 @@
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
#include <linux/socket.h> /* for sa_family_t */
#include <linux/types.h>
#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_UNUSED 1 /* Unused number */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Firewalling hook */
#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ISCSI 8 /* Open-iSCSI */
#define NETLINK_AUDIT 9 /* auditing */
#define NETLINK_FIB_LOOKUP 10
#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16
/* leave room for NETLINK_DM (DM Events) */
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
#define NETLINK_ECRYPTFS 19
#define MAX_LINKS 32
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};
struct nlmsghdr
{
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process port ID */
};
/* Flags values */
#define NLM_F_REQUEST 1 /* It is request message. */
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
#define NLM_F_MATCH 0x200 /* return all matching */
#define NLM_F_ATOMIC 0x400 /* atomic GET */
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
/* Modifiers to NEW request */
#define NLM_F_REPLACE 0x100 /* Override existing */
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
#define NLM_F_APPEND 0x800 /* Add to end of list */
/*
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
4.4BSD CHANGE NLM_F_REPLACE
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
Append NLM_F_CREATE
Check NLM_F_EXCL
*/
#define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_NOOP 0x1 /* Nothing. */
#define NLMSG_ERROR 0x2 /* Error */
#define NLMSG_DONE 0x3 /* End of a dump */
#define NLMSG_OVERRUN 0x4 /* Data lost */
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
struct nlmsgerr
{
int error;
struct nlmsghdr msg;
};
#define NETLINK_ADD_MEMBERSHIP 1
#define NETLINK_DROP_MEMBERSHIP 2
#define NETLINK_PKTINFO 3
struct nl_pktinfo
{
__u32 group;
};
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
enum {
NETLINK_UNCONNECTED = 0,
NETLINK_CONNECTED,
};
/*
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
*/
struct nlattr
{
__u16 nla_len;
__u16 nla_type;
};
/*
* nla_type (16 bits)
* +---+---+-------------------------------+
* | N | O | Attribute Type |
* +---+---+-------------------------------+
* N := Carries nested attributes
* O := Payload stored in network byte order
*
* Note: The N and O flag are mutually exclusive.
*/
#define NLA_F_NESTED (1 << 15)
#define NLA_F_NET_BYTEORDER (1 << 14)
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
#define NLA_ALIGNTO 4
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
#endif /* __LINUX_NETLINK_H */

426
include/linux/pkt_cls.h Normal file
View file

@ -0,0 +1,426 @@
#ifndef __LINUX_PKT_CLS_H
#define __LINUX_PKT_CLS_H
#include <linux/pkt_sched.h>
/* I think i could have done better macros ; for now this is stolen from
* some arch/mips code - jhs
*/
#define _TC_MAKE32(x) ((x))
#define _TC_MAKEMASK1(n) (_TC_MAKE32(1) << _TC_MAKE32(n))
#define _TC_MAKEMASK(v,n) (_TC_MAKE32((_TC_MAKE32(1)<<(v))-1) << _TC_MAKE32(n))
#define _TC_MAKEVALUE(v,n) (_TC_MAKE32(v) << _TC_MAKE32(n))
#define _TC_GETVALUE(v,n,m) ((_TC_MAKE32(v) & _TC_MAKE32(m)) >> _TC_MAKE32(n))
/* verdict bit breakdown
*
bit 0: when set -> this packet has been munged already
bit 1: when set -> It is ok to munge this packet
bit 2,3,4,5: Reclassify counter - sort of reverse TTL - if exceeded
assume loop
bit 6,7: Where this packet was last seen
0: Above the transmit example at the socket level
1: on the Ingress
2: on the Egress
bit 8: when set --> Request not to classify on ingress.
bits 9,10,11: redirect counter - redirect TTL. Loop avoidance
*
* */
#define TC_MUNGED _TC_MAKEMASK1(0)
#define SET_TC_MUNGED(v) ( TC_MUNGED | (v & ~TC_MUNGED))
#define CLR_TC_MUNGED(v) ( v & ~TC_MUNGED)
#define TC_OK2MUNGE _TC_MAKEMASK1(1)
#define SET_TC_OK2MUNGE(v) ( TC_OK2MUNGE | (v & ~TC_OK2MUNGE))
#define CLR_TC_OK2MUNGE(v) ( v & ~TC_OK2MUNGE)
#define S_TC_VERD _TC_MAKE32(2)
#define M_TC_VERD _TC_MAKEMASK(4,S_TC_VERD)
#define G_TC_VERD(x) _TC_GETVALUE(x,S_TC_VERD,M_TC_VERD)
#define V_TC_VERD(x) _TC_MAKEVALUE(x,S_TC_VERD)
#define SET_TC_VERD(v,n) ((V_TC_VERD(n)) | (v & ~M_TC_VERD))
#define S_TC_FROM _TC_MAKE32(6)
#define M_TC_FROM _TC_MAKEMASK(2,S_TC_FROM)
#define G_TC_FROM(x) _TC_GETVALUE(x,S_TC_FROM,M_TC_FROM)
#define V_TC_FROM(x) _TC_MAKEVALUE(x,S_TC_FROM)
#define SET_TC_FROM(v,n) ((V_TC_FROM(n)) | (v & ~M_TC_FROM))
#define AT_STACK 0x0
#define AT_INGRESS 0x1
#define AT_EGRESS 0x2
#define TC_NCLS _TC_MAKEMASK1(8)
#define SET_TC_NCLS(v) ( TC_NCLS | (v & ~TC_NCLS))
#define CLR_TC_NCLS(v) ( v & ~TC_NCLS)
#define S_TC_RTTL _TC_MAKE32(9)
#define M_TC_RTTL _TC_MAKEMASK(3,S_TC_RTTL)
#define G_TC_RTTL(x) _TC_GETVALUE(x,S_TC_RTTL,M_TC_RTTL)
#define V_TC_RTTL(x) _TC_MAKEVALUE(x,S_TC_RTTL)
#define SET_TC_RTTL(v,n) ((V_TC_RTTL(n)) | (v & ~M_TC_RTTL))
#define S_TC_AT _TC_MAKE32(12)
#define M_TC_AT _TC_MAKEMASK(2,S_TC_AT)
#define G_TC_AT(x) _TC_GETVALUE(x,S_TC_AT,M_TC_AT)
#define V_TC_AT(x) _TC_MAKEVALUE(x,S_TC_AT)
#define SET_TC_AT(v,n) ((V_TC_AT(n)) | (v & ~M_TC_AT))
/* Action attributes */
enum
{
TCA_ACT_UNSPEC,
TCA_ACT_KIND,
TCA_ACT_OPTIONS,
TCA_ACT_INDEX,
TCA_ACT_STATS,
__TCA_ACT_MAX
};
#define TCA_ACT_MAX __TCA_ACT_MAX
#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
#define TCA_ACT_MAX_PRIO 32
#define TCA_ACT_BIND 1
#define TCA_ACT_NOBIND 0
#define TCA_ACT_UNBIND 1
#define TCA_ACT_NOUNBIND 0
#define TCA_ACT_REPLACE 1
#define TCA_ACT_NOREPLACE 0
#define MAX_REC_LOOP 4
#define MAX_RED_LOOP 4
#define TC_ACT_UNSPEC (-1)
#define TC_ACT_OK 0
#define TC_ACT_RECLASSIFY 1
#define TC_ACT_SHOT 2
#define TC_ACT_PIPE 3
#define TC_ACT_STOLEN 4
#define TC_ACT_QUEUED 5
#define TC_ACT_REPEAT 6
#define TC_ACT_JUMP 0x10000000
/* Action type identifiers*/
enum
{
TCA_ID_UNSPEC=0,
TCA_ID_POLICE=1,
/* other actions go here */
__TCA_ID_MAX=255
};
#define TCA_ID_MAX __TCA_ID_MAX
struct tc_police
{
__u32 index;
int action;
#define TC_POLICE_UNSPEC TC_ACT_UNSPEC
#define TC_POLICE_OK TC_ACT_OK
#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY
#define TC_POLICE_SHOT TC_ACT_SHOT
#define TC_POLICE_PIPE TC_ACT_PIPE
__u32 limit;
__u32 burst;
__u32 mtu;
struct tc_ratespec rate;
struct tc_ratespec peakrate;
int refcnt;
int bindcnt;
__u32 capab;
};
struct tcf_t
{
__u64 install;
__u64 lastuse;
__u64 expires;
};
struct tc_cnt
{
int refcnt;
int bindcnt;
};
#define tc_gen \
__u32 index; \
__u32 capab; \
int action; \
int refcnt; \
int bindcnt
enum
{
TCA_POLICE_UNSPEC,
TCA_POLICE_TBF,
TCA_POLICE_RATE,
TCA_POLICE_PEAKRATE,
TCA_POLICE_AVRATE,
TCA_POLICE_RESULT,
__TCA_POLICE_MAX
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
};
#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
/* U32 filters */
#define TC_U32_HTID(h) ((h)&0xFFF00000)
#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
#define TC_U32_HASH(h) (((h)>>12)&0xFF)
#define TC_U32_NODE(h) ((h)&0xFFF)
#define TC_U32_KEY(h) ((h)&0xFFFFF)
#define TC_U32_UNSPEC 0
#define TC_U32_ROOT (0xFFF00000)
enum
{
TCA_U32_UNSPEC,
TCA_U32_CLASSID,
TCA_U32_HASH,
TCA_U32_LINK,
TCA_U32_DIVISOR,
TCA_U32_SEL,
TCA_U32_POLICE,
TCA_U32_ACT,
TCA_U32_INDEV,
TCA_U32_PCNT,
TCA_U32_MARK,
__TCA_U32_MAX
};
#define TCA_U32_MAX (__TCA_U32_MAX - 1)
struct tc_u32_key
{
__u32 mask;
__u32 val;
int off;
int offmask;
};
struct tc_u32_sel
{
unsigned char flags;
unsigned char offshift;
unsigned char nkeys;
__u16 offmask;
__u16 off;
short offoff;
short hoff;
__u32 hmask;
struct tc_u32_key keys[0];
};
struct tc_u32_mark
{
__u32 val;
__u32 mask;
__u32 success;
};
struct tc_u32_pcnt
{
__u64 rcnt;
__u64 rhit;
__u64 kcnts[0];
};
/* Flags */
#define TC_U32_TERMINAL 1
#define TC_U32_OFFSET 2
#define TC_U32_VAROFFSET 4
#define TC_U32_EAT 8
#define TC_U32_MAXDEPTH 8
/* RSVP filter */
enum
{
TCA_RSVP_UNSPEC,
TCA_RSVP_CLASSID,
TCA_RSVP_DST,
TCA_RSVP_SRC,
TCA_RSVP_PINFO,
TCA_RSVP_POLICE,
TCA_RSVP_ACT,
__TCA_RSVP_MAX
};
#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
struct tc_rsvp_gpi
{
__u32 key;
__u32 mask;
int offset;
};
struct tc_rsvp_pinfo
{
struct tc_rsvp_gpi dpi;
struct tc_rsvp_gpi spi;
__u8 protocol;
__u8 tunnelid;
__u8 tunnelhdr;
__u8 pad;
};
/* ROUTE filter */
enum
{
TCA_ROUTE4_UNSPEC,
TCA_ROUTE4_CLASSID,
TCA_ROUTE4_TO,
TCA_ROUTE4_FROM,
TCA_ROUTE4_IIF,
TCA_ROUTE4_POLICE,
TCA_ROUTE4_ACT,
__TCA_ROUTE4_MAX
};
#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
/* FW filter */
enum
{
TCA_FW_UNSPEC,
TCA_FW_CLASSID,
TCA_FW_POLICE,
TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */
TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
TCA_FW_MASK,
__TCA_FW_MAX
};
#define TCA_FW_MAX (__TCA_FW_MAX - 1)
/* TC index filter */
enum
{
TCA_TCINDEX_UNSPEC,
TCA_TCINDEX_HASH,
TCA_TCINDEX_MASK,
TCA_TCINDEX_SHIFT,
TCA_TCINDEX_FALL_THROUGH,
TCA_TCINDEX_CLASSID,
TCA_TCINDEX_POLICE,
TCA_TCINDEX_ACT,
__TCA_TCINDEX_MAX
};
#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
/* Basic filter */
enum
{
TCA_BASIC_UNSPEC,
TCA_BASIC_CLASSID,
TCA_BASIC_EMATCHES,
TCA_BASIC_ACT,
TCA_BASIC_POLICE,
__TCA_BASIC_MAX
};
#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
/* Extended Matches */
struct tcf_ematch_tree_hdr
{
__u16 nmatches;
__u16 progid;
};
enum
{
TCA_EMATCH_TREE_UNSPEC,
TCA_EMATCH_TREE_HDR,
TCA_EMATCH_TREE_LIST,
__TCA_EMATCH_TREE_MAX
};
#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
struct tcf_ematch_hdr
{
__u16 matchid;
__u16 kind;
__u16 flags;
__u16 pad; /* currently unused */
};
/* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +-----------------------+-+-+---+
* | Unused |S|I| R |
* +-----------------------+-+-+---+
*
* R(2) ::= relation to next ematch
* where: 0 0 END (last ematch)
* 0 1 AND
* 1 0 OR
* 1 1 Unused (invalid)
* I(1) ::= invert result
* S(1) ::= simple payload
*/
#define TCF_EM_REL_END 0
#define TCF_EM_REL_AND (1<<0)
#define TCF_EM_REL_OR (1<<1)
#define TCF_EM_INVERT (1<<2)
#define TCF_EM_SIMPLE (1<<3)
#define TCF_EM_REL_MASK 3
#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
enum
{
TCF_LAYER_LINK,
TCF_LAYER_NETWORK,
TCF_LAYER_TRANSPORT,
__TCF_LAYER_MAX
};
#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
/* Ematch type assignments
* 1..32767 Reserved for ematches inside kernel tree
* 32768..65535 Free to use, not reliable
*/
#define TCF_EM_CONTAINER 0
#define TCF_EM_CMP 1
#define TCF_EM_NBYTE 2
#define TCF_EM_U32 3
#define TCF_EM_META 4
#define TCF_EM_TEXT 5
#define TCF_EM_MAX 5
enum
{
TCF_EM_PROG_TC
};
enum
{
TCF_EM_OPND_EQ,
TCF_EM_OPND_GT,
TCF_EM_OPND_LT
};
#endif

478
include/linux/pkt_sched.h Normal file
View file

@ -0,0 +1,478 @@
#ifndef __LINUX_PKT_SCHED_H
#define __LINUX_PKT_SCHED_H
/* Logical priority bands not depending on specific packet scheduler.
Every scheduler will map them to real traffic classes, if it has
no more precise mechanism to classify packets.
These numbers have no special meaning, though their coincidence
with obsolete IPv6 values is not occasional :-). New IPv6 drafts
preferred full anarchy inspired by diffserv group.
Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
class, actually, as rule it will be handled with more care than
filler or even bulk.
*/
#define TC_PRIO_BESTEFFORT 0
#define TC_PRIO_FILLER 1
#define TC_PRIO_BULK 2
#define TC_PRIO_INTERACTIVE_BULK 4
#define TC_PRIO_INTERACTIVE 6
#define TC_PRIO_CONTROL 7
#define TC_PRIO_MAX 15
/* Generic queue statistics, available for all the elements.
Particular schedulers may have also their private records.
*/
struct tc_stats
{
__u64 bytes; /* NUmber of enqueues bytes */
__u32 packets; /* Number of enqueued packets */
__u32 drops; /* Packets dropped because of lack of resources */
__u32 overlimits; /* Number of throttle events when this
* flow goes out of allocated bandwidth */
__u32 bps; /* Current flow byte rate */
__u32 pps; /* Current flow packet rate */
__u32 qlen;
__u32 backlog;
};
struct tc_estimator
{
signed char interval;
unsigned char ewma_log;
};
/* "Handles"
---------
All the traffic control objects have 32bit identifiers, or "handles".
They can be considered as opaque numbers from user API viewpoint,
but actually they always consist of two fields: major and
minor numbers, which are interpreted by kernel specially,
that may be used by applications, though not recommended.
F.e. qdisc handles always have minor number equal to zero,
classes (or flows) have major equal to parent qdisc major, and
minor uniquely identifying class inside qdisc.
Macros to manipulate handles:
*/
#define TC_H_MAJ_MASK (0xFFFF0000U)
#define TC_H_MIN_MASK (0x0000FFFFU)
#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
#define TC_H_UNSPEC (0U)
#define TC_H_ROOT (0xFFFFFFFFU)
#define TC_H_INGRESS (0xFFFFFFF1U)
struct tc_ratespec
{
unsigned char cell_log;
unsigned char __reserved;
unsigned short feature;
short addend;
unsigned short mpu;
__u32 rate;
};
/* FIFO section */
struct tc_fifo_qopt
{
__u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
};
/* PRIO section */
#define TCQ_PRIO_BANDS 16
#define TCQ_MIN_PRIO_BANDS 2
struct tc_prio_qopt
{
int bands; /* Number of bands */
__u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
};
enum
{
TCA_PRIO_UNSPEC,
TCA_PRIO_MQ,
__TCA_PRIO_MAX
};
#define TCA_PRIO_MAX (__TCA_PRIO_MAX - 1)
/* TBF section */
struct tc_tbf_qopt
{
struct tc_ratespec rate;
struct tc_ratespec peakrate;
__u32 limit;
__u32 buffer;
__u32 mtu;
};
enum
{
TCA_TBF_UNSPEC,
TCA_TBF_PARMS,
TCA_TBF_RTAB,
TCA_TBF_PTAB,
__TCA_TBF_MAX,
};
#define TCA_TBF_MAX (__TCA_TBF_MAX - 1)
/* TEQL section */
/* TEQL does not require any parameters */
/* SFQ section */
struct tc_sfq_qopt
{
unsigned quantum; /* Bytes per round allocated to flow */
int perturb_period; /* Period of hash perturbation */
__u32 limit; /* Maximal packets in queue */
unsigned divisor; /* Hash divisor */
unsigned flows; /* Maximal number of flows */
};
/*
* NOTE: limit, divisor and flows are hardwired to code at the moment.
*
* limit=flows=128, divisor=1024;
*
* The only reason for this is efficiency, it is possible
* to change these parameters in compile time.
*/
/* RED section */
enum
{
TCA_RED_UNSPEC,
TCA_RED_PARMS,
TCA_RED_STAB,
__TCA_RED_MAX,
};
#define TCA_RED_MAX (__TCA_RED_MAX - 1)
struct tc_red_qopt
{
__u32 limit; /* HARD maximal queue length (bytes) */
__u32 qth_min; /* Min average length threshold (bytes) */
__u32 qth_max; /* Max average length threshold (bytes) */
unsigned char Wlog; /* log(W) */
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
unsigned char Scell_log; /* cell size for idle damping */
unsigned char flags;
#define TC_RED_ECN 1
#define TC_RED_HARDDROP 2
};
struct tc_red_xstats
{
__u32 early; /* Early drops */
__u32 pdrop; /* Drops due to queue limits */
__u32 other; /* Drops due to drop() calls */
__u32 marked; /* Marked packets */
};
/* GRED section */
#define MAX_DPs 16
enum
{
TCA_GRED_UNSPEC,
TCA_GRED_PARMS,
TCA_GRED_STAB,
TCA_GRED_DPS,
__TCA_GRED_MAX,
};
#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
struct tc_gred_qopt
{
__u32 limit; /* HARD maximal queue length (bytes) */
__u32 qth_min; /* Min average length threshold (bytes) */
__u32 qth_max; /* Max average length threshold (bytes) */
__u32 DP; /* upto 2^32 DPs */
__u32 backlog;
__u32 qave;
__u32 forced;
__u32 early;
__u32 other;
__u32 pdrop;
__u8 Wlog; /* log(W) */
__u8 Plog; /* log(P_max/(qth_max-qth_min)) */
__u8 Scell_log; /* cell size for idle damping */
__u8 prio; /* prio of this VQ */
__u32 packets;
__u32 bytesin;
};
/* gred setup */
struct tc_gred_sopt
{
__u32 DPs;
__u32 def_DP;
__u8 grio;
__u8 flags;
__u16 pad1;
};
/* HTB section */
#define TC_HTB_NUMPRIO 8
#define TC_HTB_MAXDEPTH 8
#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */
struct tc_htb_opt
{
struct tc_ratespec rate;
struct tc_ratespec ceil;
__u32 buffer;
__u32 cbuffer;
__u32 quantum;
__u32 level; /* out only */
__u32 prio;
};
struct tc_htb_glob
{
__u32 version; /* to match HTB/TC */
__u32 rate2quantum; /* bps->quantum divisor */
__u32 defcls; /* default class number */
__u32 debug; /* debug flags */
/* stats */
__u32 direct_pkts; /* count of non shapped packets */
};
enum
{
TCA_HTB_UNSPEC,
TCA_HTB_PARMS,
TCA_HTB_INIT,
TCA_HTB_CTAB,
TCA_HTB_RTAB,
__TCA_HTB_MAX,
};
#define TCA_HTB_MAX (__TCA_HTB_MAX - 1)
struct tc_htb_xstats
{
__u32 lends;
__u32 borrows;
__u32 giants; /* too big packets (rate will not be accurate) */
__u32 tokens;
__u32 ctokens;
};
/* HFSC section */
struct tc_hfsc_qopt
{
__u16 defcls; /* default class */
};
struct tc_service_curve
{
__u32 m1; /* slope of the first segment in bps */
__u32 d; /* x-projection of the first segment in us */
__u32 m2; /* slope of the second segment in bps */
};
struct tc_hfsc_stats
{
__u64 work; /* total work done */
__u64 rtwork; /* work done by real-time criteria */
__u32 period; /* current period */
__u32 level; /* class level in hierarchy */
};
enum
{
TCA_HFSC_UNSPEC,
TCA_HFSC_RSC,
TCA_HFSC_FSC,
TCA_HFSC_USC,
__TCA_HFSC_MAX,
};
#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1)
/* CBQ section */
#define TC_CBQ_MAXPRIO 8
#define TC_CBQ_MAXLEVEL 8
#define TC_CBQ_DEF_EWMA 5
struct tc_cbq_lssopt
{
unsigned char change;
unsigned char flags;
#define TCF_CBQ_LSS_BOUNDED 1
#define TCF_CBQ_LSS_ISOLATED 2
unsigned char ewma_log;
unsigned char level;
#define TCF_CBQ_LSS_FLAGS 1
#define TCF_CBQ_LSS_EWMA 2
#define TCF_CBQ_LSS_MAXIDLE 4
#define TCF_CBQ_LSS_MINIDLE 8
#define TCF_CBQ_LSS_OFFTIME 0x10
#define TCF_CBQ_LSS_AVPKT 0x20
__u32 maxidle;
__u32 minidle;
__u32 offtime;
__u32 avpkt;
};
struct tc_cbq_wrropt
{
unsigned char flags;
unsigned char priority;
unsigned char cpriority;
unsigned char __reserved;
__u32 allot;
__u32 weight;
};
struct tc_cbq_ovl
{
unsigned char strategy;
#define TC_CBQ_OVL_CLASSIC 0
#define TC_CBQ_OVL_DELAY 1
#define TC_CBQ_OVL_LOWPRIO 2
#define TC_CBQ_OVL_DROP 3
#define TC_CBQ_OVL_RCLASSIC 4
unsigned char priority2;
__u16 pad;
__u32 penalty;
};
struct tc_cbq_police
{
unsigned char police;
unsigned char __res1;
unsigned short __res2;
};
struct tc_cbq_fopt
{
__u32 split;
__u32 defmap;
__u32 defchange;
};
struct tc_cbq_xstats
{
__u32 borrows;
__u32 overactions;
__s32 avgidle;
__s32 undertime;
};
enum
{
TCA_CBQ_UNSPEC,
TCA_CBQ_LSSOPT,
TCA_CBQ_WRROPT,
TCA_CBQ_FOPT,
TCA_CBQ_OVL_STRATEGY,
TCA_CBQ_RATE,
TCA_CBQ_RTAB,
TCA_CBQ_POLICE,
__TCA_CBQ_MAX,
};
#define TCA_CBQ_MAX (__TCA_CBQ_MAX - 1)
/* dsmark section */
enum {
TCA_DSMARK_UNSPEC,
TCA_DSMARK_INDICES,
TCA_DSMARK_DEFAULT_INDEX,
TCA_DSMARK_SET_TC_INDEX,
TCA_DSMARK_MASK,
TCA_DSMARK_VALUE,
__TCA_DSMARK_MAX,
};
#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1)
/* ATM section */
enum {
TCA_ATM_UNSPEC,
TCA_ATM_FD, /* file/socket descriptor */
TCA_ATM_PTR, /* pointer to descriptor - later */
TCA_ATM_HDR, /* LL header */
TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */
TCA_ATM_ADDR, /* PVC address (for output only) */
TCA_ATM_STATE, /* VC state (ATM_VS_*; for output only) */
__TCA_ATM_MAX,
};
#define TCA_ATM_MAX (__TCA_ATM_MAX - 1)
/* Network emulator */
enum
{
TCA_NETEM_UNSPEC,
TCA_NETEM_CORR,
TCA_NETEM_DELAY_DIST,
TCA_NETEM_REORDER,
TCA_NETEM_CORRUPT,
__TCA_NETEM_MAX,
};
#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
struct tc_netem_qopt
{
__u32 latency; /* added delay (us) */
__u32 limit; /* fifo limit (packets) */
__u32 loss; /* random packet loss (0=none ~0=100%) */
__u32 gap; /* re-ordering gap (0 for none) */
__u32 duplicate; /* random packet dup (0=none ~0=100%) */
__u32 jitter; /* random jitter in latency (us) */
};
struct tc_netem_corr
{
__u32 delay_corr; /* delay correlation */
__u32 loss_corr; /* packet loss correlation */
__u32 dup_corr; /* duplicate correlation */
};
struct tc_netem_reorder
{
__u32 probability;
__u32 correlation;
};
struct tc_netem_corrupt
{
__u32 probability;
__u32 correlation;
};
#define NETEM_DIST_SCALE 8192
#endif

559
include/linux/rtnetlink.h Normal file
View file

@ -0,0 +1,559 @@
#ifndef __LINUX_RTNETLINK_H
#define __LINUX_RTNETLINK_H
#include <linux/netlink.h>
#include <linux/if_link.h>
#include <linux/if_addr.h>
#include <linux/neighbour.h>
/****
* Routing/neighbour discovery messages.
****/
/* Types of messages */
enum {
RTM_BASE = 16,
#define RTM_BASE RTM_BASE
RTM_NEWLINK = 16,
#define RTM_NEWLINK RTM_NEWLINK
RTM_DELLINK,
#define RTM_DELLINK RTM_DELLINK
RTM_GETLINK,
#define RTM_GETLINK RTM_GETLINK
RTM_SETLINK,
#define RTM_SETLINK RTM_SETLINK
RTM_NEWADDR = 20,
#define RTM_NEWADDR RTM_NEWADDR
RTM_DELADDR,
#define RTM_DELADDR RTM_DELADDR
RTM_GETADDR,
#define RTM_GETADDR RTM_GETADDR
RTM_NEWROUTE = 24,
#define RTM_NEWROUTE RTM_NEWROUTE
RTM_DELROUTE,
#define RTM_DELROUTE RTM_DELROUTE
RTM_GETROUTE,
#define RTM_GETROUTE RTM_GETROUTE
RTM_NEWNEIGH = 28,
#define RTM_NEWNEIGH RTM_NEWNEIGH
RTM_DELNEIGH,
#define RTM_DELNEIGH RTM_DELNEIGH
RTM_GETNEIGH,
#define RTM_GETNEIGH RTM_GETNEIGH
RTM_NEWRULE = 32,
#define RTM_NEWRULE RTM_NEWRULE
RTM_DELRULE,
#define RTM_DELRULE RTM_DELRULE
RTM_GETRULE,
#define RTM_GETRULE RTM_GETRULE
RTM_NEWQDISC = 36,
#define RTM_NEWQDISC RTM_NEWQDISC
RTM_DELQDISC,
#define RTM_DELQDISC RTM_DELQDISC
RTM_GETQDISC,
#define RTM_GETQDISC RTM_GETQDISC
RTM_NEWTCLASS = 40,
#define RTM_NEWTCLASS RTM_NEWTCLASS
RTM_DELTCLASS,
#define RTM_DELTCLASS RTM_DELTCLASS
RTM_GETTCLASS,
#define RTM_GETTCLASS RTM_GETTCLASS
RTM_NEWTFILTER = 44,
#define RTM_NEWTFILTER RTM_NEWTFILTER
RTM_DELTFILTER,
#define RTM_DELTFILTER RTM_DELTFILTER
RTM_GETTFILTER,
#define RTM_GETTFILTER RTM_GETTFILTER
RTM_NEWACTION = 48,
#define RTM_NEWACTION RTM_NEWACTION
RTM_DELACTION,
#define RTM_DELACTION RTM_DELACTION
RTM_GETACTION,
#define RTM_GETACTION RTM_GETACTION
RTM_NEWPREFIX = 52,
#define RTM_NEWPREFIX RTM_NEWPREFIX
RTM_GETMULTICAST = 58,
#define RTM_GETMULTICAST RTM_GETMULTICAST
RTM_GETANYCAST = 62,
#define RTM_GETANYCAST RTM_GETANYCAST
RTM_NEWNEIGHTBL = 64,
#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL
RTM_GETNEIGHTBL = 66,
#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL
RTM_SETNEIGHTBL,
#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
#define RTM_NR_MSGTYPES (RTM_MAX + 1 - RTM_BASE)
#define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2)
#define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2)
/*
Generic structure for encapsulation of optional route information.
It is reminiscent of sockaddr, but with sa_family replaced
with attribute type.
*/
struct rtattr
{
unsigned short rta_len;
unsigned short rta_type;
};
/* Macros to handle rtattributes */
#define RTA_ALIGNTO 4
#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
(rta)->rta_len >= sizeof(struct rtattr) && \
(rta)->rta_len <= (len))
#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
(struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len))
#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
/******************************************************************************
* Definitions used in routing table administration.
****/
struct rtmsg
{
unsigned char rtm_family;
unsigned char rtm_dst_len;
unsigned char rtm_src_len;
unsigned char rtm_tos;
unsigned char rtm_table; /* Routing table id */
unsigned char rtm_protocol; /* Routing protocol; see below */
unsigned char rtm_scope; /* See below */
unsigned char rtm_type; /* See below */
unsigned rtm_flags;
};
/* rtm_type */
enum
{
RTN_UNSPEC,
RTN_UNICAST, /* Gateway or direct route */
RTN_LOCAL, /* Accept locally */
RTN_BROADCAST, /* Accept locally as broadcast,
send as broadcast */
RTN_ANYCAST, /* Accept locally as broadcast,
but send as unicast */
RTN_MULTICAST, /* Multicast route */
RTN_BLACKHOLE, /* Drop */
RTN_UNREACHABLE, /* Destination is unreachable */
RTN_PROHIBIT, /* Administratively prohibited */
RTN_THROW, /* Not in this table */
RTN_NAT, /* Translate this address */
RTN_XRESOLVE, /* Use external resolver */
__RTN_MAX
};
#define RTN_MAX (__RTN_MAX - 1)
/* rtm_protocol */
#define RTPROT_UNSPEC 0
#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects;
not used by current IPv4 */
#define RTPROT_KERNEL 2 /* Route installed by kernel */
#define RTPROT_BOOT 3 /* Route installed during boot */
#define RTPROT_STATIC 4 /* Route installed by administrator */
/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
they are just passed from user and back as is.
It will be used by hypothetical multiple routing daemons.
Note that protocol values should be standardized in order to
avoid conflicts.
*/
#define RTPROT_GATED 8 /* Apparently, GateD */
#define RTPROT_RA 9 /* RDISC/ND router advertisements */
#define RTPROT_MRT 10 /* Merit MRT */
#define RTPROT_ZEBRA 11 /* Zebra */
#define RTPROT_BIRD 12 /* BIRD */
#define RTPROT_DNROUTED 13 /* DECnet routing daemon */
#define RTPROT_XORP 14 /* XORP */
#define RTPROT_NTK 15 /* Netsukuku */
/* rtm_scope
Really it is not scope, but sort of distance to the destination.
NOWHERE are reserved for not existing destinations, HOST is our
local addresses, LINK are destinations, located on directly attached
link and UNIVERSE is everywhere in the Universe.
Intermediate values are also possible f.e. interior routes
could be assigned a value between UNIVERSE and LINK.
*/
enum rt_scope_t
{
RT_SCOPE_UNIVERSE=0,
/* User defined values */
RT_SCOPE_SITE=200,
RT_SCOPE_LINK=253,
RT_SCOPE_HOST=254,
RT_SCOPE_NOWHERE=255
};
/* rtm_flags */
#define RTM_F_NOTIFY 0x100 /* Notify user of route change */
#define RTM_F_CLONED 0x200 /* This route is cloned */
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
/* Reserved table identifiers */
enum rt_class_t
{
RT_TABLE_UNSPEC=0,
/* User defined values */
RT_TABLE_DEFAULT=253,
RT_TABLE_MAIN=254,
RT_TABLE_LOCAL=255,
RT_TABLE_MAX=0xFFFFFFFF
};
/* Routing message attributes */
enum rtattr_type_t
{
RTA_UNSPEC,
RTA_DST,
RTA_SRC,
RTA_IIF,
RTA_OIF,
RTA_GATEWAY,
RTA_PRIORITY,
RTA_PREFSRC,
RTA_METRICS,
RTA_MULTIPATH,
RTA_PROTOINFO,
RTA_FLOW,
RTA_CACHEINFO,
RTA_SESSION,
RTA_MP_ALGO,
RTA_TABLE,
__RTA_MAX
};
#define RTA_MAX (__RTA_MAX - 1)
#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
/* RTM_MULTIPATH --- array of struct rtnexthop.
*
* "struct rtnexthop" describes all necessary nexthop information,
* i.e. parameters of path to a destination via this nexthop.
*
* At the moment it is impossible to set different prefsrc, mtu, window
* and rtt for different paths from multipath.
*/
struct rtnexthop
{
unsigned short rtnh_len;
unsigned char rtnh_flags;
unsigned char rtnh_hops;
int rtnh_ifindex;
};
/* rtnh_flags */
#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
#define RTNH_F_ONLINK 4 /* Gateway is forced on link */
/* Macros to handle hexthops */
#define RTNH_ALIGNTO 4
#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) )
#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \
((int)(rtnh)->rtnh_len) <= (len))
#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len)))
#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len))
#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
/* RTM_CACHEINFO */
struct rta_cacheinfo
{
__u32 rta_clntref;
__u32 rta_lastuse;
__s32 rta_expires;
__u32 rta_error;
__u32 rta_used;
#define RTNETLINK_HAVE_PEERINFO 1
__u32 rta_id;
__u32 rta_ts;
__u32 rta_tsage;
};
/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
enum
{
RTAX_UNSPEC,
#define RTAX_UNSPEC RTAX_UNSPEC
RTAX_LOCK,
#define RTAX_LOCK RTAX_LOCK
RTAX_MTU,
#define RTAX_MTU RTAX_MTU
RTAX_WINDOW,
#define RTAX_WINDOW RTAX_WINDOW
RTAX_RTT,
#define RTAX_RTT RTAX_RTT
RTAX_RTTVAR,
#define RTAX_RTTVAR RTAX_RTTVAR
RTAX_SSTHRESH,
#define RTAX_SSTHRESH RTAX_SSTHRESH
RTAX_CWND,
#define RTAX_CWND RTAX_CWND
RTAX_ADVMSS,
#define RTAX_ADVMSS RTAX_ADVMSS
RTAX_REORDERING,
#define RTAX_REORDERING RTAX_REORDERING
RTAX_HOPLIMIT,
#define RTAX_HOPLIMIT RTAX_HOPLIMIT
RTAX_INITCWND,
#define RTAX_INITCWND RTAX_INITCWND
RTAX_FEATURES,
#define RTAX_FEATURES RTAX_FEATURES
__RTAX_MAX
};
#define RTAX_MAX (__RTAX_MAX - 1)
#define RTAX_FEATURE_ECN 0x00000001
#define RTAX_FEATURE_SACK 0x00000002
#define RTAX_FEATURE_TIMESTAMP 0x00000004
#define RTAX_FEATURE_ALLFRAG 0x00000008
struct rta_session
{
__u8 proto;
__u8 pad1;
__u16 pad2;
union {
struct {
__u16 sport;
__u16 dport;
} ports;
struct {
__u8 type;
__u8 code;
__u16 ident;
} icmpt;
__u32 spi;
} u;
};
/****
* General form of address family dependent message.
****/
struct rtgenmsg
{
unsigned char rtgen_family;
};
/*****************************************************************
* Link layer specific messages.
****/
/* struct ifinfomsg
* passes link level specific information, not dependent
* on network protocol.
*/
struct ifinfomsg
{
unsigned char ifi_family;
unsigned char __ifi_pad;
unsigned short ifi_type; /* ARPHRD_* */
int ifi_index; /* Link index */
unsigned ifi_flags; /* IFF_* flags */
unsigned ifi_change; /* IFF_* change mask */
};
/********************************************************************
* prefix information
****/
struct prefixmsg
{
unsigned char prefix_family;
unsigned char prefix_pad1;
unsigned short prefix_pad2;
int prefix_ifindex;
unsigned char prefix_type;
unsigned char prefix_len;
unsigned char prefix_flags;
unsigned char prefix_pad3;
};
enum
{
PREFIX_UNSPEC,
PREFIX_ADDRESS,
PREFIX_CACHEINFO,
__PREFIX_MAX
};
#define PREFIX_MAX (__PREFIX_MAX - 1)
struct prefix_cacheinfo
{
__u32 preferred_time;
__u32 valid_time;
};
/*****************************************************************
* Traffic control messages.
****/
struct tcmsg
{
unsigned char tcm_family;
unsigned char tcm__pad1;
unsigned short tcm__pad2;
int tcm_ifindex;
__u32 tcm_handle;
__u32 tcm_parent;
__u32 tcm_info;
};
enum
{
TCA_UNSPEC,
TCA_KIND,
TCA_OPTIONS,
TCA_STATS,
TCA_XSTATS,
TCA_RATE,
TCA_FCNT,
TCA_STATS2,
__TCA_MAX
};
#define TCA_MAX (__TCA_MAX - 1)
#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
#ifndef __KERNEL__
/* RTnetlink multicast groups - backwards compatibility for userspace */
#define RTMGRP_LINK 1
#define RTMGRP_NOTIFY 2
#define RTMGRP_NEIGH 4
#define RTMGRP_TC 8
#define RTMGRP_IPV4_IFADDR 0x10
#define RTMGRP_IPV4_MROUTE 0x20
#define RTMGRP_IPV4_ROUTE 0x40
#define RTMGRP_IPV4_RULE 0x80
#define RTMGRP_IPV6_IFADDR 0x100
#define RTMGRP_IPV6_MROUTE 0x200
#define RTMGRP_IPV6_ROUTE 0x400
#define RTMGRP_IPV6_IFINFO 0x800
#define RTMGRP_DECnet_IFADDR 0x1000
#define RTMGRP_DECnet_ROUTE 0x4000
#define RTMGRP_IPV6_PREFIX 0x20000
#endif
/* RTnetlink multicast groups */
enum rtnetlink_groups {
RTNLGRP_NONE,
#define RTNLGRP_NONE RTNLGRP_NONE
RTNLGRP_LINK,
#define RTNLGRP_LINK RTNLGRP_LINK
RTNLGRP_NOTIFY,
#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
RTNLGRP_NEIGH,
#define RTNLGRP_NEIGH RTNLGRP_NEIGH
RTNLGRP_TC,
#define RTNLGRP_TC RTNLGRP_TC
RTNLGRP_IPV4_IFADDR,
#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
RTNLGRP_IPV4_MROUTE,
#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE
RTNLGRP_IPV4_ROUTE,
#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE
RTNLGRP_IPV4_RULE,
#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE
RTNLGRP_IPV6_IFADDR,
#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR
RTNLGRP_IPV6_MROUTE,
#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE
RTNLGRP_IPV6_ROUTE,
#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE
RTNLGRP_IPV6_IFINFO,
#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO
RTNLGRP_DECnet_IFADDR,
#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR
RTNLGRP_NOP2,
RTNLGRP_DECnet_ROUTE,
#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE
RTNLGRP_DECnet_RULE,
#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE
RTNLGRP_NOP4,
RTNLGRP_IPV6_PREFIX,
#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX
RTNLGRP_IPV6_RULE,
#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
/* TC action piece */
struct tcamsg
{
unsigned char tca_family;
unsigned char tca__pad1;
unsigned short tca__pad2;
};
#define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
#define TCA_ACT_TAB 1 /* attr type must be >=1 */
#define TCAA_MAX 1
#endif /* __LINUX_RTNETLINK_H */

20
include/netlink-generic.h Normal file
View file

@ -0,0 +1,20 @@
/*
* netlink-generic.h Local Generic Netlink Interface
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_PRIV_H_
#define NETLINK_GENL_PRIV_H_
#include <netlink-local.h>
#include <netlink/netlink.h>
#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
#endif

436
include/netlink-local.h Normal file
View file

@ -0,0 +1,436 @@
/*
* netlink-local.h Local Netlink Interface
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_LOCAL_H_
#define NETLINK_LOCAL_H_
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <time.h>
#include <stdarg.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <inttypes.h>
#include <assert.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif
typedef uint8_t __u8;
typedef uint16_t __u16;
typedef int16_t __s16;
typedef uint32_t __u32;
typedef int32_t __s32;
typedef uint64_t __u64;
/* local header copies */
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/pkt_sched.h>
#include <linux/pkt_cls.h>
#include <linux/gen_stats.h>
#include <netlink/netlink.h>
#include <netlink/handlers.h>
#include <netlink/cache.h>
#include <netlink/route/tc.h>
#include <netlink-types.h>
struct trans_tbl {
int i;
const char *a;
};
#define __ADD(id, name) { .i = id, .a = #name },
struct trans_list {
int i;
char *a;
struct nl_list_head list;
};
#define NL_DEBUG 1
#define NL_DBG(LVL,FMT,ARG...) \
do { \
if (LVL <= nl_debug) \
fprintf(stderr, "DBG<" #LVL ">: " FMT, ##ARG); \
} while (0)
#define BUG() \
do { \
fprintf(stderr, "BUG: %s:%d\n", \
__FILE__, __LINE__); \
assert(0); \
} while (0)
#define RET_ERR(R, E) \
do { \
errno = E; \
return -R; \
} while (0)
extern int __nl_error(int, const char *, unsigned int,
const char *, const char *, ...);
extern int __nl_read_num_str_file(const char *path,
int (*cb)(long, const char *));
#ifdef NL_ERROR_ASSERT
#include <assert.h>
static inline int __assert_error(const char *file, int line, char *func,
const char *fmt, ...)
{
va_list args;
fprintf(stderr, "%s:%d:%s: ", file, line, func);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
assert(0);
return 0;
}
#define nl_error(E, FMT,ARG...) \
__assert_error(__FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
#else
#define nl_error(E, FMT,ARG...) \
__nl_error(E, __FILE__, __LINE__, __FUNCTION__, FMT, ##ARG)
#endif
#define nl_errno(E) nl_error(E, NULL)
static inline int __trans_list_add(int i, const char *a,
struct nl_list_head *head)
{
struct trans_list *tl;
tl = calloc(1, sizeof(*tl));
if (!tl)
return nl_errno(ENOMEM);
tl->i = i;
tl->a = strdup(a);
nl_list_add_tail(&tl->list, head);
return 0;
}
static inline void __trans_list_clear(struct nl_list_head *head)
{
struct trans_list *tl, *next;
nl_list_for_each_entry_safe(tl, next, head, list) {
free(tl->a);
free(tl);
}
}
static inline char *__type2str(int type, char *buf, size_t len,
struct trans_tbl *tbl, size_t tbl_len)
{
int i;
for (i = 0; i < tbl_len; i++) {
if (tbl[i].i == type) {
snprintf(buf, len, "%s", tbl[i].a);
return buf;
}
}
snprintf(buf, len, "0x%x", type);
return buf;
}
static inline char *__list_type2str(int type, char *buf, size_t len,
struct nl_list_head *head)
{
struct trans_list *tl;
nl_list_for_each_entry(tl, head, list) {
if (tl->i == type) {
snprintf(buf, len, "%s", tl->a);
return buf;
}
}
snprintf(buf, len, "0x%x", type);
return buf;
}
static inline char *__flags2str(int flags, char *buf, size_t len,
struct trans_tbl *tbl, size_t tbl_len)
{
int i;
int tmp = flags;
memset(buf, 0, len);
for (i = 0; i < tbl_len; i++) {
if (tbl[i].i & tmp) {
tmp &= ~tbl[i].i;
strncat(buf, tbl[i].a, len - strlen(buf) - 1);
if ((tmp & flags))
strncat(buf, ",", len - strlen(buf) - 1);
}
}
return buf;
}
static inline int __str2type(const char *buf, struct trans_tbl *tbl,
size_t tbl_len)
{
unsigned long l;
char *end;
int i;
if (*buf == '\0')
return -1;
for (i = 0; i < tbl_len; i++)
if (!strcasecmp(tbl[i].a, buf))
return tbl[i].i;
l = strtoul(buf, &end, 0);
if (l == ULONG_MAX || *end != '\0')
return -1;
return (int) l;
}
static inline int __list_str2type(const char *buf, struct nl_list_head *head)
{
struct trans_list *tl;
unsigned long l;
char *end;
if (*buf == '\0')
return -1;
nl_list_for_each_entry(tl, head, list) {
if (!strcasecmp(tl->a, buf))
return tl->i;
}
l = strtoul(buf, &end, 0);
if (l == ULONG_MAX || *end != '\0')
return -1;
return (int) l;
}
static inline int __str2flags(const char *buf, struct trans_tbl *tbl,
size_t tbl_len)
{
int i, flags = 0, len;
char *p = (char *) buf, *t;
for (;;) {
if (*p == ' ')
p++;
t = strchr(p, ',');
len = t ? t - p : strlen(p);
for (i = 0; i < tbl_len; i++)
if (!strncasecmp(tbl[i].a, p, len))
flags |= tbl[i].i;
if (!t)
return flags;
p = ++t;
}
return 0;
}
static inline void dp_new_line(struct nl_dump_params *params,
int line_nr)
{
if (params->dp_prefix) {
int i;
for (i = 0; i < params->dp_prefix; i++) {
if (params->dp_fd)
fprintf(params->dp_fd, " ");
else if (params->dp_buf)
strncat(params->dp_buf, " ",
params->dp_buflen -
sizeof(params->dp_buf) - 1);
}
}
if (params->dp_nl_cb)
params->dp_nl_cb(params, line_nr);
}
static inline void __dp_dump(struct nl_dump_params *parms, const char *fmt,
va_list args)
{
if (parms->dp_fd)
vfprintf(parms->dp_fd, fmt, args);
else if (parms->dp_buf || parms->dp_cb) {
char *buf = NULL;
vasprintf(&buf, fmt, args);
if (parms->dp_cb)
parms->dp_cb(parms, buf);
else
strncat(parms->dp_buf, buf,
parms->dp_buflen - strlen(parms->dp_buf) - 1);
free(buf);
}
}
static inline void dp_dump(struct nl_dump_params *parms, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
__dp_dump(parms, fmt, args);
va_end(args);
}
static inline void dp_dump_line(struct nl_dump_params *parms, int line,
const char *fmt, ...)
{
va_list args;
dp_new_line(parms, line);
va_start(args, fmt);
__dp_dump(parms, fmt, args);
va_end(args);
}
static inline void dump_from_ops(struct nl_object *obj,
struct nl_dump_params *params)
{
int type = params->dp_type;
if (type < 0 || type > NL_DUMP_MAX)
BUG();
if (params->dp_dump_msgtype) {
#if 0
/* XXX */
char buf[64];
dp_dump_line(params, 0, "%s ",
nl_cache_mngt_type2name(obj->ce_ops,
obj->ce_ops->co_protocol,
obj->ce_msgtype,
buf, sizeof(buf)));
#endif
params->dp_pre_dump = 1;
} else
dp_new_line(params, 0);
if (obj->ce_ops->oo_dump[type])
obj->ce_ops->oo_dump[type](obj, params);
}
static inline struct nl_cache *dp_cache(struct nl_object *obj)
{
if (obj->ce_cache == NULL)
return nl_cache_mngt_require(obj->ce_ops->oo_name);
return obj->ce_cache;
}
static inline int nl_cb_call(struct nl_cb *cb, int type, struct nl_msg *msg)
{
return cb->cb_set[type](msg, cb->cb_args[type]);
}
#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define __init __attribute__ ((constructor))
#define __exit __attribute__ ((destructor))
#define P_ACCEPT 0
#define P_IGNORE 0
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
#define max(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x > _y ? _x : _y; })
#define min_t(type,x,y) \
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
#define max_t(type,x,y) \
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
struct nlmsghdr *, struct nl_parser_param *);
static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
struct tc_ratespec *src)
{
dst->rs_cell_log = src->cell_log;
dst->rs_feature = src->feature;
dst->rs_addend = src->addend;
dst->rs_mpu = src->mpu;
dst->rs_rate = src->rate;
}
static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
struct rtnl_ratespec *src)
{
dst->cell_log = src->rs_cell_log;
dst->feature = src->rs_feature;
dst->addend = src->rs_addend;
dst->mpu = src->rs_mpu;
dst->rate = src->rs_rate;
}
static inline char *nl_cache_name(struct nl_cache *cache)
{
return cache->c_ops ? cache->c_ops->co_name : "unknown";
}
#define GENL_FAMILY(id, name) \
{ \
{ id, NL_ACT_UNSPEC, name }, \
END_OF_MSGTYPES_LIST, \
}
#define REQUESTED(LIST, ATTR) ((LIST) & (ATTR))
#define AVAILABLE(A, B, ATTR) (((A)->ce_mask & (B)->ce_mask) & (ATTR))
#define ATTR_MATCH(A, B, ATTR, EXPR) (!AVAILABLE(A, B, ATTR) || (EXPR))
#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
({ int diff = 0; \
if (REQUESTED(LIST, ATTR) && ATTR_MATCH(A, B, ATTR, EXPR)) \
diff = ATTR; \
diff; })
#endif

70
include/netlink-tc.h Normal file
View file

@ -0,0 +1,70 @@
/*
* netlink-tc.h Local Traffic Control Interface
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_TC_PRIV_H_
#define NETLINK_TC_PRIV_H_
#include <netlink-local.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TCA_ATTR_HANDLE 0x001
#define TCA_ATTR_PARENT 0x002
#define TCA_ATTR_IFINDEX 0x004
#define TCA_ATTR_KIND 0x008
#define TCA_ATTR_FAMILY 0x010
#define TCA_ATTR_INFO 0x020
#define TCA_ATTR_OPTS 0x040
#define TCA_ATTR_STATS 0x080
#define TCA_ATTR_XSTATS 0x100
#define TCA_ATTR_MAX TCA_ATTR_XSTATS
extern int tca_parse(struct nlattr **, int, struct rtnl_tca *,
struct nla_policy *);
extern int tca_msg_parser(struct nlmsghdr *, struct rtnl_tca *);
extern void tca_free_data(struct rtnl_tca *);
extern int tca_clone(struct rtnl_tca *, struct rtnl_tca *);
extern int tca_dump_brief(struct rtnl_tca *, const char *,
struct nl_dump_params *, int);
extern int tca_dump_full(struct rtnl_tca *, struct nl_dump_params *, int);
extern int tca_dump_stats(struct rtnl_tca *,
struct nl_dump_params *, int);
extern int tca_compare(struct nl_object *, struct nl_object *, uint32_t, int);
extern void tca_set_ifindex(struct rtnl_tca *, int);
extern int tca_get_ifindex(struct rtnl_tca *);
extern void tca_set_handle(struct rtnl_tca *, uint32_t);
extern uint32_t tca_get_handle(struct rtnl_tca *);
extern void tca_set_parent(struct rtnl_tca *, uint32_t);
extern uint32_t tca_get_parent(struct rtnl_tca *);
extern void tca_set_kind(struct rtnl_tca *, const char *);
extern char *tca_get_kind(struct rtnl_tca *);
extern uint64_t tca_get_stat(struct rtnl_tca *, int );
extern struct nl_msg *tca_build_msg(struct rtnl_tca *tca, int type, int flags);
static inline void *tca_priv(struct rtnl_tca *tca)
{
return tca->tc_subdata;
}
static inline void *tca_xstats(struct rtnl_tca *tca)
{
return tca->tc_xstats->d_data;
}
#ifdef __cplusplus
}
#endif
#endif

865
include/netlink-types.h Normal file
View file

@ -0,0 +1,865 @@
/*
* netlink-types.h Netlink Types (Private)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_LOCAL_TYPES_H_
#define NETLINK_LOCAL_TYPES_H_
#include <netlink/list.h>
#include <netlink/route/link.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
#define NL_SOCK_BUFSIZE_SET (1<<0)
#define NL_SOCK_PASSCRED (1<<1)
#define NL_OWN_PORT (1<<2)
#define NL_MSG_PEEK (1<<3)
#define NL_MSG_CRED_PRESENT 1
struct nl_cache_ops;
struct nl_handle;
struct nl_object;
struct nl_cb
{
nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1];
void * cb_args[NL_CB_TYPE_MAX+1];
nl_recvmsg_err_cb_t cb_err;
void * cb_err_arg;
/** May be used to replace nl_recvmsgs with your own implementation
* in all internal calls to nl_recvmsgs. */
int (*cb_recvmsgs_ow)(struct nl_handle *,
struct nl_cb *);
/** Overwrite internal calls to nl_recv, must return the number of
* octets read and allocate a buffer for the received data. */
int (*cb_recv_ow)(struct nl_handle *,
struct sockaddr_nl *,
unsigned char **,
struct ucred **);
/** Overwrites internal calls to nl_send, must send the netlink
* message. */
int (*cb_send_ow)(struct nl_handle *,
struct nl_msg *);
int cb_refcnt;
};
struct nl_handle
{
struct sockaddr_nl h_local;
struct sockaddr_nl h_peer;
int h_fd;
int h_proto;
unsigned int h_seq_next;
unsigned int h_seq_expect;
int h_flags;
struct nl_cb * h_cb;
};
struct nl_cache
{
struct nl_list_head c_items;
int c_nitems;
int c_iarg1;
int c_iarg2;
struct nl_cache_ops * c_ops;
};
struct nl_cache_assoc
{
struct nl_cache * ca_cache;
change_func_t ca_change;
};
struct nl_cache_mngr
{
int cm_protocol;
int cm_flags;
int cm_nassocs;
struct nl_handle * cm_handle;
struct nl_cache_assoc * cm_assocs;
};
struct nl_parser_param;
enum {
NL_ACT_UNSPEC,
NL_ACT_NEW,
NL_ACT_DEL,
NL_ACT_GET,
NL_ACT_SET,
NL_ACT_CHANGE,
__NL_ACT_MAX,
};
#define NL_ACT_MAX (__NL_ACT_MAX - 1)
#define END_OF_MSGTYPES_LIST { -1, -1, NULL }
struct nl_msgtype
{
int mt_id;
int mt_act;
char * mt_name;
};
struct genl_info
{
struct sockaddr_nl * who;
struct nlmsghdr * nlh;
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
};
#define LOOSE_FLAG_COMPARISON 1
struct nl_object_ops
{
/* Name of object */
char * oo_name;
/* Size of object structure */
size_t oo_size;
/* List of attributes needed to uniquely identify the object */
uint32_t oo_id_attrs;
/**
* Called whenever a new object was allocated
*/
void (*oo_constructor)(struct nl_object *);
/**
* Called whenever a object in the cache gets destroyed, must
* free the type specific memory allocations
*/
void (*oo_free_data)(struct nl_object *);
/**
* Callened whenever an object needs to be cloned
*/
int (*oo_clone)(struct nl_object *, struct nl_object *);
/**
* Called whenever a dump of a cache object is requested. Must
* dump the specified object to the specified file descriptor
*/
int (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
struct nl_dump_params *);
int (*oo_compare)(struct nl_object *, struct nl_object *,
uint32_t, int);
char *(*oo_attrs2str)(int, char *, size_t);
};
struct nl_af_group
{
int ag_family;
int ag_group;
};
#define END_OF_GROUP_LIST AF_UNSPEC, 0
struct nl_cache_ops
{
char * co_name;
int co_hdrsize;
int co_protocol;
struct nl_af_group * co_groups;
/**
* Called whenever an update of the cache is required. Must send
* a request message to the kernel requesting a complete dump.
*/
int (*co_request_update)(struct nl_cache *, struct nl_handle *);
/**
* Called whenever a message was received that needs to be parsed.
* Must parse the message and call the paser callback function
* (nl_parser_param) provided via the argument.
*/
int (*co_msg_parser)(struct nl_cache_ops *, struct sockaddr_nl *,
struct nlmsghdr *, void *);
struct nl_object_ops * co_obj_ops;
struct nl_cache_ops *co_next;
struct nl_cache *co_major_cache;
struct genl_ops * co_genl;
struct nl_msgtype co_msgtypes[];
};
#define NL_OBJ_MARK 1
#define NLHDR_COMMON \
int ce_refcnt; \
struct nl_object_ops * ce_ops; \
struct nl_cache * ce_cache; \
struct nl_list_head ce_list; \
int ce_msgtype; \
int ce_flags; \
uint32_t ce_mask;
struct nl_object
{
NLHDR_COMMON
};
struct nl_parser_param
{
int (*pp_cb)(struct nl_object *, struct nl_parser_param *);
void * pp_arg;
};
struct nl_data
{
size_t d_size;
void * d_data;
};
struct nl_addr
{
int a_family;
unsigned int a_maxsize;
unsigned int a_len;
int a_prefixlen;
int a_refcnt;
char a_addr[0];
};
struct nl_msg
{
int nm_protocol;
int nm_flags;
struct sockaddr_nl nm_src;
struct sockaddr_nl nm_dst;
struct ucred nm_creds;
struct nlmsghdr * nm_nlh;
};
struct rtnl_link_map
{
uint64_t lm_mem_start;
uint64_t lm_mem_end;
uint64_t lm_base_addr;
uint16_t lm_irq;
uint8_t lm_dma;
uint8_t lm_port;
};
#define IFQDISCSIZ 32
struct rtnl_link
{
NLHDR_COMMON
char l_name[IFNAMSIZ];
uint32_t l_family;
uint32_t l_arptype;
uint32_t l_index;
uint32_t l_flags;
uint32_t l_change;
uint32_t l_mtu;
uint32_t l_link;
uint32_t l_txqlen;
uint32_t l_weight;
uint32_t l_master;
struct nl_addr *l_addr;
struct nl_addr *l_bcast;
char l_qdisc[IFQDISCSIZ];
struct rtnl_link_map l_map;
uint64_t l_stats[RTNL_LINK_STATS_MAX+1];
uint32_t l_flag_mask;
};
struct rtnl_ncacheinfo
{
uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */
uint32_t nci_used; /**< Time since neighbour entry was last ued */
uint32_t nci_updated; /**< Time since last update */
uint32_t nci_refcnt; /**< Reference counter */
};
struct rtnl_neigh
{
NLHDR_COMMON
uint32_t n_family;
uint32_t n_ifindex;
uint16_t n_state;
uint8_t n_flags;
uint8_t n_type;
struct nl_addr *n_lladdr;
struct nl_addr *n_dst;
uint32_t n_probes;
struct rtnl_ncacheinfo n_cacheinfo;
uint32_t n_state_mask;
uint32_t n_flag_mask;
};
struct rtnl_addr_cacheinfo
{
/* Preferred lifetime in seconds */
uint32_t aci_prefered;
/* Valid lifetime in seconds */
uint32_t aci_valid;
/* Timestamp of creation in 1/100s seince boottime */
uint32_t aci_cstamp;
/* Timestamp of last update in 1/100s since boottime */
uint32_t aci_tstamp;
};
struct rtnl_addr
{
NLHDR_COMMON
uint8_t a_family;
uint8_t a_prefixlen;
uint8_t a_flags;
uint8_t a_scope;
uint32_t a_ifindex;
struct nl_addr *a_peer;
struct nl_addr *a_local;
struct nl_addr *a_bcast;
struct nl_addr *a_anycast;
struct nl_addr *a_multicast;
struct rtnl_addr_cacheinfo a_cacheinfo;
char a_label[IFNAMSIZ];
uint32_t a_flag_mask;
};
#define NEXTHOP_HAS_FLAGS 0x000001
#define NEXTHOP_HAS_WEIGHT 0x000002
#define NEXTHOP_HAS_IFINDEX 0x000004
#define NEXTHOP_HAS_GATEWAY 0x000008
struct rtnl_nexthop
{
uint8_t rtnh_flags;
uint8_t rtnh_flag_mask;
uint8_t rtnh_weight;
/* 1 byte spare */
uint32_t rtnh_ifindex;
struct nl_addr * rtnh_gateway;
uint32_t rtnh_mask;
struct nl_list_head rtnh_list;
};
struct rtnl_route
{
NLHDR_COMMON
uint8_t rt_family;
uint8_t rt_dst_len;
uint8_t rt_src_len;
uint8_t rt_tos;
uint8_t rt_table;
uint8_t rt_protocol;
uint8_t rt_scope;
uint8_t rt_type;
uint32_t rt_flags;
struct nl_addr * rt_dst;
struct nl_addr * rt_src;
char rt_iif[IFNAMSIZ];
uint32_t rt_oif;
struct nl_addr * rt_gateway;
uint32_t rt_prio;
uint32_t rt_metrics[RTAX_MAX];
uint32_t rt_metrics_mask;
struct nl_addr * rt_pref_src;
struct nl_list_head rt_nexthops;
realm_t rt_realms;
struct rtnl_rtcacheinfo rt_cacheinfo;
uint32_t rt_mp_algo;
uint32_t rt_flag_mask;
};
struct rtnl_rule
{
NLHDR_COMMON
uint64_t r_mark;
uint32_t r_prio;
uint32_t r_realms;
uint32_t r_table;
uint8_t r_dsfield;
uint8_t r_type;
uint8_t r_family;
uint8_t r_src_len;
uint8_t r_dst_len;
char r_iif[IFNAMSIZ];
struct nl_addr *r_src;
struct nl_addr *r_dst;
struct nl_addr *r_srcmap;
};
struct rtnl_neightbl_parms
{
/**
* Interface index of the device this parameter set is assigned
* to or 0 for the default set.
*/
uint32_t ntp_ifindex;
/**
* Number of references to this parameter set.
*/
uint32_t ntp_refcnt;
/**
* Queue length for pending arp requests, i.e. the number of
* packets which are accepted from other layers while the
* neighbour address is still being resolved
*/
uint32_t ntp_queue_len;
/**
* Number of requests to send to the user level ARP daemon.
* Specify 0 to disable.
*/
uint32_t ntp_app_probes;
/**
* Maximum number of retries for unicast solicitation.
*/
uint32_t ntp_ucast_probes;
/**
* Maximum number of retries for multicast solicitation.
*/
uint32_t ntp_mcast_probes;
/**
* Base value in milliseconds to ompute reachable time, see RFC2461.
*/
uint64_t ntp_base_reachable_time;
/**
* Actual reachable time (read-only)
*/
uint64_t ntp_reachable_time; /* secs */
/**
* The time in milliseconds between retransmitted Neighbor
* Solicitation messages.
*/
uint64_t ntp_retrans_time;
/**
* Interval in milliseconds to check for stale neighbour
* entries.
*/
uint64_t ntp_gc_stale_time; /* secs */
/**
* Delay in milliseconds for the first time probe if
* the neighbour is reachable.
*/
uint64_t ntp_probe_delay; /* secs */
/**
* Maximum delay in milliseconds of an answer to a neighbour
* solicitation message.
*/
uint64_t ntp_anycast_delay;
/**
* Minimum age in milliseconds before a neighbour entry
* may be replaced.
*/
uint64_t ntp_locktime;
/**
* Delay in milliseconds before answering to an ARP request
* for which a proxy ARP entry exists.
*/
uint64_t ntp_proxy_delay;
/**
* Queue length for the delayed proxy arp requests.
*/
uint32_t ntp_proxy_qlen;
/**
* Mask of available parameter attributes
*/
uint32_t ntp_mask;
};
#define NTBLNAMSIZ 32
/**
* Neighbour table
* @ingroup neightbl
*/
struct rtnl_neightbl
{
NLHDR_COMMON
char nt_name[NTBLNAMSIZ];
uint32_t nt_family;
uint32_t nt_gc_thresh1;
uint32_t nt_gc_thresh2;
uint32_t nt_gc_thresh3;
uint64_t nt_gc_interval;
struct ndt_config nt_config;
struct rtnl_neightbl_parms nt_parms;
struct ndt_stats nt_stats;
};
struct rtnl_ratespec
{
uint8_t rs_cell_log;
uint16_t rs_feature;
uint16_t rs_addend;
uint16_t rs_mpu;
uint32_t rs_rate;
};
struct rtnl_tstats
{
struct {
uint64_t bytes;
uint64_t packets;
} tcs_basic;
struct {
uint32_t bps;
uint32_t pps;
} tcs_rate_est;
struct {
uint32_t qlen;
uint32_t backlog;
uint32_t drops;
uint32_t requeues;
uint32_t overlimits;
} tcs_queue;
};
#define TCKINDSIZ 32
#define NL_TCA_GENERIC(pre) \
NLHDR_COMMON \
uint32_t pre ##_family; \
uint32_t pre ##_ifindex; \
uint32_t pre ##_handle; \
uint32_t pre ##_parent; \
uint32_t pre ##_info; \
char pre ##_kind[TCKINDSIZ]; \
struct nl_data * pre ##_opts; \
uint64_t pre ##_stats[RTNL_TC_STATS_MAX+1]; \
struct nl_data * pre ##_xstats; \
void * pre ##_subdata; \
struct rtnl_tca
{
NL_TCA_GENERIC(tc);
};
struct rtnl_qdisc
{
NL_TCA_GENERIC(q);
struct rtnl_qdisc_ops *q_ops;
};
struct rtnl_class
{
NL_TCA_GENERIC(c);
struct rtnl_class_ops *c_ops;
};
struct rtnl_cls
{
NL_TCA_GENERIC(c);
uint32_t c_prio;
uint32_t c_protocol;
struct rtnl_cls_ops *c_ops;
};
struct rtnl_u32
{
uint32_t cu_divisor;
uint32_t cu_hash;
uint32_t cu_classid;
uint32_t cu_link;
struct nl_data * cu_pcnt;
struct nl_data * cu_selector;
struct nl_data * cu_act;
struct nl_data * cu_police;
char cu_indev[IFNAMSIZ];
int cu_mask;
};
struct rtnl_fw
{
uint32_t cf_classid;
struct nl_data * cf_act;
struct nl_data * cf_police;
char cf_indev[IFNAMSIZ];
int cf_mask;
};
struct rtnl_dsmark_qdisc
{
uint16_t qdm_indices;
uint16_t qdm_default_index;
uint32_t qdm_set_tc_index;
uint32_t qdm_mask;
};
struct rtnl_dsmark_class
{
uint8_t cdm_bmask;
uint8_t cdm_value;
uint32_t cdm_mask;
};
struct rtnl_fifo
{
uint32_t qf_limit;
uint32_t qf_mask;
};
struct rtnl_prio
{
uint32_t qp_bands;
uint8_t qp_priomap[TC_PRIO_MAX+1];
uint32_t qp_mask;
};
struct rtnl_tbf
{
uint32_t qt_limit;
uint32_t qt_mpu;
struct rtnl_ratespec qt_rate;
uint32_t qt_rate_bucket;
uint32_t qt_rate_txtime;
struct rtnl_ratespec qt_peakrate;
uint32_t qt_peakrate_bucket;
uint32_t qt_peakrate_txtime;
uint32_t qt_mask;
};
struct rtnl_sfq
{
uint32_t qs_quantum;
uint32_t qs_perturb;
uint32_t qs_limit;
uint32_t qs_divisor;
uint32_t qs_flows;
uint32_t qs_mask;
};
struct rtnl_netem_corr
{
uint32_t nmc_delay;
uint32_t nmc_loss;
uint32_t nmc_duplicate;
};
struct rtnl_netem_reo
{
uint32_t nmro_probability;
uint32_t nmro_correlation;
};
struct rtnl_netem
{
uint32_t qnm_latency;
uint32_t qnm_limit;
uint32_t qnm_loss;
uint32_t qnm_gap;
uint32_t qnm_duplicate;
uint32_t qnm_jitter;
uint32_t qnm_mask;
struct rtnl_netem_corr qnm_corr;
struct rtnl_netem_reo qnm_ro;
};
struct rtnl_htb_qdisc
{
uint32_t qh_rate2quantum;
uint32_t qh_defcls;
uint32_t qh_mask;
};
struct rtnl_htb_class
{
uint32_t ch_prio;
uint32_t ch_mtu;
struct rtnl_ratespec ch_rate;
struct rtnl_ratespec ch_ceil;
uint32_t ch_rbuffer;
uint32_t ch_cbuffer;
uint32_t ch_quantum;
uint8_t ch_overhead;
uint8_t ch_mpu;
uint32_t ch_mask;
};
struct rtnl_cbq
{
struct tc_cbq_lssopt cbq_lss;
struct tc_ratespec cbq_rate;
struct tc_cbq_wrropt cbq_wrr;
struct tc_cbq_ovl cbq_ovl;
struct tc_cbq_fopt cbq_fopt;
struct tc_cbq_police cbq_police;
};
struct rtnl_red
{
uint32_t qr_limit;
uint32_t qr_qth_min;
uint32_t qr_qth_max;
uint8_t qr_flags;
uint8_t qr_wlog;
uint8_t qr_plog;
uint8_t qr_scell_log;
uint32_t qr_mask;
};
struct flnl_request
{
NLHDR_COMMON
struct nl_addr * lr_addr;
uint32_t lr_fwmark;
uint8_t lr_tos;
uint8_t lr_scope;
uint8_t lr_table;
};
struct flnl_result
{
NLHDR_COMMON
struct flnl_request * fr_req;
uint8_t fr_table_id;
uint8_t fr_prefixlen;
uint8_t fr_nh_sel;
uint8_t fr_type;
uint8_t fr_scope;
uint32_t fr_error;
};
#define GENL_OP_HAS_POLICY 1
#define GENL_OP_HAS_DOIT 2
#define GENL_OP_HAS_DUMPIT 4
struct genl_family_op
{
uint32_t o_id;
uint32_t o_flags;
struct nl_list_head o_list;
};
struct genl_family
{
NLHDR_COMMON
uint16_t gf_id;
char gf_name[GENL_NAMSIZ];
uint32_t gf_version;
uint32_t gf_hdrsize;
uint32_t gf_maxattr;
struct nl_list_head gf_ops;
};
union nfnl_ct_proto
{
struct {
uint16_t src;
uint16_t dst;
} port;
struct {
uint16_t id;
uint8_t type;
uint8_t code;
} icmp;
};
struct nfnl_ct_dir {
struct nl_addr * src;
struct nl_addr * dst;
union nfnl_ct_proto proto;
uint64_t packets;
uint64_t bytes;
};
union nfnl_ct_protoinfo {
struct {
uint8_t state;
} tcp;
};
struct nfnl_ct {
NLHDR_COMMON
uint8_t ct_family;
uint8_t ct_proto;
union nfnl_ct_protoinfo ct_protoinfo;
uint32_t ct_status;
uint32_t ct_timeout;
uint32_t ct_mark;
uint32_t ct_use;
uint32_t ct_id;
struct nfnl_ct_dir ct_orig;
struct nfnl_ct_dir ct_repl;
};
struct nfnl_log {
NLHDR_COMMON
uint8_t log_family;
uint8_t log_hook;
uint16_t log_hwproto;
uint32_t log_mark;
struct timeval log_timestamp;
uint32_t log_indev;
uint32_t log_outdev;
uint32_t log_physindev;
uint32_t log_physoutdev;
uint8_t log_hwaddr[8];
int log_hwaddr_len;
void * log_payload;
int log_payload_len;
char * log_prefix;
uint32_t log_uid;
uint32_t log_seq;
uint32_t log_seq_global;
};
#endif

67
include/netlink/addr.h Normal file
View file

@ -0,0 +1,67 @@
/*
* netlink/addr.h Abstract Address
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_ADDR_H_
#define NETLINK_ADDR_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_addr;
/* Creation */
extern struct nl_addr * nl_addr_alloc(size_t);
extern struct nl_addr * nl_addr_build(int, void *, size_t);
extern struct nl_addr * nl_addr_parse(const char *, int);
extern struct nl_addr * nl_addr_clone(struct nl_addr *);
/* Destroyage */
extern void nl_addr_destroy(struct nl_addr *);
/* Usage Management */
extern struct nl_addr * nl_addr_get(struct nl_addr *);
extern void nl_addr_put(struct nl_addr *);
extern int nl_addr_shared(struct nl_addr *);
extern int nl_addr_cmp(struct nl_addr *, struct nl_addr *);
extern int nl_addr_cmp_prefix(struct nl_addr *, struct nl_addr *);
extern int nl_addr_valid(char *, int);
extern int nl_addr_guess_family(struct nl_addr *);
extern int nl_addr_fill_sockaddr(struct nl_addr *,
struct sockaddr *, socklen_t *);
extern struct addrinfo *nl_addr_info(struct nl_addr *addr);
extern int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen);
/* Access Functions */
extern void nl_addr_set_family(struct nl_addr *, int);
extern int nl_addr_get_family(struct nl_addr *);
extern int nl_addr_set_binary_addr(struct nl_addr *, void *,
size_t);
extern void * nl_addr_get_binary_addr(struct nl_addr *);
extern unsigned int nl_addr_get_len(struct nl_addr *);
extern void nl_addr_set_prefixlen(struct nl_addr *, int);
extern unsigned int nl_addr_get_prefixlen(struct nl_addr *);
/* Address Family Translations */
extern char * nl_af2str(int, char *, size_t);
extern int nl_str2af(const char *);
/* Translations to Strings */
extern char * nl_addr2str(struct nl_addr *, char *, size_t);
#ifdef __cplusplus
}
#endif
#endif

287
include/netlink/attr.h Normal file
View file

@ -0,0 +1,287 @@
/*
* netlink/attr.h Netlink Attributes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_ATTR_H_
#define NETLINK_ATTR_H_
#include <netlink/netlink.h>
#include <netlink/object.h>
#include <netlink/addr.h>
#include <netlink/data.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_msg;
/**
* @name Validation Policy Types
* @{
*/
/**
* @ingroup attr
* Standard attribute types to specify validation policy
*/
enum {
NLA_UNSPEC, /**< Unspecified type */
NLA_U8, /**< 8bit integer */
NLA_U16, /**< 16bit integer */
NLA_U32, /**< 32bit integer */
NLA_U64, /**< 64bit integer */
NLA_STRING, /**< character string */
NLA_FLAG, /**< flag */
NLA_MSECS, /**< micro seconds (64bit) */
NLA_NESTED, /**< nested attributes */
__NLA_TYPE_MAX,
};
/**
* @ingroup attr
* Maximum netlink validation policy type
*/
#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
/** @} */
/**
* @ingroup attr
* attribute validation policy
*
* Policies are defined as arrays of this struct, the array must
* be accessible by attribute type up to the highest identifier
* to be expected.
*
* Example:
* @code
* static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = {
* [ATTR_FOO] = { .type = NLA_U16 },
* [ATTR_BAR] = { .type = NLA_STRING },
* [ATTR_BAZ] = { .minlen = sizeof(struct mystruct) },
* };
* @endcode
*/
struct nla_policy {
/** Type of attribute or NLA_UNSPEC */
uint16_t type;
/** Minimal length of payload required to be available */
uint16_t minlen;
/** Maximal length of payload required to be available */
uint16_t maxlen;
};
/* size calculations */
extern int nla_attr_size(int payload);
extern int nla_total_size(int payload);
extern int nla_padlen(int payload);
/* payload access */
extern int nla_type(const struct nlattr *);
extern void * nla_data(const struct nlattr *);
extern int nla_len(const struct nlattr *);
/* attribute parsing */
extern int nla_ok(const struct nlattr *, int);
extern struct nlattr * nla_next(const struct nlattr *, int *);
extern int nla_parse(struct nlattr **, int, struct nlattr *,
int, struct nla_policy *);
extern int nla_parse_nested(struct nlattr **, int, struct nlattr *,
struct nla_policy *);
extern int nla_validate(struct nlattr *, int, int,
struct nla_policy *);
extern struct nlattr * nla_find(struct nlattr *, int, int);
/* utilities */
extern int nla_memcpy(void *, struct nlattr *, int);
extern size_t nla_strlcpy(char *, const struct nlattr *, size_t);
extern int nla_memcmp(const struct nlattr *, const void *, size_t);
extern int nla_strcmp(const struct nlattr *, const char *);
/* attribute construction */
extern struct nlattr * nla_reserve(struct nl_msg *, int, int);
extern int nla_put(struct nl_msg *, int, int, const void *);
extern int nla_put_nested(struct nl_msg *, int, struct nl_msg *);
extern int nla_put_u8(struct nl_msg *, int, uint8_t);
extern int nla_put_u16(struct nl_msg *, int, uint16_t);
extern int nla_put_u32(struct nl_msg *, int, uint32_t);
extern int nla_put_u64(struct nl_msg *, int, uint64_t);
extern int nla_put_string(struct nl_msg *, int, const char *);
extern int nla_put_flag(struct nl_msg *, int);
extern int nla_put_msecs(struct nl_msg *, int, unsigned long);
extern int nla_put_data(struct nl_msg *, int, struct nl_data *);
extern int nla_put_addr(struct nl_msg *, int, struct nl_addr *);
/* attribute nesting */
extern struct nlattr * nla_nest_start(struct nl_msg *, int);
extern int nla_nest_end(struct nl_msg *, struct nlattr *);
/* attribute reading */
extern uint8_t nla_get_u8(struct nlattr *);
extern uint16_t nla_get_u16(struct nlattr *);
extern uint32_t nla_get_u32(struct nlattr *);
extern uint64_t nla_get_u64(struct nlattr *);
extern char * nla_get_string(struct nlattr *);
extern int nla_get_flag(struct nlattr *);
extern unsigned long nla_get_msecs(struct nlattr *);
extern struct nl_data * nla_get_data(struct nlattr *);
extern struct nl_addr * nla_get_addr(struct nlattr *, int);
/**
* @name Attribute Construction (Exception Based)
*
* All these functions jump to nla_put_failure in case of a failure
* instead of returning an error code.
*
* @{
*/
/**
* @ingroup attr
* Add a netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg attrlen length of attribute payload
* @arg data head of attribute payload
*/
#define NLA_PUT(n, attrtype, attrlen, data) \
do { \
if (nla_put(n, attrtype, attrlen, data) < 0) \
goto nla_put_failure; \
} while(0)
/**
* @ingroup attr
* Add a basic netlink attribute to a netlink message
* @arg n netlink message
* @arg type atomic type
* @arg attrtype attribute type
* @arg value head of attribute payload
*/
#define NLA_PUT_TYPE(n, type, attrtype, value) \
do { \
type __tmp = value; \
NLA_PUT(n, attrtype, sizeof(type), &__tmp); \
} while(0)
/**
* Add a u8 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
#define NLA_PUT_U8(n, attrtype, value) \
NLA_PUT_TYPE(n, uint8_t, attrtype, value)
/**
* Add a u16 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
#define NLA_PUT_U16(n, attrtype, value) \
NLA_PUT_TYPE(n, uint16_t, attrtype, value)
/**
* Add a u32 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
#define NLA_PUT_U32(n, attrtype, value) \
NLA_PUT_TYPE(n, uint32_t, attrtype, value)
/**
* Add a u64 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
#define NLA_PUT_U64(n, attrtype, value) \
NLA_PUT_TYPE(n, uint64_t, attrtype, value)
/**
* Add a character string netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value character string
*/
#define NLA_PUT_STRING(n, attrtype, value) \
NLA_PUT(n, attrtype, strlen(value) + 1, value)
/**
* Add a flag netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
*/
#define NLA_PUT_FLAG(n, attrtype) \
NLA_PUT(n, attrtype, 0, NULL)
/**
* Add a msecs netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg msecs numeric value in micro seconds
*/
#define NLA_PUT_MSECS(n, attrtype, msecs) \
NLA_PUT_U64(n, attrtype, msecs)
/**
* Add a address attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg addr abstract address object
*/
#define NLA_PUT_ADDR(n, attrtype, addr) \
NLA_PUT(n, attrtype, nl_addr_get_len(addr), \
nl_addr_get_binary_addr(addr))
/** @} */
/**
* @name Iterators
* @{
*/
/**
* @ingroup attr
* iterate over a stream of attributes
* @arg pos loop counter, set to current attribute
* @arg head head of attribute stream
* @arg len length of attribute stream
* @arg rem initialized to len, holds bytes currently remaining in stream
*/
#define nla_for_each_attr(pos, head, len, rem) \
for (pos = head, rem = len; \
nla_ok(pos, rem); \
pos = nla_next(pos, &(rem)))
/**
* @ingroup attr
* iterate over a stream of nested attributes
* @arg pos loop counter, set to current attribute
* @arg nla attribute containing the nested attributes
* @arg rem initialized to len, holds bytes currently remaining in stream
*/
#define nla_for_each_nested(pos, nla, rem) \
for (pos = nla_data(nla), rem = nla_len(nla); \
nla_ok(pos, rem); \
pos = nla_next(pos, &(rem)))
/** @} */
#ifdef __cplusplus
}
#endif
#endif

123
include/netlink/cache.h Normal file
View file

@ -0,0 +1,123 @@
/*
* netlink/cache.h Caching Module
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CACHE_H_
#define NETLINK_CACHE_H_
#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_cache;
struct nl_cache_ops;
typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int);
/* Access Functions */
extern int nl_cache_nitems(struct nl_cache *);
extern int nl_cache_nitems_filter(struct nl_cache *,
struct nl_object *);
extern struct nl_cache_ops * nl_cache_get_ops(struct nl_cache *);
extern struct nl_object * nl_cache_get_first(struct nl_cache *);
extern struct nl_object * nl_cache_get_last(struct nl_cache *);
extern struct nl_object * nl_cache_get_next(struct nl_object *);
extern struct nl_object * nl_cache_get_prev(struct nl_object *);
/* Cache creation/deletion */
#define nl_cache_alloc_from_ops(ptr) nl_cache_alloc(ptr)
extern struct nl_cache * nl_cache_alloc(struct nl_cache_ops *);
extern struct nl_cache * nl_cache_alloc_name(const char *);
extern struct nl_cache * nl_cache_subset(struct nl_cache *,
struct nl_object *);
extern void nl_cache_clear(struct nl_cache *);
extern void nl_cache_free(struct nl_cache *);
/* Cache modification */
extern int nl_cache_add(struct nl_cache *,
struct nl_object *);
extern int nl_cache_parse_and_add(struct nl_cache *,
struct nl_msg *);
#define nl_cache_delete(a, b) nl_cache_remove(b)
extern void nl_cache_remove(struct nl_object *);
#define nl_cache_update(a, b) nl_cache_refill(a, b)
extern int nl_cache_refill(struct nl_handle *,
struct nl_cache *);
extern int nl_cache_pickup(struct nl_handle *,
struct nl_cache *);
extern int nl_cache_resync(struct nl_handle *,
struct nl_cache *,
change_func_t);
extern int nl_cache_include(struct nl_cache *,
struct nl_object *,
change_func_t);
/* General */
extern int nl_cache_is_empty(struct nl_cache *);
extern void nl_cache_mark_all(struct nl_cache *);
/* Dumping */
extern void nl_cache_dump(struct nl_cache *,
struct nl_dump_params *);
extern void nl_cache_dump_filter(struct nl_cache *,
struct nl_dump_params *,
struct nl_object *);
/* Iterators */
extern void nl_cache_foreach(struct nl_cache *,
void (*cb)(struct nl_object *,
void *),
void *arg);
extern void nl_cache_foreach_filter(struct nl_cache *,
struct nl_object *,
void (*cb)(struct
nl_object *,
void *),
void *arg);
/* --- cache management --- */
/* Cache type management */
extern struct nl_cache_ops * nl_cache_ops_lookup(const char *);
extern struct nl_cache_ops * nl_cache_ops_lookup_for_obj(struct nl_object_ops *);
extern void nl_cache_mngt_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
extern int nl_cache_mngt_register(struct nl_cache_ops *);
extern int nl_cache_mngt_unregister(struct nl_cache_ops *);
/* Global cache provisioning/requiring */
extern void nl_cache_mngt_provide(struct nl_cache *);
extern void nl_cache_mngt_unprovide(struct nl_cache *);
extern struct nl_cache * nl_cache_mngt_require(const char *);
struct nl_cache_mngr;
#define NL_AUTO_PROVIDE 1
extern struct nl_cache_mngr * nl_cache_mngr_alloc(struct nl_handle *,
int, int);
extern struct nl_cache * nl_cache_mngr_add(struct nl_cache_mngr *,
const char *,
change_func_t);
extern int nl_cache_mngr_get_fd(struct nl_cache_mngr *);
extern int nl_cache_mngr_poll(struct nl_cache_mngr *,
int);
extern int nl_cache_mngr_data_ready(struct nl_cache_mngr *);
extern void nl_cache_mngr_free(struct nl_cache_mngr *);
#ifdef __cplusplus
}
#endif
#endif

40
include/netlink/data.h Normal file
View file

@ -0,0 +1,40 @@
/*
* netlink/data.h Abstract Data
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_DATA_H_
#define NETLINK_DATA_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_data;
/* General */
extern struct nl_data * nl_data_alloc(void *, size_t);
extern struct nl_data * nl_data_clone(struct nl_data *);
extern int nl_data_append(struct nl_data *, void *, size_t);
extern void nl_data_free(struct nl_data *);
/* Access Functions */
extern void * nl_data_get(struct nl_data *);
extern size_t nl_data_get_size(struct nl_data *);
/* Misc */
extern int nl_data_cmp(struct nl_data *, struct nl_data *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* netlink/fib_lookup/fib_lookup.h FIB Lookup
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_FIB_LOOKUP_H_
#define NETLINK_FIB_LOOKUP_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#include <netlink/fib_lookup/request.h>
#ifdef __cplusplus
extern "C" {
#endif
struct flnl_result;
extern struct flnl_result * flnl_result_alloc(void);
extern void flnl_result_put(struct flnl_result *);
extern struct nl_cache * flnl_result_alloc_cache(void);
extern struct nl_msg * flnl_lookup_build_request(struct flnl_request *,
int);
extern int flnl_lookup(struct nl_handle *,
struct flnl_request *,
struct nl_cache *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,51 @@
/*
* netlink/fib_lookup/request.h FIB Lookup Request
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_FIB_LOOKUP_REQUEST_H_
#define NETLINK_FIB_LOOKUP_REQUEST_H_
#include <netlink/netlink.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct flnl_request;
#define REQUEST_CAST(ptr) ((struct flnl_request *) (ptr))
extern struct flnl_request * flnl_request_alloc(void);
extern void flnl_request_set_fwmark(struct flnl_request *,
uint64_t);
extern uint64_t flnl_request_get_fwmark(struct flnl_request *);
extern void flnl_request_set_tos(struct flnl_request *,
int);
extern int flnl_request_get_tos(struct flnl_request *);
extern void flnl_request_set_scope(struct flnl_request *,
int);
extern int flnl_request_get_scope(struct flnl_request *);
extern void flnl_request_set_table(struct flnl_request *,
int);
extern int flnl_request_get_table(struct flnl_request *);
extern int flnl_request_set_addr(struct flnl_request *,
struct nl_addr *);
extern struct nl_addr * flnl_request_get_addr(struct flnl_request *);
extern int flnl_request_cmp(struct flnl_request *,
struct flnl_request *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,36 @@
/*
* netlink/genl/ctrl.h Generic Netlink Controller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_CTRL_H_
#define NETLINK_GENL_CTRL_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct genl_family;
extern struct nl_cache * genl_ctrl_alloc_cache(struct nl_handle *);
extern struct genl_family * genl_ctrl_search(struct nl_cache *, int);
extern struct genl_family * genl_ctrl_search_by_name(struct nl_cache *,
const char *);
extern int genl_ctrl_resolve(struct nl_handle *,
const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,50 @@
/*
* netlink/genl/family.h Generic Netlink Family
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_FAMILY_H_
#define NETLINK_GENL_FAMILY_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#ifdef __cplusplus
extern "C" {
#endif
struct genl_family;
extern struct genl_family * genl_family_alloc(void);
extern void genl_family_put(struct genl_family *);
extern unsigned int genl_family_get_id(struct genl_family *);
extern void genl_family_set_id(struct genl_family *,
unsigned int);
extern char * genl_family_get_name(struct genl_family *);
extern void genl_family_set_name(struct genl_family *,
const char *name);
extern uint8_t genl_family_get_version(struct genl_family *);
extern void genl_family_set_version(struct genl_family *,
uint8_t);
extern uint32_t genl_family_get_hdrsize(struct genl_family *);
extern void genl_family_set_hdrsize(struct genl_family *,
uint32_t);
extern uint32_t genl_family_get_maxattr(struct genl_family *);
extern void genl_family_set_maxattr(struct genl_family *,
uint32_t);
extern int genl_family_add_op(struct genl_family *,
int, int);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,37 @@
/*
* netlink/genl/genl.h Generic Netlink
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_H_
#define NETLINK_GENL_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int genl_connect(struct nl_handle *);
extern int genl_send_simple(struct nl_handle *, int, int,
int, int);
extern void * genlmsg_put(struct nl_msg *, uint32_t, uint32_t,
int, int, int, uint8_t, uint8_t);
extern void * genlmsg_data(const struct genlmsghdr *);
extern int genlmsg_len(const struct genlmsghdr *);
extern char * genl_op2name(int, int, char *, size_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,78 @@
/*
* netlink/genl/mngt.h Generic Netlink Management
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_GENL_MNGT_H_
#define NETLINK_GENL_MNGT_H_
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/list.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_cache_ops;
/**
* @ingroup genl_mngt
* Generic Netlink Command
*/
struct genl_cmd
{
/** Unique command identifier */
int c_id;
/** Name/description of command */
char * c_name;
/**
* Maximum attribute identifier, must be provided if
* a message parser is available.
*/
int c_maxattr;
int (*c_msg_parser)(struct nl_cache_ops *,
struct genl_cmd *,
struct genl_info *, void *);
/**
* Attribute validation policy (optional)
*/
struct nla_policy * c_attr_policy;
};
/**
* @ingroup genl_mngt
* Generic Netlink Operations
*/
struct genl_ops
{
int o_family;
int o_id;
char * o_name;
struct nl_cache_ops * o_cache_ops;
struct genl_cmd * o_cmds;
int o_ncmds;
/* linked list of all genl cache operations */
struct nl_list_head o_list;
};
extern int genl_register(struct nl_cache_ops *);
extern void genl_unregister(struct nl_cache_ops *);
#ifdef __cplusplus
}
#endif
#endif

147
include/netlink/handlers.h Normal file
View file

@ -0,0 +1,147 @@
/*
* netlink/handlers.c default netlink message handlers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_HANDLERS_H_
#define NETLINK_HANDLERS_H_
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <netlink/netlink-compat.h>
#include <netlink/netlink-kernel.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_cb;
struct nl_handle;
struct nl_msg;
/**
* @name Callback Typedefs
* @{
*/
/**
* nl_recvmsgs() callback for message processing customization
* @ingroup cb
* @arg msg netlink message being processed
* @arg arg argument passwd on through caller
*/
typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
/**
* nl_recvmsgs() callback for error message processing customization
* @ingroup cb
* @arg nla netlink address of the peer
* @arg nlerr netlink error message being processed
* @arg arg argument passed on through caller
*/
typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla,
struct nlmsgerr *nlerr, void *arg);
/** @} */
/**
* Callback actions
* @ingroup cb
*/
enum nl_cb_action {
/** Proceed with wathever would come next */
NL_OK,
/** Skip this message */
NL_SKIP,
/** Stop parsing altogether and discard remaining messages */
NL_STOP,
};
/* backwards compatibility */
#define NL_PROCEED NL_OK
#define NL_EXIT NL_STOP
/**
* Callback kinds
* @ingroup cb
*/
enum nl_cb_kind {
/** Default handlers (quiet) */
NL_CB_DEFAULT,
/** Verbose default handlers (error messages printed) */
NL_CB_VERBOSE,
/** Debug handlers for debugging */
NL_CB_DEBUG,
/** Customized handler specified by the user */
NL_CB_CUSTOM,
__NL_CB_KIND_MAX,
};
#define NL_CB_KIND_MAX (__NL_CB_KIND_MAX - 1)
/**
* Callback types
* @ingroup cb
*/
enum nl_cb_type {
/** Message is valid */
NL_CB_VALID,
/** Last message in a series of multi part messages received */
NL_CB_FINISH,
/** Report received that data was lost */
NL_CB_OVERRUN,
/** Message wants to be skipped */
NL_CB_SKIPPED,
/** Message is an acknowledge */
NL_CB_ACK,
/** Called for every message received */
NL_CB_MSG_IN,
/** Called for every message sent out except for nl_sendto() */
NL_CB_MSG_OUT,
/** Message is malformed and invalid */
NL_CB_INVALID,
/** Called instead of internal sequence number checking */
NL_CB_SEQ_CHECK,
/** Sending of an acknowledge message has been requested */
NL_CB_SEND_ACK,
__NL_CB_TYPE_MAX,
};
#define NL_CB_TYPE_MAX (__NL_CB_TYPE_MAX - 1)
extern struct nl_cb * nl_cb_alloc(enum nl_cb_kind);
extern struct nl_cb * nl_cb_clone(struct nl_cb *);
extern struct nl_cb * nl_cb_get(struct nl_cb *);
extern void nl_cb_put(struct nl_cb *);
extern int nl_cb_set(struct nl_cb *, enum nl_cb_type, enum nl_cb_kind,
nl_recvmsg_msg_cb_t, void *);
extern int nl_cb_set_all(struct nl_cb *, enum nl_cb_kind,
nl_recvmsg_msg_cb_t, void *);
extern int nl_cb_err(struct nl_cb *, enum nl_cb_kind, nl_recvmsg_err_cb_t,
void *);
extern void nl_cb_overwrite_recvmsgs(struct nl_cb *,
int (*func)(struct nl_handle *,
struct nl_cb *));
extern void nl_cb_overwrite_recv(struct nl_cb *,
int (*func)(struct nl_handle *,
struct sockaddr_nl *,
unsigned char **,
struct ucred **));
extern void nl_cb_overwrite_send(struct nl_cb *,
int (*func)(struct nl_handle *,
struct nl_msg *));
#ifdef __cplusplus
}
#endif
#endif

85
include/netlink/list.h Normal file
View file

@ -0,0 +1,85 @@
/*
* netlink/list.h Netlink List Utilities
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_LIST_H_
#define NETLINK_LIST_H_
struct nl_list_head
{
struct nl_list_head * next;
struct nl_list_head * prev;
};
static inline void __nl_list_add(struct nl_list_head *obj,
struct nl_list_head *prev,
struct nl_list_head *next)
{
prev->next = obj;
obj->prev = prev;
next->prev = obj;
obj->next = next;
}
static inline void nl_list_add_tail(struct nl_list_head *obj,
struct nl_list_head *head)
{
__nl_list_add(obj, head->prev, head);
}
static inline void nl_list_add_head(struct nl_list_head *obj,
struct nl_list_head *head)
{
__nl_list_add(obj, head, head->next);
}
static inline void nl_list_del(struct nl_list_head *obj)
{
obj->next->prev = obj->prev;
obj->prev->next = obj->next;
}
static inline int nl_list_empty(struct nl_list_head *head)
{
return head->next == head;
}
#define nl_container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - ((size_t) &((type *)0)->member));})
#define nl_list_entry(ptr, type, member) \
nl_container_of(ptr, type, member)
#define nl_list_at_tail(pos, head, member) \
((pos)->member.next == (head))
#define nl_list_at_head(pos, head, member) \
((pos)->member.prev == (head))
#define NL_LIST_HEAD(name) \
struct nl_list_head name = { &(name), &(name) }
#define nl_list_for_each_entry(pos, head, member) \
for (pos = nl_list_entry((head)->next, typeof(*pos), member); \
&(pos)->member != (head); \
(pos) = nl_list_entry((pos)->member.next, typeof(*(pos)), member))
#define nl_list_for_each_entry_safe(pos, n, head, member) \
for (pos = nl_list_entry((head)->next, typeof(*pos), member), \
n = nl_list_entry(pos->member.next, typeof(*pos), member); \
&(pos)->member != (head); \
pos = n, n = nl_list_entry(n->member.next, typeof(*n), member))
#define nl_init_list_head(head) \
do { (head)->next = (head); (head)->prev = (head); } while (0)
#endif

143
include/netlink/msg.h Normal file
View file

@ -0,0 +1,143 @@
/*
* netlink/msg.c Netlink Messages Interface
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_MSG_H_
#define NETLINK_MSG_H_
#include <netlink/netlink.h>
#include <netlink/object.h>
#include <netlink/attr.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NL_DONTPAD 0
/**
* @ingroup msg
* @brief
* Will cause the netlink pid to be set to the pid assigned to
* the netlink handle (socket) just before sending the message off.
* @note Requires the use of nl_send_auto_complete()!
*/
#define NL_AUTO_PID 0
/**
* @ingroup msg
* @brief
* May be used to refer to a sequence number which should be
* automatically set just before sending the message off.
* @note Requires the use of nl_send_auto_complete()!
*/
#define NL_AUTO_SEQ 0
struct nl_msg;
struct nl_tree;
struct ucred;
/* size calculations */
extern int nlmsg_msg_size(int);
extern int nlmsg_total_size(int);
extern int nlmsg_padlen(int);
/* payload access */
extern void * nlmsg_data(const struct nlmsghdr *);
extern int nlmsg_len(const struct nlmsghdr *);
extern void * nlmsg_tail(const struct nlmsghdr *);
/* attribute access */
extern struct nlattr * nlmsg_attrdata(const struct nlmsghdr *, int);
extern int nlmsg_attrlen(const struct nlmsghdr *, int);
/* message parsing */
extern int nlmsg_ok(const struct nlmsghdr *, int);
extern struct nlmsghdr * nlmsg_next(struct nlmsghdr *, int *);
extern int nlmsg_parse(struct nlmsghdr *, int, struct nlattr **,
int, struct nla_policy *);
extern struct nlattr * nlmsg_find_attr(struct nlmsghdr *, int, int);
extern int nlmsg_validate(struct nlmsghdr *, int, int,
struct nla_policy *);
/* Backward compatibility */
#define nlmsg_new() nlmsg_alloc()
#define nlmsg_build_simple(a, b) nlmsg_alloc_simple(a, b)
#define nlmsg_build(ptr) nlmsg_inherit(ptr)
extern struct nl_msg * nlmsg_alloc(void);
extern struct nl_msg * nlmsg_alloc_simple(int, int);
extern struct nl_msg * nlmsg_inherit(struct nlmsghdr *);
extern struct nl_msg * nlmsg_convert(struct nlmsghdr *);
extern void * nlmsg_reserve(struct nl_msg *, size_t, int);
extern int nlmsg_append(struct nl_msg *, void *, size_t, int);
extern struct nlmsghdr * nlmsg_put(struct nl_msg *, uint32_t, uint32_t,
int, int, int);
extern struct nlmsghdr * nlmsg_hdr(struct nl_msg *);
extern void nlmsg_free(struct nl_msg *);
/* attribute modification */
extern void nlmsg_set_proto(struct nl_msg *, int);
extern int nlmsg_get_proto(struct nl_msg *);
extern void nlmsg_set_src(struct nl_msg *, struct sockaddr_nl *);
extern struct sockaddr_nl *nlmsg_get_src(struct nl_msg *);
extern void nlmsg_set_dst(struct nl_msg *, struct sockaddr_nl *);
extern struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *);
extern void nlmsg_set_creds(struct nl_msg *, struct ucred *);
extern struct ucred * nlmsg_get_creds(struct nl_msg *);
extern char * nl_nlmsgtype2str(int, char *, size_t);
extern int nl_str2nlmsgtype(const char *);
extern char * nl_nlmsg_flags2str(int, char *, size_t);
extern int nl_msg_parse(struct nl_msg *,
void (*cb)(struct nl_object *, void *),
void *);
extern void nl_msg_dump(struct nl_msg *, FILE *);
/**
* @name Iterators
* @{
*/
/**
* @ingroup msg
* Iterate over a stream of attributes in a message
* @arg pos loop counter, set to current attribute
* @arg nlh netlink message header
* @arg hdrlen length of family header
* @arg rem initialized to len, holds bytes currently remaining in stream
*/
#define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
nlmsg_attrlen(nlh, hdrlen), rem)
/**
* Iterate over a stream of messages
* @arg pos loop counter, set to current message
* @arg head head of message stream
* @arg len length of message stream
* @arg rem initialized to len, holds bytes currently remaining in stream
*/
#define nlmsg_for_each_msg(pos, head, len, rem) \
for (pos = head, rem = len; \
nlmsg_ok(pos, rem); \
pos = nlmsg_next(pos, &(rem)))
/** @} */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,115 @@
/*
* netlink/netfilter/ct.h Conntrack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
*/
#ifndef NETLINK_CT_H_
#define NETLINK_CT_H_
#include <netlink/netlink.h>
#include <netlink/addr.h>
#include <netlink/cache.h>
#include <netlink/msg.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nfnl_ct;
extern struct nl_object_ops ct_obj_ops;
/* General */
extern struct nfnl_ct * nfnl_ct_alloc(void);
extern struct nl_cache *nfnl_ct_alloc_cache(struct nl_handle *);
extern int nfnlmsg_ct_group(struct nlmsghdr *);
extern struct nfnl_ct * nfnlmsg_ct_parse(struct nlmsghdr *);
extern void nfnl_ct_get(struct nfnl_ct *);
extern void nfnl_ct_put(struct nfnl_ct *);
extern int nfnl_ct_dump_request(struct nl_handle *);
extern void nfnl_ct_set_family(struct nfnl_ct *, uint8_t);
extern uint8_t nfnl_ct_get_family(const struct nfnl_ct *);
extern void nfnl_ct_set_proto(struct nfnl_ct *, uint8_t);
extern int nfnl_ct_test_proto(const struct nfnl_ct *);
extern uint8_t nfnl_ct_get_proto(const struct nfnl_ct *);
extern void nfnl_ct_set_tcp_state(struct nfnl_ct *, uint8_t);
extern int nfnl_ct_test_tcp_state(const struct nfnl_ct *);
extern uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *);
extern char * nfnl_ct_tcp_state2str(uint8_t, char *, size_t);
extern int nfnl_ct_str2tcp_state(const char *name);
extern void nfnl_ct_set_status(struct nfnl_ct *, uint32_t);
extern int nfnl_ct_test_status(const struct nfnl_ct *);
extern uint32_t nfnl_ct_get_status(const struct nfnl_ct *);
extern void nfnl_ct_set_timeout(struct nfnl_ct *, uint32_t);
extern int nfnl_ct_test_timeout(const struct nfnl_ct *);
extern uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *);
extern void nfnl_ct_set_mark(struct nfnl_ct *, uint32_t);
extern int nfnl_ct_test_mark(const struct nfnl_ct *);
extern uint32_t nfnl_ct_get_mark(const struct nfnl_ct *);
extern void nfnl_ct_set_use(struct nfnl_ct *, uint32_t);
extern int nfnl_ct_test_use(const struct nfnl_ct *);
extern uint32_t nfnl_ct_get_use(const struct nfnl_ct *);
extern void nfnl_ct_set_id(struct nfnl_ct *, uint32_t);
extern int nfnl_ct_test_id(const struct nfnl_ct *);
extern uint32_t nfnl_ct_get_id(const struct nfnl_ct *);
extern int nfnl_ct_set_src(struct nfnl_ct *, int,
struct nl_addr *);
extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_ct *, int);
extern int nfnl_ct_set_dst(struct nfnl_ct *, int,
struct nl_addr *);
extern struct nl_addr * nfnl_ct_get_dst(const struct nfnl_ct *, int);
extern void nfnl_ct_set_src_port(struct nfnl_ct *, int, uint16_t);
extern int nfnl_ct_test_src_port(const struct nfnl_ct *, int);
extern uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *, int);
extern void nfnl_ct_set_dst_port(struct nfnl_ct *, int, uint16_t);
extern int nfnl_ct_test_dst_port(const struct nfnl_ct *, int);
extern uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *, int);
extern void nfnl_ct_set_icmp_id(struct nfnl_ct *, int, uint16_t);
extern int nfnl_ct_test_icmp_id(const struct nfnl_ct *, int);
extern uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *, int);
extern void nfnl_ct_set_icmp_type(struct nfnl_ct *, int, uint8_t);
extern int nfnl_ct_test_icmp_type(const struct nfnl_ct *, int);
extern uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *, int);
extern void nfnl_ct_set_icmp_code(struct nfnl_ct *, int, uint8_t);
extern int nfnl_ct_test_icmp_code(const struct nfnl_ct *, int);
extern uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *, int);
extern void nfnl_ct_set_packets(struct nfnl_ct *, int, uint64_t);
extern int nfnl_ct_test_packets(const struct nfnl_ct *, int);
extern uint64_t nfnl_ct_get_packets(const struct nfnl_ct *,int);
extern void nfnl_ct_set_bytes(struct nfnl_ct *, int, uint64_t);
extern int nfnl_ct_test_bytes(const struct nfnl_ct *, int);
extern uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *, int);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,105 @@
/*
* netlink/netfilter/log.h Netfilter Log
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
*/
#ifndef NETLINK_LOG_H_
#define NETLINK_LOG_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_handle;
struct nlmsghdr;
struct nfnl_log;
extern struct nl_object_ops log_obj_ops;
/* General */
extern struct nfnl_log *nfnl_log_alloc(void);
extern struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *);
extern void nfnl_log_get(struct nfnl_log *);
extern void nfnl_log_put(struct nfnl_log *);
extern struct nl_msg * nfnl_log_build_bind(uint16_t);;
extern int nfnl_log_bind(struct nl_handle *, uint16_t);
extern struct nl_msg * nfnl_log_build_unbind(uint16_t);
extern int nfnl_log_unbind(struct nl_handle *, uint16_t);
extern struct nl_msg * nfnl_log_build_pf_bind(uint8_t);
extern int nfnl_log_pf_bind(struct nl_handle *, uint8_t);
extern struct nl_msg * nfnl_log_build_pf_unbind(uint8_t);
extern int nfnl_log_pf_unbind(struct nl_handle *, uint8_t);
extern struct nl_msg * nfnl_log_build_mode(uint16_t, uint8_t, uint32_t);
extern int nfnl_log_set_mode(struct nl_handle *, uint16_t,
uint8_t, uint32_t);
extern void nfnl_log_set_family(struct nfnl_log *, uint8_t);
extern uint8_t nfnl_log_get_family(const struct nfnl_log *);
extern void nfnl_log_set_hwproto(struct nfnl_log *, uint16_t);
extern int nfnl_log_test_hwproto(const struct nfnl_log *);
extern uint16_t nfnl_log_get_hwproto(const struct nfnl_log *);
extern void nfnl_log_set_hook(struct nfnl_log *, uint8_t);
extern int nfnl_log_test_hook(const struct nfnl_log *);
extern uint8_t nfnl_log_get_hook(const struct nfnl_log *);
extern void nfnl_log_set_mark(struct nfnl_log *, uint32_t);
extern int nfnl_log_test_mark(const struct nfnl_log *);
extern uint32_t nfnl_log_get_mark(const struct nfnl_log *);
extern void nfnl_log_set_timestamp(struct nfnl_log *,
struct timeval *);
extern const struct timeval *nfnl_log_get_timestamp(const struct nfnl_log *);
extern void nfnl_log_set_indev(struct nfnl_log *, uint32_t);
extern uint32_t nfnl_log_get_indev(const struct nfnl_log *);
extern void nfnl_log_set_outdev(struct nfnl_log *, uint32_t);
extern uint32_t nfnl_log_get_outdev(const struct nfnl_log *);
extern void nfnl_log_set_physindev(struct nfnl_log *, uint32_t);
extern uint32_t nfnl_log_get_physindev(const struct nfnl_log *);
extern void nfnl_log_set_physoutdev(struct nfnl_log *, uint32_t);
extern uint32_t nfnl_log_get_physoutdev(const struct nfnl_log *);
extern void nfnl_log_set_hwaddr(struct nfnl_log *, uint8_t *, int);
extern const uint8_t * nfnl_log_get_hwaddr(const struct nfnl_log *, int *);
extern int nfnl_log_set_payload(struct nfnl_log *, uint8_t *, int);
extern const void * nfnl_log_get_payload(const struct nfnl_log *, int *);
extern int nfnl_log_set_prefix(struct nfnl_log *, void *);
extern const char * nfnl_log_get_prefix(const struct nfnl_log *);
extern void nfnl_log_set_uid(struct nfnl_log *, uint32_t);
extern int nfnl_log_test_uid(const struct nfnl_log *);
extern uint32_t nfnl_log_get_uid(const struct nfnl_log *);
extern void nfnl_log_set_seq(struct nfnl_log *, uint32_t);
extern int nfnl_log_test_seq(const struct nfnl_log *);
extern uint32_t nfnl_log_get_seq(const struct nfnl_log *);
extern void nfnl_log_set_seq_global(struct nfnl_log *, uint32_t);
extern int nfnl_log_test_seq_global(const struct nfnl_log *);
extern uint32_t nfnl_log_get_seq_global(const struct nfnl_log *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,44 @@
/*
* netlink/nfnl/nfnl.h Netfilter Netlink
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
*/
#ifndef NETLINK_NFNL_H_
#define NETLINK_NFNL_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NFNL_HDRLEN NLMSG_ALIGN(sizeof(struct nfgenmsg))
#define NFNLMSG_TYPE(subsys, subtype) (((subsys) << 8) | (subtype))
extern int nfnl_connect(struct nl_handle *);
extern uint8_t nfnlmsg_subsys(struct nlmsghdr *);
extern uint8_t nfnlmsg_subtype(struct nlmsghdr *);
extern uint8_t nfnlmsg_family(struct nlmsghdr *);
extern uint16_t nfnlmsg_res_id(struct nlmsghdr *);
extern int nfnl_send_simple(struct nl_handle *, uint8_t, uint8_t,
int, uint8_t, uint16_t);
extern struct nl_msg * nfnlmsg_alloc_simple(uint8_t, uint8_t, int,
uint8_t, uint16_t);
extern int nfnlmsg_put(struct nl_msg *, uint32_t, uint32_t,
uint8_t, uint8_t, int, uint8_t, uint16_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,50 @@
/*
* netlink/netlink-compat.h Netlink Compatability
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_COMPAT_H_
#define NETLINK_COMPAT_H_
#if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H
typedef unsigned short sa_family_t;
#endif
#ifndef IFNAMSIZ
/** Maximum length of a interface name */
#define IFNAMSIZ 16
#endif
/* patch 2.4.x if_arp */
#ifndef ARPHRD_INFINIBAND
#define ARPHRD_INFINIBAND 32
#endif
/* patch 2.4.x eth header file */
#ifndef ETH_P_MPLS_UC
#define ETH_P_MPLS_UC 0x8847
#endif
#ifndef ETH_P_MPLS_MC
#define ETH_P_MPLS_MC 0x8848
#endif
#ifndef ETH_P_EDP2
#define ETH_P_EDP2 0x88A2
#endif
#ifndef ETH_P_HDLC
#define ETH_P_HDLC 0x0019
#endif
#ifndef AF_LLC
#define AF_LLC 26
#endif
#endif

View file

@ -0,0 +1,196 @@
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
/**
* Netlink socket address
* @ingroup nl
*/
struct sockaddr_nl
{
/** socket family (AF_NETLINK) */
sa_family_t nl_family;
/** Padding (unused) */
unsigned short nl_pad;
/** Unique process ID */
uint32_t nl_pid;
/** Multicast group subscriptions */
uint32_t nl_groups;
};
/**
* Netlink message header
* @ingroup msg
*/
struct nlmsghdr
{
/**
* Length of message including header.
*/
uint32_t nlmsg_len;
/**
* Message type (content type)
*/
uint16_t nlmsg_type;
/**
* Message flags
*/
uint16_t nlmsg_flags;
/**
* Sequence number
*/
uint32_t nlmsg_seq;
/**
* Netlink PID of the proccess sending the message.
*/
uint32_t nlmsg_pid;
};
/**
* @name Standard message flags
* @{
*/
/**
* Must be set on all request messages (typically from user space to
* kernel space).
* @ingroup msg
*/
#define NLM_F_REQUEST 1
/**
* Indicates the message is part of a multipart message terminated
* by NLMSG_DONE.
*/
#define NLM_F_MULTI 2
/**
* Request for an acknowledgment on success.
*/
#define NLM_F_ACK 4
/**
* Echo this request
*/
#define NLM_F_ECHO 8
/** @} */
/**
* @name Additional message flags for GET requests
* @{
*/
/**
* Return the complete table instead of a single entry.
* @ingroup msg
*/
#define NLM_F_ROOT 0x100
/**
* Return all entries matching criteria passed in message content.
*/
#define NLM_F_MATCH 0x200
/**
* Return an atomic snapshot of the table being referenced. This
* may require special privileges because it has the potential to
* interrupt service in the FE for a longer time.
*/
#define NLM_F_ATOMIC 0x400
/**
* Dump all entries
*/
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
/** @} */
/**
* @name Additional messsage flags for NEW requests
* @{
*/
/**
* Replace existing matching config object with this request.
* @ingroup msg
*/
#define NLM_F_REPLACE 0x100
/**
* Don't replace the config object if it already exists.
*/
#define NLM_F_EXCL 0x200
/**
* Create config object if it doesn't already exist.
*/
#define NLM_F_CREATE 0x400
/**
* Add to the end of the object list.
*/
#define NLM_F_APPEND 0x800
/** @} */
/**
* @name Standard Message types
* @{
*/
/**
* No operation, message must be ignored
* @ingroup msg
*/
#define NLMSG_NOOP 0x1
/**
* The message signals an error and the payload contains a nlmsgerr
* structure. This can be looked at as a NACK and typically it is
* from FEC to CPC.
*/
#define NLMSG_ERROR 0x2
/**
* Message terminates a multipart message.
*/
#define NLMSG_DONE 0x3
/**
* The message signals that data got lost
*/
#define NLMSG_OVERRUN 0x4
/**
* Lower limit of reserved message types
*/
#define NLMSG_MIN_TYPE 0x10
/** @} */
/**
* Netlink error message
* @ingroup msg
*/
struct nlmsgerr
{
/** Error code (errno number) */
int error;
/** Original netlink message causing the error */
struct nlmsghdr msg;
};
struct nl_pktinfo
{
__u32 group;
};
#endif /* __LINUX_NETLINK_H */

74
include/netlink/netlink.h Normal file
View file

@ -0,0 +1,74 @@
/*
* netlink/netlink.h Netlink Interface
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_NETLINK_H_
#define NETLINK_NETLINK_H_
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netlink/netlink-compat.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/genetlink.h>
#include <linux/ip_mp_alg.h>
#include <linux/netfilter/nfnetlink.h>
#include <netlink/types.h>
#include <netlink/handlers.h>
#include <netlink/socket.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int nl_debug;
extern struct nl_dump_params nl_debug_dp;
/* Connection Management */
extern int nl_connect(struct nl_handle *, int);
extern void nl_close(struct nl_handle *);
/* Send */
extern int nl_sendto(struct nl_handle *, void *, size_t);
extern int nl_sendmsg(struct nl_handle *, struct nl_msg *,
struct msghdr *);
extern int nl_send(struct nl_handle *, struct nl_msg *);
extern int nl_send_auto_complete(struct nl_handle *,
struct nl_msg *);
extern int nl_send_simple(struct nl_handle *, int, int,
void *, size_t);
/* Receive */
extern int nl_recv(struct nl_handle *,
struct sockaddr_nl *, unsigned char **,
struct ucred **);
extern int nl_recvmsgs(struct nl_handle *, struct nl_cb *);
#define nl_recvmsgs_def(handle) nl_recvmsgs_default(handle)
extern int nl_recvmsgs_default(struct nl_handle *);
extern int nl_wait_for_ack(struct nl_handle *);
/* Netlink Family Translations */
extern char * nl_nlfamily2str(int, char *, size_t);
extern int nl_str2nlfamily(const char *);
#ifdef __cplusplus
}
#endif
#endif

64
include/netlink/object.h Normal file
View file

@ -0,0 +1,64 @@
/*
* netlink/object.c Generic Cacheable Object
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_OBJECT_H_
#define NETLINK_OBJECT_H_
#include <netlink/netlink.h>
#include <netlink/utils.h>
#ifdef __cplusplus
extern "C" {
#endif
struct nl_cache;
struct nl_object;
struct nl_object_ops;
#define OBJ_CAST(ptr) ((struct nl_object *) (ptr))
/* General */
extern struct nl_object * nl_object_alloc(struct nl_object_ops *);
extern struct nl_object * nl_object_alloc_name(const char *);
extern void nl_object_free(struct nl_object *);
extern struct nl_object * nl_object_clone(struct nl_object *obj);
extern void nl_object_get(struct nl_object *);
extern void nl_object_put(struct nl_object *);
extern int nl_object_shared(struct nl_object *);
extern void nl_object_dump(struct nl_object *,
struct nl_dump_params *);
extern int nl_object_identical(struct nl_object *,
struct nl_object *);
extern uint32_t nl_object_diff(struct nl_object *,
struct nl_object *);
extern int nl_object_match_filter(struct nl_object *,
struct nl_object *);
extern char * nl_object_attrs2str(struct nl_object *,
uint32_t attrs, char *buf,
size_t);
extern char * nl_object_attr_list(struct nl_object *,
char *, size_t);
/* Marks */
extern void nl_object_mark(struct nl_object *);
extern void nl_object_unmark(struct nl_object *);
extern int nl_object_is_marked(struct nl_object *);
/* Access Functions */
extern int nl_object_get_refcnt(struct nl_object *);
extern struct nl_cache * nl_object_get_cache(struct nl_object *);
extern inline void * nl_object_priv(struct nl_object *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,91 @@
/*
* netlink/route/addr.c rtnetlink addr layer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Baruch Even <baruch@ev-en.org>,
* Mediatrix Telecom, inc. <ericb@mediatrix.com>
*/
#ifndef NETADDR_ADDR_H_
#define NETADDR_ADDR_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_addr;
/* General */
extern struct rtnl_addr *rtnl_addr_alloc(void);
extern void rtnl_addr_put(struct rtnl_addr *);
extern struct nl_cache *rtnl_addr_alloc_cache(struct nl_handle *);
/* Address Addition */
extern struct nl_msg * rtnl_addr_build_add_request(struct rtnl_addr *, int);
extern int rtnl_addr_add(struct nl_handle *, struct rtnl_addr *,
int);
/* Address Deletion */
extern struct nl_msg * rtnl_addr_build_delete_request(struct rtnl_addr *, int);
extern int rtnl_addr_delete(struct nl_handle *,
struct rtnl_addr *, int);
/* Address Flags Translations */
extern char * rtnl_addr_flags2str(int, char *, size_t);
extern int rtnl_addr_str2flags(const char *);
/* Attribute Access */
extern void rtnl_addr_set_label(struct rtnl_addr *, const char *);
extern char * rtnl_addr_get_label(struct rtnl_addr *);
extern void rtnl_addr_set_ifindex(struct rtnl_addr *, int);
extern int rtnl_addr_get_ifindex(struct rtnl_addr *);
extern void rtnl_addr_set_family(struct rtnl_addr *, int);
extern int rtnl_addr_get_family(struct rtnl_addr *);
extern void rtnl_addr_set_prefixlen(struct rtnl_addr *, int);
extern int rtnl_addr_get_prefixlen(struct rtnl_addr *);
extern void rtnl_addr_set_scope(struct rtnl_addr *, int);
extern int rtnl_addr_get_scope(struct rtnl_addr *);
extern void rtnl_addr_set_flags(struct rtnl_addr *, unsigned int);
extern void rtnl_addr_unset_flags(struct rtnl_addr *, unsigned int);
extern unsigned int rtnl_addr_get_flags(struct rtnl_addr *);
extern int rtnl_addr_set_local(struct rtnl_addr *,
struct nl_addr *);
extern struct nl_addr * rtnl_addr_get_local(struct rtnl_addr *);
extern int rtnl_addr_set_peer(struct rtnl_addr *,
struct nl_addr *);
extern struct nl_addr * rtnl_addr_get_peer(struct rtnl_addr *);
extern int rtnl_addr_set_broadcast(struct rtnl_addr *,
struct nl_addr *);
extern struct nl_addr * rtnl_addr_get_broadcast(struct rtnl_addr *);
extern int rtnl_addr_set_anycast(struct rtnl_addr *,
struct nl_addr *);
extern struct nl_addr * rtnl_addr_get_anycast(struct rtnl_addr *);
extern int rtnl_addr_set_multicast(struct rtnl_addr *,
struct nl_addr *);
extern struct nl_addr * rtnl_addr_get_multicast(struct rtnl_addr *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,73 @@
/*
* netlink/route/class-modules.h Class Module API
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CLASS_MODULES_H_
#define NETLINK_CLASS_MODULES_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Class operations
* @ingroup class_api
*/
struct rtnl_class_ops
{
/**
* Kind/Name of class
*/
char co_kind[32];
/**
* Dump callbacks
*/
int (*co_dump[NL_DUMP_MAX+1])(struct rtnl_class *,
struct nl_dump_params *, int);
/**
* Must return the contents supposed to be in TCA_OPTIONS
*/
struct nl_msg *(*co_get_opts)(struct rtnl_class *);
/**
* TCA_OPTIONS message parser
*/
int (*co_msg_parser)(struct rtnl_class *);
/**
* Called before a class object gets destroyed
*/
void (*co_free_data)(struct rtnl_class *);
/**
* Called whenever a class object needs to be cloned
*/
int (*co_clone)(struct rtnl_class *, struct rtnl_class *);
/**
* INTERNAL (Do not use)
*/
struct rtnl_class_ops *co_next;
};
extern int rtnl_class_register(struct rtnl_class_ops *);
extern int rtnl_class_unregister(struct rtnl_class_ops *);
extern struct rtnl_class_ops * rtnl_class_lookup_ops(struct rtnl_class *);
extern struct rtnl_class_ops * __rtnl_class_lookup_ops(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,68 @@
/*
* netlink/route/class.h Classes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CLASS_H_
#define NETLINK_CLASS_H_
#include <netlink/netlink.h>
#include <netlink/route/tc.h>
#include <netlink/route/qdisc.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_class;
extern struct nl_object_ops class_obj_ops;
/* General */
extern struct rtnl_class * rtnl_class_alloc(void);
extern void rtnl_class_put(struct rtnl_class *);
extern struct nl_cache * rtnl_class_alloc_cache(struct nl_handle *, int);
/* leaf qdisc access */
extern struct rtnl_qdisc * rtnl_class_leaf_qdisc(struct rtnl_class *,
struct nl_cache *);
/* class addition */
extern struct nl_msg * rtnl_class_build_add_request(struct rtnl_class *, int);
extern int rtnl_class_add(struct nl_handle *, struct rtnl_class *, int);
/* attribute modification */
extern void rtnl_class_set_ifindex(struct rtnl_class *, int);
extern int rtnl_class_get_ifindex(struct rtnl_class *);
extern void rtnl_class_set_handle(struct rtnl_class *, uint32_t);
extern uint32_t rtnl_class_get_handle(struct rtnl_class *);
extern void rtnl_class_set_parent(struct rtnl_class *, uint32_t);
extern uint32_t rtnl_class_get_parent(struct rtnl_class *);
extern void rtnl_class_set_kind(struct rtnl_class *, const char *);
extern char * rtnl_class_get_kind(struct rtnl_class *);
extern uint64_t rtnl_class_get_stat(struct rtnl_class *,
enum rtnl_tc_stats_id);
/* iterators */
extern void rtnl_class_foreach_child(struct rtnl_class *,
struct nl_cache *,
void (*cb)(struct nl_object *,
void *),
void *);
extern void rtnl_class_foreach_cls(struct rtnl_class *,
struct nl_cache *,
void (*cb)(struct nl_object *,
void *),
void *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,72 @@
/*
* netlink/route/classifier-modules.h Classifier Module API
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CLASS_MODULES_H_
#define NETLINK_CLASS_MODULES_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Classifier operations
* @ingroup cls_api
*/
struct rtnl_cls_ops
{
/**
* Kind/Name of classifier
*/
char co_kind[32];
/**
* Dump callbacks
*/
int (*co_dump[NL_DUMP_MAX+1])(struct rtnl_cls *,
struct nl_dump_params *, int);
/**
* Must return the contents supposed to be in TCA_OPTIONS
*/
struct nl_msg *(*co_get_opts)(struct rtnl_cls *);
/**
* TCA_OPTIONS message parser
*/
int (*co_msg_parser)(struct rtnl_cls *);
/**
* Called before a class object gets destroyed
*/
void (*co_free_data)(struct rtnl_cls *);
/**
* Called whenever a classifier object needs to be cloned
*/
int (*co_clone)(struct rtnl_cls *, struct rtnl_cls *);
/**
* INTERNAL (Do not use)
*/
struct rtnl_cls_ops *co_next;
};
extern int rtnl_cls_register(struct rtnl_cls_ops *);
extern int rtnl_cls_unregister(struct rtnl_cls_ops *);
extern struct rtnl_cls_ops * rtnl_cls_lookup_ops(struct rtnl_cls *);
extern struct rtnl_cls_ops * __rtnl_cls_lookup_ops(const char *kind);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,56 @@
/*
* netlink/route/classifier.h Classifiers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CLASSIFIER_H_
#define NETLINK_CLASSIFIER_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/route/tc.h>
#include <netlink/utils.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct nl_object_ops cls_obj_ops;
extern struct rtnl_cls *rtnl_cls_alloc(void);
extern void rtnl_cls_put(struct rtnl_cls *);
extern struct nl_cache *rtnl_cls_alloc_cache(struct nl_handle *, int, uint32_t);
/* classifier addition */
extern int rtnl_cls_add(struct nl_handle *, struct rtnl_cls *,
int);
extern struct nl_msg * rtnl_cls_build_add_request(struct rtnl_cls *, int);
extern struct nl_msg *rtnl_cls_build_change_request(struct rtnl_cls *, int);
extern struct nl_msg *rtnl_cls_build_delete_request(struct rtnl_cls *, int);
extern int rtnl_cls_delete(struct nl_handle *, struct rtnl_cls *, int);
/* attribute modification */
extern void rtnl_cls_set_ifindex(struct rtnl_cls *, int);
extern void rtnl_cls_set_handle(struct rtnl_cls *, uint32_t);
extern void rtnl_cls_set_parent(struct rtnl_cls *, uint32_t);
extern void rtnl_cls_set_kind(struct rtnl_cls *, const char *);
extern void rtnl_cls_set_prio(struct rtnl_cls *, int);
extern int rtnl_cls_get_prio(struct rtnl_cls *);
extern void rtnl_cls_set_protocol(struct rtnl_cls *, int);
extern int rtnl_cls_get_protocol(struct rtnl_cls *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,29 @@
/*
* netlink/route/cls/fw.h fw classifier
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2006 Petr Gotthard <petr.gotthard@siemens.com>
* Copyright (c) 2006 Siemens AG Oesterreich
*/
#ifndef NETLINK_FW_H_
#define NETLINK_FW_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_fw_set_classid(struct rtnl_cls *, uint32_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,29 @@
/*
* netlink/route/cls/police.h Policer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CLS_POLICE_H_
#define NETLINK_CLS_POLICE_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char * nl_police2str(int, char *, size_t);
extern int nl_str2police(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,43 @@
/*
* netlink/route/cls/u32.h u32 classifier
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_U32_H_
#define NETLINK_U32_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void rtnl_u32_set_handle(struct rtnl_cls *, int, int, int);
extern int rtnl_u32_set_classid(struct rtnl_cls *, uint32_t);
extern int rtnl_u32_set_flags(struct rtnl_cls *, int);
extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t,
int, int);
extern int rtnl_u32_add_key_uint8(struct rtnl_cls *, uint8_t, uint8_t,
int, int);
extern int rtnl_u32_add_key_uint16(struct rtnl_cls *, uint16_t, uint16_t,
int, int);
extern int rtnl_u32_add_key_uint32(struct rtnl_cls *, uint32_t, uint32_t,
int, int);
extern int rtnl_u32_add_key_in_addr(struct rtnl_cls *, struct in_addr *,
uint8_t, int, int);
extern int rtnl_u32_add_key_in6_addr(struct rtnl_cls *, struct in6_addr *,
uint8_t, int, int);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,151 @@
/*
* netlink/route/link.h Links (Interfaces)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_LINK_H_
#define NETLINK_LINK_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_link;
enum rtnl_link_st {
RTNL_LINK_RX_PACKETS,
RTNL_LINK_TX_PACKETS,
RTNL_LINK_RX_BYTES,
RTNL_LINK_TX_BYTES,
RTNL_LINK_RX_ERRORS,
RTNL_LINK_TX_ERRORS,
RTNL_LINK_RX_DROPPED,
RTNL_LINK_TX_DROPPED,
RTNL_LINK_RX_COMPRESSED,
RTNL_LINK_TX_COMPRESSED,
RTNL_LINK_RX_FIFO_ERR,
RTNL_LINK_TX_FIFO_ERR,
RTNL_LINK_RX_LEN_ERR,
RTNL_LINK_RX_OVER_ERR,
RTNL_LINK_RX_CRC_ERR,
RTNL_LINK_RX_FRAME_ERR,
RTNL_LINK_RX_MISSED_ERR,
RTNL_LINK_TX_ABORT_ERR,
RTNL_LINK_TX_CARRIER_ERR,
RTNL_LINK_TX_HBEAT_ERR,
RTNL_LINK_TX_WIN_ERR,
RTNL_LINK_TX_COLLISIONS,
RTNL_LINK_MULTICAST,
__RTNL_LINK_STATS_MAX,
};
#define RTNL_LINK_STATS_MAX (__RTNL_LINK_STATS_MAX - 1)
/**
* Special interface index stating the link was not found.
* @ingroup link
*/
#define RTNL_LINK_NOT_FOUND -1
/* link object allocation/freeage */
extern struct rtnl_link * rtnl_link_alloc(void);
extern void rtnl_link_put(struct rtnl_link *);
extern void rtnl_link_free(struct rtnl_link *);
/* link cache management */
extern struct nl_cache * rtnl_link_alloc_cache(struct nl_handle *);
extern struct rtnl_link * rtnl_link_get(struct nl_cache *, int);
extern struct rtnl_link * rtnl_link_get_by_name(struct nl_cache *,
const char *);
/* Link Modifications */
extern struct nl_msg * rtnl_link_build_change_request(struct rtnl_link *,
struct rtnl_link *,
int);
extern int rtnl_link_change(struct nl_handle *,
struct rtnl_link *,
struct rtnl_link *, int);
/* Name <-> Index Translations */
extern char * rtnl_link_i2name(struct nl_cache *, int,
char *, size_t);
extern int rtnl_link_name2i(struct nl_cache *,
const char *);
/* Name <-> Statistic Translations */
extern char * rtnl_link_stat2str(int, char *, size_t);
extern int rtnl_link_str2stat(const char *);
/* Link Flags Translations */
extern char * rtnl_link_flags2str(int, char *, size_t);
extern int rtnl_link_str2flags(const char *);
/* Access Functions */
extern void rtnl_link_set_qdisc(struct rtnl_link *,
const char *);
extern char * rtnl_link_get_qdisc(struct rtnl_link *);
extern void rtnl_link_set_name(struct rtnl_link *,
const char *);
extern char * rtnl_link_get_name(struct rtnl_link *);
extern void rtnl_link_set_flags(struct rtnl_link *,
unsigned int);
extern void rtnl_link_unset_flags(struct rtnl_link *,
unsigned int);
extern unsigned int rtnl_link_get_flags(struct rtnl_link *);
extern void rtnl_link_set_mtu(struct rtnl_link *,
unsigned int);
extern unsigned int rtnl_link_get_mtu(struct rtnl_link *);
extern void rtnl_link_set_txqlen(struct rtnl_link *,
unsigned int);
extern unsigned int rtnl_link_get_txqlen(struct rtnl_link *);
extern void rtnl_link_set_weight(struct rtnl_link *,
unsigned int);
extern unsigned int rtnl_link_get_weight(struct rtnl_link *);
extern void rtnl_link_set_ifindex(struct rtnl_link *, int);
extern int rtnl_link_get_ifindex(struct rtnl_link *);
extern void rtnl_link_set_family(struct rtnl_link *, int);
extern int rtnl_link_get_family(struct rtnl_link *);
extern void rtnl_link_set_arptype(struct rtnl_link *,
unsigned int);
extern unsigned int rtnl_link_get_arptype(struct rtnl_link *);
extern void rtnl_link_set_addr(struct rtnl_link *,
struct nl_addr *);
extern struct nl_addr * rtnl_link_get_addr(struct rtnl_link *);
extern void rtnl_link_set_broadcast(struct rtnl_link *,
struct nl_addr *);
extern struct nl_addr * rtnl_link_get_broadcast(struct rtnl_link *);
extern void rtnl_link_set_link(struct rtnl_link *, int);
extern int rtnl_link_get_link(struct rtnl_link *);
extern void rtnl_link_set_master(struct rtnl_link *, int);
extern int rtnl_link_get_master(struct rtnl_link *);
extern uint64_t rtnl_link_get_stat(struct rtnl_link *, int);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,91 @@
/*
* netlink/route/neighbour.h Neighbours
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_NEIGHBOUR_H_
#define NETLINK_NEIGHBOUR_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_neigh;
/* neighbour object allocation/freeage */
extern struct rtnl_neigh * rtnl_neigh_alloc(void);
extern void rtnl_neigh_put(struct rtnl_neigh *);
/* neighbour cache management */
extern struct nl_cache * rtnl_neigh_alloc_cache(struct nl_handle *);
extern struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *, int,
struct nl_addr *);
/* Neigbour state translations */
extern char * rtnl_neigh_state2str(int, char *, size_t);
extern int rtnl_neigh_str2state(const char *);
/* Neighbour flags translations */
extern char * rtnl_neigh_flags2str(int, char *, size_t);
extern int rtnl_neigh_str2flag(const char *);
/* Neighbour Addition */
extern int rtnl_neigh_add(struct nl_handle *,
struct rtnl_neigh *, int);
extern struct nl_msg * rtnl_neigh_build_add_request(struct rtnl_neigh *, int);
/* Neighbour Modification */
extern int rtnl_neigh_change(struct nl_handle *,
struct rtnl_neigh *, int);
extern struct nl_msg * rtnl_neigh_build_change_request(struct rtnl_neigh *, int);
/* Neighbour Deletion */
extern int rtnl_neigh_delete(struct nl_handle *,
struct rtnl_neigh *, int);
extern struct nl_msg * rtnl_neigh_build_delete_request(struct rtnl_neigh *, int);
/* Access functions */
extern void rtnl_neigh_set_state(struct rtnl_neigh *, int);
extern int rtnl_neigh_get_state(struct rtnl_neigh *);
extern void rtnl_neigh_unset_state(struct rtnl_neigh *,
int);
extern void rtnl_neigh_set_flags(struct rtnl_neigh *,
unsigned int);
extern void rtnl_neigh_unset_flags(struct rtnl_neigh *,
unsigned int);
extern unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *);
extern void rtnl_neigh_set_ifindex(struct rtnl_neigh *,
int);
extern int rtnl_neigh_get_ifindex(struct rtnl_neigh *);
extern void rtnl_neigh_set_lladdr(struct rtnl_neigh *,
struct nl_addr *);
extern struct nl_addr * rtnl_neigh_get_lladdr(struct rtnl_neigh *);
extern int rtnl_neigh_set_dst(struct rtnl_neigh *,
struct nl_addr *);
extern struct nl_addr * rtnl_neigh_get_dst(struct rtnl_neigh *);
extern void rtnl_neigh_set_type(struct rtnl_neigh *, int);
extern int rtnl_neigh_get_type(struct rtnl_neigh *);
extern void rtnl_neigh_set_family(struct rtnl_neigh *, int);
extern int rtnl_neigh_get_family(struct rtnl_neigh *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,64 @@
/*
* netlink/route/neightbl.h Neighbour Tables
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_NEIGHTBL_H_
#define NETLINK_NEIGHTBL_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_neightbl;
extern struct rtnl_neightbl *rtnl_neightbl_alloc(void);
extern void rtnl_neightbl_put(struct rtnl_neightbl *);
extern void rtnl_neightbl_free(struct rtnl_neightbl *);
extern struct nl_cache *rtnl_neightbl_alloc_cache(struct nl_handle *);
extern struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *,
const char *, int);
extern void rtnl_neightbl_dump(struct rtnl_neightbl *, FILE *,
struct nl_dump_params *);
extern struct nl_msg *rtnl_neightbl_build_change_request(struct rtnl_neightbl *,
struct rtnl_neightbl *);
extern int rtnl_neightbl_change(struct nl_handle *, struct rtnl_neightbl *,
struct rtnl_neightbl *);
extern void rtnl_neightbl_set_family(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_gc_tresh1(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_gc_tresh2(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_gc_tresh3(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_name(struct rtnl_neightbl *, const char *);
extern void rtnl_neightbl_set_dev(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_queue_len(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_proxy_queue_len(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_app_probes(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_ucast_probes(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_mcast_probes(struct rtnl_neightbl *, int);
extern void rtnl_neightbl_set_base_reachable_time(struct rtnl_neightbl *,
uint64_t);
extern void rtnl_neightbl_set_retrans_time(struct rtnl_neightbl *, uint64_t);
extern void rtnl_neightbl_set_gc_stale_time(struct rtnl_neightbl *, uint64_t);
extern void rtnl_neightbl_set_delay_probe_time(struct rtnl_neightbl *,
uint64_t);
extern void rtnl_neightbl_set_anycast_delay(struct rtnl_neightbl *, uint64_t);
extern void rtnl_neightbl_set_proxy_delay(struct rtnl_neightbl *, uint64_t);
extern void rtnl_neightbl_set_locktime(struct rtnl_neightbl *, uint64_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* netlink/route/nexthop.h Routing Nexthop
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_ROUTE_NEXTHOP_H_
#define NETLINK_ROUTE_NEXTHOP_H_
#include <netlink/netlink.h>
#include <netlink/addr.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_nexthop;
extern struct rtnl_nexthop * rtnl_route_nh_alloc(void);
extern struct rtnl_nexthop * rtnl_route_nh_clone(struct rtnl_nexthop *);
extern void rtnl_route_nh_free(struct rtnl_nexthop *);
extern void rtnl_route_nh_set_weight(struct rtnl_nexthop *, int);
extern void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *, int);
extern void rtnl_route_nh_set_gateway(struct rtnl_nexthop *,
struct nl_addr *);
extern void rtnl_route_nh_set_flags(struct rtnl_nexthop *,
unsigned int);
extern void rtnl_route_nh_unset_flags(struct rtnl_nexthop *,
unsigned int);
extern unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,73 @@
/*
* netlink/route/qdisc-modules.h Qdisc Module API
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_QDISC_MODULES_H_
#define NETLINK_QDISC_MODULES_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Qdisc Operations
* @ingroup qdisc
*/
struct rtnl_qdisc_ops
{
/**
* Kind/Name of Qdisc
*/
char qo_kind[32];
/**
* Dump callbacks
*/
int (*qo_dump[NL_DUMP_MAX+1])(struct rtnl_qdisc *,
struct nl_dump_params *, int);
/**
* Must return the contents supposed to be in TCA_OPTIONS
*/
struct nl_msg *(*qo_get_opts)(struct rtnl_qdisc *);
/**
* TCA_OPTIONS message parser
*/
int (*qo_msg_parser)(struct rtnl_qdisc *);
/**
* Called before a Qdisc object gets destroyed
*/
void (*qo_free_data)(struct rtnl_qdisc *);
/**
* Called whenever a qdisc object needs to be cloned
*/
int (*qo_clone)(struct rtnl_qdisc *, struct rtnl_qdisc *);
/**
* INTERNAL (Do not use)
*/
struct rtnl_qdisc_ops *qo_next;
};
extern int rtnl_qdisc_register(struct rtnl_qdisc_ops *);
extern int rtnl_qdisc_unregister(struct rtnl_qdisc_ops *);
extern struct rtnl_qdisc_ops * rtnl_qdisc_lookup_ops(struct rtnl_qdisc *);
extern struct rtnl_qdisc_ops * __rtnl_qdisc_lookup_ops(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,87 @@
/*
* netlink/route/qdisc.h Queueing Disciplines
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_QDISC_H_
#define NETLINK_QDISC_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/route/tc.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_qdisc;
extern struct nl_object_ops qdisc_obj_ops;
/* General */
extern struct rtnl_qdisc * rtnl_qdisc_alloc(void);
extern void rtnl_qdisc_put(struct rtnl_qdisc *);
/* Cache Management */
extern struct nl_cache * rtnl_qdisc_alloc_cache(struct nl_handle *);
extern struct rtnl_qdisc * rtnl_qdisc_get(struct nl_cache *,
int, uint32_t);
extern struct rtnl_qdisc * rtnl_qdisc_get_by_parent(struct nl_cache *,
int, uint32_t);
/* qdisc addition */
extern struct nl_msg * rtnl_qdisc_build_add_request(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_add(struct nl_handle *, struct rtnl_qdisc *,
int);
/* qdisc modification */
extern struct nl_msg * rtnl_qdisc_build_change_request(struct rtnl_qdisc *,
struct rtnl_qdisc *);
extern int rtnl_qdisc_change(struct nl_handle *,
struct rtnl_qdisc *,
struct rtnl_qdisc *);
/* qdisc deletion */
extern struct nl_msg * rtnl_qdisc_build_delete_request(struct rtnl_qdisc *);
extern int rtnl_qdisc_delete(struct nl_handle *,
struct rtnl_qdisc *);
/* attribute modifications */
extern void rtnl_qdisc_set_ifindex(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_get_ifindex(struct rtnl_qdisc *);
extern void rtnl_qdisc_set_handle(struct rtnl_qdisc *, uint32_t);
extern uint32_t rtnl_qdisc_get_handle(struct rtnl_qdisc *);
extern void rtnl_qdisc_set_parent(struct rtnl_qdisc *, uint32_t);
extern uint32_t rtnl_qdisc_get_parent(struct rtnl_qdisc *);
extern void rtnl_qdisc_set_kind(struct rtnl_qdisc *, const char *);
extern char * rtnl_qdisc_get_kind(struct rtnl_qdisc *);
extern uint64_t rtnl_qdisc_get_stat(struct rtnl_qdisc *,
enum rtnl_tc_stats_id);
/* iterators */
extern void rtnl_qdisc_foreach_child(struct rtnl_qdisc *,
struct nl_cache *,
void (*cb)(struct nl_object *,
void *),
void *);
extern void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *,
struct nl_cache *,
void (*cb)(struct nl_object *,
void *),
void *);
/* qdisc specific options */
extern struct nl_msg * rtnl_qdisc_get_opts(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,125 @@
/*
* netlink/route/route.h Routes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_ROUTE_H_
#define NETLINK_ROUTE_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#include <netlink/data.h>
#include <netlink/route/nexthop.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_route;
struct rtnl_rtcacheinfo
{
uint32_t rtci_clntref;
uint32_t rtci_last_use;
uint32_t rtci_expires;
int32_t rtci_error;
uint32_t rtci_used;
uint32_t rtci_id;
uint32_t rtci_ts;
uint32_t rtci_tsage;
};
extern struct nl_object_ops route_obj_ops;
/* General */
extern struct rtnl_route * rtnl_route_alloc(void);
extern void rtnl_route_put(struct rtnl_route *);
extern struct nl_cache * rtnl_route_alloc_cache(struct nl_handle *);
extern void rtnl_route_get(struct rtnl_route *);
extern void rtnl_route_put(struct rtnl_route *);
extern struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *, int);
extern int rtnl_route_add(struct nl_handle *, struct rtnl_route *, int);
extern struct nl_msg *rtnl_route_build_del_request(struct rtnl_route *, int);
extern int rtnl_route_del(struct nl_handle *, struct rtnl_route *, int);
extern void rtnl_route_set_table(struct rtnl_route *, int);
extern int rtnl_route_get_table(struct rtnl_route *);
extern void rtnl_route_set_scope(struct rtnl_route *, int);
extern int rtnl_route_get_scope(struct rtnl_route *);
extern void rtnl_route_set_tos(struct rtnl_route *, int);
extern int rtnl_route_get_tos(struct rtnl_route *);
extern void rtnl_route_set_realms(struct rtnl_route *, realm_t);
extern realm_t rtnl_route_get_realms(struct rtnl_route *);
extern void rtnl_route_set_protocol(struct rtnl_route *, int);
extern int rtnl_route_get_protocol(struct rtnl_route *);
extern void rtnl_route_set_prio(struct rtnl_route *, int);
extern int rtnl_route_get_prio(struct rtnl_route *);
extern void rtnl_route_set_family(struct rtnl_route *, int);
extern int rtnl_route_get_family(struct rtnl_route *);
extern void rtnl_route_set_type(struct rtnl_route *, int);
extern int rtnl_route_get_type(struct rtnl_route *);
extern void rtnl_route_set_flags(struct rtnl_route *,
unsigned int);
extern void rtnl_route_unset_flags(struct rtnl_route *,
unsigned int);
extern unsigned int rtnl_route_get_flags(struct rtnl_route *);
extern int rtnl_route_set_metric(struct rtnl_route *, int,
unsigned int);
extern int rtnl_route_unset_metric(struct rtnl_route *, int);
extern unsigned int rtnl_route_get_metric(struct rtnl_route *, int);
extern int rtnl_route_set_dst(struct rtnl_route *,
struct nl_addr *);
extern struct nl_addr * rtnl_route_get_dst(struct rtnl_route *);
extern int rtnl_route_set_src(struct rtnl_route *,
struct nl_addr *);
extern struct nl_addr * rtnl_route_get_src(struct rtnl_route *);
extern int rtnl_route_set_gateway(struct rtnl_route *,
struct nl_addr *);
extern struct nl_addr * rtnl_route_get_gateway(struct rtnl_route *);
extern int rtnl_route_set_pref_src(struct rtnl_route *,
struct nl_addr *);
extern struct nl_addr * rtnl_route_get_pref_src(struct rtnl_route *);
extern void rtnl_route_set_oif(struct rtnl_route *, int);
extern int rtnl_route_get_oif(struct rtnl_route *);
extern void rtnl_route_set_iif(struct rtnl_route *, const char *);
extern char * rtnl_route_get_iif(struct rtnl_route *);
extern int rtnl_route_get_dst_len(struct rtnl_route *);
extern int rtnl_route_get_src_len(struct rtnl_route *);
extern void rtnl_route_add_nexthop(struct rtnl_route *,
struct rtnl_nexthop *);
extern void rtnl_route_remove_nexthop(struct rtnl_nexthop *);
extern struct nl_list_head * rtnl_route_get_nexthops(struct rtnl_route *);
extern void rtnl_route_set_cacheinfo(struct rtnl_route *,
struct rtnl_rtcacheinfo *);
extern uint32_t rtnl_route_get_mp_algo(struct rtnl_route *);
extern void rtnl_route_set_mp_algo(struct rtnl_route *, uint32_t);
extern char * rtnl_route_table2str(int, char *, size_t);
extern int rtnl_route_str2table(const char *);
extern int rtnl_route_read_table_names(const char *);
extern char * rtnl_route_proto2str(int, char *, size_t);
extern int rtnl_route_str2proto(const char *);
extern int rtnl_route_read_protocol_names(const char *);
extern char * rtnl_route_metric2str(int, char *, size_t);
extern int rtnl_route_str2metric(const char *);
extern char * rtnl_route_nh_flags2str(int, char *, size_t);
extern int rtnl_route_nh_str2flags(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,71 @@
/*
* netlink/route/rtnl.h Routing Netlink
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_RTNL_H_
#define NETLINK_RTNL_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Realms
* @{
*/
typedef uint32_t realm_t;
/**
* Mask specying the size of each realm part
* @ingroup rtnl
*/
#define RTNL_REALM_MASK (0xFFFF)
/**
* Extract FROM realm from a realms field
*/
#define RTNL_REALM_FROM(realm) ((realm) >> 16)
/**
* Extract TO realm from a realms field
*/
#define RTNL_REALM_TO(realm) ((realm) & RTNL_REALM_MASK)
/**
* Build a realms field
*/
#define RTNL_MAKE_REALM(from, to) \
((RTNL_REALM_TO(from) << 16) & RTNL_REALM_TO(to))
/** @} */
/* General */
extern int nl_rtgen_request(struct nl_handle *, int, int, int);
/* Routing Type Translations */
extern char * nl_rtntype2str(int, char *, size_t);
extern int nl_str2rtntype(const char *);
/* Scope Translations */
extern char * rtnl_scope2str(int, char *, size_t);
extern int rtnl_str2scope(const char *);
/* Realms Translations */
extern char * rtnl_realms2str(uint32_t, char *, size_t);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,79 @@
/*
* netlink/route/rule.h Rules
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_RULE_H_
#define NETLINK_RULE_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/addr.h>
#include <netlink/route/route.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtnl_rule;
/* General */
extern struct rtnl_rule * rtnl_rule_alloc(void);
extern void rtnl_rule_put(struct rtnl_rule *);
extern struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *);
extern struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *,
int);
extern void rtnl_rule_dump(struct rtnl_rule *, FILE *, struct nl_dump_params *);
extern struct nl_msg * rtnl_rule_build_add_request(struct rtnl_rule *, int);
extern int rtnl_rule_add(struct nl_handle *, struct rtnl_rule *, int);
extern struct nl_msg * rtnl_rule_build_delete_request(struct rtnl_rule *, int);
extern int rtnl_rule_delete(struct nl_handle *, struct rtnl_rule *, int);
/* attribute modification */
extern void rtnl_rule_set_family(struct rtnl_rule *, int);
extern int rtnl_rule_get_family(struct rtnl_rule *);
extern void rtnl_rule_set_prio(struct rtnl_rule *, int);
extern int rtnl_rule_get_prio(struct rtnl_rule *);
#define rtnl_rule_set_fwmark(ptr, n) rtnl_rule_set_mark(ptr, n)
extern void rtnl_rule_set_mark(struct rtnl_rule *, uint64_t);
#define rtnl_rule_get_fwmark(ptr) rtnl_rule_get_mark(ptr)
extern uint64_t rtnl_rule_get_mark(struct rtnl_rule *);
extern void rtnl_rule_set_table(struct rtnl_rule *, int);
extern int rtnl_rule_get_table(struct rtnl_rule *);
extern void rtnl_rule_set_dsfield(struct rtnl_rule *, int);
extern int rtnl_rule_get_dsfield(struct rtnl_rule *);
extern int rtnl_rule_set_src(struct rtnl_rule *, struct nl_addr *);
extern struct nl_addr * rtnl_rule_get_src(struct rtnl_rule *);
extern int rtnl_rule_set_dst(struct rtnl_rule *, struct nl_addr *);
extern struct nl_addr * rtnl_rule_get_dst(struct rtnl_rule *);
extern void rtnl_rule_set_src_len(struct rtnl_rule *, int);
extern int rtnl_rule_get_src_len(struct rtnl_rule *);
extern void rtnl_rule_set_dst_len(struct rtnl_rule *, int);
extern int rtnl_rule_get_dst_len(struct rtnl_rule *);
extern void rtnl_rule_set_action(struct rtnl_rule *, int);
extern int rtnl_rule_get_action(struct rtnl_rule *);
extern int rtnl_rule_set_iif(struct rtnl_rule *, const char *);
extern char * rtnl_rule_get_iif(struct rtnl_rule *);
extern void rtnl_rule_set_classid(struct rtnl_rule *, uint32_t);
extern uint32_t rtnl_rule_get_classid(struct rtnl_rule *);
extern void rtnl_rule_set_realms(struct rtnl_rule *, realm_t);
extern realm_t rtnl_rule_get_realms(struct rtnl_rule *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,30 @@
/*
* netlink/route/sch/cbq.h Class Based Queueing
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_CBQ_H_
#define NETLINK_CBQ_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/route/qdisc.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char * nl_ovl_strategy2str(int, char *, size_t);
extern int nl_str2ovl_strategy(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* netlink/route/sch/dsmark.h DSMARK
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_DSMARK_H_
#define NETLINK_DSMARK_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_class_dsmark_set_bmask(struct rtnl_class *, uint8_t);
extern int rtnl_class_dsmark_get_bmask(struct rtnl_class *);
extern int rtnl_class_dsmark_set_value(struct rtnl_class *, uint8_t);
extern int rtnl_class_dsmark_get_value(struct rtnl_class *);
extern int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *, uint16_t);
extern int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *);
extern int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *,
uint16_t);
extern int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *);
extern int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,28 @@
/*
* netlink/route/sch/fifo.c FIFO Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_FIFO_H_
#define NETLINK_FIFO_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* netlink/route/sch/htb.h HTB Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2005 Petr Gotthard <petr.gotthard@siemens.com>
* Copyright (c) 2005 Siemens AG Oesterreich
*/
#ifndef NETLINK_HTB_H_
#define NETLINK_HTB_H_
#include <netlink/netlink.h>
#include <netlink/route/tc.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *, uint32_t);
extern void rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t);
extern void rtnl_htb_set_prio(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_mtu(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_rate(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_ceil(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t);
extern void rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum);
extern void rtnl_htb_set_overhead(struct rtnl_class *class, uint8_t overhead);
extern void rtnl_htb_set_mpu(struct rtnl_class *class, uint8_t mpu);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,62 @@
/*
* netlink/route/sch/netem.h Network Emulator Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_NETEM_H_
#define NETLINK_NETEM_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_netem_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_limit(struct rtnl_qdisc *);
/* Packet Re-ordering */
extern int rtnl_netem_set_gap(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_gap(struct rtnl_qdisc *);
extern int rtnl_netem_set_reorder_probability(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *);
extern int rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *);
/* Packet Loss */
extern int rtnl_netem_set_loss(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_loss(struct rtnl_qdisc *);
extern int rtnl_netem_set_loss_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *);
/* Packet Duplication */
extern int rtnl_netem_set_duplicate(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_duplicate(struct rtnl_qdisc *);
extern int rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *);
/* Packet Delay */
extern int rtnl_netem_set_delay(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_delay(struct rtnl_qdisc *);
extern int rtnl_netem_set_jitter(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_jitter(struct rtnl_qdisc *);
extern int rtnl_netem_set_delay_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,53 @@
/*
* netlink/route/sch/prio.c PRIO Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_PRIO_H_
#define NETLINK_PRIO_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Default Values
* @{
*/
/**
* Default number of bands.
* @ingroup prio
*/
#define QDISC_PRIO_DEFAULT_BANDS 3
/**
* Default priority mapping.
* @ingroup prio
*/
#define QDISC_PRIO_DEFAULT_PRIOMAP \
{ 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }
/** @} */
extern int rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *);
extern int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *, uint8_t[], int);
extern uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *);
extern char * rtnl_prio2str(int, char *, size_t);
extern int rtnl_str2prio(const char *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,17 @@
/*
* netlink/route/sch/red.h RED Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_RED_H_
#define NETLINK_RED_H_
#include <netlink/netlink.h>
#endif

View file

@ -0,0 +1,36 @@
/*
* netlink/route/sch/sfq.c SFQ Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_SFQ_H_
#define NETLINK_SFQ_H_
#include <netlink/netlink.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_sfq_set_quantum(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_quantum(struct rtnl_qdisc *);
extern int rtnl_sfq_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_limit(struct rtnl_qdisc *);
extern int rtnl_sfq_set_perturb(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_perturb(struct rtnl_qdisc *);
extern int rtnl_sfq_get_divisor(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,43 @@
/*
* netlink/route/sch/tbf.h TBF Qdisc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_TBF_H_
#define NETLINK_TBF_H_
#include <netlink/netlink.h>
#include <netlink/route/tc.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_set_mpu(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_tbf_get_mpu(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *, int, int, int);
extern int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *, int, int, int);
extern int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,63 @@
/*
* netlink/route/tc.h Traffic Control
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_TC_H_
#define NETLINK_TC_H_
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/data.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* TC statistics identifiers
* @ingroup tc
*/
enum rtnl_tc_stats_id {
RTNL_TC_PACKETS, /**< Packets seen */
RTNL_TC_BYTES, /**< Bytes seen */
RTNL_TC_RATE_BPS, /**< Current bits/s (rate estimator) */
RTNL_TC_RATE_PPS, /**< Current packet/s (rate estimator) */
RTNL_TC_QLEN, /**< Queue length */
RTNL_TC_BACKLOG, /**< Backlog length */
RTNL_TC_DROPS, /**< Packets dropped */
RTNL_TC_REQUEUES, /**< Number of requeues */
RTNL_TC_OVERLIMITS, /**< Number of overlimits */
__RTNL_TC_STATS_MAX,
};
#define RTNL_TC_STATS_MAX (__RTNL_TC_STATS_MAX - 1)
extern int rtnl_tc_calc_txtime(int, int);
extern int rtnl_tc_calc_bufsize(int, int);
extern int rtnl_tc_calc_cell_log(int);
/**
* Number of entries in a transmission time lookup table
* @ingroup tc
*/
#define RTNL_TC_RTABLE_SIZE 256
extern int rtnl_tc_build_rate_table(uint32_t *, uint8_t, uint8_t, int, int);
/* TC Handle Translations */
extern char * rtnl_tc_handle2str(uint32_t, char *, size_t);
extern int rtnl_tc_str2handle(const char *, uint32_t *);
#ifdef __cplusplus
}
#endif
#endif

66
include/netlink/socket.h Normal file
View file

@ -0,0 +1,66 @@
/*
* netlink/socket.h Netlink Socket
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_SOCKET_H_
#define NETLINK_SOCKET_H_
#include <netlink/types.h>
#include <netlink/handlers.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct nl_handle * nl_handle_alloc(void);
extern struct nl_handle * nl_handle_alloc_cb(struct nl_cb *);
extern void nl_handle_destroy(struct nl_handle *);
extern uint32_t nl_socket_get_local_port(struct nl_handle *);
extern void nl_socket_set_local_port(struct nl_handle *,
uint32_t);
extern int nl_socket_add_membership(struct nl_handle *,
int);
extern int nl_socket_drop_membership(struct nl_handle *,
int);
extern void nl_join_groups(struct nl_handle *, int);
extern uint32_t nl_socket_get_peer_port(struct nl_handle *);
extern void nl_socket_set_peer_port(struct nl_handle *,
uint32_t);
extern struct nl_cb * nl_socket_get_cb(struct nl_handle *);
extern void nl_socket_set_cb(struct nl_handle *,
struct nl_cb *);
extern int nl_socket_modify_cb(struct nl_handle *,
enum nl_cb_type,
enum nl_cb_kind,
nl_recvmsg_msg_cb_t,
void *);
extern int nl_set_buffer_size(struct nl_handle *,
int, int);
extern int nl_set_passcred(struct nl_handle *, int);
extern int nl_socket_recv_pktinfo(struct nl_handle *, int);
extern void nl_disable_sequence_check(struct nl_handle *);
extern unsigned int nl_socket_use_seq(struct nl_handle *);
extern int nl_socket_get_fd(struct nl_handle *);
extern int nl_socket_set_nonblocking(struct nl_handle *);
extern void nl_socket_enable_msg_peek(struct nl_handle *);
extern void nl_socket_disable_msg_peek(struct nl_handle *);
#ifdef __cplusplus
}
#endif
#endif

105
include/netlink/types.h Normal file
View file

@ -0,0 +1,105 @@
/*
* netlink/netlink-types.h Netlink Types
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef __NETLINK_TYPES_H_
#define __NETLINK_TYPES_H_
#include <stdio.h>
/**
* Dumping types (dp_type)
* @ingroup utils
*/
enum nl_dump_type {
NL_DUMP_BRIEF, /**< Dump object in a brief one-liner */
NL_DUMP_FULL, /**< Dump all attributes but no statistics */
NL_DUMP_STATS, /**< Dump all attributes including statistics */
NL_DUMP_XML, /**< Dump all attribtes in XML format */
NL_DUMP_ENV, /**< Dump all attribtues as env variables */
NL_DUMP_EVENTS, /**< Dump event */
__NL_DUMP_MAX,
};
#define NL_DUMP_MAX (__NL_DUMP_MAX - 1)
/**
* Dumping parameters
* @ingroup utils
*/
struct nl_dump_params
{
/**
* Specifies the type of dump that is requested.
*/
enum nl_dump_type dp_type;
/**
* Specifies the number of whitespaces to be put in front
* of every new line (indentation).
*/
int dp_prefix;
/**
* Causes the cache index to be printed for each element.
*/
int dp_print_index;
/**
* Causes each element to be prefixed with the message type.
*/
int dp_dump_msgtype;
/**
* A callback invoked for output
*
* Passed arguments are:
* - dumping parameters
* - string to append to the output
*/
void (*dp_cb)(struct nl_dump_params *, char *);
/**
* A callback invoked for every new line, can be used to
* customize the indentation.
*
* Passed arguments are:
* - dumping parameters
* - line number starting from 0
*/
void (*dp_nl_cb)(struct nl_dump_params *, int);
/**
* User data pointer, can be used to pass data to callbacks.
*/
void *dp_data;
/**
* File descriptor the dumping output should go to
*/
FILE * dp_fd;
/**
* Alternatively the output may be redirected into a buffer
*/
char * dp_buf;
/**
* Length of the buffer dp_buf
*/
size_t dp_buflen;
/**
* PRIVATE
* Set if a dump was performed prior to the actual dump handler.
*/
int dp_pre_dump;
};
#endif

76
include/netlink/utils.h Normal file
View file

@ -0,0 +1,76 @@
/*
* netlink/utils.h Utility Functions
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_UTILS_H_
#define NETLINK_UTILS_H_
#include <netlink/netlink.h>
#include <netlink/list.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Probability Constants
* @{
*/
/**
* Lower probability limit
* @ingroup utils
*/
#define NL_PROB_MIN 0x0
/**
* Upper probability limit
* @ingroup utils
*/
#define NL_PROB_MAX 0xffffffff
/** @} */
extern char * nl_geterror(void);
extern int nl_get_errno(void);
extern void nl_perror(const char *);
/* unit pretty-printing */
extern double nl_cancel_down_bytes(unsigned long long, char **);
extern double nl_cancel_down_bits(unsigned long long, char **);
extern double nl_cancel_down_us(uint32_t, char **);
/* generic unit translations */
extern long nl_size2int(const char *);
extern long nl_prob2int(const char *);
/* time translations */
extern int nl_get_hz(void);
extern uint32_t nl_us2ticks(uint32_t);
extern uint32_t nl_ticks2us(uint32_t);
extern char * nl_msec2str(uint64_t, char *, size_t);
/* link layer protocol translations */
extern char * nl_llproto2str(int, char *, size_t);
extern int nl_str2llproto(const char *);
/* ethernet protocol translations */
extern char * nl_ether_proto2str(int, char *, size_t);
extern int nl_str2ether_proto(const char *);
/* IP protocol translations */
extern char * nl_ip_proto2str(int, char *, size_t);
extern int nl_str2ip_proto(const char *);
#ifdef __cplusplus
}
#endif
#endif

294
install-sh Executable file
View file

@ -0,0 +1,294 @@
#!/bin/sh
#
# install - install a program, script, or datafile
#
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "$0: no input file specified" >&2
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d "$dst" ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "$0: no destination specified" >&2
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d "$dst" ]
then
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS=$oIFS
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp=$pathcomp$1
shift
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "$pathcomp"
else
:
fi
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename "$dst"`
else
:
fi
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up temp files at exit.
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
trap '(exit $?); exit' 1 2 13 15
# Move or copy the file name to the temp name
$doit $instcmd "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# Now remove or move aside any old file at destination location. We try this
# two ways since rm can't unlink itself on some systems and the destination
# file might be busy for other reasons. In this case, the final cleanup
# might fail but the new file should still install successfully.
{
if [ -f "$dstdir/$dstfile" ]
then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
{
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
fi &&
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit
}

74
lib/Makefile Normal file
View file

@ -0,0 +1,74 @@
#
# lib/Makefile
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
#
ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
include ../Makefile.opts
endif
# Core
CIN := $(wildcard *.c)
# NETLINK_ROUTE
CIN += $(wildcard route/*.c)
# Schedulers
CIN += $(wildcard route/sch/*.c)
# Classifiers
CIN += $(wildcard route/cls/*.c)
# NETLINK_GENERIC
CIN += $(wildcard genl/*.c)
# fib lookup
CIN += $(wildcard fib_lookup/*.c)
# Netfilter
CIN += $(wildcard netfilter/*.c)
DEPS := $(CIN:%.c=%.d)
OBJ := $(CIN:%.c=%.o)
CFLAGS += -fPIC
OUT_SLIB := $(PACKAGE_NAME).so.$(PACKAGE_VERSION)
LN_SLIB := $(PACKAGE_NAME).so
LN1_SLIB := $(LN_SLIB).1
export
.PHONY: all clean install librtn.a $(OUT_SLIB)
all:
@echo " MAKE $(OUT_SLIB)"; \
$(MAKE) $(OUT_SLIB)
$(OUT_SLIB): ../Makefile.opts $(OBJ)
@echo " LD $(OUT_SLIB)"; \
$(CC) -shared -Wl,-soname,libnl.so.1 -o $(OUT_SLIB) $(OBJ) $(LIBNL_LIB) -lc
@echo " LN $(OUT_SLIB) $(LN1_SLIB)"; \
rm -f $(LN1_SLIB) ; $(LN) -s $(OUT_SLIB) $(LN1_SLIB)
@echo " LN $(LN1_SLIB) $(LN_SLIB)"; \
rm -f $(LN_SLIB) ; $(LN) -s $(LN1_SLIB) $(LN_SLIB)
clean:
@echo " CLEAN lib"; \
$(RM) -f $(OBJ) $(OUT_SLIB) $(LN_SLIB) $(LN1_SLIB); \
$(RM) -f $(DEPS) $(OUT_SLIB) $(LN_SLIB) $(LN1_SLIB)
distclean:
@echo " DISTCLEAN lib"; \
$(RM) -f $(DEPS)
install:
mkdir -p $(DESTDIR)$(libdir)/
install -m 0644 $(OUT_SLIB) $(DESTDIR)$(libdir)
rm -f $(DESTDIR)$(libdir)/$(LN1_SLIB)
$(LN) -s $(OUT_SLIB) $(DESTDIR)$(libdir)/$(LN1_SLIB)
rm -f $(DESTDIR)$(libdir)/$(LN_SLIB)
$(LN) -s $(LN1_SLIB) $(DESTDIR)$(libdir)/$(LN_SLIB)
$(DEPS): ../Makefile.opts
include ../Makefile.rules

883
lib/addr.c Normal file
View file

@ -0,0 +1,883 @@
/*
* lib/addr.c Abstract Address
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup utils
* @defgroup addr Abstract Address
*
* @par 1) Transform character string to abstract address
* @code
* struct nl_addr *a = nl_addr_parse("::1", AF_UNSPEC);
* printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a)));
* nl_addr_put(a);
* a = nl_addr_parse("11:22:33:44:55:66", AF_UNSPEC);
* printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a)));
* nl_addr_put(a);
* @endcode
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/addr.h>
#include <linux/socket.h>
/* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
* this, probably Alexey. */
static inline uint16_t dn_ntohs(uint16_t addr)
{
union {
uint8_t byte[2];
uint16_t word;
} u = {
.word = addr,
};
return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
}
static inline int do_digit(char *str, uint16_t *addr, uint16_t scale,
size_t *pos, size_t len, int *started)
{
uint16_t tmp = *addr / scale;
if (*pos == len)
return 1;
if (((tmp) > 0) || *started || (scale == 1)) {
*str = tmp + '0';
*started = 1;
(*pos)++;
*addr -= (tmp * scale);
}
return 0;
}
static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str,
size_t len)
{
uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
uint16_t area = addr >> 10;
size_t pos = 0;
int started = 0;
if (addrlen != 2)
return NULL;
addr &= 0x03ff;
if (len == 0)
return str;
if (do_digit(str + pos, &area, 10, &pos, len, &started))
return str;
if (do_digit(str + pos, &area, 1, &pos, len, &started))
return str;
if (pos == len)
return str;
*(str + pos) = '.';
pos++;
started = 0;
if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
return str;
if (do_digit(str + pos, &addr, 100, &pos, len, &started))
return str;
if (do_digit(str + pos, &addr, 10, &pos, len, &started))
return str;
if (do_digit(str + pos, &addr, 1, &pos, len, &started))
return str;
if (pos == len)
return str;
*(str + pos) = 0;
return str;
}
static int dnet_num(const char *src, uint16_t * dst)
{
int rv = 0;
int tmp;
*dst = 0;
while ((tmp = *src++) != 0) {
tmp -= '0';
if ((tmp < 0) || (tmp > 9))
return rv;
rv++;
(*dst) *= 10;
(*dst) += tmp;
}
return rv;
}
static inline int dnet_pton(const char *src, char *addrbuf)
{
uint16_t area = 0;
uint16_t node = 0;
int pos;
pos = dnet_num(src, &area);
if ((pos == 0) || (area > 63) ||
((*(src + pos) != '.') && (*(src + pos) != ',')))
return -EINVAL;
pos = dnet_num(src + pos + 1, &node);
if ((pos == 0) || (node > 1023))
return -EINVAL;
*(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
return 1;
}
/**
* @name Creating Abstract Addresses
* @{
*/
/**
* Allocate new abstract address object.
* @arg maxsize Maximum size of the binary address.
* @return Newly allocated address object or NULL
*/
struct nl_addr *nl_addr_alloc(size_t maxsize)
{
struct nl_addr *addr;
addr = calloc(1, sizeof(*addr) + maxsize);
if (!addr) {
nl_errno(ENOMEM);
return NULL;
}
addr->a_refcnt = 1;
addr->a_maxsize = maxsize;
return addr;
}
/**
* Allocate new abstract address object based on a binary address.
* @arg family Address family.
* @arg buf Buffer containing the binary address.
* @arg size Length of binary address buffer.
* @return Newly allocated address handle or NULL
*/
struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
{
struct nl_addr *addr;
addr = nl_addr_alloc(size);
if (!addr)
return NULL;
addr->a_family = family;
addr->a_len = size;
addr->a_prefixlen = size*8;
if (size)
memcpy(addr->a_addr, buf, size);
return addr;
}
/**
* Allocate abstract address object based on a character string
* @arg addrstr Address represented as character string.
* @arg hint Address family hint or AF_UNSPEC.
*
* Regognizes the following address formats:
*@code
* Format Len Family
* ----------------------------------------------------------------
* IPv6 address format 16 AF_INET6
* ddd.ddd.ddd.ddd 4 AF_INET
* HH:HH:HH:HH:HH:HH 6 AF_LLC
* AA{.|,}NNNN 2 AF_DECnet
* HH:HH:HH:... variable AF_UNSPEC
* @endcode
*
* Special values:
* - none: All bits and length set to 0.
* - {default|all|any}: All bits set to 0, length based on hint or
* AF_INET if no hint is given.
*
* The prefix length may be appened at the end prefixed with a
* slash, e.g. 10.0.0.0/8.
*
* @return Newly allocated abstract address object or NULL.
*/
struct nl_addr *nl_addr_parse(const char *addrstr, int hint)
{
int err, copy = 0, len = 0, family = AF_UNSPEC;
char *str, *prefix, buf[32];
struct nl_addr *addr = NULL; /* gcc ain't that smart */
str = strdup(addrstr);
if (!str) {
err = nl_errno(ENOMEM);
goto errout;
}
prefix = strchr(str, '/');
if (prefix)
*prefix = '\0';
if (!strcasecmp(str, "none")) {
family = hint;
goto prefix;
}
if (!strcasecmp(str, "default") ||
!strcasecmp(str, "all") ||
!strcasecmp(str, "any")) {
switch (hint) {
case AF_INET:
case AF_UNSPEC:
/* Kind of a hack, we assume that if there is
* no hint given the user wants to have a IPv4
* address given back. */
family = AF_INET;
len = 4;
goto prefix;
case AF_INET6:
family = AF_INET6;
len = 16;
goto prefix;
case AF_LLC:
family = AF_LLC;
len = 6;
goto prefix;
default:
err = nl_error(EINVAL, "Unsuported address" \
"family for default address");
goto errout;
}
}
copy = 1;
if (hint == AF_INET || hint == AF_UNSPEC) {
if (inet_pton(AF_INET, str, buf) > 0) {
family = AF_INET;
len = 4;
goto prefix;
}
if (hint == AF_INET) {
err = nl_error(EINVAL, "Invalid IPv4 address");
goto errout;
}
}
if (hint == AF_INET6 || hint == AF_UNSPEC) {
if (inet_pton(AF_INET6, str, buf) > 0) {
family = AF_INET6;
len = 16;
goto prefix;
}
if (hint == AF_INET6) {
err = nl_error(EINVAL, "Invalid IPv6 address");
goto errout;
}
}
if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
unsigned int a, b, c, d, e, f;
if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
&a, &b, &c, &d, &e, &f) == 6) {
family = AF_LLC;
len = 6;
buf[0] = (unsigned char) a;
buf[1] = (unsigned char) b;
buf[2] = (unsigned char) c;
buf[3] = (unsigned char) d;
buf[4] = (unsigned char) e;
buf[5] = (unsigned char) f;
goto prefix;
}
if (hint == AF_LLC) {
err = nl_error(EINVAL, "Invalid link layer address");
goto errout;
}
}
if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
(strchr(str, '.') || strchr(str, ','))) {
if (dnet_pton(str, buf) > 0) {
family = AF_DECnet;
len = 2;
goto prefix;
}
if (hint == AF_DECnet) {
err = nl_error(EINVAL, "Invalid DECnet address");
goto errout;
}
}
if (hint == AF_UNSPEC && strchr(str, ':')) {
int i = 0;
char *s = str, *p;
for (;;) {
long l = strtol(s, &p, 16);
if (s == p || l > 0xff || i >= sizeof(buf)) {
err = -EINVAL;
goto errout;
}
buf[i++] = (unsigned char) l;
if (*p == '\0')
break;
s = ++p;
}
len = i;
family = AF_UNSPEC;
goto prefix;
}
err = nl_error(EINVAL, "Invalid address");
goto errout;
prefix:
addr = nl_addr_alloc(len);
if (!addr) {
err = nl_errno(ENOMEM);
goto errout;
}
nl_addr_set_family(addr, family);
if (copy)
nl_addr_set_binary_addr(addr, buf, len);
if (prefix) {
char *p;
long pl = strtol(++prefix, &p, 0);
if (p == prefix) {
nl_addr_destroy(addr);
err = -EINVAL;
goto errout;
}
nl_addr_set_prefixlen(addr, pl);
} else
nl_addr_set_prefixlen(addr, len * 8);
err = 0;
errout:
free(str);
return err ? NULL : addr;
}
/**
* Clone existing abstract address object.
* @arg addr Abstract address object.
* @return Newly allocated abstract address object being a duplicate of the
* specified address object or NULL if a failure occured.
*/
struct nl_addr *nl_addr_clone(struct nl_addr *addr)
{
struct nl_addr *new;
new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
if (new)
new->a_prefixlen = addr->a_prefixlen;
return new;
}
/** @} */
/**
* @name Destroying Abstract Addresses
* @{
*/
/**
* Destroy abstract address object.
* @arg addr Abstract address object.
*/
void nl_addr_destroy(struct nl_addr *addr)
{
if (!addr)
return;
if (addr->a_refcnt != 1)
BUG();
free(addr);
}
/** @} */
/**
* @name Managing Usage References
* @{
*/
struct nl_addr *nl_addr_get(struct nl_addr *addr)
{
addr->a_refcnt++;
return addr;
}
void nl_addr_put(struct nl_addr *addr)
{
if (!addr)
return;
if (addr->a_refcnt == 1)
nl_addr_destroy(addr);
else
addr->a_refcnt--;
}
/**
* Check whether an abstract address object is shared.
* @arg addr Abstract address object.
* @return Non-zero if the abstract address object is shared, otherwise 0.
*/
int nl_addr_shared(struct nl_addr *addr)
{
return addr->a_refcnt > 1;
}
/** @} */
/**
* @name Miscellaneous
* @{
*/
/**
* Compares two abstract address objects.
* @arg a A abstract address object.
* @arg b Another abstract address object.
*
* @return Integer less than, equal to or greather than zero if \c is found,
* respectively to be less than, to, or be greater than \c b.
*/
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
{
int d = a->a_family - b->a_family;
if (d == 0) {
d = a->a_len - b->a_len;
if (a->a_len && d == 0)
return memcmp(a->a_addr, b->a_addr, a->a_len);
}
return d;
}
/**
* Compares the prefix of two abstract address objects.
* @arg a A abstract address object.
* @arg b Another abstract address object.
*
* @return Integer less than, equal to or greather than zero if \c is found,
* respectively to be less than, to, or be greater than \c b.
*/
int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
{
int d = a->a_family - b->a_family;
if (d == 0) {
int len = min(a->a_prefixlen, b->a_prefixlen);
int bytes = len / 8;
d = memcmp(a->a_addr, b->a_addr, bytes);
if (d == 0) {
int mask = (1UL << (len % 8)) - 1UL;
d = (a->a_addr[bytes] & mask) -
(b->a_addr[bytes] & mask);
}
}
return d;
}
/**
* Check if an address matches a certain family.
* @arg addr Address represented as character string.
* @arg family Desired address family.
*
* @return 1 if the address is of the desired address family,
* otherwise 0 is returned.
*/
int nl_addr_valid(char *addr, int family)
{
int ret;
char buf[32];
switch (family) {
case AF_INET:
case AF_INET6:
ret = inet_pton(family, addr, buf);
if (ret <= 0)
return 0;
break;
case AF_DECnet:
ret = dnet_pton(addr, buf);
if (ret <= 0)
return 0;
break;
case AF_LLC:
if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
return 0;
break;
}
return 1;
}
/**
* Guess address family of an abstract address object based on address size.
* @arg addr Abstract address object.
* @return Address family or AF_UNSPEC if guessing wasn't successful.
*/
int nl_addr_guess_family(struct nl_addr *addr)
{
switch (addr->a_len) {
case 4:
return AF_INET;
case 6:
return AF_LLC;
case 16:
return AF_INET6;
default:
return AF_UNSPEC;
}
}
/**
* Fill out sockaddr structure with values from abstract address object.
* @arg addr Abstract address object.
* @arg sa Destination sockaddr structure buffer.
* @arg salen Length of sockaddr structure buffer.
*
* Fills out the specified sockaddr structure with the data found in the
* specified abstract address. The salen argument needs to be set to the
* size of sa but will be modified to the actual size used during before
* the function exits.
*
* @return 0 on success or a negative error code
*/
int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
socklen_t *salen)
{
switch (addr->a_family) {
case AF_INET: {
struct sockaddr_in *sai = (struct sockaddr_in *) sa;
if (*salen < sizeof(*sai))
return -EINVAL;
sai->sin_family = addr->a_family;
memcpy(&sai->sin_addr, addr->a_addr, 4);
*salen = sizeof(*sai);
}
break;
case AF_INET6: {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
if (*salen < sizeof(*sa6))
return -EINVAL;
sa6->sin6_family = addr->a_family;
memcpy(&sa6->sin6_addr, addr->a_addr, 16);
*salen = sizeof(*sa6);
}
break;
default:
return -EINVAL;
}
return 0;
}
/** @} */
/**
* @name Getting Information About Addresses
* @{
*/
/**
* Call getaddrinfo() for an abstract address object.
* @arg addr Abstract address object.
*
* Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST
* mode.
*
* @note The caller is responsible for freeing the linked list using the
* interface provided by getaddrinfo(3).
*
* @return A linked list of addrinfo handles or NULL with an error message
* associated.
*/
struct addrinfo *nl_addr_info(struct nl_addr *addr)
{
int err;
struct addrinfo *res;
char buf[INET6_ADDRSTRLEN+5];
struct addrinfo hint = {
.ai_flags = AI_NUMERICHOST,
.ai_family = addr->a_family,
};
nl_addr2str(addr, buf, sizeof(buf));
err = getaddrinfo(buf, NULL, &hint, &res);
if (err != 0) {
nl_error(err, gai_strerror(err));
return NULL;
}
return res;
}
/**
* Resolve abstract address object to a name using getnameinfo().
* @arg addr Abstract address object.
* @arg host Destination buffer for host name.
* @arg hostlen Length of destination buffer.
*
* Resolves the abstract address to a name and writes the looked up result
* into the host buffer. getnameinfo() is used to perform the lookup and
* is put into NI_NAMEREQD mode so the function will fail if the lookup
* couldn't be performed.
*
* @return 0 on success or a negative error code.
*/
int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
{
int err;
struct sockaddr_in6 buf;
socklen_t salen = sizeof(buf);
err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
if (err < 0)
return err;
return getnameinfo((struct sockaddr *) &buf, salen,
host, hostlen, NULL, 0, NI_NAMEREQD);
}
/** @} */
/**
* @name Attributes
* @{
*/
void nl_addr_set_family(struct nl_addr *addr, int family)
{
addr->a_family = family;
}
int nl_addr_get_family(struct nl_addr *addr)
{
return addr->a_family;
}
/**
* Set binary address of abstract address object.
* @arg addr Abstract address object.
* @arg buf Buffer containing binary address.
* @arg len Length of buffer containing binary address.
*/
int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
{
if (len > addr->a_maxsize)
return -ERANGE;
addr->a_len = len;
memcpy(addr->a_addr, buf, len);
return 0;
}
/**
* Get binary address of abstract address object.
* @arg addr Abstract address object.
*/
void *nl_addr_get_binary_addr(struct nl_addr *addr)
{
return addr->a_addr;
}
/**
* Get length of binary address of abstract address object.
* @arg addr Abstract address object.
*/
unsigned int nl_addr_get_len(struct nl_addr *addr)
{
return addr->a_len;
}
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
{
addr->a_prefixlen = prefixlen;
}
/**
* Get prefix length of abstract address object.
* @arg addr Abstract address object.
*/
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
{
return addr->a_prefixlen;
}
/** @} */
/**
* @name Translations to Strings
* @{
*/
/**
* Convert abstract address object to character string.
* @arg addr Abstract address object.
* @arg buf Destination buffer.
* @arg size Size of destination buffer.
*
* Converts an abstract address to a character string and stores
* the result in the specified destination buffer.
*
* @return Address represented in ASCII stored in destination buffer.
*/
char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
{
int i;
char tmp[16];
if (!addr->a_len) {
snprintf(buf, size, "none");
goto prefix;
}
switch (addr->a_family) {
case AF_INET:
inet_ntop(AF_INET, addr->a_addr, buf, size);
break;
case AF_INET6:
inet_ntop(AF_INET6, addr->a_addr, buf, size);
break;
case AF_DECnet:
dnet_ntop(addr->a_addr, addr->a_len, buf, size);
break;
case AF_LLC:
default:
snprintf(buf, size, "%02x",
(unsigned char) addr->a_addr[0]);
for (i = 1; i < addr->a_len; i++) {
snprintf(tmp, sizeof(tmp), ":%02x",
(unsigned char) addr->a_addr[i]);
strncat(buf, tmp, size - strlen(buf) - 1);
}
break;
}
prefix:
if (addr->a_prefixlen != (8 * addr->a_len)) {
snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
strncat(buf, tmp, size - strlen(buf) - 1);
}
return buf;
}
/** @} */
/**
* @name Address Family Transformations
* @{
*/
static struct trans_tbl afs[] = {
__ADD(AF_UNSPEC,unspec)
__ADD(AF_UNIX,unix)
__ADD(AF_LOCAL,local)
__ADD(AF_INET,inet)
__ADD(AF_AX25,ax25)
__ADD(AF_IPX,ipx)
__ADD(AF_APPLETALK,appletalk)
__ADD(AF_NETROM,netrom)
__ADD(AF_BRIDGE,bridge)
__ADD(AF_ATMPVC,atmpvc)
__ADD(AF_X25,x25)
__ADD(AF_INET6,inet6)
__ADD(AF_ROSE,rose)
__ADD(AF_DECnet,decnet)
__ADD(AF_NETBEUI,netbeui)
__ADD(AF_SECURITY,security)
__ADD(AF_KEY,key)
__ADD(AF_NETLINK,netlink)
__ADD(AF_ROUTE,route)
__ADD(AF_PACKET,packet)
__ADD(AF_ASH,ash)
__ADD(AF_ECONET,econet)
__ADD(AF_ATMSVC,atmsvc)
__ADD(AF_SNA,sna)
__ADD(AF_IRDA,irda)
__ADD(AF_PPPOX,pppox)
__ADD(AF_WANPIPE,wanpipe)
__ADD(AF_LLC,llc)
__ADD(AF_BLUETOOTH,bluetooth)
};
char *nl_af2str(int family, char *buf, size_t size)
{
return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
}
int nl_str2af(const char *name)
{
int fam = __str2type(name, afs, ARRAY_SIZE(afs));
return fam >= 0 ? fam : AF_UNSPEC;
}
/** @} */
/** @} */

787
lib/attr.c Normal file
View file

@ -0,0 +1,787 @@
/*
* lib/attr.c Netlink Attributes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/addr.h>
#include <netlink/attr.h>
#include <netlink/msg.h>
#include <linux/socket.h>
/**
* @ingroup msg
* @defgroup attr Attributes
* Netlink Attributes Construction/Parsing Interface
* @par 0) Introduction
* Netlink attributes are chained together following each other:
* @code
* <------- nla_total_size(payload) ------->
* <---- nla_attr_size(payload) ----->
* +----------+- - -+- - - - - - - - - +- - -+-------- - -
* | Header | Pad | Payload | Pad | Header
* +----------+- - -+- - - - - - - - - +- - -+-------- - -
* <- nla_len(nla) -> ^
* nla_data(nla)----^ |
* nla_next(nla)-----------------------------'
* @endcode
*
* @par
* The attribute header and payload must be aligned properly:
* @code
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
* @endcode
*
* @par Nested TLVs:
* Nested TLVs are an array of TLVs nested into another TLV. This can be useful
* to allow subsystems to have their own formatting rules without the need to
* make the underlying layer be aware of it. It can also be useful to transfer
* arrays, lists and flattened trees.
* \code
* <-------------------- NLA_ALIGN(...) ------------------->
* +---------------+- - - - - - - - - - - - - - - - - -+- - -+
* | |+---------+---------+- - -+-------+| |
* | TLV Header || TLV 1 | TLV 2 | | TLV n || Pad |
* | |+---------+---------+- - -+-------+| |
* +---------------+- - - - - - - - - - - - - - - - - -+- - -+
* <--------- nla_data(nla) --------->
* \endcode
*
* @par 1) Constructing a message with attributes
* @code
* int param1 = 10;
* char *param2 = "parameter text";
* struct nlmsghdr hdr = {
* .nlmsg_type = MY_ACTION,
* };
* struct nl_msg *m = nlmsg_build(&hdr);
* nla_put_u32(m, 1, param1);
* nla_put_string(m, 2, param2);
*
* nl_send_auto_complete(handle, nl_msg_get(m));
* nlmsg_free(m);
* @endcode
*
* @par 2) Constructing nested attributes
* @code
* struct nl_msg * nested_config(void)
* {
* int a = 5, int b = 10;
* struct nl_msg *n = nlmsg_build(NULL);
* nla_put_u32(n, 10, a);
* nla_put_u32(n, 20, b);
* return n;
* }
*
* ...
* struct nl_msg *m = nlmsg_build(&hdr);
* struct nl_msg *nest = nested_config();
* nla_put_nested(m, 1, nest);
*
* nl_send_auto_complete(handle, nl_msg_get(m));
* nlmsg_free(nest);
* nlmsg_free(m);
* @endcode
* @{
*/
/**
* @name Size Calculations
* @{
*/
/**
* length of attribute not including padding
* @arg payload length of payload
*/
int nla_attr_size(int payload)
{
return NLA_HDRLEN + payload;
}
/**
* total length of attribute including padding
* @arg payload length of payload
*/
int nla_total_size(int payload)
{
return NLA_ALIGN(nla_attr_size(payload));
}
/**
* length of padding at the tail of the attribute
* @arg payload length of payload
*/
int nla_padlen(int payload)
{
return nla_total_size(payload) - nla_attr_size(payload);
}
/** @} */
/**
* @name Payload Access
* @{
*/
/**
* attribute type
* @arg nla netlink attribute
*/
int nla_type(const struct nlattr *nla)
{
return nla->nla_type & NLA_TYPE_MASK;
}
/**
* head of payload
* @arg nla netlink attribute
*/
void *nla_data(const struct nlattr *nla)
{
return (char *) nla + NLA_HDRLEN;
}
/**
* length of payload
* @arg nla netlink attribute
*/
int nla_len(const struct nlattr *nla)
{
return nla->nla_len - NLA_HDRLEN;
}
/** @} */
/**
* @name Attribute Parsing
* @{
*/
/**
* check if the netlink attribute fits into the remaining bytes
* @arg nla netlink attribute
* @arg remaining number of bytes remaining in attribute stream
*/
int nla_ok(const struct nlattr *nla, int remaining)
{
return remaining >= sizeof(*nla) &&
nla->nla_len >= sizeof(*nla) &&
nla->nla_len <= remaining;
}
/**
* next netlink attribte in attribute stream
* @arg nla netlink attribute
* @arg remaining number of bytes remaining in attribute stream
*
* @return the next netlink attribute in the attribute stream and
* decrements remaining by the size of the current attribute.
*/
struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
{
int totlen = NLA_ALIGN(nla->nla_len);
*remaining -= totlen;
return (struct nlattr *) ((char *) nla + totlen);
}
static uint16_t nla_attr_minlen[NLA_TYPE_MAX+1] = {
[NLA_U8] = sizeof(uint8_t),
[NLA_U16] = sizeof(uint16_t),
[NLA_U32] = sizeof(uint32_t),
[NLA_U64] = sizeof(uint64_t),
[NLA_STRING] = 1,
[NLA_NESTED] = NLA_HDRLEN,
};
static int validate_nla(struct nlattr *nla, int maxtype,
struct nla_policy *policy)
{
struct nla_policy *pt;
int minlen = 0, type = nla_type(nla);
if (type <= 0 || type > maxtype)
return 0;
pt = &policy[type];
if (pt->type > NLA_TYPE_MAX)
BUG();
if (pt->minlen)
minlen = pt->minlen;
else if (pt->type != NLA_UNSPEC)
minlen = nla_attr_minlen[pt->type];
if (pt->type == NLA_FLAG && nla_len(nla) > 0)
return nl_errno(ERANGE);
if (nla_len(nla) < minlen)
return nl_errno(ERANGE);
if (pt->maxlen && nla_len(nla) > pt->maxlen)
return nl_errno(ERANGE);
if (pt->type == NLA_STRING) {
char *data = nla_data(nla);
if (data[nla_len(nla) - 1] != '\0')
return nl_errno(EINVAL);
}
return 0;
}
/**
* Parse a stream of attributes into a tb buffer
* @arg tb destination array with maxtype+1 elements
* @arg maxtype maximum attribute type to be expected
* @arg head head of attribute stream
* @arg len length of attribute stream
* @arg policy validation policy
*
* Parses a stream of attributes and stores a pointer to each attribute in
* the tb array accessable via the attribute type. Attributes with a type
* exceeding maxtype will be silently ignored for backwards compatibility
* reasons. policy may be set to NULL if no validation is required.
*
* @return 0 on success or a negative error code.
*/
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
nla_for_each_attr(nla, head, len, rem) {
int type = nla_type(nla);
if (type == 0) {
fprintf(stderr, "Illegal nla->nla_type == 0\n");
continue;
}
if (type <= maxtype) {
if (policy) {
err = validate_nla(nla, maxtype, policy);
if (err < 0)
goto errout;
}
tb[type] = nla;
}
}
if (rem > 0)
fprintf(stderr, "netlink: %d bytes leftover after parsing "
"attributes.\n", rem);
err = 0;
errout:
return err;
}
/**
* parse nested attributes
* @arg tb destination array with maxtype+1 elements
* @arg maxtype maximum attribute type to be expected
* @arg nla attribute containing the nested attributes
* @arg policy validation policy
*
* @see nla_parse()
*/
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
struct nla_policy *policy)
{
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
}
/**
* Validate a stream of attributes
* @arg head head of attribute stream
* @arg len length of attribute stream
* @arg maxtype maximum attribute type to be expected
* @arg policy validation policy
*
* Validates all attributes in the specified attribute stream
* against the specified policy. Attributes with a type exceeding
* maxtype will be ignored. See documenation of struct nla_policy
* for more details.
*
* @return 0 on success or a negative error code.
*/
int nla_validate(struct nlattr *head, int len, int maxtype,
struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
nla_for_each_attr(nla, head, len, rem) {
err = validate_nla(nla, maxtype, policy);
if (err < 0)
goto errout;
}
err = 0;
errout:
return err;
}
/**
* Find a specific attribute in a stream of attributes
* @arg head head of attribute stream
* @arg len length of attribute stream
* @arg attrtype type of attribute to look for
*
* @return the first attribute in the stream matching the specified type.
*/
struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
{
struct nlattr *nla;
int rem;
nla_for_each_attr(nla, head, len, rem)
if (nla_type(nla) == attrtype)
return nla;
return NULL;
}
/** @} */
/**
* @name Utilities
* @{
*/
/**
* Copy a netlink attribute into another memory area
* @arg dest where to copy to memcpy
* @arg src netlink attribute to copy from
* @arg count size of the destination area
*
* Note: The number of bytes copied is limited by the length of
* attribute's payload. memcpy
*
* @return the number of bytes copied.
*/
int nla_memcpy(void *dest, struct nlattr *src, int count)
{
int minlen;
if (!src)
return 0;
minlen = min_t(int, count, nla_len(src));
memcpy(dest, nla_data(src), minlen);
return minlen;
}
/**
* Copy string attribute payload into a sized buffer
* @arg dst where to copy the string to
* @arg nla attribute to copy the string from
* @arg dstsize size of destination buffer
*
* Copies at most dstsize - 1 bytes into the destination buffer.
* The result is always a valid NUL-terminated string. Unlike
* strlcpy the destination buffer is always padded out.
*
* @return the length of the source buffer.
*/
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
{
size_t srclen = nla_len(nla);
char *src = nla_data(nla);
if (srclen > 0 && src[srclen - 1] == '\0')
srclen--;
if (dstsize > 0) {
size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
memset(dst, 0, dstsize);
memcpy(dst, src, len);
}
return srclen;
}
/**
* Compare an attribute with sized memory area
* @arg nla netlink attribute
* @arg data memory area
* @arg size size of memory area
*/
int nla_memcmp(const struct nlattr *nla, const void *data,
size_t size)
{
int d = nla_len(nla) - size;
if (d == 0)
d = memcmp(nla_data(nla), data, size);
return d;
}
/**
* Compare a string attribute against a string
* @arg nla netlink string attribute
* @arg str another string
*/
int nla_strcmp(const struct nlattr *nla, const char *str)
{
int len = strlen(str) + 1;
int d = nla_len(nla) - len;
if (d == 0)
d = memcmp(nla_data(nla), str, len);
return d;
}
/** @} */
/**
* @name Attribute Construction
* @{
*/
/**
* reserve room for attribute on the skb
* @arg n netlink message
* @arg attrtype attribute type
* @arg attrlen length of attribute payload
*
* Adds a netlink attribute header to a netlink message and reserves
* room for the payload but does not copy it.
*/
struct nlattr *nla_reserve(struct nl_msg *n, int attrtype, int attrlen)
{
struct nlattr *nla;
int tlen;
tlen = NLMSG_ALIGN(n->nm_nlh->nlmsg_len) + nla_total_size(attrlen);
n->nm_nlh = realloc(n->nm_nlh, tlen);
if (!n->nm_nlh) {
nl_errno(ENOMEM);
return NULL;
}
nla = (struct nlattr *) nlmsg_tail(n->nm_nlh);
nla->nla_type = attrtype;
nla->nla_len = nla_attr_size(attrlen);
memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
n->nm_nlh->nlmsg_len = tlen;
NL_DBG(2, "msg %p: Reserved %d bytes at offset +%d for attr %d "
"nlmsg_len=%d\n", n, attrlen,
(void *) nla - nlmsg_data(n->nm_nlh),
attrtype, n->nm_nlh->nlmsg_len);
return nla;
}
/**
* Add a netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg attrlen length of attribute payload
* @arg data head of attribute payload
*
* @return -1 if the tailroom of the skb is insufficient to store
* the attribute header and payload.
*/
int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data)
{
struct nlattr *nla;
nla = nla_reserve(n, attrtype, attrlen);
if (!nla)
return nl_errno(ENOMEM);
memcpy(nla_data(nla), data, attrlen);
NL_DBG(2, "msg %p: Wrote %d bytes at offset +%d for attr %d\n",
n, attrlen, (void *) nla - nlmsg_data(n->nm_nlh), attrtype);
return 0;
}
/**
* Add a nested netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg nested netlink attribute to nest
*
* @return -1 if the tailroom of the skb is insufficient to store
* the attribute header and payload.
*/
int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
{
return nla_put(n, attrtype, nlmsg_len(nested->nm_nlh),
nlmsg_data(nested->nm_nlh));
}
/**
* Add a u16 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
int nla_put_u8(struct nl_msg *n, int attrtype, uint8_t value)
{
return nla_put(n, attrtype, sizeof(uint8_t), &value);
}
/**
* Add a u16 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
int nla_put_u16(struct nl_msg *n, int attrtype, uint16_t value)
{
return nla_put(n, attrtype, sizeof(uint16_t), &value);
}
/**
* Add a u32 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
int nla_put_u32(struct nl_msg *n, int attrtype, uint32_t value)
{
return nla_put(n, attrtype, sizeof(uint32_t), &value);
}
/**
* Add a u64 netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg value numeric value
*/
int nla_put_u64(struct nl_msg *n, int attrtype, uint64_t value)
{
return nla_put(n, attrtype, sizeof(uint64_t), &value);
}
/**
* Add a string netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg str NUL terminated string
*/
int nla_put_string(struct nl_msg *n, int attrtype, const char *str)
{
return nla_put(n, attrtype, strlen(str) + 1, str);
}
/**
* Add a flag netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
*/
int nla_put_flag(struct nl_msg *n, int attrtype)
{
return nla_put(n, attrtype, 0, NULL);
}
/**
* Add a msecs netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg msecs number of msecs
*/
int nla_put_msecs(struct nl_msg *n, int attrtype, unsigned long msecs)
{
return nla_put_u64(n, attrtype, msecs);
}
/**
* Add an abstract data netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg data abstract data
*/
int nla_put_data(struct nl_msg *n, int attrtype, struct nl_data *data)
{
return nla_put(n, attrtype, nl_data_get_size(data),
nl_data_get(data));
}
/**
* Add an abstract address netlink attribute to a netlink message
* @arg n netlink message
* @arg attrtype attribute type
* @arg addr abstract address
*/
int nla_put_addr(struct nl_msg *n, int attrtype, struct nl_addr *addr)
{
return nla_put(n, attrtype, nl_addr_get_len(addr),
nl_addr_get_binary_addr(addr));
}
/** @} */
/**
* @name Attribute Nesting
* @{
*/
/**
* Start a new level of nested attributes
* @arg n netlink message
* @arg attrtype attribute type of container
*
* @return the container attribute
*/
struct nlattr *nla_nest_start(struct nl_msg *n, int attrtype)
{
struct nlattr *start = (struct nlattr *) nlmsg_tail(n->nm_nlh);
if (nla_put(n, attrtype, 0, NULL) < 0)
return NULL;
return start;
}
/**
* Finalize nesting of attributes
* @arg n netlink message
* @arg start container attribute
*
* Corrects the container attribute header to include the all
* appeneded attributes.
*
* @return the total data length of the skb.
*/
int nla_nest_end(struct nl_msg *n, struct nlattr *start)
{
start->nla_len = (unsigned char *) nlmsg_tail(n->nm_nlh) -
(unsigned char *) start;
return 0;
}
/** @} */
/**
* @name Attribute Reading
* @{
*/
/**
* Return payload of u32 attribute
* @arg nla u32 netlink attribute
*/
uint32_t nla_get_u32(struct nlattr *nla)
{
return *(uint32_t *) nla_data(nla);
}
/**
* Return payload of u16 attribute
* @arg nla u16 netlink attribute
*/
uint16_t nla_get_u16(struct nlattr *nla)
{
return *(uint16_t *) nla_data(nla);
}
/**
* Return payload of u8 attribute
* @arg nla u8 netlink attribute
*/
uint8_t nla_get_u8(struct nlattr *nla)
{
return *(uint8_t *) nla_data(nla);
}
/**
* Return payload of u64 attribute
* @arg nla u64 netlink attribute
*/
uint64_t nla_get_u64(struct nlattr *nla)
{
uint64_t tmp;
nla_memcpy(&tmp, nla, sizeof(tmp));
return tmp;
}
/**
* return payload of string attribute
* @arg nla string netlink attribute
*/
char *nla_get_string(struct nlattr *nla)
{
return (char *) nla_data(nla);
}
/**
* Return payload of flag attribute
* @arg nla flag netlink attribute
*/
int nla_get_flag(struct nlattr *nla)
{
return !!nla;
}
/**
* Return payload of msecs attribute
* @arg nla msecs netlink attribute
*
* @return the number of milliseconds.
*/
unsigned long nla_get_msecs(struct nlattr *nla)
{
return nla_get_u64(nla);
}
/**
* Return payload of address attribute
* @arg nla address netlink attribute
* @arg family address family
*
* @return Newly allocated address handle or NULL
*/
struct nl_addr *nla_get_addr(struct nlattr *nla, int family)
{
return nl_addr_build(family, nla_data(nla), nla_len(nla));
}
/**
* Return payload of abstract data attribute
* @arg nla abstract data netlink attribute
*
* @return Newly allocated abstract data handle or NULL
*/
struct nl_data *nla_get_data(struct nlattr *nla)
{
return nl_data_alloc(nla_data(nla), nla_len(nla));
}
/** @} */
/** @} */

805
lib/cache.c Normal file
View file

@ -0,0 +1,805 @@
/*
* lib/cache.c Caching Module
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup cache_mngt
* @defgroup cache Cache
*
* @code
* Cache Management | | Type Specific Cache Operations
*
* | | +----------------+ +------------+
* | request update | | msg_parser |
* | | +----------------+ +------------+
* +- - - - -^- - - - - - - -^- -|- - - -
* nl_cache_update: | | | |
* 1) --------- co_request_update ------+ | |
* | | |
* 2) destroy old cache +----------- pp_cb ---------|---+
* | | |
* 3) ---------- nl_recvmsgs ----------+ +- cb_valid -+
* +--------------+ | | | |
* | nl_cache_add |<-----+ + - - -v- -|- - - - - - - - - - -
* +--------------+ | | +-------------+
* | nl_recvmsgs |
* | | +-----|-^-----+
* +---v-|---+
* | | | nl_recv |
* +---------+
* | | Core Netlink
* @endcode
*
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/object.h>
#include <netlink/utils.h>
/**
* @name Access Functions
* @{
*/
/**
* Return the number of items in the cache
* @arg cache cache handle
*/
int nl_cache_nitems(struct nl_cache *cache)
{
return cache->c_nitems;
}
/**
* Return the number of items matching a filter in the cache
* @arg cache Cache object.
* @arg filter Filter object.
*/
int nl_cache_nitems_filter(struct nl_cache *cache, struct nl_object *filter)
{
struct nl_object_ops *ops;
struct nl_object *obj;
int nitems = 0;
if (cache->c_ops == NULL)
BUG();
ops = cache->c_ops->co_obj_ops;
nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
if (filter && !nl_object_match_filter(obj, filter))
continue;
nitems++;
}
return nitems;
}
/**
* Returns \b true if the cache is empty.
* @arg cache Cache to check
* @return \a true if the cache is empty, otherwise \b false is returned.
*/
int nl_cache_is_empty(struct nl_cache *cache)
{
return nl_list_empty(&cache->c_items);
}
/**
* Return the operations set of the cache
* @arg cache cache handle
*/
struct nl_cache_ops *nl_cache_get_ops(struct nl_cache *cache)
{
return cache->c_ops;
}
/**
* Return the first element in the cache
* @arg cache cache handle
*/
struct nl_object *nl_cache_get_first(struct nl_cache *cache)
{
if (nl_list_empty(&cache->c_items))
return NULL;
return nl_list_entry(cache->c_items.next,
struct nl_object, ce_list);
}
/**
* Return the last element in the cache
* @arg cache cache handle
*/
struct nl_object *nl_cache_get_last(struct nl_cache *cache)
{
if (nl_list_empty(&cache->c_items))
return NULL;
return nl_list_entry(cache->c_items.prev,
struct nl_object, ce_list);
}
/**
* Return the next element in the cache
* @arg obj current object
*/
struct nl_object *nl_cache_get_next(struct nl_object *obj)
{
if (nl_list_at_tail(obj, &obj->ce_cache->c_items, ce_list))
return NULL;
else
return nl_list_entry(obj->ce_list.next,
struct nl_object, ce_list);
}
/**
* Return the previous element in the cache
* @arg obj current object
*/
struct nl_object *nl_cache_get_prev(struct nl_object *obj)
{
if (nl_list_at_head(obj, &obj->ce_cache->c_items, ce_list))
return NULL;
else
return nl_list_entry(obj->ce_list.prev,
struct nl_object, ce_list);
}
/** @} */
/**
* @name Cache Creation/Deletion
* @{
*/
/**
* Allocate an empty cache
* @arg ops cache operations to base the cache on
*
* @return A newly allocated and initialized cache.
*/
struct nl_cache *nl_cache_alloc(struct nl_cache_ops *ops)
{
struct nl_cache *cache;
cache = calloc(1, sizeof(*cache));
if (!cache) {
nl_errno(ENOMEM);
return NULL;
}
nl_init_list_head(&cache->c_items);
cache->c_ops = ops;
NL_DBG(2, "Allocated cache %p <%s>.\n", cache, nl_cache_name(cache));
return cache;
}
/**
* Allocate an empty cache based on type name
* @arg kind Name of cache type
* @return A newly allocated and initialized cache.
*/
struct nl_cache *nl_cache_alloc_name(const char *kind)
{
struct nl_cache_ops *ops;
ops = nl_cache_ops_lookup(kind);
if (!ops) {
nl_error(ENOENT, "Unable to lookup cache \"%s\"", kind);
return NULL;
}
return nl_cache_alloc(ops);
}
/**
* Allocate a new cache containing a subset of a cache
* @arg orig Original cache to be based on
* @arg filter Filter defining the subset to be filled into new cache
* @return A newly allocated cache or NULL.
*/
struct nl_cache *nl_cache_subset(struct nl_cache *orig,
struct nl_object *filter)
{
struct nl_cache *cache;
struct nl_object_ops *ops;
struct nl_object *obj;
if (!filter)
BUG();
cache = nl_cache_alloc(orig->c_ops);
if (!cache)
return NULL;
ops = orig->c_ops->co_obj_ops;
nl_list_for_each_entry(obj, &orig->c_items, ce_list) {
if (!nl_object_match_filter(obj, filter))
continue;
nl_cache_add(cache, obj);
}
return cache;
}
/**
* Clear a cache.
* @arg cache cache to clear
*
* Removes all elements of a cache.
*/
void nl_cache_clear(struct nl_cache *cache)
{
struct nl_object *obj, *tmp;
NL_DBG(1, "Clearing cache %p <%s>...\n", cache, nl_cache_name(cache));
nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list)
nl_cache_remove(obj);
}
/**
* Free a cache.
* @arg cache Cache to free.
*
* Removes all elements of a cache and frees all memory.
*
* @note Use this function if you are working with allocated caches.
*/
void nl_cache_free(struct nl_cache *cache)
{
nl_cache_clear(cache);
NL_DBG(1, "Freeing cache %p <%s>...\n", cache, nl_cache_name(cache));
free(cache);
}
/** @} */
/**
* @name Cache Modifications
* @{
*/
static int __cache_add(struct nl_cache *cache, struct nl_object *obj)
{
obj->ce_cache = cache;
nl_list_add_tail(&obj->ce_list, &cache->c_items);
cache->c_nitems++;
NL_DBG(1, "Added %p to cache %p <%s>.\n",
obj, cache, nl_cache_name(cache));
return 0;
}
/**
* Add object to a cache.
* @arg cache Cache to add object to
* @arg obj Object to be added to the cache
*
* Adds the given object to the specified cache. The object is cloned
* if it has been added to another cache already.
*
* @return 0 or a negative error code.
*/
int nl_cache_add(struct nl_cache *cache, struct nl_object *obj)
{
struct nl_object *new;
if (cache->c_ops->co_obj_ops != obj->ce_ops)
return nl_error(EINVAL, "Object mismatches cache type");
if (!nl_list_empty(&obj->ce_list)) {
new = nl_object_clone(obj);
if (!new)
return nl_errno(ENOMEM);
} else {
nl_object_get(obj);
new = obj;
}
return __cache_add(cache, new);
}
/**
* Move object from one cache to another
* @arg cache Cache to move object to.
* @arg obj Object subject to be moved
*
* Removes the given object from its associated cache if needed
* and adds it to the new cache.
*
* @return 0 on success or a negative error code.
*/
int nl_cache_move(struct nl_cache *cache, struct nl_object *obj)
{
if (cache->c_ops->co_obj_ops != obj->ce_ops)
return nl_error(EINVAL, "Object mismatches cache type");
NL_DBG(3, "Moving object %p to cache %p\n", obj, cache);
/* Acquire reference, if already in a cache this will be
* reverted during removal */
nl_object_get(obj);
if (!nl_list_empty(&obj->ce_list))
nl_cache_remove(obj);
return __cache_add(cache, obj);
}
/**
* Removes an object from a cache.
* @arg obj Object to remove from its cache
*
* Removes the object \c obj from the cache it is assigned to, since
* an object can only be assigned to one cache at a time, the cache
* must ne be passed along with it.
*/
void nl_cache_remove(struct nl_object *obj)
{
struct nl_cache *cache = obj->ce_cache;
if (cache == NULL)
return;
nl_list_del(&obj->ce_list);
obj->ce_cache = NULL;
nl_object_put(obj);
cache->c_nitems--;
NL_DBG(1, "Deleted %p from cache %p <%s>.\n",
obj, cache, nl_cache_name(cache));
}
/**
* Search for an object in a cache
* @arg cache Cache to search in.
* @arg needle Object to look for.
*
* Iterates over the cache and looks for an object with identical
* identifiers as the needle.
*
* @return Reference to object or NULL if not found.
* @note The returned object must be returned via nl_object_put().
*/
struct nl_object *nl_cache_search(struct nl_cache *cache,
struct nl_object *needle)
{
struct nl_object *obj;
nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
if (nl_object_identical(obj, needle)) {
nl_object_get(obj);
return obj;
}
}
return NULL;
}
/** @} */
/**
* @name Synchronization
* @{
*/
/**
* Request a full dump from the kernel to fill a cache
* @arg handle Netlink handle
* @arg cache Cache subjected to be filled.
*
* Send a dumping request to the kernel causing it to dump all objects
* related to the specified cache to the netlink socket.
*
* Use nl_cache_pickup() to read the objects from the socket and fill them
* into a cache.
*/
int nl_cache_request_full_dump(struct nl_handle *handle, struct nl_cache *cache)
{
NL_DBG(2, "Requesting dump from kernel for cache %p <%s>...\n",
cache, nl_cache_name(cache));
return cache->c_ops->co_request_update(cache, handle);
}
/** @cond SKIP */
struct update_xdata {
struct nl_cache_ops *ops;
struct nl_parser_param *params;
};
static int update_msg_parser(struct nl_msg *msg, void *arg)
{
struct update_xdata *x = arg;
return nl_cache_parse(x->ops, &msg->nm_src, msg->nm_nlh, x->params);
}
/** @endcond */
int __cache_pickup(struct nl_handle *handle, struct nl_cache *cache,
struct nl_parser_param *param)
{
int err;
struct nl_cb *cb;
struct update_xdata x = {
.ops = cache->c_ops,
.params = param,
};
NL_DBG(1, "Picking up answer for cache %p <%s>...\n",
cache, nl_cache_name(cache));
cb = nl_cb_clone(handle->h_cb);
if (cb == NULL)
return nl_get_errno();
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, update_msg_parser, &x);
err = nl_recvmsgs(handle, cb);
if (err < 0)
NL_DBG(2, "While picking up for %p <%s>, recvmsgs() returned " \
"%d: %s", cache, nl_cache_name(cache),
err, nl_geterror());
nl_cb_put(cb);
return err;
}
static int pickup_cb(struct nl_object *c, struct nl_parser_param *p)
{
return nl_cache_add((struct nl_cache *) p->pp_arg, c);
}
/**
* Pickup a netlink dump response and put it into a cache.
* @arg handle Netlink handle.
* @arg cache Cache to put items into.
*
* Waits for netlink messages to arrive, parses them and puts them into
* the specified cache.
*
* @return 0 on success or a negative error code.
*/
int nl_cache_pickup(struct nl_handle *handle, struct nl_cache *cache)
{
struct nl_parser_param p = {
.pp_cb = pickup_cb,
.pp_arg = cache,
};
return __cache_pickup(handle, cache, &p);
}
static int cache_include(struct nl_cache *cache, struct nl_object *obj,
struct nl_msgtype *type, change_func_t cb)
{
struct nl_object *old;
switch (type->mt_act) {
case NL_ACT_NEW:
case NL_ACT_DEL:
old = nl_cache_search(cache, obj);
if (old) {
nl_cache_remove(old);
if (type->mt_act == NL_ACT_DEL && cb)
cb(cache, old, NL_ACT_DEL);
}
if (type->mt_act == NL_ACT_NEW) {
nl_cache_move(cache, obj);
if (old == NULL && cb)
cb(cache, obj, NL_ACT_NEW);
else if (old) {
if (nl_object_diff(old, obj) && cb)
cb(cache, obj, NL_ACT_CHANGE);
nl_object_put(old);
}
}
break;
default:
NL_DBG(2, "Unknown action associated to object %p\n", obj);
return 0;
}
return 0;
}
int nl_cache_include(struct nl_cache *cache, struct nl_object *obj,
change_func_t change_cb)
{
struct nl_cache_ops *ops = cache->c_ops;
int i;
if (ops->co_obj_ops != obj->ce_ops)
return nl_error(EINVAL, "Object mismatches cache type");
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
return cache_include(cache, obj, &ops->co_msgtypes[i],
change_cb);
return nl_errno(EINVAL);
}
static int resync_cb(struct nl_object *c, struct nl_parser_param *p)
{
struct nl_cache_assoc *ca = p->pp_arg;
return nl_cache_include(ca->ca_cache, c, ca->ca_change);
}
int nl_cache_resync(struct nl_handle *handle, struct nl_cache *cache,
change_func_t change_cb)
{
struct nl_object *obj, *next;
struct nl_cache_assoc ca = {
.ca_cache = cache,
.ca_change = change_cb,
};
struct nl_parser_param p = {
.pp_cb = resync_cb,
.pp_arg = &ca,
};
int err;
NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache));
/* Mark all objects so we can see if some of them are obsolete */
nl_cache_mark_all(cache);
err = nl_cache_request_full_dump(handle, cache);
if (err < 0)
goto errout;
err = __cache_pickup(handle, cache, &p);
if (err < 0)
goto errout;
nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list)
if (nl_object_is_marked(obj))
nl_cache_remove(obj);
NL_DBG(1, "Finished resyncing %p <%s>\n", cache, nl_cache_name(cache));
err = 0;
errout:
return err;
}
/** @} */
/**
* @name Parsing
* @{
*/
/** @cond SKIP */
int nl_cache_parse(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *nlh, struct nl_parser_param *params)
{
int i, err;
if (nlh->nlmsg_len < nlmsg_msg_size(ops->co_hdrsize)) {
err = nl_error(EINVAL, "netlink message too short to be "
"of kind %s", ops->co_name);
goto errout;
}
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
if (ops->co_msgtypes[i].mt_id == nlh->nlmsg_type) {
err = ops->co_msg_parser(ops, who, nlh, params);
if (err != -ENOENT)
goto errout;
}
}
err = nl_error(EINVAL, "Unsupported netlink message type %d",
nlh->nlmsg_type);
errout:
return err;
}
/** @endcond */
/**
* Parse a netlink message and add it to the cache.
* @arg cache cache to add element to
* @arg msg netlink message
*
* Parses a netlink message by calling the cache specific message parser
* and adds the new element to the cache.
*
* @return 0 or a negative error code.
*/
int nl_cache_parse_and_add(struct nl_cache *cache, struct nl_msg *msg)
{
struct nl_parser_param p = {
.pp_cb = pickup_cb,
.pp_arg = cache,
};
return nl_cache_parse(cache->c_ops, NULL, nlmsg_hdr(msg), &p);
}
/**
* (Re)fill a cache with the contents in the kernel.
* @arg handle netlink handle
* @arg cache cache to update
*
* Clears the specified cache and fills it with the current state in
* the kernel.
*
* @return 0 or a negative error code.
*/
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
{
int err;
err = nl_cache_request_full_dump(handle, cache);
if (err < 0)
return err;
NL_DBG(2, "Upading cache %p <%s>, request sent, waiting for dump...\n",
cache, nl_cache_name(cache));
nl_cache_clear(cache);
return nl_cache_pickup(handle, cache);
}
/** @} */
/**
* @name Utillities
* @{
*/
/**
* Mark all objects in a cache
* @arg cache Cache to mark all objects in
*/
void nl_cache_mark_all(struct nl_cache *cache)
{
struct nl_object *obj;
NL_DBG(2, "Marking all objects in cache %p <%s>...\n",
cache, nl_cache_name(cache));
nl_list_for_each_entry(obj, &cache->c_items, ce_list)
nl_object_mark(obj);
}
/** @} */
/**
* @name Dumping
* @{
*/
/**
* Dump all elements of a cache.
* @arg cache cache to dump
* @arg params dumping parameters
*
* Dumps all elements of the \a cache to the file descriptor \a fd.
*/
void nl_cache_dump(struct nl_cache *cache, struct nl_dump_params *params)
{
nl_cache_dump_filter(cache, params, NULL);
}
/**
* Dump all elements of a cache (filtered).
* @arg cache cache to dump
* @arg params dumping parameters (optional)
* @arg filter filter object
*
* Dumps all elements of the \a cache to the file descriptor \a fd
* given they match the given filter \a filter.
*/
void nl_cache_dump_filter(struct nl_cache *cache,
struct nl_dump_params *params,
struct nl_object *filter)
{
int type = params ? params->dp_type : NL_DUMP_FULL;
struct nl_object_ops *ops;
struct nl_object *obj;
NL_DBG(2, "Dumping cache %p <%s> filter %p\n",
cache, nl_cache_name(cache), filter);
if (type > NL_DUMP_MAX || type < 0)
BUG();
if (cache->c_ops == NULL)
BUG();
ops = cache->c_ops->co_obj_ops;
if (!ops->oo_dump[type])
return;
nl_list_for_each_entry(obj, &cache->c_items, ce_list) {
if (filter && !nl_object_match_filter(obj, filter))
continue;
NL_DBG(4, "Dumping object %p...\n", obj);
dump_from_ops(obj, params);
}
}
/** @} */
/**
* @name Iterators
* @{
*/
/**
* Call a callback on each element of the cache.
* @arg cache cache to iterate on
* @arg cb callback function
* @arg arg argument passed to callback function
*
* Calls a callback function \a cb on each element of the \a cache.
* The argument \a arg is passed on the callback function.
*/
void nl_cache_foreach(struct nl_cache *cache,
void (*cb)(struct nl_object *, void *), void *arg)
{
nl_cache_foreach_filter(cache, NULL, cb, arg);
}
/**
* Call a callback on each element of the cache (filtered).
* @arg cache cache to iterate on
* @arg filter filter object
* @arg cb callback function
* @arg arg argument passed to callback function
*
* Calls a callback function \a cb on each element of the \a cache
* that matches the \a filter. The argument \a arg is passed on
* to the callback function.
*/
void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter,
void (*cb)(struct nl_object *, void *), void *arg)
{
struct nl_object *obj, *tmp;
struct nl_object_ops *ops;
if (cache->c_ops == NULL)
BUG();
ops = cache->c_ops->co_obj_ops;
nl_list_for_each_entry_safe(obj, tmp, &cache->c_items, ce_list) {
if (filter && !nl_object_match_filter(obj, filter))
continue;
cb(obj, arg);
}
}
/** @} */
/** @} */

392
lib/cache_mngr.c Normal file
View file

@ -0,0 +1,392 @@
/*
* lib/cache_mngr.c Cache Manager
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2007 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup cache_mngt
* @defgroup cache_mngr Manager
* @brief Helps keeping caches up to date.
*
* The purpose of a cache manager is to keep track of caches and
* automatically receive event notifications to keep the caches
* up to date with the kernel state. Each manager has exactly one
* netlink socket assigned which limits the scope of each manager
* to exactly one netlink family. Therefore all caches committed
* to a manager must be part of the same netlink family. Due to the
* nature of a manager, it is not possible to have a cache maintain
* two instances of the same cache type. The socket is subscribed
* to the event notification group of each cache and also put into
* non-blocking mode. Functions exist to poll() on the socket to
* wait for new events to be received.
*
* @code
* App libnl Kernel
* | |
* +-----------------+ [ notification, link change ]
* | | Cache Manager | | [ (IFF_UP | IFF_RUNNING) ]
* | | |
* | | +------------+| | | [ notification, new addr ]
* <-------|---| route/link |<-------(async)--+ [ 10.0.1.1/32 dev eth1 ]
* | | +------------+| | |
* | +------------+| |
* <---|---|---| route/addr |<------|-(async)--------------+
* | +------------+|
* | | +------------+| |
* <-------|---| ... ||
* | | +------------+| |
* +-----------------+
* | |
* @endcode
*
* @par 1) Creating a new cache manager
* @code
* struct nl_cache_mngr *mngr;
*
* // Allocate a new cache manager for RTNETLINK and automatically
* // provide the caches added to the manager.
* mngr = nl_cache_mngr_alloc(NETLINK_ROUTE, NL_AUTO_PROVIDE);
* @endcode
*
* @par 2) Keep track of a cache
* @code
* struct nl_cache *cache;
*
* // Create a new cache for links/interfaces and ask the manager to
* // keep it up to date for us. This will trigger a full dump request
* // to initially fill the cache.
* cache = nl_cache_mngr_add(mngr, "route/link");
* @endcode
*
* @par 3) Make the manager receive updates
* @code
* // Give the manager the ability to receive updates, will call poll()
* // with a timeout of 5 seconds.
* if (nl_cache_mngr_poll(mngr, 5000) > 0) {
* // Manager received at least one update, dump cache?
* nl_cache_dump(cache, ...);
* }
* @endcode
*
* @par 4) Release cache manager
* @code
* nl_cache_mngr_free(mngr);
* @endcode
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
static int include_cb(struct nl_object *obj, struct nl_parser_param *p)
{
struct nl_cache_assoc *ca = p->pp_arg;
int err;
NL_DBG(2, "Including object %p into cache %p\n", obj, ca->ca_cache);
#ifdef NL_DEBUG
if (nl_debug >= 4)
nl_object_dump(obj, &nl_debug_dp);
#endif
err = nl_cache_include(ca->ca_cache, obj, ca->ca_change);
nl_object_put(obj);
return err;
}
static int event_input(struct nl_msg *msg, void *arg)
{
struct nl_cache_mngr *mngr = arg;
int protocol = nlmsg_get_proto(msg);
int type = nlmsg_hdr(msg)->nlmsg_type;
struct nl_cache_ops *ops;
int i, n;
struct nl_parser_param p = {
.pp_cb = include_cb,
};
NL_DBG(2, "Cache manager %p, handling new message %p as event\n",
mngr, msg);
#ifdef NL_DEBUG
if (nl_debug >= 4)
nl_msg_dump(msg, stderr);
#endif
if (mngr->cm_protocol != protocol)
BUG();
for (i = 0; i < mngr->cm_nassocs; i++) {
if (mngr->cm_assocs[i].ca_cache) {
ops = mngr->cm_assocs[i].ca_cache->c_ops;
for (n = 0; ops->co_msgtypes[n].mt_id >= 0; n++)
if (ops->co_msgtypes[n].mt_id == type)
goto found;
}
}
return NL_SKIP;
found:
NL_DBG(2, "Associated message %p to cache %p\n",
msg, mngr->cm_assocs[i].ca_cache);
p.pp_arg = &mngr->cm_assocs[i];
return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);
}
/**
* Allocate new cache manager
* @arg protocol Netlink Protocol this manager is used for
* @arg flags Flags
*
* @return Newly allocated cache manager or NULL on failure.
*/
struct nl_cache_mngr *nl_cache_mngr_alloc(struct nl_handle *handle,
int protocol, int flags)
{
struct nl_cache_mngr *mngr;
if (handle == NULL)
BUG();
mngr = calloc(1, sizeof(*mngr));
if (!mngr)
goto enomem;
mngr->cm_handle = handle;
mngr->cm_nassocs = 32;
mngr->cm_protocol = protocol;
mngr->cm_flags = flags;
mngr->cm_assocs = calloc(mngr->cm_nassocs,
sizeof(struct nl_cache_assoc));
if (!mngr->cm_assocs)
goto enomem;
nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM,
event_input, mngr);
/* Required to receive async event notifications */
nl_disable_sequence_check(mngr->cm_handle);
if (nl_connect(mngr->cm_handle, protocol) < 0)
goto errout;
if (nl_socket_set_nonblocking(mngr->cm_handle) < 0)
goto errout;
NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n",
mngr, protocol, mngr->cm_nassocs);
return mngr;
enomem:
nl_errno(ENOMEM);
errout:
nl_cache_mngr_free(mngr);
return NULL;
}
/**
* Add cache responsibility to cache manager
* @arg mngr Cache manager.
* @arg name Name of cache to keep track of
*
* Allocates a new cache of the specified type and adds it to the manager.
* The operation will trigger a full dump request from the kernel to
* initially fill the contents of the cache. The manager will subscribe
* to the notification group of the cache to keep track of any further
* changes.
*
* @return The newly allocated cache or NULL on failure.
*/
struct nl_cache *nl_cache_mngr_add(struct nl_cache_mngr *mngr, const char *name,
change_func_t cb)
{
struct nl_cache_ops *ops;
struct nl_cache *cache;
struct nl_af_group *grp;
int err, i;
ops = nl_cache_ops_lookup(name);
if (!ops) {
nl_error(ENOENT, "Unknown cache type");
return NULL;
}
if (ops->co_protocol != mngr->cm_protocol) {
nl_error(EINVAL, "Netlink protocol mismatch");
return NULL;
}
if (ops->co_groups == NULL) {
nl_error(EOPNOTSUPP, NULL);
return NULL;
}
for (i = 0; i < mngr->cm_nassocs; i++) {
if (mngr->cm_assocs[i].ca_cache &&
mngr->cm_assocs[i].ca_cache->c_ops == ops) {
nl_error(EEXIST, "Cache of this type already managed");
return NULL;
}
}
retry:
for (i = 0; i < mngr->cm_nassocs; i++)
if (!mngr->cm_assocs[i].ca_cache)
break;
if (i >= mngr->cm_nassocs) {
mngr->cm_nassocs += 16;
mngr->cm_assocs = realloc(mngr->cm_assocs,
mngr->cm_nassocs *
sizeof(struct nl_cache_assoc));
if (mngr->cm_assocs == NULL) {
nl_errno(ENOMEM);
return NULL;
} else {
NL_DBG(1, "Increased capacity of cache manager %p " \
"to %d\n", mngr, mngr->cm_nassocs);
goto retry;
}
}
cache = nl_cache_alloc(ops);
if (!cache) {
nl_errno(ENOMEM);
return NULL;
}
for (grp = ops->co_groups; grp->ag_group; grp++) {
err = nl_socket_add_membership(mngr->cm_handle, grp->ag_group);
if (err < 0)
goto errout_free_cache;
}
err = nl_cache_refill(mngr->cm_handle, cache);
if (err < 0)
goto errout_drop_membership;
mngr->cm_assocs[i].ca_cache = cache;
mngr->cm_assocs[i].ca_change = cb;
if (mngr->cm_flags & NL_AUTO_PROVIDE)
nl_cache_mngt_provide(cache);
NL_DBG(1, "Added cache %p <%s> to cache manager %p\n",
cache, nl_cache_name(cache), mngr);
return cache;
errout_drop_membership:
for (grp = ops->co_groups; grp->ag_group; grp++)
nl_socket_drop_membership(mngr->cm_handle, grp->ag_group);
errout_free_cache:
nl_cache_free(cache);
return NULL;
}
/**
* Get file descriptor
* @arg mngr Cache Manager
*
* Get the file descriptor of the socket associated to the manager.
* This can be used to change socket options or monitor activity
* using poll()/select().
*/
int nl_cache_mngr_get_fd(struct nl_cache_mngr *mngr)
{
return nl_socket_get_fd(mngr->cm_handle);
}
/**
* Check for event notifications
* @arg mngr Cache Manager
* @arg timeout Upper limit poll() will block, in milliseconds.
*
* Causes poll() to be called to check for new event notifications
* being available. Automatically receives and handles available
* notifications.
*
* This functionally is ideally called regularly during an idle
* period.
*
* @return A positive value if at least one update was handled, 0
* for none, or a negative error code.
*/
int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout)
{
int ret;
struct pollfd fds = {
.fd = nl_socket_get_fd(mngr->cm_handle),
.events = POLLIN,
};
NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd);
ret = poll(&fds, 1, timeout);
NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret);
if (ret < 0)
return nl_errno(errno);
if (ret == 0)
return 0;
return nl_cache_mngr_data_ready(mngr);
}
/**
* Receive available event notifications
* @arg mngr Cache manager
*
* This function can be called if the socket associated to the manager
* contains updates to be received. This function should not be used
* if nl_cache_mngr_poll() is used.
*
* @return A positive value if at least one update was handled, 0
* for none, or a negative error code.
*/
int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr)
{
int err;
err = nl_recvmsgs_default(mngr->cm_handle);
if (err < 0)
return err;
return 1;
}
/**
* Free cache manager
* @arg mngr Cache manager
*
* Release all resources after usage of a cache manager.
*/
void nl_cache_mngr_free(struct nl_cache_mngr *mngr)
{
if (!mngr)
return;
if (mngr->cm_handle) {
nl_close(mngr->cm_handle);
nl_handle_destroy(mngr->cm_handle);
}
free(mngr->cm_assocs);
free(mngr);
NL_DBG(1, "Cache manager %p freed\n", mngr);
}
/** @} */

266
lib/cache_mngt.c Normal file
View file

@ -0,0 +1,266 @@
/*
* lib/cache_mngt.c Cache Management
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @defgroup cache_mngt Caching
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
static struct nl_cache_ops *cache_ops;
/**
* Associate a message type to a set of cache operations
* @arg protocol netlink protocol
* @arg message_type netlink message type
*
* Associates the specified netlink message type with
* a registered set of cache operations.
*
* @return The cache operations or NULL if no association
* could be made.
*/
struct nl_cache_ops *nl_cache_mngt_associate(int protocol, int message_type)
{
int i;
struct nl_cache_ops *ops;
for (ops = cache_ops; ops; ops = ops->co_next)
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
if (ops->co_msgtypes[i].mt_id == message_type &&
ops->co_protocol == protocol)
return ops;
return NULL;
}
/**
* Convert message type to character string.
* @arg ops Cache operations.
* @arg protocol Netlink Protocol.
* @arg msgtype Message type.
* @arg buf Destination buffer.
* @arg len Size of destination buffer.
*
* Converts a message type to a character string and stores it in the
* provided buffer.
*
* @return The destination buffer or the message type encoded in
* hexidecimal form if no match was found.
*/
char *nl_cache_mngt_type2name(struct nl_cache_ops *ops, int protocol,
int msgtype, char *buf, size_t len)
{
int i;
for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) {
if (ops->co_msgtypes[i].mt_id == msgtype &&
ops->co_protocol == protocol) {
snprintf(buf, len, "%s::%s",
ops->co_name,
ops->co_msgtypes[i].mt_name);
return buf;
}
}
snprintf(buf, len, "%d:%s->0x%x()", protocol, ops->co_name, msgtype);
return buf;
}
/**
* @name Cache Type Management
* @{
*/
/**
* Lookup the set cache operations of a certain cache type
* @arg name name of the cache type
*
* @return The cache operations or NULL if no operations
* have been registered under the specified name.
*/
struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
{
struct nl_cache_ops *ops;
for (ops = cache_ops; ops; ops = ops->co_next)
if (!strcmp(ops->co_name, name))
return ops;
return NULL;
}
/**
* Lookupt the set of cache operations responsible for a type of object
* @arg obj_ops Object operations
*
* @return The cache operations or NULL if not found.
*/
struct nl_cache_ops *nl_cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
{
struct nl_cache_ops *ops;
for (ops = cache_ops; ops; ops = ops->co_next)
if (ops->co_obj_ops == obj_ops)
return ops;
return NULL;
}
/**
* Call a function for each registered cache operation
* @arg cb Callback function to be called
* @arg arg User specific argument.
*/
void nl_cache_mngt_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
{
struct nl_cache_ops *ops;
for (ops = cache_ops; ops; ops = ops->co_next)
cb(ops, arg);
}
/**
* Register a set of cache operations
* @arg ops cache operations
*
* Called by users of caches to announce the avaibility of
* a certain cache type.
*
* @return 0 on success or a negative error code.
*/
int nl_cache_mngt_register(struct nl_cache_ops *ops)
{
if (!ops->co_name)
return nl_error(EINVAL, "No cache name specified");
if (!ops->co_obj_ops)
return nl_error(EINVAL, "No obj cache ops specified");
if (nl_cache_ops_lookup(ops->co_name))
return nl_error(EEXIST, "Cache operations already exist");
ops->co_next = cache_ops;
cache_ops = ops;
NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
return 0;
}
/**
* Unregister a set of cache operations
* @arg ops cache operations
*
* Called by users of caches to announce a set of
* cache operations is no longer available. The
* specified cache operations must have been registered
* previously using nl_cache_mngt_register()
*
* @return 0 on success or a negative error code
*/
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
{
struct nl_cache_ops *t, **tp;
for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
if (t == ops)
break;
if (!t)
return nl_error(ENOENT, "No such cache operations");
NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
*tp = t->co_next;
return 0;
}
/** @} */
/**
* @name Global Cache Provisioning/Requiring
* @{
*/
/**
* Provide a cache for global use
* @arg cache cache to provide
*
* Offers the specified cache to be used by other modules.
* Only one cache per type may be shared at a time,
* a previsouly provided caches will be overwritten.
*/
void nl_cache_mngt_provide(struct nl_cache *cache)
{
struct nl_cache_ops *ops;
ops = nl_cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
if (!ops)
BUG();
else
ops->co_major_cache = cache;
}
/**
* Unprovide a cache for global use
* @arg cache cache to unprovide
*
* Cancels the offer to use a cache globally. The
* cache will no longer be returned via lookups but
* may still be in use.
*/
void nl_cache_mngt_unprovide(struct nl_cache *cache)
{
struct nl_cache_ops *ops;
ops = nl_cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
if (!ops)
BUG();
else if (ops->co_major_cache == cache)
ops->co_major_cache = NULL;
}
/**
* Demand the use of a global cache
* @arg name name of the required object type
*
* Trys to find a cache of the specified type for global
* use.
*
* @return A cache provided by another subsystem of the
* specified type marked to be available.
*/
struct nl_cache *nl_cache_mngt_require(const char *name)
{
struct nl_cache_ops *ops;
ops = nl_cache_ops_lookup(name);
if (!ops || !ops->co_major_cache) {
fprintf(stderr, "Application BUG: Your application must "
"call nl_cache_mngt_provide() and\nprovide a valid "
"%s cache to be used for internal lookups.\nSee the "
" API documentation for more details.\n", name);
return NULL;
}
return ops->co_major_cache;
}
/** @} */
/** @} */

172
lib/data.c Normal file
View file

@ -0,0 +1,172 @@
/*
* lib/data.c Abstract Data
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup utils
* @defgroup data Abstract Data
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <linux/socket.h>
/**
* @name General
* @{
*/
/**
* Allocate a new abstract data object.
* @arg buf Data buffer containing the actual data.
* @arg size Size of data buffer.
*
* Allocates a new abstract data and copies the specified data
* buffer into the new handle.
*
* @return Newly allocated data handle or NULL
*/
struct nl_data *nl_data_alloc(void *buf, size_t size)
{
struct nl_data *data;
data = calloc(1, sizeof(*data));
if (!data)
goto errout;
data->d_data = calloc(1, size);
if (!data->d_data) {
free(data);
goto errout;
}
data->d_size = size;
if (buf)
memcpy(data->d_data, buf, size);
return data;
errout:
nl_errno(ENOMEM);
return NULL;
}
/**
* Clone an abstract data object.
* @arg src Abstract data object
*
* @return Cloned object or NULL
*/
struct nl_data *nl_data_clone(struct nl_data *src)
{
return nl_data_alloc(src->d_data, src->d_size);
}
/**
* Append data to an abstract data object.
* @arg data Abstract data object.
* @arg buf Data buffer containing the data to be appended.
* @arg size Size of data to be apppended.
*
* Reallocates an abstract data and copies the specified data
* buffer into the new handle.
*
* @return 0 on success or a negative error code
*/
int nl_data_append(struct nl_data *data, void *buf, size_t size)
{
if (size < 0)
BUG();
if (size > 0) {
data->d_data = realloc(data->d_data, data->d_size + size);
if (!data->d_data)
return nl_errno(ENOMEM);
if (buf)
memcpy(data->d_data + data->d_size, buf, size);
else
memset(data->d_data + data->d_size, 0, size);
data->d_size += size;
}
return 0;
}
/**
* Free an abstract data object.
* @arg data Abstract data object.
*/
void nl_data_free(struct nl_data *data)
{
if (data)
free(data->d_data);
free(data);
}
/** @} */
/**
* @name Attribute Access
* @{
*/
/**
* Get data buffer of abstract data object.
* @arg data Abstract data object.
* @return Data buffer or NULL if empty.
*/
void *nl_data_get(struct nl_data *data)
{
return data->d_size > 0 ? data->d_data : NULL;
}
/**
* Get size of data buffer of abstract data object.
* @arg data Abstract data object.
* @return Size of data buffer.
*/
size_t nl_data_get_size(struct nl_data *data)
{
return data->d_size;
}
/** @} */
/**
* @name Misc
* @{
*/
/**
* Compare two abstract data objects.
* @arg a Abstract data object.
* @arg b Another abstract data object.
* @return An integer less than, equal to, or greater than zero if
* a is found, respectively, to be less than, to match, or
* be greater than b.
*/
int nl_data_cmp(struct nl_data *a, struct nl_data *b)
{
void *a_ = nl_data_get(a);
void *b_ = nl_data_get(b);
if (a_ && b_)
return memcmp(a_, b_, nl_data_get_size(a));
else
return -1;
}
/** @} */
/** @} */

29
lib/defs.h Normal file
View file

@ -0,0 +1,29 @@
/* lib/defs.h. Generated by configure. */
/* lib/defs.h.in. Generated from configure.in by autoheader. */
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "tgraf@suug.ch"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libnl"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libnl 1.0-pre6"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libnl"
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0-pre6"
/* verbose errors */
/* #undef VERBOSE_ERRORS */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif

28
lib/defs.h.in Normal file
View file

@ -0,0 +1,28 @@
/* lib/defs.h.in. Generated from configure.in by autoheader. */
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* verbose errors */
#undef VERBOSE_ERRORS
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif

106
lib/doc.c Normal file
View file

@ -0,0 +1,106 @@
/*
* lib/doc.c Documentation Purpose
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @mainpage
*
* @section remarks Remarks
*
* @subsection cache_alloc Allocation of Caches
*
* Almost all subsystem provide a function to allocate a new cache
* of some form. The function usually looks like this:
* @code
* struct nl_cache *<object name>_alloc_cache(struct nl_handle *handle)
* @endcode
*
* These functions allocate a new cache for the own object type,
* initializes it properly and updates it to represent the current
* state of their master, e.g. a link cache would include all
* links currently configured in the kernel.
*
* Some of the allocation functions may take additional arguments
* to further specify what will be part of the cache.
*
* All such functions return a newly allocated cache or NULL
* in case of an error.
*
* @subsection addr Setting of Addresses
* @code
* int <object name>_set_addr(struct nl_object *, struct nl_addr *)
* @endcode
*
* All attribute functions avaiable for assigning addresses to objects
* take a struct nl_addr argument. The provided address object is
* validated against the address family of the object if known already.
* The assignment fails if the address families mismatch. In case the
* address family has not been specified yet, the address family of
* the new address is elected to be the new requirement.
*
* The function will acquire a new reference on the address object
* before assignment, the caller is NOT responsible for this.
*
* All functions return 0 on success or a negative error code.
*
* @subsection flags Flags to Character StringTranslations
* All functions converting a set of flags to a character string follow
* the same principles, therefore, the following information applies
* to all functions convertings flags to a character string and vice versa.
*
* @subsubsection flags2str Flags to Character String
* @code
* char *<object name>_flags2str(int flags, char *buf, size_t len)
* @endcode
* @arg flags Flags.
* @arg buf Destination buffer.
* @arg len Buffer length.
*
* Converts the specified flags to a character string separated by
* commas and stores it in the specified destination buffer.
*
* @return The destination buffer
*
* @subsubsection str2flags Character String to Flags
* @code
* int <object name>_str2flags(const char *name)
* @endcode
* @arg name Name of flag.
*
* Converts the provided character string specifying a flag
* to the corresponding numeric value.
*
* @return Link flag or a negative value if none was found.
*
* @subsubsection type2str Type to Character String
* @code
* char *<object name>_<type>2str(int type, char *buf, size_t len)
* @endcode
* @arg type Type as numeric value
* @arg buf Destination buffer.
* @arg len Buffer length.
*
* Converts an identifier (type) to a character string and stores
* it in the specified destination buffer.
*
* @return The destination buffer or the type encoded in hexidecimal
* form if the identifier is unknown.
*
* @subsubsection str2type Character String to Type
* @code
* int <object name>_str2<type>(const char *name)
* @endcode
* @arg name Name of identifier (type).
*
* Converts the provided character string specifying a identifier
* to the corresponding numeric value.
*
* @return Identifier as numeric value or a negative value if none was found.
*/

62
lib/family.c Normal file
View file

@ -0,0 +1,62 @@
/*
* lib/family.c Netlink Family
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @defgroup nlfam Netlink Families
* @brief
*
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
/**
* @name Netlink Family Name Translation
* @{
*/
static struct trans_tbl nlfamilies[] = {
__ADD(NETLINK_ROUTE,route)
__ADD(NETLINK_USERSOCK,usersock)
__ADD(NETLINK_FIREWALL,firewall)
__ADD(NETLINK_INET_DIAG,inetdiag)
__ADD(NETLINK_NFLOG,nflog)
__ADD(NETLINK_XFRM,xfrm)
__ADD(NETLINK_SELINUX,selinux)
__ADD(NETLINK_ISCSI,iscsi)
__ADD(NETLINK_AUDIT,audit)
__ADD(NETLINK_FIB_LOOKUP,fib_lookup)
__ADD(NETLINK_CONNECTOR,connector)
__ADD(NETLINK_NETFILTER,netfilter)
__ADD(NETLINK_IP6_FW,ip6_fw)
__ADD(NETLINK_DNRTMSG,dnrtmsg)
__ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent)
__ADD(NETLINK_GENERIC,generic)
__ADD(NETLINK_SCSITRANSPORT,scsitransport)
__ADD(NETLINK_ECRYPTFS,ecryptfs)
};
char * nl_nlfamily2str(int family, char *buf, size_t size)
{
return __type2str(family, buf, size, nlfamilies,
ARRAY_SIZE(nlfamilies));
}
int nl_str2nlfamily(const char *name)
{
return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies));
}
/** @} */
/** @} */

353
lib/fib_lookup/lookup.c Normal file
View file

@ -0,0 +1,353 @@
/*
* lib/fib_lookup/lookup.c FIB Lookup
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup nlfam
* @defgroup fib_lookup FIB Lookup
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
#include <netlink/fib_lookup/request.h>
#include <netlink/fib_lookup/lookup.h>
/** @cond SKIP */
static struct nl_cache_ops fib_lookup_ops;
static struct nl_object_ops result_obj_ops;
/* not exported so far */
struct fib_result_nl {
uint32_t fl_addr; /* To be looked up*/
uint32_t fl_fwmark;
unsigned char fl_tos;
unsigned char fl_scope;
unsigned char tb_id_in;
unsigned char tb_id; /* Results */
unsigned char prefixlen;
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
int err;
};
/** @endcond */
static void result_free_data(struct nl_object *obj)
{
struct flnl_result *res = nl_object_priv(obj);
if (res && res->fr_req)
nl_object_put(OBJ_CAST(res->fr_req));
}
static int result_clone(struct nl_object *_dst, struct nl_object *_src)
{
struct flnl_result *dst = nl_object_priv(_dst);
struct flnl_result *src = nl_object_priv(_src);
if (src->fr_req)
if (!(dst->fr_req = (struct flnl_request *)
nl_object_clone(OBJ_CAST(src->fr_req))))
return nl_get_errno();
return 0;
}
static int result_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
struct flnl_result *res;
struct fib_result_nl *fr;
struct nl_parser_param *pp = arg;
struct nl_addr *addr;
int err = -EINVAL;
res = flnl_result_alloc();
if (!res)
goto errout;
res->ce_msgtype = n->nlmsg_type;
res->fr_req = flnl_request_alloc();
if (!res->fr_req)
goto errout;
fr = nlmsg_data(n);
addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
if (!addr)
goto errout;
err = flnl_request_set_addr(res->fr_req, addr);
nl_addr_put(addr);
if (err < 0)
goto errout;
flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
flnl_request_set_tos(res->fr_req, fr->fl_tos);
flnl_request_set_scope(res->fr_req, fr->fl_scope);
flnl_request_set_table(res->fr_req, fr->tb_id_in);
res->fr_table_id = fr->tb_id;
res->fr_prefixlen = fr->prefixlen;
res->fr_nh_sel = fr->nh_sel;
res->fr_type = fr->type;
res->fr_scope = fr->scope;
res->fr_error = fr->err;
err = pp->pp_cb((struct nl_object *) res, pp);
if (err < 0)
goto errout;
/* REAL HACK, fib_lookup doesn't support ACK nor does it
* send a DONE message, enforce end of message stream
* after just the first message */
return NL_STOP;
errout:
flnl_result_put(res);
return err;
}
static int result_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
{
struct flnl_result *res = (struct flnl_result *) obj;
char buf[128];
int line = 1;
dp_dump(p, "table %s prefixlen %u next-hop-selector %u\n",
rtnl_route_table2str(res->fr_table_id, buf, sizeof(buf)),
res->fr_prefixlen, res->fr_nh_sel);
dp_dump_line(p, line++, "type %s ",
nl_rtntype2str(res->fr_type, buf, sizeof(buf)));
dp_dump(p, "scope %s error %s (%d)\n",
rtnl_scope2str(res->fr_scope, buf, sizeof(buf)),
strerror(-res->fr_error), res->fr_error);
return line;
}
static int result_dump_full(struct nl_object *obj, struct nl_dump_params *p)
{
return result_dump_brief(obj, p);
}
static int result_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
return 0;
}
/**
* @name Allocation/Freeing
* @{
*/
struct flnl_result *flnl_result_alloc(void)
{
return (struct flnl_result *) nl_object_alloc(&result_obj_ops);
}
void flnl_result_put(struct flnl_result *res)
{
nl_object_put((struct nl_object *) res);
}
/** @} */
/**
* @name Cache Management
* @{
*/
/**
* Allocate lookup result cache.
*
* Allocates a new lookup result cache and initializes it properly.
*
* @note Free the memory after usage using nl_cache_destroy_and_free().
* @return Newly allocated cache or NULL if an error occured.
*/
struct nl_cache *flnl_result_alloc_cache(void)
{
return nl_cache_alloc(&fib_lookup_ops);
}
/** @} */
/**
* @name Lookup
* @{
*/
/**
* Builds a netlink request message to do a lookup
* @arg req Requested match.
* @arg flags additional netlink message flags
*
* Builds a new netlink message requesting a change of link attributes.
* The netlink message header isn't fully equipped with all relevant
* fields and must be sent out via nl_send_auto_complete() or
* supplemented as needed.
* \a old must point to a link currently configured in the kernel
* and \a tmpl must contain the attributes to be changed set via
* \c rtnl_link_set_* functions.
*
* @return New netlink message
* @note Not all attributes can be changed, see
* \ref link_changeable "Changeable Attributes" for more details.
*/
struct nl_msg *flnl_lookup_build_request(struct flnl_request *req, int flags)
{
struct nl_msg *msg;
struct nl_addr *addr;
uint64_t fwmark;
int tos, scope, table;
struct fib_result_nl fr = {0};
fwmark = flnl_request_get_fwmark(req);
tos = flnl_request_get_tos(req);
scope = flnl_request_get_scope(req);
table = flnl_request_get_table(req);
fr.fl_fwmark = fwmark != UINT_LEAST64_MAX ? fwmark : 0;
fr.fl_tos = tos >= 0 ? tos : 0;
fr.fl_scope = scope >= 0 ? scope : RT_SCOPE_UNIVERSE;
fr.tb_id_in = table >= 0 ? table : RT_TABLE_UNSPEC;
addr = flnl_request_get_addr(req);
if (!addr) {
nl_error(EINVAL, "Request must specify the address");
return NULL;
}
fr.fl_addr = *(uint32_t *) nl_addr_get_binary_addr(addr);
msg = nlmsg_alloc_simple(0, flags);
if (!msg)
goto errout;
if (nlmsg_append(msg, &fr, sizeof(fr), NLMSG_ALIGNTO) < 0)
goto errout;
return msg;
errout:
nlmsg_free(msg);
return NULL;
}
/**
* Perform FIB Lookup
* @arg handle Netlink handle.
* @arg req Lookup request object.
* @arg cache Cache for result.
*
* Builds a netlink message to request a FIB lookup, waits for the
* reply and adds the result to the specified cache.
*
* @return 0 on success or a negative error code.
*/
int flnl_lookup(struct nl_handle *handle, struct flnl_request *req,
struct nl_cache *cache)
{
struct nl_msg *msg;
int err;
msg = flnl_lookup_build_request(req, 0);
if (!msg)
return nl_errno(ENOMEM);
err = nl_send_auto_complete(handle, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return nl_cache_pickup(handle, cache);
}
/** @} */
/**
* @name Attribute Access
* @{
*/
int flnl_result_get_table_id(struct flnl_result *res)
{
return res->fr_table_id;
}
int flnl_result_get_prefixlen(struct flnl_result *res)
{
return res->fr_prefixlen;
}
int flnl_result_get_nexthop_sel(struct flnl_result *res)
{
return res->fr_nh_sel;
}
int flnl_result_get_type(struct flnl_result *res)
{
return res->fr_type;
}
int flnl_result_get_scope(struct flnl_result *res)
{
return res->fr_scope;
}
int flnl_result_get_error(struct flnl_result *res)
{
return res->fr_error;
}
/** @} */
static struct nl_object_ops result_obj_ops = {
.oo_name = "fib_lookup/result",
.oo_size = sizeof(struct flnl_result),
.oo_free_data = result_free_data,
.oo_clone = result_clone,
.oo_dump[NL_DUMP_BRIEF] = result_dump_brief,
.oo_dump[NL_DUMP_FULL] = result_dump_full,
.oo_compare = result_compare,
};
static struct nl_cache_ops fib_lookup_ops = {
.co_name = "fib_lookup/fib_lookup",
.co_hdrsize = sizeof(struct fib_result_nl),
.co_msgtypes = {
{ 0, NL_ACT_UNSPEC, "any" },
END_OF_MSGTYPES_LIST,
},
.co_protocol = NETLINK_FIB_LOOKUP,
.co_msg_parser = result_msg_parser,
.co_obj_ops = &result_obj_ops,
};
static void __init fib_lookup_init(void)
{
nl_cache_mngt_register(&fib_lookup_ops);
}
static void __exit fib_lookup_exit(void)
{
nl_cache_mngt_unregister(&fib_lookup_ops);
}
/** @} */

187
lib/fib_lookup/request.c Normal file
View file

@ -0,0 +1,187 @@
/*
* lib/fib_lookup/request.c FIB Lookup Request
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup fib_lookup
* @defgroup flreq Request
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/fib_lookup/request.h>
static struct nl_object_ops request_obj_ops;
/** @cond SKIP */
#define REQUEST_ATTR_ADDR 0x01
#define REQUEST_ATTR_FWMARK 0x02
#define REQUEST_ATTR_TOS 0x04
#define REQUEST_ATTR_SCOPE 0x08
#define REQUEST_ATTR_TABLE 0x10
/** @endcond */
static void request_free_data(struct nl_object *obj)
{
struct flnl_request *req = REQUEST_CAST(obj);
if (req)
nl_addr_put(req->lr_addr);
}
static int request_clone(struct nl_object *_dst, struct nl_object *_src)
{
struct flnl_request *dst = nl_object_priv(_dst);
struct flnl_request *src = nl_object_priv(_src);
if (src->lr_addr)
if (!(dst->lr_addr = nl_addr_clone(src->lr_addr)))
goto errout;
return 0;
errout:
return nl_get_errno();
}
static int request_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
struct flnl_request *a = (struct flnl_request *) _a;
struct flnl_request *b = (struct flnl_request *) _b;
int diff = 0;
#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
diff |= REQ_DIFF(FWMARK, a->lr_fwmark != b->lr_fwmark);
diff |= REQ_DIFF(TOS, a->lr_tos != b->lr_tos);
diff |= REQ_DIFF(SCOPE, a->lr_scope != b->lr_scope);
diff |= REQ_DIFF(TABLE, a->lr_table != b->lr_table);
diff |= REQ_DIFF(ADDR, nl_addr_cmp(a->lr_addr, b->lr_addr));
#undef REQ_DIFF
return diff;
}
/**
* @name Lookup Request Creation/Deletion
* @{
*/
struct flnl_request *flnl_request_alloc(void)
{
return REQUEST_CAST(nl_object_alloc(&request_obj_ops));
}
/** @} */
/**
* @name Attributes
* @{
*/
void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark)
{
req->lr_fwmark = fwmark;
req->ce_mask |= REQUEST_ATTR_FWMARK;
}
uint64_t flnl_request_get_fwmark(struct flnl_request *req)
{
if (req->ce_mask & REQUEST_ATTR_FWMARK)
return req->lr_fwmark;
else
return UINT_LEAST64_MAX;
}
void flnl_request_set_tos(struct flnl_request *req, int tos)
{
req->lr_tos = tos;
req->ce_mask |= REQUEST_ATTR_TOS;
}
int flnl_request_get_tos(struct flnl_request *req)
{
if (req->ce_mask & REQUEST_ATTR_TOS)
return req->lr_tos;
else
return -1;
}
void flnl_request_set_scope(struct flnl_request *req, int scope)
{
req->lr_scope = scope;
req->ce_mask |= REQUEST_ATTR_SCOPE;
}
int flnl_request_get_scope(struct flnl_request *req)
{
if (req->ce_mask & REQUEST_ATTR_SCOPE)
return req->lr_scope;
else
return -1;
}
void flnl_request_set_table(struct flnl_request *req, int table)
{
req->lr_table = table;
req->ce_mask |= REQUEST_ATTR_TABLE;
}
int flnl_request_get_table(struct flnl_request *req)
{
if (req->ce_mask & REQUEST_ATTR_TABLE)
return req->lr_table;
else
return -1;
}
int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr)
{
if (addr->a_family != AF_INET)
return nl_error(EINVAL, "Address must be an IPv4 address");
if (req->lr_addr)
nl_addr_put(req->lr_addr);
nl_addr_get(addr);
req->lr_addr = addr;
req->ce_mask |= REQUEST_ATTR_ADDR;
return 0;
}
struct nl_addr *flnl_request_get_addr(struct flnl_request *req)
{
if (req->ce_mask & REQUEST_ATTR_ADDR)
return req->lr_addr;
else
return NULL;
}
/** @} */
static struct nl_object_ops request_obj_ops = {
.oo_name = "fib_lookup/request",
.oo_size = sizeof(struct flnl_request),
.oo_free_data = request_free_data,
.oo_clone = request_clone,
.oo_compare = request_compare,
.oo_id_attrs = ~0,
};
/** @} */

319
lib/genl/ctrl.c Normal file
View file

@ -0,0 +1,319 @@
/*
* lib/genl/ctrl.c Generic Netlink Controller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl_mngt
* @defgroup ctrl Controller
* @brief
*
* @{
*/
#include <netlink-generic.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/mngt.h>
#include <netlink/genl/ctrl.h>
#include <netlink/utils.h>
/** @cond SKIP */
#define CTRL_VERSION 0x0001
static struct nl_cache_ops genl_ctrl_ops;
/** @endcond */
static int ctrl_request_update(struct nl_cache *c, struct nl_handle *h)
{
return genl_send_simple(h, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
CTRL_VERSION, NLM_F_DUMP);
}
static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
.maxlen = GENL_NAMSIZ },
[CTRL_ATTR_VERSION] = { .type = NLA_U32 },
[CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
[CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
[CTRL_ATTR_OPS] = { .type = NLA_NESTED },
};
static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
[CTRL_ATTR_OP_ID] = { .type = NLA_U32 },
[CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 },
};
static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd,
struct genl_info *info, void *arg)
{
struct genl_family *family;
struct nl_parser_param *pp = arg;
int err;
family = genl_family_alloc();
if (family == NULL) {
err = nl_errno(ENOMEM);
goto errout;
}
if (info->attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
err = nl_error(EINVAL, "Missing family name TLV");
goto errout;
}
if (info->attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
err = nl_error(EINVAL, "Missing family id TLV");
goto errout;
}
family->ce_msgtype = info->nlh->nlmsg_type;
genl_family_set_id(family,
nla_get_u16(info->attrs[CTRL_ATTR_FAMILY_ID]));
genl_family_set_name(family,
nla_get_string(info->attrs[CTRL_ATTR_FAMILY_NAME]));
if (info->attrs[CTRL_ATTR_VERSION]) {
uint32_t version = nla_get_u32(info->attrs[CTRL_ATTR_VERSION]);
genl_family_set_version(family, version);
}
if (info->attrs[CTRL_ATTR_HDRSIZE]) {
uint32_t hdrsize = nla_get_u32(info->attrs[CTRL_ATTR_HDRSIZE]);
genl_family_set_hdrsize(family, hdrsize);
}
if (info->attrs[CTRL_ATTR_MAXATTR]) {
uint32_t maxattr = nla_get_u32(info->attrs[CTRL_ATTR_MAXATTR]);
genl_family_set_maxattr(family, maxattr);
}
if (info->attrs[CTRL_ATTR_OPS]) {
struct nlattr *nla, *nla_ops;
int remaining;
nla_ops = info->attrs[CTRL_ATTR_OPS];
nla_for_each_nested(nla, nla_ops, remaining) {
struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
int flags = 0, id;
err = nla_parse_nested(tb, CTRL_ATTR_OP_MAX, nla,
family_op_policy);
if (err < 0)
goto errout;
if (tb[CTRL_ATTR_OP_ID] == NULL) {
err = nl_errno(EINVAL);
goto errout;
}
id = nla_get_u32(tb[CTRL_ATTR_OP_ID]);
if (tb[CTRL_ATTR_OP_FLAGS])
flags = nla_get_u32(tb[CTRL_ATTR_OP_FLAGS]);
err = genl_family_add_op(family, id, flags);
if (err < 0)
goto errout;
}
}
err = pp->pp_cb((struct nl_object *) family, pp);
if (err < 0)
goto errout;
return P_ACCEPT;
errout:
genl_family_put(family);
return err;
}
/**
* @name Cache Management
* @{
*/
struct nl_cache *genl_ctrl_alloc_cache(struct nl_handle *handle)
{
struct nl_cache * cache;
cache = nl_cache_alloc(&genl_ctrl_ops);
if (cache == NULL)
return NULL;
if (handle && nl_cache_refill(handle, cache) < 0) {
nl_cache_free(cache);
return NULL;
}
return cache;
}
/**
* Look up generic netlink family by id in the provided cache.
* @arg cache Generic netlink family cache.
* @arg id Family identifier.
*
* Searches through the cache looking for a registered family
* matching the specified identifier. The caller will own a
* reference on the returned object which needs to be given
* back after usage using genl_family_put().
*
* @return Generic netlink family object or NULL if no match was found.
*/
struct genl_family *genl_ctrl_search(struct nl_cache *cache, int id)
{
struct genl_family *fam;
if (cache->c_ops != &genl_ctrl_ops)
BUG();
nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
if (fam->gf_id == id) {
nl_object_get((struct nl_object *) fam);
return fam;
}
}
return NULL;
}
/**
* @name Resolver
* @{
*/
/**
* Look up generic netlink family by family name in the provided cache.
* @arg cache Generic netlink family cache.
* @arg name Family name.
*
* Searches through the cache looking for a registered family
* matching the specified name. The caller will own a reference
* on the returned object which needs to be given back after
* usage using genl_family_put().
*
* @return Generic netlink family object or NULL if no match was found.
*/
struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache,
const char *name)
{
struct genl_family *fam;
if (cache->c_ops != &genl_ctrl_ops)
BUG();
nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
if (!strcmp(name, fam->gf_name)) {
nl_object_get((struct nl_object *) fam);
return fam;
}
}
return NULL;
}
/** @} */
/**
* Resolve generic netlink family name to its identifier
* @arg handle Netlink Handle
* @arg name Name of generic netlink family
*
* Resolves the generic netlink family name to its identifer and returns
* it.
*
* @return A positive identifier or a negative error code.
*/
int genl_ctrl_resolve(struct nl_handle *handle, const char *name)
{
struct nl_cache *cache;
struct genl_family *family;
int err;
cache = genl_ctrl_alloc_cache(handle);
if (cache == NULL)
return nl_get_errno();
family = genl_ctrl_search_by_name(cache, name);
if (family == NULL) {
err = nl_error(ENOENT, "Generic Netlink Family not found");
goto errout;
}
err = genl_family_get_id(family);
genl_family_put(family);
errout:
nl_cache_free(cache);
return err;
}
/** @} */
static struct genl_cmd genl_cmds[] = {
{
.c_id = CTRL_CMD_NEWFAMILY,
.c_name = "NEWFAMILY" ,
.c_maxattr = CTRL_ATTR_MAX,
.c_attr_policy = ctrl_policy,
.c_msg_parser = ctrl_msg_parser,
},
{
.c_id = CTRL_CMD_DELFAMILY,
.c_name = "DELFAMILY" ,
},
{
.c_id = CTRL_CMD_GETFAMILY,
.c_name = "GETFAMILY" ,
},
{
.c_id = CTRL_CMD_NEWOPS,
.c_name = "NEWOPS" ,
},
{
.c_id = CTRL_CMD_DELOPS,
.c_name = "DELOPS" ,
},
};
static struct genl_ops genl_ops = {
.o_cmds = genl_cmds,
.o_ncmds = ARRAY_SIZE(genl_cmds),
};
/** @cond SKIP */
extern struct nl_object_ops genl_family_ops;
/** @endcond */
static struct nl_cache_ops genl_ctrl_ops = {
.co_name = "genl/family",
.co_hdrsize = GENL_HDRSIZE(0),
.co_msgtypes = GENL_FAMILY(GENL_ID_CTRL, "nlctrl"),
.co_genl = &genl_ops,
.co_protocol = NETLINK_GENERIC,
.co_request_update = ctrl_request_update,
.co_obj_ops = &genl_family_ops,
};
static void __init ctrl_init(void)
{
genl_register(&genl_ctrl_ops);
}
static void __exit ctrl_exit(void)
{
genl_unregister(&genl_ctrl_ops);
}
/** @} */

285
lib/genl/family.c Normal file
View file

@ -0,0 +1,285 @@
/*
* lib/genl/family.c Generic Netlink Family
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl
* @defgroup genl_family Generic Netlink Family
* @brief
*
* @{
*/
#include <netlink-generic.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/utils.h>
/** @cond SKIP */
#define FAMILY_ATTR_ID 0x01
#define FAMILY_ATTR_NAME 0x02
#define FAMILY_ATTR_VERSION 0x04
#define FAMILY_ATTR_HDRSIZE 0x08
#define FAMILY_ATTR_MAXATTR 0x10
#define FAMILY_ATTR_OPS 0x20
struct nl_object_ops genl_family_ops;
/** @endcond */
static void family_constructor(struct nl_object *c)
{
struct genl_family *family = (struct genl_family *) c;
nl_init_list_head(&family->gf_ops);
}
static void family_free_data(struct nl_object *c)
{
struct genl_family *family = (struct genl_family *) c;
struct genl_family_op *ops, *tmp;
if (family == NULL)
return;
nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
nl_list_del(&ops->o_list);
free(ops);
}
}
static int family_clone(struct nl_object *_dst, struct nl_object *_src)
{
struct genl_family *dst = nl_object_priv(_dst);
struct genl_family *src = nl_object_priv(_src);
struct genl_family_op *ops;
int err;
nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
if (err < 0)
return err;
}
return 0;
}
static int family_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
{
struct genl_family *family = (struct genl_family *) obj;
dp_dump(p, "0x%04x %s version %u\n",
family->gf_id, family->gf_name, family->gf_version);
return 1;
}
static struct trans_tbl ops_flags[] = {
__ADD(GENL_ADMIN_PERM, admin-perm)
__ADD(GENL_CMD_CAP_DO, has-doit)
__ADD(GENL_CMD_CAP_DUMP, has-dump)
__ADD(GENL_CMD_CAP_HASPOL, has-policy)
};
static char *ops_flags2str(int flags, char *buf, size_t len)
{
return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
}
static int family_dump_full(struct nl_object *obj, struct nl_dump_params *p)
{
struct genl_family *family = (struct genl_family *) obj;
int line;
line = family_dump_brief(obj, p);
dp_dump_line(p, line++, " hdrsize %u maxattr %u\n",
family->gf_hdrsize, family->gf_maxattr);
if (family->ce_mask & FAMILY_ATTR_OPS) {
struct genl_family_op *op;
char buf[64];
nl_list_for_each_entry(op, &family->gf_ops, o_list) {
ops_flags2str(op->o_flags, buf, sizeof(buf));
genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));
dp_dump_line(p, line++, " op %s (0x%02x)",
buf, op->o_id);
if (op->o_flags)
dp_dump(p, " <%s>",
ops_flags2str(op->o_flags, buf,
sizeof(buf)));
dp_dump(p, "\n");
}
}
return line;
}
static int family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
{
return family_dump_full(obj, p);
}
static int family_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
struct genl_family *a = (struct genl_family *) _a;
struct genl_family *b = (struct genl_family *) _b;
int diff = 0;
#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
diff |= FAM_DIFF(ID, a->gf_id != b->gf_id);
diff |= FAM_DIFF(VERSION, a->gf_version != b->gf_version);
diff |= FAM_DIFF(HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
diff |= FAM_DIFF(MAXATTR, a->gf_maxattr != b->gf_maxattr);
diff |= FAM_DIFF(NAME, strcmp(a->gf_name, b->gf_name));
#undef FAM_DIFF
return diff;
}
/**
* @name Family Object
* @{
*/
struct genl_family *genl_family_alloc(void)
{
return (struct genl_family *) nl_object_alloc(&genl_family_ops);
}
void genl_family_put(struct genl_family *family)
{
nl_object_put((struct nl_object *) family);
}
/** @} */
/**
* @name Attributes
* @{
*/
unsigned int genl_family_get_id(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_ID)
return family->gf_id;
else
return GENL_ID_GENERATE;
}
void genl_family_set_id(struct genl_family *family, unsigned int id)
{
family->gf_id = id;
family->ce_mask |= FAMILY_ATTR_ID;
}
char *genl_family_get_name(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_NAME)
return family->gf_name;
else
return NULL;
}
void genl_family_set_name(struct genl_family *family, const char *name)
{
strncpy(family->gf_name, name, GENL_NAMSIZ-1);
family->ce_mask |= FAMILY_ATTR_NAME;
}
uint8_t genl_family_get_version(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_VERSION)
return family->gf_version;
else
return 0;
}
void genl_family_set_version(struct genl_family *family, uint8_t version)
{
family->gf_version = version;
family->ce_mask |= FAMILY_ATTR_VERSION;
}
uint32_t genl_family_get_hdrsize(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
return family->gf_hdrsize;
else
return 0;
}
void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
{
family->gf_hdrsize = hdrsize;
family->ce_mask |= FAMILY_ATTR_HDRSIZE;
}
uint32_t genl_family_get_maxattr(struct genl_family *family)
{
if (family->ce_mask & FAMILY_ATTR_MAXATTR)
return family->gf_maxattr;
else
return family->gf_maxattr;
}
void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
{
family->gf_maxattr = maxattr;
family->ce_mask |= FAMILY_ATTR_MAXATTR;
}
int genl_family_add_op(struct genl_family *family, int id, int flags)
{
struct genl_family_op *op;
op = calloc(1, sizeof(*op));
if (op == NULL)
return nl_errno(ENOMEM);
op->o_id = id;
op->o_flags = flags;
nl_list_add_tail(&op->o_list, &family->gf_ops);
family->ce_mask |= FAMILY_ATTR_OPS;
return 0;
}
/** @} */
/** @cond SKIP */
struct nl_object_ops genl_family_ops = {
.oo_name = "genl/family",
.oo_size = sizeof(struct genl_family),
.oo_constructor = family_constructor,
.oo_free_data = family_free_data,
.oo_clone = family_clone,
.oo_dump[NL_DUMP_BRIEF] = family_dump_brief,
.oo_dump[NL_DUMP_FULL] = family_dump_full,
.oo_dump[NL_DUMP_STATS] = family_dump_stats,
#if 0
.oo_dump[NL_DUMP_XML] = addr_dump_xml,
.oo_dump[NL_DUMP_ENV] = addr_dump_env,
#endif
.oo_compare = family_compare,
.oo_id_attrs = FAMILY_ATTR_ID,
};
/** @endcond */
/** @} */

210
lib/genl/genl.c Normal file
View file

@ -0,0 +1,210 @@
/*
* lib/genl/genl.c Generic Netlink
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup nlfam
* @defgroup genl Generic Netlink
*
* @par Message Format
* @code
* <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
* +----------------------------+- - -+- - - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | struct nlmsghdr | | | |
* +----------------------------+- - -+- - - - - - - - - - -+- - -+
* @endcode
* @code
* <-------- GENL_HDRLEN -------> <--- hdrlen -->
* <------- genlmsg_len(ghdr) ------>
* +------------------------+- - -+---------------+- - -+------------+
* | Generic Netlink Header | Pad | Family Header | Pad | Attributes |
* | struct genlmsghdr | | | | |
* +------------------------+- - -+---------------+- - -+------------+
* genlmsg_data(ghdr)--------------^ ^
* genlmsg_attrdata(ghdr, hdrlen)-------------------------
* @endcode
*
* @par 1) Creating a new generic netlink message
* @code
* struct nl_msg *msg;
* struct myhdr {
* int a;
* int b;
* } *hdr;
*
* // Create a new empty netlink message
* msg = nlmsg_alloc();
*
* // Append the netlink and generic netlink message header, this
* // operation also reserves room for the family specific header.
* hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, sizeof(hdr),
* NLM_F_ECHO, MYOP, VERSION);
*
* // Fill out your own family specific header.
* hdr->a = 1;
* hdr->b = 2;
*
* // Append the optional attributes.
* nla_put_u32(msg, 1, 0x10);
*
* // Message is ready to be sent.
* nl_send_auto_complete(nl_handle, msg);
*
* // All done? Free the message.
* nlmsg_free(msg);
* @endcode
*
* @par 2) Sending of trivial messages
* @code
* // For trivial messages not requiring any family specific header or
* // attributes, genl_send_simple() may be used to send messages directly.
* genl_send_simple(nl_handle, family, MY_SIMPLE_CMD, VERSION, 0);
* @endcode
* @{
*/
#include <netlink-generic.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/utils.h>
/**
* @name Socket Creating
* @{
*/
int genl_connect(struct nl_handle *handle)
{
return nl_connect(handle, NETLINK_GENERIC);
}
/** @} */
/**
* @name Sending
* @{
*/
/**
* Send trivial generic netlink message
* @arg handle Netlink handle.
* @arg family Generic netlink family
* @arg cmd Command
* @arg version Version
* @arg flags Additional netlink message flags.
*
* Fills out a routing netlink request message and sends it out
* using nl_send_simple().
*
* @return 0 on success or a negative error code.
*/
int genl_send_simple(struct nl_handle *handle, int family, int cmd,
int version, int flags)
{
struct genlmsghdr hdr = {
.cmd = cmd,
.version = version,
};
return nl_send_simple(handle, family, flags, &hdr, sizeof(hdr));
}
/** @} */
/**
* @name Message Parsing
* @{
*/
/**
* Get head of message payload
* @arg gnlh genetlink messsage header
*/
void *genlmsg_data(const struct genlmsghdr *gnlh)
{
return ((unsigned char *) gnlh + GENL_HDRLEN);
}
/**
* Get lenght of message payload
* @arg gnlh genetlink message header
*/
int genlmsg_len(const struct genlmsghdr *gnlh)
{
struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
NLMSG_HDRLEN);
return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* Get head of attribute data
* @arg gnlh generic netlink message header
* @arg hdrlen length of family specific header
*/
struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
{
return genlmsg_data(gnlh) + NLMSG_ALIGN(hdrlen);
}
/**
* Get length of attribute data
* @arg gnlh generic netlink message header
* @arg hdrlen length of family specific header
*/
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
{
return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen);
}
/** @} */
/**
* @name Message Building
* @{
*/
/**
* Add generic netlink header to netlink message
* @arg msg netlink message
* @arg pid netlink process id or NL_AUTO_PID
* @arg seq sequence number of message or NL_AUTO_SEQ
* @arg family generic netlink family
* @arg hdrlen length of user specific header
* @arg flags message flags
* @arg cmd generic netlink command
* @arg version protocol version
*
* Returns pointer to user specific header.
*/
void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
int hdrlen, int flags, uint8_t cmd, uint8_t version)
{
struct nlmsghdr *nlh;
struct genlmsghdr hdr = {
.cmd = cmd,
.version = version,
};
nlh = nlmsg_put(msg, pid, seq, family, GENL_HDRLEN + hdrlen, flags);
if (nlh == NULL)
return NULL;
memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr));
NL_DBG(2, "msg %p: Added generic netlink header cmd=%d version=%d\n",
msg, cmd, version);
return nlmsg_data(nlh) + GENL_HDRLEN;
}
/** @} */
/** @} */

285
lib/genl/mngt.c Normal file
View file

@ -0,0 +1,285 @@
/*
* lib/genl/mngt.c Generic Netlink Management
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup genl
* @defgroup genl_mngt Management
*
* @par 1) Registering a generic netlink module
* @code
* #include <netlink/genl/mngt.h>
*
* // First step is to define all the commands being used in
* // particular generic netlink family. The ID and name are
* // mandatory to be filled out. A callback function and
* // most the attribute policy that comes with it must be
* // defined for commands expected to be issued towards
* // userspace.
* static struct genl_cmd foo_cmds[] = {
* {
* .c_id = FOO_CMD_NEW,
* .c_name = "NEWFOO" ,
* .c_maxattr = FOO_ATTR_MAX,
* .c_attr_policy = foo_policy,
* .c_msg_parser = foo_msg_parser,
* },
* {
* .c_id = FOO_CMD_DEL,
* .c_name = "DELFOO" ,
* },
* };
*
* // The list of commands must then be integrated into a
* // struct genl_ops serving as handle for this particular
* // family.
* static struct genl_ops my_genl_ops = {
* .o_cmds = foo_cmds,
* .o_ncmds = ARRAY_SIZE(foo_cmds),
* };
*
* // Using the above struct genl_ops an arbitary number of
* // cache handles can be associated to it.
* //
* // The macro GENL_HDRSIZE() must be used to specify the
* // length of the header to automatically take headers on
* // generic layers into account.
* //
* // The macro GENL_FAMILY() is used to represent the generic
* // netlink family id.
* static struct nl_cache_ops genl_foo_ops = {
* .co_name = "genl/foo",
* .co_hdrsize = GENL_HDRSIZE(sizeof(struct my_hdr)),
* .co_msgtypes = GENL_FAMILY(GENL_ID_GENERATE, "foo"),
* .co_genl = &my_genl_ops,
* .co_protocol = NETLINK_GENERIC,
* .co_request_update = foo_request_update,
* .co_obj_ops = &genl_foo_ops,
* };
*
* // Finally each cache handle for a generic netlink family
* // must be registered using genl_register().
* static void __init foo_init(void)
* {
* genl_register(&genl_foo_ops);
* }
*
* // ... respectively unregsted again.
* static void __exit foo_exit(void)
* {
* genl_unregister(&genl_foo_ops);
* }
* @endcode
* @{
*/
#include <netlink-generic.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/mngt.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/utils.h>
static NL_LIST_HEAD(genl_ops_list);
static int genl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *nlh, void *arg)
{
int i, err;
struct genlmsghdr *ghdr;
struct genl_cmd *cmd;
ghdr = nlmsg_data(nlh);
if (ops->co_genl == NULL)
BUG();
for (i = 0; i < ops->co_genl->o_ncmds; i++) {
cmd = &ops->co_genl->o_cmds[i];
if (cmd->c_id == ghdr->cmd)
goto found;
}
err = nl_errno(ENOENT);
goto errout;
found:
if (cmd->c_msg_parser == NULL)
err = nl_error(EOPNOTSUPP, "No message parser found.");
else {
struct nlattr *tb[cmd->c_maxattr + 1];
struct genl_info info = {
.who = who,
.nlh = nlh,
.genlhdr = ghdr,
.userhdr = genlmsg_data(ghdr),
.attrs = tb,
};
err = nlmsg_parse(nlh, ops->co_hdrsize, tb, cmd->c_maxattr,
cmd->c_attr_policy);
if (err < 0)
goto errout;
err = cmd->c_msg_parser(ops, cmd, &info, arg);
}
errout:
return err;
}
char *genl_op2name(int family, int op, char *buf, size_t len)
{
struct genl_ops *ops;
int i;
nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
if (ops->o_family == family) {
for (i = 0; i < ops->o_ncmds; i++) {
struct genl_cmd *cmd;
cmd = &ops->o_cmds[i];
if (cmd->c_id == op) {
strncpy(buf, cmd->c_name, len - 1);
return buf;
}
}
}
}
strncpy(buf, "unknown", len - 1);
return NULL;
}
/**
* @name Register/Unregister
* @{
*/
/**
* Register generic netlink operations
* @arg ops cache operations
*/
int genl_register(struct nl_cache_ops *ops)
{
int err;
if (ops->co_protocol != NETLINK_GENERIC) {
err = nl_error(EINVAL, "cache operations not for protocol " \
"NETLINK_GENERIC (protocol=%s)",
ops->co_protocol);
goto errout;
}
if (ops->co_hdrsize < GENL_HDRSIZE(0)) {
err = nl_error(EINVAL, "co_hdrsize too short, probably " \
"not including genlmsghdr, minsize=%d",
GENL_HDRSIZE(0));
goto errout;
}
if (ops->co_genl == NULL) {
err = nl_error(EINVAL, "co_genl is NULL, must provide " \
"valid genl operations");
goto errout;
}
ops->co_genl->o_cache_ops = ops;
ops->co_genl->o_name = ops->co_msgtypes[0].mt_name;
ops->co_genl->o_family = ops->co_msgtypes[0].mt_id;
ops->co_msg_parser = genl_msg_parser;
/* FIXME: check for dup */
nl_list_add_tail(&ops->co_genl->o_list, &genl_ops_list);
err = nl_cache_mngt_register(ops);
errout:
return err;
}
/**
* Unregister generic netlink operations
* @arg ops cache operations
*/
void genl_unregister(struct nl_cache_ops *ops)
{
nl_cache_mngt_unregister(ops);
nl_list_del(&ops->co_genl->o_list);
}
/** @} */
/**
* @name Resolving ID/Name
* @{
*/
static int __genl_ops_resolve(struct nl_cache *ctrl, struct genl_ops *ops)
{
struct genl_family *family;
family = genl_ctrl_search_by_name(ctrl, ops->o_name);
if (family != NULL) {
ops->o_id = genl_family_get_id(family);
genl_family_put(family);
return 0;
}
return nl_error(ENOENT, "Unable to find generic netlink family \"%s\"",
ops->o_name);
}
int genl_ops_resolve(struct nl_handle *handle, struct genl_ops *ops)
{
struct nl_cache *ctrl;
int err;
ctrl = genl_ctrl_alloc_cache(handle);
if (ctrl == NULL) {
err = nl_get_errno();
goto errout;
}
err = __genl_ops_resolve(ctrl, ops);
nl_cache_free(ctrl);
errout:
return err;
}
int genl_mngt_resolve(struct nl_handle *handle)
{
struct nl_cache *ctrl;
struct genl_ops *ops;
int err = 0;
ctrl = genl_ctrl_alloc_cache(handle);
if (ctrl == NULL) {
err = nl_get_errno();
goto errout;
}
nl_list_for_each_entry(ops, &genl_ops_list, o_list) {
err = __genl_ops_resolve(ctrl, ops);
}
nl_cache_free(ctrl);
errout:
return err;
}
/** @} */
/** @} */

Some files were not shown because too many files have changed in this diff Show more