summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/.gitignore8
-rw-r--r--doc/AUTHORS1
-rw-r--r--doc/COPYING674
-rw-r--r--doc/Doxyfile.in1714
-rw-r--r--doc/DoxygenLayout.xml187
-rw-r--r--doc/Makefile.am72
-rw-r--r--doc/README13
-rw-r--r--doc/api/.gitignore8
-rwxr-xr-xdoc/autogen.sh4
-rw-r--r--doc/configure.ac107
-rw-r--r--doc/core.txt3017
-rwxr-xr-xdoc/doxygen-link.py43
-rwxr-xr-xdoc/gen-tags.sh14
-rw-r--r--doc/html/.gitignore1
-rw-r--r--doc/images/.gitignore3
-rw-r--r--doc/images/addressing.pngbin0 -> 13682 bytes
-rw-r--r--doc/images/attribute_hdr.pngbin0 -> 14996 bytes
-rw-r--r--doc/images/classful_qdisc.pngbin0 -> 31849 bytes
-rw-r--r--doc/images/classless_qdisc.pngbin0 -> 15443 bytes
-rw-r--r--doc/images/classless_qdisc_nbands.pngbin0 -> 17727 bytes
-rw-r--r--doc/images/icons/README5
-rw-r--r--doc/images/icons/callouts/1.pngbin0 -> 329 bytes
-rw-r--r--doc/images/icons/callouts/10.pngbin0 -> 361 bytes
-rw-r--r--doc/images/icons/callouts/11.pngbin0 -> 565 bytes
-rw-r--r--doc/images/icons/callouts/12.pngbin0 -> 617 bytes
-rw-r--r--doc/images/icons/callouts/13.pngbin0 -> 623 bytes
-rw-r--r--doc/images/icons/callouts/14.pngbin0 -> 411 bytes
-rw-r--r--doc/images/icons/callouts/15.pngbin0 -> 640 bytes
-rw-r--r--doc/images/icons/callouts/2.pngbin0 -> 353 bytes
-rw-r--r--doc/images/icons/callouts/3.pngbin0 -> 350 bytes
-rw-r--r--doc/images/icons/callouts/4.pngbin0 -> 345 bytes
-rw-r--r--doc/images/icons/callouts/5.pngbin0 -> 348 bytes
-rw-r--r--doc/images/icons/callouts/6.pngbin0 -> 355 bytes
-rw-r--r--doc/images/icons/callouts/7.pngbin0 -> 344 bytes
-rw-r--r--doc/images/icons/callouts/8.pngbin0 -> 357 bytes
-rw-r--r--doc/images/icons/callouts/9.pngbin0 -> 357 bytes
-rw-r--r--doc/images/icons/caution.pngbin0 -> 2734 bytes
-rw-r--r--doc/images/icons/example.pngbin0 -> 2599 bytes
-rw-r--r--doc/images/icons/home.pngbin0 -> 1340 bytes
-rw-r--r--doc/images/icons/important.pngbin0 -> 2980 bytes
-rw-r--r--doc/images/icons/next.pngbin0 -> 1302 bytes
-rw-r--r--doc/images/icons/note.pngbin0 -> 2494 bytes
-rw-r--r--doc/images/icons/prev.pngbin0 -> 1348 bytes
-rw-r--r--doc/images/icons/tip.pngbin0 -> 2718 bytes
-rw-r--r--doc/images/icons/up.pngbin0 -> 1320 bytes
-rw-r--r--doc/images/icons/warning.pngbin0 -> 3214 bytes
-rw-r--r--doc/images/ifinfomsg.pngbin0 -> 44814 bytes
-rw-r--r--doc/images/library_overview.pngbin0 -> 23870 bytes
-rw-r--r--doc/images/nlmsgerr.pngbin0 -> 43810 bytes
-rw-r--r--doc/images/nlmsghdr.pngbin0 -> 19553 bytes
-rw-r--r--doc/images/qdisc_default.pngbin0 -> 14571 bytes
-rw-r--r--doc/images/qdisc_mq.pngbin0 -> 26121 bytes
-rw-r--r--doc/images/tc_obj.pngbin0 -> 30876 bytes
-rw-r--r--doc/images/tc_overview.pngbin0 -> 48129 bytes
-rw-r--r--doc/index.txt22
-rw-r--r--doc/libnl.css1407
-rw-r--r--doc/m4/ax_python.m497
-rwxr-xr-xdoc/resolve-asciidoc-refs.py25
-rw-r--r--doc/route.txt1889
-rw-r--r--doc/src/hidden.c42
-rw-r--r--doc/src/toc.c54
-rw-r--r--doc/stylesheets/asciidoc-manpage.css18
-rw-r--r--doc/stylesheets/asciidoc.css526
-rw-r--r--doc/stylesheets/docbook-xsl.css322
-rw-r--r--doc/stylesheets/flask-manpage.css1
-rw-r--r--doc/stylesheets/flask.css584
-rw-r--r--doc/stylesheets/pygments.css66
-rw-r--r--doc/stylesheets/slidy.css445
-rw-r--r--doc/stylesheets/toc2.css34
-rw-r--r--doc/stylesheets/volnitsky-manpage.css1
-rw-r--r--doc/stylesheets/volnitsky.css435
-rw-r--r--doc/stylesheets/xhtml11-quirks.css43
-rw-r--r--doc/stylesheets/xhtml11.css333
73 files changed, 11264 insertions, 951 deletions
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 00000000..f7cb70da
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,8 @@
+*.html
+libnl.dict
+Doxyfile
+/aclocal.m4
+/autom4te.cache/
+/build-aux/
+/config.*
+/configure
diff --git a/doc/AUTHORS b/doc/AUTHORS
new file mode 100644
index 00000000..26e3cb40
--- /dev/null
+++ b/doc/AUTHORS
@@ -0,0 +1 @@
+Thomas Graf <tgraf@suug.ch>
diff --git a/doc/COPYING b/doc/COPYING
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/doc/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index 8e311e3b..50e8f0c9 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -1,203 +1,268 @@
-# Doxyfile 1.5.2
+# Doxyfile 1.8.1.1
# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
+# doxygen (www.doxygen.org) for a project.
#
-# All text after a hash (#) is considered a comment and will be ignored
+# All text after a hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
+# Values that contain spaces should be placed between quotes (" ").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file that
-# follow. The default is UTF-8 which is also the encoding used for all text before
-# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
-# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
-# possible encodings.
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
PROJECT_NAME = libnl
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = @PACKAGE_VERSION@
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = ./
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
-# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
-# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
-# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
-REPEAT_BRIEF = NO
+REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
-ABBREVIATE_BRIEF =
+ABBREVIATE_BRIEF =
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
# description.
-ALWAYS_DETAILED_SEC = YES
+ALWAYS_DETAILED_SEC = NO
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = YES
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
# path to strip.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explicit @brief command for a brief description.
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = YES
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
-MULTILINE_CPP_IS_BRIEF = NO
+QT_AUTOBRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
-DETAILS_AT_TOP = YES
+MULTILINE_CPP_IS_BRIEF = NO
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = NO
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
-ALIASES = arg=\param
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
+ALIASES = arg=\param \
+ "ref_asciidoc{3}=<a href=\"../\1.html#\2\"><b>\3</b></a>" \
+ "ref_core{2}=\ref_asciidoc{core,\1,\2 (Netlink Core Library Development Guide)}" \
+ "ref_route{2}=\ref_asciidoc{route,\1,\2 (Netlink Routing Development Guide)}" \
+ "ref_idiagnl{2}=\ref_asciidoc{idiag,\1,\2 (Netlink Inet Diag Development Guide)}" \
+ "core_doc{2}=\ref_core{\1,\2}" \
+ "route_doc{2}=\ref_route{\1,\2}" \
+ "idiagnl_doc{2}=\ref_idiagnl{\1,\2}" \
+ "callback=\par Callback Invocation:\n" \
+ "lowlevel=\copydoc low_level_api"
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for Java.
-# For instance, namespaces will be presented as packages, qualified scopes
-# will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
-# include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
@@ -207,396 +272,551 @@ BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = NO
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = NO
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = YES
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = NO
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = NO
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
+# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = NO
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = NO
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
-GENERATE_BUGLIST = NO
+GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
-GENERATE_DEPRECATEDLIST= NO
+GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
+# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = NO
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = NO
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
-SHOW_DIRECTORIES = NO
+SHOW_NAMESPACES = YES
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from the
-# version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE = DoxygenLayout.xml
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
+# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = YES
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = NO
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
# to stderr.
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = ../lib \
- ../src/lib \
- ../include/netlink
+INPUT = @top_srcdir@/../lib \
+ @top_srcdir@/../src/lib \
+ @top_srcdir@/../include/netlink \
+ @top_srcdir@/../src \
+ @top_srcdir@/../doc/src
-# This tag can be used to specify the character encoding of the source files that
-# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
-# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
-# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
INPUT_ENCODING = UTF-8
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
FILE_PATTERNS = *.c \
*.h
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
EXCLUDE = SCCS
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the output.
-# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
-# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
# the \include command).
-EXAMPLE_PATH =
+EXAMPLE_PATH = @top_srcdir@/src
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS =
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = NO
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
# the \image command).
-IMAGE_PATH =
+IMAGE_PATH =
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
# ignored.
-INPUT_FILTER =
+INPUT_FILTER =
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
+# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
STRIP_CODE_COMMENTS = NO
-# If the REFERENCED_BY_RELATION tag is set to YES (the default)
-# then for each documented function all documented
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES (the default)
-# then for each documented function all documented entities
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
@@ -604,43 +824,44 @@ REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
+# link to the source code.
+# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
-VERBATIM_HEADERS = NO
+VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX = nl_
@@ -649,256 +870,524 @@ IGNORE_PREFIX = nl_
# configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
-HTML_OUTPUT = html
+HTML_OUTPUT = api
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
-HTML_HEADER =
+HTML_FOOTER =
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = @srcdir@/libnl.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
-HTML_FOOTER =
+HTML_COLORSTYLE_SAT = 100
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
-HTML_STYLESHEET =
+HTML_COLORSTYLE_GAMMA = 80
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
-HTML_ALIGN_MEMBERS = YES
+HTML_TIMESTAMP = YES
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
# written to the html output directory.
-CHM_FILE =
+CHM_FILE =
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
-HHC_LOCATION =
+HHC_LOCATION =
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.infradead.libnl
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
DISABLE_INDEX = NO
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
-ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = YES
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
-GENERATE_TREEVIEW = NO
+ENUM_VALUES_PER_LINE = 1
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
-TREEVIEW_WIDTH = 250
+TREEVIEW_WIDTH = 205
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
LATEX_CMD_NAME = latex
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
-LATEX_HEADER =
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
+# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
-# The MAN_EXTENSION tag determines the extension that is added to
+# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
@@ -907,33 +1396,33 @@ MAN_LINKS = NO
# configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
# syntax of the XML files.
-XML_SCHEMA =
+XML_SCHEMA =
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
# syntax of the XML files.
-XML_DTD =
+XML_DTD =
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
@@ -942,10 +1431,10 @@ XML_PROGRAMLISTING = YES
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
@@ -954,307 +1443,364 @@ GENERATE_AUTOGEN_DEF = NO
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
+# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
SEARCH_INCLUDES = NO
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
# the preprocessor.
-INCLUDE_PATH =
+INCLUDE_PATH =
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED =
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = YES
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
-# The PERL_PATH should be the absolute path and name of the perl script
+# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
+# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
CLASS_DIAGRAMS = NO
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
-# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
-# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
-# be found in the default search path.
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = FreeSans.ttf
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = NO
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = NO
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = NO
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = YES
-# If set to YES, the inheritance and collaboration graphs will show the
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = NO
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = NO
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = NO
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
-# generate a call dependency graph for every global function or class method.
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
-CALL_GRAPH = NO
+CALL_GRAPH = YES
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
-# generate a caller dependency graph for every global function or class method.
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
-CALLER_GRAPH = NO
+CALLER_GRAPH = YES
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
-DIRECTORY_GRAPH = NO
+DIRECTORY_GRAPH = YES
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
DOT_IMAGE_FORMAT = png
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
-DOT_PATH =
+DOT_PATH =
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
# \dotfile command).
-DOTFILE_DIRS =
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
-# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen will always
-# show the root nodes and its direct children regardless of this setting.
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-DOT_GRAPH_MAX_NODES = 50
+DOT_GRAPH_MAX_NODES = 100
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, which results in a white background.
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = NO
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml
new file mode 100644
index 00000000..589d0f10
--- /dev/null
+++ b/doc/DoxygenLayout.xml
@@ -0,0 +1,187 @@
+<doxygenlayout version="1.0">
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <allmemberslink visible="yes"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 040ff877..338f0772 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,9 +1,73 @@
# -*- Makefile -*-
-.PHONY: gendoc
+.PHONY: gendoc api_ref asciidoc
-gendoc:
+ASCIIDOCOPTS=-a pygments -a language=c -a icons \
+ -a toc2 \
+ -a numbered \
+ -a imagesdir="./images/" \
+ -a iconsdir="./images/icons" \
+ -a stylesdir="${abs_srcdir}/stylesheets/"
+
+EXTRA_DIST = \
+ core.txt \
+ core.html \
+ route.txt \
+ route.html \
+ index.txt \
+ index.html \
+ libnl.css \
+ stylesheets \
+ images \
+ api
+
+dist-hook:
+ rm -f $(distdir)/aclocal.m4
+ rm -f $(distdir)/configure
+ rm -f $(distdir)/configure.in
+ rm -rf $(distdir)/m4
+ rm -f $(distdir)/README
+ rm -f $(distdir)/missing
+ rm -f $(distdir)/Doxyfile.in
+ rm -f $(distdir)/Makefile.am
+ rm -f $(distdir)/Makefile.in
+
+link_doc:
+if LINK_DOC
+ ./gen-tags.sh > libnl.dict
+else
+ @echo "Warning: Linking to API reference is disabled, check configure output"
+endif
+
+
+%.html: %.txt link_doc
+ ./resolve-asciidoc-refs.py $< > asciidoc.tmp
+ asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp
+if LINK_DOC
+ ./doxygen-link.py libnl.dict $@ > asciidoc.tmp
+ mv asciidoc.tmp $@
+endif
+
+asciidoc: core.html route.html index.html
+
+api_ref:
doxygen Doxyfile;
-distclean-local:
- rm -f html/*;
+gendoc:
+if GENERATE_DOC
+if HAVE_DOXYGEN
+ $(MAKE) api_ref
+else
+ @echo "Warning: Building of API reference (doxygen) is disabled, check autoconf logs"
+endif
+if HAVE_ASCIIDOC
+ $(MAKE) asciidoc
+else
+ @echo "Warning: Building of asciidoc files is disabled, check autoconf logs"
+endif
+else
+ @echo "Warning: Building of documentation disabled by user or autoconf"
+endif
+
+clean-local:
+ rm -f api/* libnl.dict *.html;
diff --git a/doc/README b/doc/README
new file mode 100644
index 00000000..ddcdf14f
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,13 @@
+Requirements to build documentation
+
+mscgen
+ http://www.mcternan.me.uk/mscgen/
+
+mscgen-filter-1.2
+ http://code.google.com/p/asciidoc-mscgen-filter/
+
+asciidoc > 8.6.x
+doxygen > 1.8.0
+
+Building the documentation:
+make gendoc
diff --git a/doc/api/.gitignore b/doc/api/.gitignore
new file mode 100644
index 00000000..e57ca889
--- /dev/null
+++ b/doc/api/.gitignore
@@ -0,0 +1,8 @@
+*.html
+*.png
+*.css
+*.map
+*.md5
+*.js
+formula.repository
+jquery.js
diff --git a/doc/autogen.sh b/doc/autogen.sh
new file mode 100755
index 00000000..a5696148
--- /dev/null
+++ b/doc/autogen.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+autoreconf -fi;
+rm -Rf autom4te.cache;
diff --git a/doc/configure.ac b/doc/configure.ac
new file mode 100644
index 00000000..d4cda857
--- /dev/null
+++ b/doc/configure.ac
@@ -0,0 +1,107 @@
+#
+# 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-2013 Thomas Graf <tgraf@suug.ch>
+#
+
+AC_INIT(libnl-doc, [3.2.25], [http://www.infradead.org/~tgr/libnl/])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([foreign])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], [])
+
+m4_include([m4/ax_python.m4])
+
+#
+# Generating the documentation
+#
+AC_ARG_ENABLE([doc],
+ AS_HELP_STRING([--disable-doc], [Do not generate documentation]),
+ [generate_doc="$enableval"], [generate_doc=auto])
+
+AX_PYTHON
+
+if test "x$generate_doc" != "xno"; then
+ AC_PROG_SED
+ AC_PROG_EGREP
+
+ AC_CHECK_PROG(HAVE_DOXYGEN, [doxygen], yes, no)
+ if test "x$HAVE_DOXYGEN" = "xno" -a "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** doxygen package required to generate documentation])
+ fi
+
+ AC_CHECK_PROG(HAVE_DOT, [dot], yes, no)
+ if test "x$HAVE_DOT" = "xno"; then
+ if test "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** graphviz package required to generate documentation])
+ else
+ AC_MSG_WARN([*** graphviz not found, disabling building of API reference])
+ HAVE_DOXYGEN=no
+ fi
+ fi
+
+ AC_CHECK_PROG(HAVE_ASCIIDOC, [asciidoc], yes, no)
+ if test "x$HAVE_ASCIIDOC" = "xno"; then
+ if test "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** asciidoc package required to generate documentation])
+ else
+ AC_MSG_WARN([*** asciidoc not found, disabling building of guides])
+ fi
+ fi
+
+ AC_CHECK_PROG(HAVE_SOURCE_HIGHLIGHT, [source-highlight], yes, no)
+ if test "x$HAVE_SOURCE_HIGHLIGHT" = "xno"; then
+ if test "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** source-highlight required to generate documentation])
+ else
+ AC_MSG_WARN([*** source-highlight not found, disabling building of guides])
+ HAVE_ASCIIDOC=no
+ fi
+ fi
+
+ AC_CHECK_PROG(HAVE_MSCGEN, [mscgen], yes, no)
+ if test "x$HAVE_MSCGEN" = "xno"; then
+ AC_MSG_WARN([*** mscgen not found, get it at http://www.mcternan.me.uk/mscgen/])
+ if test "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** mscgen package required to generate documentation])
+ else
+ AC_MSG_WARN([*** Disabling building of guides])
+ HAVE_ASCIIDOC=no
+ HAVE_DOXYGEN=no
+ fi
+ fi
+
+ AC_CHECK_PROG(HAVE_PYGMENTIZE, [pygmentize], yes, no)
+ if test "x$HAVE_PYGMENTIZE" = "xno"; then
+ if test "x$generate_doc" = "xyes"; then
+ AC_MSG_ERROR([*** pygmentize package required to generate documentation])
+ else
+ AC_MSG_WARN([*** Disabling building of guides])
+ HAVE_ASCIIDOC=no
+ fi
+ fi
+
+ link_doc=yes
+ if test "x$HAVE_DOXYGEN" = "xno"; then
+ AC_MSG_WARN([*** Disabling API linking due to missing doxygen package])
+ link_doc=no
+ fi
+fi
+
+AM_CONDITIONAL([LINK_DOC], [test "x$link_doc" = "xyes"])
+AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$HAVE_DOXYGEN" = "xyes"])
+AM_CONDITIONAL([HAVE_ASCIIDOC], [test "x$HAVE_ASCIIDOC" = "xyes"])
+
+AM_CONDITIONAL([GENERATE_DOC], [test "x$generate_doc" != "xno"])
+
+AC_CONFIG_FILES([
+Doxyfile
+Makefile
+])
+
+AC_OUTPUT
diff --git a/doc/core.txt b/doc/core.txt
new file mode 100644
index 00000000..042369d3
--- /dev/null
+++ b/doc/core.txt
@@ -0,0 +1,3017 @@
+////
+ vim.syntax: asciidoc
+
+ Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
+////
+
+Netlink Library (libnl)
+=======================
+Thomas Graf <tgraf@suug.ch>
+3.2, May 9 2011:
+:numbered:
+
+== Introduction
+
+The core library contains the fundamentals required to communicate
+over netlink sockets. It deals with connecting and disconnectng of
+sockets, sending and receiving of data, construction and parsing of
+messages, provides a customizeable receiving state machine, and
+provides a abstract data type framework which eases the implementation
+of object based netlink protocols where objects are added, removed, or
+modified using a netlink based protocol.
+
+.Library Hierarchy
+
+The suite is split into multiple libraries:
+
+image:library_overview.png["Library Hierarchy"]
+
+link:core.html[Netlink Library] (libnl)::
+Socket handling, sending and receiving, message construction and parsing, ...
+
+link:route.html[Routing Family Library] (libnl-route)::
+Adresses, links, neighbours, routing, traffic control, neighbour tables, ...
+
+Netfilter Library (libnl-nf)::
+Connection tracking, logging, queueing
+
+Generic Netlink Library (libnl-genl)::
+Controller API, family and command registration
+
+
+=== How To Read This Documentation
+
+The libraries provide a broad set of APIs of which most applications only
+require a small subset of it. Depending on the type of application, some
+users may only be interested in the low level netlink messaging API while
+others wish to make heavy use of the high level API.
+
+In any case it is recommended to get familiar with the netlink protocol
+first.
+
+- <<core_netlink_fundamentals>>
+
+The low level APIs are described in:
+
+- <<core_sockets>>
+- <<core_send_recv>>
+
+
+=== Linking to this Library
+
+.Checking the presence of the library using autoconf
+
+Projects using autoconf may use +PKG_CHECK_MODULES()+ to check if
+a specific version of libnl is available on the system. The example
+below also shows how to retrieve the +CFLAGS+ and linking dependencies
+required to link against the library.
+
+The following example shows how to check for a specific version of libnl. If
+found, it extends the `CFLAGS` and `LIBS` variable appropriately:
+
+[source]
+----
+PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no])
+if (test "${have_libnl3}" = "yes"); then
+ CFLAGS+="$LIBNL3_CFLAGS"
+ LIBS+="$LIBNL3_LIBS"
+fi
+----
+
+NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also
+ covers library versions >= 3.1.
+
+.Header Files
+
+The main header file is `<netlink/netlink.h>`. Additional headers may need to
+be included in your sources depending on the subsystems and components your
+program makes use of.
+
+[source,c]
+-----
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/route/link.h>
+-----
+
+.Version Dependent Code
+
+If your code wishes to be capable to link against multiple versions of libnl
+you may have direct the compiler to only include portions on the code depending
+on the version of libnl that it is compiled against.
+
+[source,c]
+-----
+#include <netlink/version.h>
+
+#if LIBNL_VER_NUM >= LIBNL_VER(3,1)
+ /* include code if compiled with libnl version >= 3.1 */
+#endif
+-----
+
+.Linking
+-----
+$ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0)
+-----
+
+=== Debugging
+
+The library has been compiled with debugging statements enabled it will
+print debug information to +stderr+ if the environment variable +NLDBG+
+is set to > 0.
+
+-----
+$ NLDBG=2 ./myprogram
+-----
+
+.Debugging Levels
+[options="header", width="80%", cols="1,5", align="center"]
+|===============================================================
+| Level | Description
+| 0 | Debugging disabled (default)
+| 1 | Warnings, important events and notifications
+| 2 | More or less important debugging messages
+| 3 | Repetitive events causing a flood of debugging messages
+| 4 | Even less important messages
+|===============================================================
+
+.Debugging the Netlink Protocol
+
+It is often useful to peek into the stream of netlink messages exchanged
+with other sockets. Setting the environment variable +NLCB=debug+ will
+cause the debugging message handlers to be used which in turn print the
+netlink messages exchanged in a human readable format to to +stderr+:
+
+-----
+$ NLCB=debug ./myprogram
+-- Debug: Sent Message:
+-------------------------- BEGIN NETLINK MESSAGE ---------------------------
+ [HEADER] 16 octets
+ .nlmsg_len = 20
+ .nlmsg_type = 18 <route/link::get>
+ .nlmsg_flags = 773 <REQUEST,ACK,ROOT,MATCH>
+ .nlmsg_seq = 1301410712
+ .nlmsg_pid = 20014
+ [PAYLOAD] 16 octets
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+--------------------------- END NETLINK MESSAGE ---------------------------
+-- Debug: Received Message:
+-------------------------- BEGIN NETLINK MESSAGE ---------------------------
+ [HEADER] 16 octets
+ .nlmsg_len = 996
+ .nlmsg_type = 16 <route/link::new>
+ .nlmsg_flags = 2 <MULTI>
+ .nlmsg_seq = 1301410712
+ .nlmsg_pid = 20014
+ [PAYLOAD] 16 octets
+ 00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......
+ [ATTR 03] 3 octets
+ 6c 6f 00 lo.
+ [PADDING] 1 octets
+ 00 .
+ [ATTR 13] 4 octets
+ 00 00 00 00 ....
+ [ATTR 16] 1 octets
+ 00 .
+ [PADDING] 3 octets
+ 00 00 00 ...
+ [ATTR 17] 1 octets
+ 00 .
+ [...]
+--------------------------- END NETLINK MESSAGE ---------------------------
+
+-----
+
+[[core_netlink_fundamentals]]
+== Netlink Protocol Fundamentals
+
+The netlink protocol is a socket based IPC mechanism used for
+communication between userspace processes and the kernel or between
+userspace processes themselves. The netlink protocol is based on BSD
+sockets and uses the +AF_NETLINK+ address family. Every netlink
+protocol uses its own protocol number (e.g. +NETLINK_ROUTE+,
++NETLINK_NETFILTER+, etc). Its addressing schema is based on a 32 bit
+port number, formerly referred to as PID, which uniquely identifies
+each peer.
+
+[[core_addressing]]
+=== Addressing
+
+The netlink address (port) consists of a 32bit integer. Port 0 (zero)
+is reserved for the kernel and refers to the kernel side socket of each
+netlink protocol family. Other port numbers usually refer to user space
+owned sockets, although this is not enforced.
+
+NOTE: In the beginning, it was common practice to use the process
+ identifier (PID) as the local port number. This became unpractical
+ with the introduction of threaded netlink applications and
+ applications requiring multiple sockets. Therefore libnl generates
+ unique port numbers based on the process identifier and adds an
+ offset to it allowing for multiple sockets to be used. The initial
+ socket will still equal to the process identifier for backwards
+ compatibility reasons.
+
+image:addressing.png["Addressing Example"]
+
+The above figure illustrates three applications and the kernel side
+exposing two kernel side sockets. It shows the common netlink use
+cases:
+
+ * User space to kernel
+ * User space to user space
+ * Listening to kernel multicast notifications
+
+.User Space to Kernel
+
+The most common form of netlink usage is for a user space application
+to send requests to the kernel and process the reply which is either
+an error message or a success notification.
+
+["mscgen"]
+--------
+msc {
+ App1,App2,Kernel;
+ App1=>Kernel [label="request (src=11, dst=0)"];
+ App1<=Kernel [label="reply (src=0, dst=11)"];
+ ...;
+ App2=>Kernel [label="request (src=21, dst=0)"];
+ App2<=Kernel [label="reply (src=0, dst=21)"];
+}
+--------
+
+.User Space to User Space
+
+Netlink may also be used as an IPC mechanism to communicate between user
+space applications directly. Communication is not limited to two peers,
+any number of peers may communicate with each other and multicasting
+capabilities allow to reach multiple peers with a single message.
+
+In order for the sockets to be visible to each other, both sockets must
+be created for the same netlink protocol family.
+
+["mscgen"]
+--------
+msc {
+ App2,App3;
+ App2=>App3 [label="request (src=22, dst=31)"];
+ App2<=App3 [label="reply (src=31, dst=22)"];
+ ...;
+}
+--------
+
+.User space listening to kernel notifications
+
+This form of netlink communication is typically found in user space
+daemons that need to act on certain kernel events. Such daemons will
+typically maintain a netlink socket subscribed to a multicast group that
+is used by the kernel to notify interested user space parties about
+specific events.
+
+["mscgen"]
+--------
+msc {
+ Kernel,App3;
+ Kernel=>App3 [label="notification (src=0, group=foo)"];
+ ...;
+}
+--------
+
+Use of multicasting is preferred over direct addressing due to the
+flexibility in exchanging the user space component at any time without
+the kernel noticing.
+
+[[core_msg_format]]
+=== Message Format
+
+A netlink protocol is typically based on messages and consists of the
+netlink message header (+struct nlmsghdr+) plus the payload attached
+to it. The payload can consist of arbitrary data but usually contains
+a fixed size protocol specific header followed by a stream of
+attributes.
+
+.Netlink message header (struct nlmsghdr)
+
+image:nlmsghdr.png[align="center", alt="Netlink Message Header"]
+
+Total Length (32bit)::
+Total length of the message in bytes including the netlink message header.
+
+Message Type (16bit)::
+The message type specifies the type of payload the message is carrying.
+Several standard message types are defined by the netlink protocol.
+Additional message types may be defined by each protocol family. See
+<<core_msg_types>> for additional information.
+
+Message Flags (16bit)::
+The message flags may be used to modify the behaviour of a message type.
+See section <<core_msg_flags>> for a list of standard message flags.
+
+Sequence Number (32bit)::
+The sequence number is optional and may be used to allow referring to
+a previous message, e.g. an error message can refer to the original
+request causing the error.
+
+Port Number (32bit)::
+The port number specifies the peer to which the message should be delivered
+to. If not specified, the message will be delivered to the first matching
+kernel side socket of the same protocol family.
+
+[[core_msg_types]]
+=== Message Types
+
+Netlink differs between requests, notifications, and replies. Requests
+are messages which have the +NLM_F_REQUEST+ flag set and are meant to
+request an action from the receiver. A request is typically sent from
+a userspace process to the kernel. While not strictly enforced, requests
+should carry a sequence number incremented for each request sent.
+
+Depending on the nature of the request, the receiver may reply to the
+request with another netlink message. The sequence number of a reply
+must match the sequence number of the request it relates to.
+
+Notifications are of informal nature and no reply is expected, therefore
+the sequence number is typically set to 0.
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="GET (seq=1, NLM_F_REQUEST)"];
+ A<=B [label="PUT (seq=1)"];
+ ...;
+ A<=B [label="NOTIFY (seq=0)"];
+}
+--------
+
+
+The type of message is primarly identified by its 16 bit message type set
+in the message header. The following standard message types are defined:
+
+- +NLMSG_NOOP+ - No operation, message must be discarded
+- +NLMSG_ERROR+ - Error message or ACK, see <<core_errmsg>>
+ respectively <<core_msg_ack>>
+- +NLMSG_DONE+ - End of multipart sequence, see <<core_multipart>>
+- +NLMSG_OVERRUN+ - Overrun notification (Error)
+
+Every netlink protocol is free to define own message types. Note that
+message type values +< NLMSG_MIN_TYPE (0x10)+ are reserved and may
+not be used.
+
+It is common practice to use own message types to implement RPC schemas.
+Suppose the goal of the netlink protocol you are implementing is allow
+configuration of a particular network device, therefore you want to
+provide read/write access to various configuration options. The typical
+"netlink way" of doing this would be to define two message types
++MSG_SETCFG+, +MSG_GETCFG+:
+
+[source,c]
+--------
+#define MSG_SETCFG 0x11
+#define MSG_GETCFG 0x12
+--------
+
+Sending a +MSG_GETCFG+ request message will typically trigger a reply
+with the message type +MSG_SETCFG+ containing the current configuration.
+In object oriented terms one would describe this as "the kernel sets
+the local copy of the configuration in userspace".
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="MSG_GETCFG (seq=1, NLM_F_REQUEST)"];
+ A<=B [label="MSG_SETCFG (seq=1)"];
+}
+--------
+
+The configuration may be changed by sending a +MSG_SETCFG+ which will
+be responded to with either a ACK (see <<core_msg_ack>>)
+or a error message (see <<core_errmsg>>).
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="MSG_SETCFG (seq=1, NLM_F_REQUEST, NLM_F_ACK)"];
+ A<=B [label="ACK (seq=1)"];
+}
+--------
+
+Optionally, the kernel may send out notifications for configuration
+changes allowing userspace to listen for changes instead of polling
+frequently. Notifications typically reuse an existing message type
+and rely on the application using a separate socket to differ between
+requests and notifications but you may also specify a separate message
+type.
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A<=B [label="MSG_SETCFG (seq=0)"];
+}
+--------
+
+[[core_multipart]]
+==== Multipart Messages
+
+Although in theory a netlink message can be up to 4GiB in size. The socket
+buffers are very likely not large enough to hold message of such sizes.
+Therefore it is common to limit messages to one page size (PAGE_SIZE) and
+use the multipart mechanism to split large pieces of data into several
+messages. A multipart message has the flag +NLM_F_MULTI+ set and the
+receiver is expected to continue receiving and parsing until the special
+message type +NLMSG_DONE+ is received.
+
+Multipart messages unlike fragmented ip packets must not be reassmbled
+even though it is perfectly legal to do so if the protocols wishes to
+work this way. Often multipart message are used to send lists or trees
+of objects were each multipart message simply carries multiple objects
+allow for each message to be parsed independently.
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="GET (seq=1, NLM_F_REQUEST)"];
+ A<=B [label="PUT (seq=1, NLM_F_MULTI)"];
+ ...;
+ A<=B [label="PUT (seq=1, NLM_F_MULTI)"];
+ A<=B [label="NLMSG_DONE (seq=1)"];
+}
+--------
+
+[[core_errmsg]]
+==== Error Message
+
+Error messages can be sent in response to a request. Error messages must
+use the standard message type +NLMSG_ERROR+. The payload consists of a
+error code and the original netlink mesage header of the request.
+
+image:nlmsgerr.png["Netlink Errror Message header"]
+
+Error messages should set the sequence number to the sequence number
+of the request which caused the error.
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="GET (seq=1, NLM_F_REQUEST)"];
+ A<=B [label="NLMSG_ERROR code=EINVAL (seq=1)"];
+}
+--------
+
+[[core_msg_ack]]
+==== ACKs
+
+A sender can request an ACK message to be sent back for each request
+processed by setting the +NLM_F_ACK+ flag in the request. This is typically
+used to allow the sender to synchronize further processing until the
+request has been processed by the receiver.
+
+["mscgen"]
+--------
+msc {
+ A,B;
+ A=>B [label="GET (seq=1, NLM_F_REQUEST | NLM_F_ACK)"];
+ A<=B [label="ACK (seq=1)"];
+}
+--------
+
+ACK messages also use the message type +NLMSG_ERROR+ and payload
+format but the error code is set to 0.
+
+[[core_msg_flags]]
+==== Message Flags
+
+The following standard flags are defined
+
+[source,c]
+--------
+#define NLM_F_REQUEST 1
+#define NLM_F_MULTI 2
+#define NLM_F_ACK 4
+#define NLM_F_ECHO 8
+--------
+
+- `NLM_F_REQUEST` - Message is a request, see <<core_msg_types>>.
+- `NLM_F_MULTI` - Multipart message, see <<core_multipart>>
+- `NLM_F_ACK` - ACK message requested, see <<core_msg_ack>>.
+- `NLM_F_ECHO` - Request to echo the request.
+
+The flag +NLM_F_ECHO+ is similar to the `NLM_F_ACK` flag. It can be
+used in combination with `NLM_F_REQUEST` and causes a notification
+which is sent as a result of a request to also be sent to the sender
+regardless of whether the sender has subscribed to the corresponding
+multicast group or not. See <<core_multicast>>
+
+Additional universal message flags are defined which only apply for
++GET+ requests:
+
+[source,c]
+--------
+#define NLM_F_ROOT 0x100
+#define NLM_F_MATCH 0x200
+#define NLM_F_ATOMIC 0x400
+#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
+--------
+
+- `NLM_F_ROOT` - Return based on root of tree.
+- `NLM_F_MATCH` - Return all matching entries.
+- `NLM_F_ATOMIC` - Obsoleted, once used to request an atomic operation.
+- `NLM_F_DUMP` - Return a list of all objects
+ (`NLM_F_ROOT`|`NLM_F_MATCH`).
+
+Use of these flags is completely optional and many netlink protocols only
+make use of the `NLM_F_DUMP` flag which typically requests the receiver
+to send a list of all objects in the context of the message type as a
+sequence of multipart messages (see <<core_multipart>>).
+
+Another set of flags exist related to `NEW` or `SET` requests. These
+flags are mutually exclusive to the `GET` flags:
+
+[source,c]
+--------
+#define NLM_F_REPLACE 0x100
+#define NLM_F_EXCL 0x200
+#define NLM_F_CREATE 0x400
+#define NLM_F_APPEND 0x800
+--------
+
+- `NLM_F_REPLACE` - Replace an existing object if it exists.
+- `NLM_F_EXCL` - Do not update object if it exists already.
+- `NLM_F_CREATE` - Create object if it does not exist yet.
+- `NLM_F_APPEND` - Add object at end of list.
+
+Behaviour of these flags may differ slightly between different netlink
+protocols.
+
+[[core_seq_num]]
+=== Sequence Numbers
+
+Netlink allows the use of sequence numbers to help relate replies to
+requests. It should be noted that unlike in protocols such as TCP
+there is no strict enforcment of the sequence number. The sole purpose
+of sequence numbers is to assist a sender in relating replies to the
+corresponding requests. See <<core_msg_types>> for more information.
+
+Sequence numbers are managed on a per socket basis, see
+<<core_sk_seq_num>> for more information on how to use sequence numbers.
+
+[[core_multicast]]
+=== Multicast Groups
+
+TODO
+
+See <<core_sk_multicast>>
+
+[[core_sockets]]
+== Netlink Sockets
+
+In order to use the netlink protocol, a netlink socket is required.
+Each socket defines an independent context for sending and receiving of
+messages. An application may make use multiple sockets, e.g. a socket to
+send requests and receive the replies and another socket subscribed to a
+multicast group to receive notifications.
+
+=== Socket structure (struct nl_sock)
+
+The netlink socket and all related attributes including the actual file
+descriptor are represented by +struct nl_sock+.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+struct nl_sock *nl_socket_alloc(void)
+void nl_socket_free(struct nl_sock *sk)
+--------
+
+The application must allocate an instance of +struct nl_sock+ for each
+netlink socket it wishes to use.
+
+[[core_sk_seq_num]]
+=== Sequence Numbers
+
+The library will automatically take care of sequence number handling
+for the application. A sequence number counter is stored in the
+socket structure which is used and incremented automatically when a
+message needs to be sent which is expected to generate a reply such as
+an error or any other message type that needs to be related to the
+original message.
+
+Alternatively, the counter can be used directly via the function
+nl_socket_use_seq(). It will return the current value of the counter
+and increment it by one afterwards.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+unsigned int nl_socket_use_seq(struct nl_sock *sk);
+--------
+
+Most applications will not want to deal with sequence number handling
+themselves though. When using nl_send_auto() the sequence number is
+filled in automatically and matched again when a reply is received. See
+section <<core_send_recv>> for more information.
+
+This behaviour can and must be disabled if the netlink protocol
+implemented does not use a request/reply model, e.g. when a socket is
+used to receive notification messages.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+void nl_socket_disable_seq_check(struct nl_sock *sk);
+--------
+
+For more information on the theory behind netlink sequence numbers,
+see section <<core_seq_num>>.
+
+[[core_sk_multicast]]
+=== Multicast Group Subscriptions
+
+Each socket can subscribe to any number of multicast groups of the
+netlink protocol it is connected to. The socket will then receive a
+copy of each message sent to any of the groups. Multicast groups are
+commonly used to implement event notifications.
+
+Prior to kernel 2.6.14 the group subscription was performed using a
+bitmask which limited the number of groups per protocol family to 32.
+This outdated interface can still be accessed via the function
+nl_join_groups() even though it is not recommended for new code.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+void nl_join_groups(struct nl_sock *sk, int bitmask);
+--------
+
+Starting with 2.6.14 a new method was introduced which supports subscribing
+to an almost infinite number of multicast groups.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_add_memberships(struct nl_sock *sk, int group, ...);
+int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...);
+--------
+
+==== Multicast Example
+
+[source,c]
+--------
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/msg.h>
+
+/*
+ * This function will be called for each valid netlink message received
+ * in nl_recvmsgs_default()
+ */
+static int my_func(struct nl_msg *msg, void *arg)
+{
+ return 0;
+}
+
+struct nl_sock *sk;
+
+/* Allocate a new socket */
+sk = nl_socket_alloc();
+
+/*
+ * Notifications do not use sequence numbers, disable sequence number
+ * checking.
+ */
+nl_socket_disable_seq_check(sk);
+
+/*
+ * Define a callback function, which will be called for each notification
+ * received
+ */
+nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
+
+/* Connect to routing netlink protocol */
+nl_connect(sk, NETLINK_ROUTE);
+
+/* Subscribe to link notifications group */
+nl_socket_add_memberships(sk, RTNLGRP_LINK, 0);
+
+/*
+ * Start receiving messages. The function nl_recvmsgs_default() will block
+ * until one or more netlink messages (notification) are received which
+ * will be passed on to my_func().
+ */
+while (1)
+ nl_recvmsgs_default(sock);
+--------
+
+[[core_sk_cb]]
+=== Modifiying Socket Callback Configuration
+
+See <<core_cb>> for more information on
+callback hooks and overwriting capabilities.
+
+Each socket is assigned a callback configuration which controls the
+behaviour of the socket. This is f.e. required to have a separate
+message receive function per socket. It is perfectly legal to share
+callback configurations between sockets though.
+
+The following functions can be used to access and set the callback
+configuration of a socket:
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+struct nl_cb *nl_socket_get_cb(const struct nl_sock *sk);
+void nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb);
+--------
+
+Additionaly a shortcut exists to modify the callback configuration
+assigned to a socket directly:
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_modify_cb(struct nl_sock *sk, enum nl_cb_type type, enum nl_cb_kind kind,
+ nl_recvmsg_msg_cb_t func, void *arg);
+--------
+
+.Example:
+[source,c]
+--------
+#include <netlink/socket.h>
+
+// Call my_input() for all valid messages received in socket sk
+nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_input, NULL);
+--------
+
+=== Socket Attributes
+
+.Local Port
+
+The local port number uniquely identifies the socket and is used to
+address it. A unique local port is generated automatically when the
+socket is allocated. It will consist of the Process ID (22 bits) and a
+random number (10 bits) thus allowing up to 1024 sockets per process.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+uint32_t nl_socket_get_local_port(const struct nl_sock *sk);
+void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port);
+--------
+
+See section <<core_addressing>> for more information on port numbers.
+
+CAUTION: Overwriting the local port is possible but you have to ensure
+that the provided value is unique and no other socket in any other
+application is using the same value.
+
+.Peer Port
+
+A peer port can be assigned to the socket which will result in all
+unicast messages sent over the socket to be addresses to the peer. If
+no peer is specified, the message is sent to the kernel which will try
+to automatically bind the socket to a kernel side socket of the same
+netlink protocol family. It is common practice not to bind the socket
+to a peer port as typically only one kernel side socket exists per
+netlink protocol family.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+uint32_t nl_socket_get_peer_port(const struct nl_sock *sk);
+void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port);
+--------
+
+See section <<core_addressing>> for more information on port numbers.
+
+.File Descriptor
+
+Netlink uses the BSD socket interface, therefore a file descriptor is
+behind each socket and you may use it directly.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_get_fd(const struct nl_sock *sk);
+--------
+
+If a socket is used to only receive notifications it usually is best
+to put the socket in non-blocking mode and periodically poll for new
+notifications.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_set_nonblocking(const struct nl_sock *sk);
+--------
+
+.Send/Receive Buffer Size
+
+The socket buffer is used to queue netlink messages between sender and
+receiver. The size of these buffers specifies the maximum size you
+will be able to write() to a netlink socket, i.e. it will indirectly
+define the maximum message size. The default is 32KiB.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_set_buffer_size(struct nl_sock *sk, int rx, int tx);
+--------
+
+[[core_sk_cred]]
+.Enable/Disable Credentials
+
+TODO
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_set_passcred(struct nl_sock *sk, int state);
+--------
+
+.Enable/Disable Auto-ACK Mode
+
+The following functions allow to enable/disable Auto-ACK mode on a socket.
+See <<core_auto_ack>> for more information on what implications that has.
+Auto-ACK mode is enabled by default.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+void nl_socket_enable_auto_ack(struct nl_sock *sk);
+void nl_socket_disable_auto_ack(struct nl_sock *sk);
+--------
+
+.Enable/Disable Message Peeking
+
+If enabled, message peeking causes nl_recv() to try and use MSG_PEEK
+to retrieve the size of the next message received and allocate a
+buffer of that size. Message peeking is enabled by default but can be
+disabled using the following function:
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+void nl_socket_enable_msg_peek(struct nl_sock *sk);
+void nl_socket_disable_msg_peek(struct nl_sock *sk);
+--------
+
+.Enable/Disable Receival of Packet Information
+
+If enabled, each received netlink message from the kernel will include
+an additional struct nl_pktinfo in the control message. The following
+function can be used to enable/disable receival of packet information.
+
+[source,c]
+--------
+#include <netlink/socket.h>
+
+int nl_socket_recv_pktinfo(struct nl_sock *sk, int state);
+--------
+
+CAUTION: Processing of NETLINK_PKTINFO has not been implemented yet.
+
+[[core_send_recv]]
+== Sending and Receiving of Messages / Data
+
+[[core_send]]
+=== Sending Messages
+
+The standard method of sending a netlink message over a netlink socket
+is to use the function nl_send_auto(). It will automatically complete
+the netlink message by filling the missing bits and pieces in the
+netlink message header and will deal with addressing based on the
+options and address set in the netlink socket. The message is then
+passed on to nl_send().
+
+If the default sending semantics implemented by nl_send() do not suit
+the application, it may overwrite the sending function nl_send() by
+specifying an own implementation using the function
+nl_cb_overwrite_send().
+
+[source,c]
+--------
+ nl_send_auto(sk, msg)
+ |
+ |-----> nl_complete_msg(sk, msg)
+ |
+ |
+ | Own send function specified via nl_cb_overwrite_send()
+ |- - - - - - - - - - - - - - - - - - - -
+ v v
+ nl_send(sk, msg) send_func()
+--------
+
+.Using nl_send()
+
+If you do not require any of the automatic message completion
+functionality you may use nl_send() directly but beware that any
+internal calls to nl_send_auto() by the library to send netlink
+messages will still use nl_send(). Therefore if you wish to use any
+higher level interfaces and the behaviour of nl_send() is to your
+dislike then you must overwrite the nl_send() function via
+nl_cb_overwrite_send()
+
+The purpose of nl_send() is to embed the netlink message into a iovec
+structure and pass it on to nl_send_iovec().
+
+[source,c]
+--------
+ nl_send(sk, msg)
+ |
+ v
+ nl_send_iovec(sk, msg, iov, iovlen)
+--------
+
+.Using nl_send_iovec()
+
+nl_send_iovec() expects a finalized netlink message and fills out the
+struct msghdr used for addressing. It will first check if the struct
+nl_msg is addressed to a specific peer (see nlmsg_set_dst()). If not,
+it will try to fall back to the peer address specified in the socket
+(see nl_socket_set_peer_port(). Otherwise the message will be sent
+unaddressed and it is left to the kernel to find the correct peer.
+
+nl_send_iovec() also adds credentials if present and enabled
+(see <<core_sk_cred>>).
+
+The message is then passed on to nl_sendmsg().
+
+[source,c]
+--------
+ nl_send_iovec(sk, msg, iov, iovlen)
+ |
+ v
+ nl_sendmsg(sk, msg, msghdr)
+--------
+
+.Using nl_sendmsg()
+
+nl_sendmsg() expects a finalized netlink message and an optional
+struct msghdr containing the peer address. It will copy the local
+address as defined in the socket (see nl_socket_set_local_port()) into
+the netlink message header.
+
+At this point, construction of the message finished and it is ready to
+be sent.
+
+[source,c]
+--------
+ nl_sendmsg(sk, msg, msghdr)
+ |- - - - - - - - - - - - - - - - - - - - v
+ | NL_CB_MSG_OUT()
+ |<- - - - - - - - - - - - - - - - - - - -+
+ v
+ sendmsg()
+--------
+
+Before sending the application has one last chance to modify the
+message. It is passed to the NL_CB_MSG_OUT callback function which
+may inspect or modify the message and return an error code. If this
+error code is NL_OK the message is sent using sendmsg() resulting in
+the number of bytes written being returned. Otherwise the message
+sending process is aborted and the error code specified by the
+callback function is returned. See <<core_sk_cb>> for more information
+on how to set callbacks.
+
+.Sending Raw Data with nl_sendto()
+
+If you wish to send raw data over a netlink socket, the following
+function will pass on any buffer provided to it directly to sendto():
+
+[source,c]
+--------
+#include <netlink/netlink.h>
+
+int nl_sendto(struct nl_sock *sk, void *buf, size_t size);
+--------
+
+.Sending of Simple Messages
+
+A special interface exists for sending of trivial messages. The function
+expects the netlink message type, optional netlink message flags, and an
+optional data buffer and data length.
+[source,c]
+--------
+#include <netlink/netlink.h>
+
+int nl_send_simple(struct nl_sock *sk, int type, int flags,
+ void *buf, size_t size);
+--------
+
+The function will construct a netlink message header based on the message
+type and flags provided and append the data buffer as message payload. The
+newly constructed message is sent with nl_send_auto().
+
+The following example will send a netlink request message causing the
+kernel to dump a list of all network links to userspace:
+
+[source,c]
+--------
+#include <netlink/netlink.h>
+
+struct nl_sock *sk;
+struct rtgenmsg rt_hdr = {
+ .rtgen_family = AF_UNSPEC,
+};
+
+sk = nl_socket_alloc();
+nl_connect(sk, NETLINK_ROUTE);
+
+nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
+--------
+
+[[core_recv]]
+=== Receiving Messages
+
+The easiest method to receive netlink messages is to call nl_recvmsgs_default().
+It will receive messages based on the semantics defined in the socket. The
+application may customize these in detail although the default behaviour will
+probably suit most applications.
+
+nl_recvmsgs_default() will also be called internally by the library whenever
+it needs to receive and parse a netlink message.
+
+The function will fetch the callback configuration stored in the socket and
+call nl_recvmsgs():
+
+[source,c]
+--------
+ nl_recvmsgs_default(sk)
+ |
+ | cb = nl_socket_get_cb(sk)
+ v
+ nl_recvmsgs(sk, cb)
+--------
+
+.Using nl_recvmsgs()
+
+nl_recvmsgs() implements the actual receiving loop, it blocks until a
+netlink message has been received unless the socket has been put into
+non-blocking mode.
+
+For the unlikely scenario that certain required receive characteristics
+can not be achieved by fine tuning the internal recvmsgs function using
+the callback configuration (see <<core_sk_cb>>) the application may provide
+a complete own implementation of it and overwrite all calls to nl_recvmsgs()
+with the function nl_cb_overwrite_recvmsgs().
+
+[source,c]
+--------
+ nl_recvmsgs(sk, cb)
+ |
+ | Own recvmsgs function specified via nl_cb_overwrite_recvmsgs()
+ |- - - - - - - - - - - - - - - - - - - -
+ v v
+ internal_recvmsgs() my_recvmsgs()
+--------
+
+[[core_recv_character]]
+.Receive Characteristics
+
+If the application does not provide its own recvmsgs() implementation
+with the function nl_cb_overwrite_recvmsgs() the following characteristics
+apply while receiving data from a netlink socket:
+
+[source,c]
+--------
+ internal_recvmsgs()
+ |
++-------------->| Own recv function specified with nl_cb_overwrite_recv()
+| |- - - - - - - - - - - - - - - -
+| v v
+| nl_recv() my_recv()
+| |<- - - - - - - - - - - - - - -+
+| |<-------------+
+| v | More data to parse? (nlmsg_next())
+| Parse Message |
+| |--------------+
+| v
++------- NLM_F_MULTI set?
+ |
+ v
+ (SUCCESS)
+--------
+
+The function nl_recv() is invoked first to receive data from the
+netlink socket. This function may be overwritten by the application
+by an own implementation using the function nl_cb_overwrite_recv().
+This may be useful if the netlink byte stream is in fact not received
+from a socket directly but is read from a file or another source.
+
+If data has been read, it will be attemped to parse the data. This
+will be done repeately until the parser returns NL_STOP, an error was
+returned or all data has been parsed.
+
+In case the last message parsed successfully was a multipart message
+(see <<core_multipart>>) and the parser did not
+quit due to either an error or NL_STOP nl_recv() respectively the
+applications own implementation will be called again and the parser
+starts all over.
+
+See <<core_parse_character>> for information on how to extract valid
+netlink messages from the parser and on how to control the behaviour
+of it.
+
+[[core_parse_character]]
+.Parsing Characteristics
+
+The internal parser is invoked for each netlink message received from
+a netlink socket. It is typically fed by nl_recv() (see
+<<core_recv_character>>).
+
+The parser will first ensure that the length of the data stream
+provided is sufficient to contain a netlink message header and that
+the message length as specified in the message header does not exceed
+it.
+
+If this criteria is met, a new struct nl_msg is allocated and the
+message is passed on to the the callback function NL_CB_MSG_IN if one
+is set. Like any other callback function, it may return NL_SKIP to
+skip the current message but continue parsing the next message or
+NL_STOP to stop parsing completely.
+
+The next step is to check the sequence number of the message against
+the currently expected sequence number. The application may provide
+its own sequence number checking algorithm by setting the callback
+function NL_CB_SEQ_CHECK to its own implementation. In fact, calling
+nl_socket_disable_seq_check() to disable sequence number checking will
+do nothing more than set the NL_CB_SEQ_CHECK hook to a function which
+always returns NL_OK.
+
+Another callback hook NL_CB_SEND_ACK exists which is called if the
+message has the NLM_F_ACK flag set. Although I am not aware of any
+userspace netlink socket doing this, the application may want to send
+an ACK message back to the sender (see <<core_msg_ack>>).
+
+[source,c]
+--------
+ parse()
+ |
+ v
+ nlmsg_ok() --> Ignore
+ |
+ |- - - - - - - - - - - - - - - v
+ | NL_CB_MSG_IN()
+ |<- - - - - - - - - - - - - - -+
+ |
+ |- - - - - - - - - - - - - - - v
+ Sequence Check NL_CB_SEQ_CHECK()
+ |<- - - - - - - - - - - - - - -+
+ |
+ | Message has NLM_F_ACK set
+ |- - - - - - - - - - - - - - - v
+ | NL_CB_SEND_ACK()
+ |<- - - - - - - - - - - - - - -+
+ |
+ Handle Message Type
+--------
+
+[[core_auto_ack]]
+=== Auto-ACK Mode
+
+TODO
+
+== Message Parsing & Construction
+
+=== Message Format
+
+See <<core_netlink_fundamentals>> for an introduction to the netlink
+protocol and its message format.
+
+.Alignment
+
+Most netlink protocols enforce a strict alignment policy for all
+boundries. The alignment value is defined by NLMSG_ALIGNTO and is
+fixed to 4 bytes. Therefore all netlink message headers, begin of
+payload sections, protocol specific headers, and attribute sections
+must start at an offset which is a multiple of NLMSG_ALIGNTO.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+int nlmsg_size(int payloadlen);
+int nlmsg_total_size(int payloadlen);
+--------
+
+The library provides a set of function to handle alignment
+requirements automatically. The function nlmsg_total_size() returns
+the total size of a netlink message including the padding to ensure
+the next message header is aligned correctly.
+
+[source,c]
+--------
+ <----------- nlmsg_total_size(len) ------------>
+ <----------- nlmsg_size(len) ------------>
+ +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - -
+ | struct nlmsghdr | Pad | Payload | Pad | struct nlsmghdr |
+ +-------------------+- - -+- - - - - - - - +- - -+-------------------+- - -
+ <---- NLMSG_HDRLEN -----> <- NLMSG_ALIGN(len) -> <---- NLMSG_HDRLEN ---
+--------
+
+If you need to know if padding needs to be added at the end of a
+message, nlmsg_padlen() returns the number of padding bytes that need
+to be added for a specific payload length.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+int nlmsg_padlen(int payloadlen);
+--------
+
+=== Parsing a Message
+
+The library offers two different methods of parsing netlink messages.
+It offers a low level interface for applications which want to do all
+the parsing manually. This method is described below. Alternatively
+the library also offers an interface to implement a parser as part of
+a cache operations set which is especially useful when your protocol
+deals with objects of any sort such as network links, routes, etc.
+This high level interface is described in <<core_cache>>.
+
+.Splitting a byte stream into separate messages
+
+What you receive from a netlink socket is typically a stream of
+messages. You will be given a buffer and its length, the buffer may
+contain any number of netlink messages.
+
+The first message header starts at the beginning of message stream.
+Any subsequent message headers are access by calling nlmsg_next() on
+the previous header.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlmsghdr *nlmsg_next(struct nlmsghdr *hdr, int *remaining);
+--------
+
+The function nlmsg_next() will automatically substract the size of the
+previous message from the remaining number of bytes.
+
+Please note, there is no indication in the previous message whether
+another message follows or not. You must assume that more messages
+follow until all bytes of the message stream have been processed.
+
+To simplify this, the function nlmsg_ok() exists which returns true if
+another message fits into the remaining number of bytes in the message
+stream. nlmsg_valid_hdr() is similar, it checks whether a specific
+netlink message contains at least a minimum of payload.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+int nlmsg_valid_hdr(const struct nlmsghdr *hdr, int payloadlen);
+int nlmsg_ok(const struct nlmsghdr *hdr, int remaining);
+--------
+
+A typical use of these functions looks like this:
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+void my_parse(void *stream, int length)
+{
+ struct nlmsghdr *hdr = stream;
+
+ while (nlmsg_ok(hdr, length)) {
+ // Parse message here
+ hdr = nlmsg_next(hdr, &length);
+ }
+}
+--------
+
+CAUTION: nlmsg_ok() only returns true if the *complete* message including
+ the message payload fits into the remaining buffer length. It will
+ return false if only a part of it fits.
+
+The above can also be written using the iterator nlmsg_for_each():
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlmsghdr *hdr;
+
+nlmsg_for_each(hdr, stream, length) {
+ /* do something with message */
+}
+--------
+
+.Message Payload
+
+The message payload is appended to the message header and is guranteed
+to start at a multiple of +NLMSG_ALIGNTO+. Padding at the end of the
+message header is added if necessary to ensure this. The function
+nlmsg_data() will calculate the necessary offset based on the message
+and returns a pointer to the start of the message payload.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+void *nlmsg_data(const struct nlmsghdr *nlh);
+void *nlmsg_tail(const struct nlmsghdr *nlh);
+int nlmsg_datalen(const struct nlmsghdr *nlh);
+--------
+
+The length of the message payload is returned by nlmsg_datalen().
+
+[source,c]
+--------
+ <--- nlmsg_datalen(nlh) --->
+ +-------------------+- - -+----------------------------+- - -+
+ | struct nlmsghdr | Pad | Payload | Pad |
+ +-------------------+- - -+----------------------------+- - -+
+nlmsg_data(nlh) ---------------^ ^
+nlmsg_tail(nlh) --------------------------------------------------^
+--------
+
+The payload may consist of arbitary data but may have strict alignment
+and formatting rules depening on the actual netlink protocol.
+
+[[core_msg_attr]]
+.Message Attributes
+
+Most netlink protocols use netlink attributes. It not only makes the
+protocol self documenting but also gives flexibility in expanding the
+protocol at a later point. New attributes can be added at any time and
+older attributes can be obsoleted by newer ones without breaking
+binary compatibility of the protocol.
+
+[source,c]
+--------
+ <---------------------- payload ------------------------->
+ <----- hdrlen ----> <- nlmsg_attrlen(nlh, hdrlen) ->
+ +-------------------+- - -+----- ------------+- - -+--------------------------------+- - -+
+ | struct nlmsghdr | Pad | Protocol Header | Pad | Attributes | Pad |
+ +-------------------+- - -+-------------------+- - -+--------------------------------+- - -+
+nlmsg_attrdata(nlh, hdrlen) -----------------------------^
+--------
+
+The function nlmsg_attrdata() returns a pointer to the begin of the
+attributes section. The length of the attributes section is returned
+by the function nlmsg_attrlen().
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlattr *nlmsg_attrdata(const struct nlmsghdr *hdr, int hdrlen);
+int nlmsg_attrlen(const struct nlmsghdr *hdr, int hdrlen);
+--------
+
+See <<core_attr>> for more information on how to use netlink attributes.
+
+.Parsing a Message the Easy Way
+
+The function nlmsg_parse() validate a complete netlink message in one
+step. If +hdrlen > 0+ it will first call nlmsg_valid_hdr() to check
+if the protocol header fits into the message. If there is more payload
+to parse, it will assume it to be attributes and parse the payload
+accordingly. The function behaves exactly like nla_parse() when
+parsing attributes, see <<core_attr_parse_easy>>.
+
+[source,c]
+--------
+int nlmsg_parse(struct nlmsghdr *hdr, int hdrlen, struct nlattr **attrs,
+ int maxtype, struct nla_policy *policy);
+--------
+
+The function nlmsg_validate() is based on nla_validate() and behaves
+exactly the same as nlmsg_parse() except that it only validates and
+will not fill a array with pointers to each attribute.
+
+[source,c]
+--------
+int nlmsg_validate(struct nlmsghdr *hdr, int hdrlen, intmaxtype,
+ struct nla_policy *policy);
+--------
+
+See <<core_attr_parse_easy>> for an example and more information on
+attribute parsing.
+
+=== Construction of a Message
+
+See <<core_msg_format>> for information on the netlink message format
+and alignment requirements.
+
+Message construction is based on struct nl_msg which uses an internal
+buffer to store the actual netlink message. struct nl_msg +does not+
+point to the netlink message header. Use nlmsg_hdr() to retrieve a
+pointer to the netlink message header.
+
+At allocation time, a maximum message size is specified. It defaults
+to a page (PAGE_SIZE). The application constructing the message will
+reserve space out of this maximum message size repeatedly for each
+header or attribute added. This allows construction of messages across
+various layers of code where lower layers do not need to know about
+the space requirements of upper layers.
+
++Why is setting the maximum message size necessary?+ This
+question is often raised in combination with the proposed solution of
+reallocating the message payload buffer on the fly using realloc().
+While it is possible to reallocate the buffer during construction
+using nlmsg_expand() it will make all pointers into the message buffer
+become stale. This breaks usage of nlmsg_hdr(), nla_nest_start(), and
+nla_nest_end() and is therefore not acceptable as default behaviour.
+
+.Allocating struct nl_msg
+
+The first step in constructing a new netlink message it to allocate a
+`struct nl_msg` to hold the message header and payload. Several
+functions exist to simplify various tasks.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nl_msg *nlmsg_alloc(void);
+void nlmsg_free(struct nl_msg *msg);
+--------
+
+The function nlmsg_alloc() is the default message allocation function.
+It allocates a new message using the default maximum message size which
+equals to one page (PAGE_SIZE). The application can change the default
+size for messages by calling nlmsg_set_default_size():
+
+[source,c]
+--------
+void nlmsg_set_default_size(size_t);
+--------
+
+CAUTION: Calling nlmsg_set_default_size() does not change the maximum
+ message size of already allocated messages.
+
+[source,c]
+--------
+struct nl_msg *nlmsg_alloc_size(size_t max);
+--------
+
+Instead of changing the default message size, the function
+nlmsg_alloc_size() can be used to allocate a message with a individual
+maximum message size.
+
+
+If the netlink message header is already known at allocation time, the
+application may sue nlmsg_inherit(). It will allocate a message using
+the default maximum message size and copy the header into the message.
+Calling nlmsg_inherit with +set+ to NULL is equivalent to calling
+nlmsg_alloc().
+
+[source,c]
+--------
+struct nl_msg *nlmsg_inherit(struct nlmsghdr *hdr);
+--------
+
+Alternatively nlmsg_alloc_simple() takes a netlink message type and
+netlink message flags. It is equivalent to nlmsg_inherit() except that it
+takes the two common header fields as arguments instead of a complete
+header.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nl_msg *nlmsg_alloc_simple(int nlmsg_type, int flags);
+--------
+
+.Appending the netlink message header
+
+After allocating struct nl_msg, the netlink message header needs to be
+added unless one of the function nlmsg_alloc_simple() or nlmsg_inherit()
+have been used for allocation in which case this step will replace the
+netlink message header already in place.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlmsghdr *nlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seqnr,
+ int nlmsg_type, int payload, int nlmsg_flags);
+--------
+
+The function nlmsg_put() will build a netlink message header out of
++nlmsg_type+, +nlmsg_flags+, +seqnr+, and +port+ and copy it into the
+netlink message. +seqnr+ can be set to +NL_AUTO_SEQ+ to indiciate
+that the next possible sequence number should be used automatically.
+To use this feature, the message must be sent using the function
+nl_send_auto(). Like +port+, the argument +seqnr+ can be set to
++NL_AUTO_PORT+ indicating that the local port assigned to the socket
+should be used as source port. This is generally a good idea unless
+you are replying to a request. See <<core_netlink_fundamentals>>
+for more information on how to fill the header.
+
+NOTE: The argument +payload+ can be used by the application to reserve
+ room for additional data after the header. A value of > 0 is
+ equivalent to calling +nlmsg_reserve(msg, payload, NLMSG_ALIGNTO)+.
+ See <<core_msg_reserve>> for more information on reserving room for
+ data.
+
+.Example
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlmsghdr *hdr;
+struct nl_msg *msg;
+struct myhdr {
+ uint32_t foo1, foo2;
+} hdr = { 10, 20 };
+
+/* Allocate a message with the default maximum message size */
+msg = nlmsg_alloc();
+
+/*
+ * Add header with message type MY_MSGTYPE, the flag NLM_F_CREATE,
+ * let library fill port and sequence number, and reserve room for
+ * struct myhdr
+ */
+hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, MY_MSGTYPE, sizeof(hdr), NLM_F_CREATE);
+
+/* Copy own header into newly reserved payload section */
+memcpy(nlmsg_data(hdr), &hdr, sizeof(hdr));
+
+/*
+ * The message will now look like this:
+ * +-------------------+- - -+----------------+- - -+
+ * | struct nlmsghdr | Pad | struct myhdr | Pad |
+ * +-------------------+-----+----------------+- - -+
+ * nlh -^ / \
+ * +--------+---------+
+ * | foo1 | foo2 |
+ * +--------+---------+
+ */
+--------
+
+[[core_msg_reserve]]
+.Reserving room at the end of the message
+
+Most functions described later on will automatically take care of
+reserving room for the data that is added to the end of the netlink
+message. In some situations it may be requried for the application
+to reserve room directly though.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+void *nlmsg_reserve(struct nl_msg *msg, size_t len, int pad);
+--------
+
+The function nlmsg_reserve() reserves +len+ bytes at the end of the
+netlink message and returns a pointer to the start of the reserved area.
+The +pad+ argument can be used to request +len+ to be aligned to any
+number of bytes prior to reservation.
+
+The following example requests to reserve a 17 bytes area at the end of
+message aligned to 4 bytes. Therefore a total of 20 bytes will be
+reserved.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+void *buf = nlmsg_reserve(msg, 17, 4);
+--------
+
+NOTE: `nlmsg_reserve()` will *not* align the start of the buffer. Any
+ alignment requirements must be provided by the owner of the
+ previous message section.
+
+.Appending data at the end of the message
+
+The function `nlmsg_append()` appends `len` bytes at the end of the
+message, padding it if requested and necessary.
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+int nlmsg_append(struct nl_msg *msg, void *data, size_t len, int pad);
+--------
+
+It is equivalent to calling `nlmsg_reserve()` and `memcpy()`ing the
+data into the freshly reserved data section.
+
+NOTE: `nlmsg_append()` will *not* align the start of the data. Any
+ alignment requirements must be provided by the owner of the
+ previous message section.
+
+.Adding attribtues to a message
+
+Construction of attributes and addition of attribtues to the message is
+covereted in section <<core_attr>>.
+
+[[core_attr]]
+== Attributes
+
+Any form of payload should be encoded as netlink attributes whenever
+possible. Use of attributes allows to extend any netlink protocol in
+the future without breaking binary compatibility. F.e. Suppose your
+device may currently be using 32 bit counters for statistics but years
+later the device switches to maintaining 64 bit counters to account
+for faster network hardware. If your protocol is using attributes the
+move to 64 bit counters is trivial and only involves in sending an
+additional attribute containing the 64 bit variants while still
+providing the old legacy 32 bit counters. If your protocol is not using
+attributes you will not be able to switch data types without breaking
+all existing users of the protocol.
+
+The concept of nested attributes also allows for subsystems of your
+protocol to implement and maintain their own attribute schemas. Suppose
+a new generation of network device is introduced which requires a
+completely new set of configuration settings which was unthinkable when
+the netlink protocol was initially designed. Using attributes the new
+generation of devices may define a new attribute and fill it with its
+own new structure of attributes which extend or even obsolete the old
+attributes.
+
+Therefore, _always_ use attributes even if you are almost certain that
+the message format will never ever change in the future.
+
+[[core_attr_format]]
+=== Attribute Format
+
+Netlink attributes allow for any number of data chunks of arbitary
+length to be attached to a netlink message. See <<core_msg_attr>>
+for more information on where attributes are stored in the message.
+
+The format of the attributes data returned by nlmsg_attrdata() is as
+follows:
+
+[source,c]
+--------
+ <----------- nla_total_size(payload) ----------->
+ <---------- nla_size(payload) ----------->
+ +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - -
+ | struct nlattr | Pad | Payload | Pad | struct nlattr |
+ +-----------------+- - -+- - - - - - - - - +- - -+-----------------+- - -
+ <---- NLA_HDRLEN -----> <--- NLA_ALIGN(len) ---> <---- NLA_HDRLEN ---
+--------
+
+Every attribute must start at an offset which is a multiple of
++NLA_ALIGNTO+ (4 bytes). If you need to know whether an attribute needs
+to be padded at the end, the function nla_padlen() returns the number
+of padding bytes that will or need to be added.
+
+image:attribute_hdr.png["Netlink Attribute Header"]
+
+Every attribute is encoded with a type and length field, both 16 bits,
+stored in the attribute header (struct nlattr) preceding the attribute
+payload. The length of an attribute is used to calculate the offset to
+the next attribute.
+
+[[core_attr_parse]]
+=== Parsing Attributes
+
+[[core_attr_parse_split]]
+.Splitting an Attributes Stream into Attributes
+
+Although most applications will use one of the functions from the
+nlmsg_parse() family (See <<core_attr_parse_easy>>) an interface exists
+to split the attributes stream manually.
+
+As described in <<core_attr_format>> the attributes section contains a
+infinite sequence or stream of attributes. The pointer returned by
+nlmsg_attrdata() (See <<core_msg_attr>>) points to the first attribute
+header. Any subsequent attribute is accessed with the function nla_next()
+based on the previous header.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+struct nlattr *nla_next(const struct nlattr *attr, int *remaining);
+--------
+
+The semantics are equivalent to nlmsg_next() and thus nla_next() will also
+subtract the size of the previous attribute from the remaining number of
+bytes in the attributes stream.
+
+Like messages, attributes do not contain an indicator whether another
+attribute follows or not. The only indication is the number of bytes left
+in the attribute stream. The function nla_ok() exists to determine whether
+another attribute fits into the remaining number of bytes or not.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+int nla_ok(const struct nlattr *attr, int remaining);
+--------
+
+A typical use of nla_ok() and nla_next() looks like this:
+
+.nla_ok()/nla_next() usage
+[source,c]
+--------
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+struct nlattr *hdr = nlmsg_attrdata(msg, 0);
+int remaining = nlmsg_attrlen(msg, 0);
+
+while (nla_ok(hdr, remaining)) {
+ /* parse attribute here */
+ hdr = nla_next(hdr, &remaining);
+};
+--------
+
+NOTE: `nla_ok()` only returns true if the *complete* attributes
+ including the attribute payload fits into the remaining number
+ of bytes.
+
+.Accessing Attribute Header and Payload
+
+Once the individual attributes have been sorted out by either splitting
+the attributes stream or using another interface the attribute header
+and payload can be accessed.
+
+[source,c]
+--------
+ <- nla_len(hdr) ->
+ +-----------------+- - -+- - - - - - - - - +- - -+
+ | struct nlattr | Pad | Payload | Pad |
+ +-----------------+- - -+- - - - - - - - - +- - -+
+nla_data(hdr) ---------------^
+--------
+
+The functions nla_len() and nla_type() can be used to access the attribute
+header. nla_len() will return the length of the payload not including
+eventual padding bytes. nla_type returns the attribute type.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+int nla_len(const struct nlattr *hdr);
+int nla_type(const struct nlattr *hdr);
+--------
+
+The function nla_data() will return a pointer to the attribute
+payload. Please note that due to +NLA_ALIGNTO+ being 4 bytes it may
+not be safe to cast and dereference the pointer for any datatype
+larger than 32 bit depending on the architecture the application is
+run on.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+void *nla_data(const struct nlattr *hdr);
+--------
+
+[NOTE]
+Never rely on the size of a payload being what you expect it to be.
+_Always_ verify the payload size and make sure that it matches your
+expectations. See <<core_attr_validation>>
+
+[[core_attr_validation]]
+.Attribute Validation
+
+When receiving netlink attributes, the receiver has certain expections
+on how the attributes should look like. These expectations must be
+defined to make sure the sending side meets our expecations. For this
+purpose, a attribute validation interface exists which must be used
+prior to accessing any payload.
+
+All functions providing attribute validation functionality are based
+on struct nla_policy:
+
+[source,c]
+--------
+struct nla_policy {
+ uint16_t type;
+ uint16_t minlen;
+ uint16_t maxlen;
+};
+--------
+
+The +type+ member specifies the datatype of the attribute, e.g.
++NLA_U32+, +NLA_STRING+, +NLA_FLAG+. The default is +NLA_UNSPEC+. The
++minlen+ member defines the minmum payload length of an attribute to
+be considered a valid attribute. The value for +minlen+ is implicit
+for most basic datatypes such as integers or flags. The +maxlen+
+member can be used to define a maximum payload length for an
+attribute to still be considered valid.
+
+NOTE: Specyfing a maximum payload length is not recommended when
+ encoding structures in an attribute as it will prevent any
+ extension of the structure in the future. Something that is
+ frequently done in netlink protocols and does not break
+ backwards compatibility.
+
+One of the functions which use struct nla_policy is nla_validate().
+The function expects an array of struct nla_policy and will access the
+array using the attribute type as index. If an attribute type is out
+of bounds the attribute is assumed to be valid. This is intentional
+behaviour to allow older applications not yet aware of recently
+introduced attributes to continue functioning.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+int nla_validate(struct nlattr *head, int len, int maxtype, struct nla_policy *policy);
+--------
+
+The function nla_validate() returns 0 if all attributes are valid,
+otherwise a validation failure specific error code is returned.
+
+Most applications will rarely use nla_validate() directly but use
+nla_parse() instead which takes care of validation in the same way but
+also parses the the attributes in the same step. See
+<<core_attr_parse_easy>> for an example and more information.
+
+The validation process in detail:
+
+. If attribute type is 0 or exceeds +maxtype+ attribute is
+ considered valid, 0 is returned.
+. If payload length is < +minlen+, +-NLE_ERANGE+ is returned.
+. If +maxlen+ is defined and payload exceeds it, +-NLE_ERANGE+
+ is returned.
+. Datatype specific requirements rules, see <<core_attr_types>>
+. If all is ok, 0 is returned.
+
+[[core_attr_parse_easy]]
+.Parsing Attributes the Easy Way
+
+Most applications will not want to deal with splitting attribute
+streams themselves as described in <<core_attr_parse_split>>
+A much easier method is to use nla_parse().
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+int nla_parse(struct nlattr **attrs, int maxtype, struct nlattr *head,
+ int len, struct nla_policy *policy);
+--------
+
+The function nla_parse() will iterate over a stream of attributes,
+validate each attribute as described in <<core_attr_validation>>
+If the validation of all attributes succeeds, a pointer to each attribute
+is stored in the +attrs+ array at `attrs[nla_type(attr)]`.
+
+As an alernative to nla_parse() the function nlmsg_parse() can be used
+to parse the message and its attributes in one step. See
+<<core_attr_parse_easy>> for information on how to use these functions.
+
+.Example:
+
+The following example demonstrates how to parse a netlink message sent
+over a netlink protocol which does not use protocol headers. The example
+does enforce a attribute policy however, the attribute MY_ATTR_FOO must
+be a 32 bit integer, and the attribute MY_ATTR_BAR must be a string with
+a maximum length of 16 characters.
+
+[source,c]
+---------
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+enum {
+ MY_ATTR_FOO = 1,
+ MY_ATTR_BAR,
+ __MY_ATTR_MAX,
+};
+
+#define MY_ATTR_MAX (__MY_ATTR_MAX - 1)
+
+static struct nla_policy my_policy[MY_ATTR_MAX+1] = {
+ [MY_ATTR_FOO] = { .type = NLA_U32 },
+ [MY_ATTR_BAR] = { .type = NLA_STRING,
+ .maxlen = 16 },
+};
+
+void parse_msg(struct nlmsghdr *nlh)
+{
+ struct nlattr *attrs[MY_ATTR_MAX+1];
+
+ if (nlmsg_parse(nlh, 0, attrs, MY_ATTR_MAX, my_policy) < 0)
+ /* error */
+
+ if (attrs[MY_ATTR_FOO]) {
+ /* MY_ATTR_FOO is present in message */
+ printf("value: %u\n", nla_get_u32(attrs[MY_ATTR_FOO]));
+ }
+}
+---------
+
+.Locating a Single Attribute
+
+An application only interested in a single attribute can use one of the
+functions nla_find() or nlmsg_find_attr(). These function will iterate
+over all attributes, search for a matching attribute and return a pointer
+to the corresponding attribute header.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+struct nlattr *nla_find(struct nlattr *head, int len, int attrtype);
+--------
+
+[source,c]
+--------
+#include <netlink/msg.h>
+
+struct nlattr *nlmsg_find_attr(struct nlmsghdr *hdr, int hdrlen, int attrtype);
+--------
+
+NOTE: `nla_find()` and `nlmsg_find_attr()` will *not* search in nested
+ attributes recursively, see <<core_attr_nested>>.
+
+==== Iterating over a Stream of Attributes
+
+In some situations it does not make sense to assign a unique attribute
+type to each attribute in the attribute stream. For example a list may
+be transferd using a stream of attributes and even if the attribute type
+is incremented for each attribute it may not make sense to use the
+nlmsg_parse() or nla_parse() function to fill an array.
+
+Therefore methods exist to iterate over a stream of attributes:
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+nla_for_each_attr(attr, head, len, remaining)
+--------
+
+nla_for_each_attr() is a macro which can be used in front of a code
+block:
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+struct nalttr *nla;
+int rem;
+
+nla_for_each_attr(nla, attrstream, streamlen, rem) {
+ /* validate & parse attribute */
+}
+
+if (rem > 0)
+ /* unparsed attribute data */
+--------
+
+[[core_attr_constr]]
+=== Attribute Construction
+
+The interface to add attributes to a netlink message is based on the
+regular message construction interface. It assumes that the message
+header and an eventual protocol header has been added to the message
+already.
+
+[source,c]
+--------
+struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int len);
+--------
+
+The function nla_reserve() adds an attribute header at the end of the
+message and reserves room for +len+ bytes of payload. The function
+returns a pointer to the attribute payload section inside the message.
+Padding is added at the end of the attribute to ensure the next
+attribute is properly aligned.
+
+[source,c]
+--------
+int nla_put(struct nl_msg *msg, int attrtype, int attrlen, const void *data);
+--------
+
+The function nla_put() is base don nla_reserve() but takes an additional
+pointer +data+ pointing to a buffer containing the attribute payload.
+It will copy the buffer into the message automatically.
+
+.Example:
+
+[source,c]
+--------
+struct my_attr_struct {
+ uint32_t a;
+ uint32_t b;
+};
+
+int my_put(struct nl_msg *msg)
+{
+ struct my_attr_struct obj = {
+ .a = 10,
+ .b = 20,
+ };
+
+ return nla_put(msg, ATTR_MY_STRUCT, sizeof(obj), &obj);
+}
+--------
+
+See <<core_attr_types>> for datatype specific attribute construction
+functions.
+
+.Exception Based Attribute Construction
+
+Like in the kernel API an exception based construction interface is
+provided. The behaviour of the macros is identical to their regular
+function counterparts except that in case of an error, the target
+`nla_put_failure` is jumped.
+
+.Example:
+[source,c]
+--------
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+void construct_attrs(struct nl_msg *msg)
+{
+ NLA_PUT_STRING(msg, MY_ATTR_FOO1, "some text");
+ NLA_PUT_U32(msg, MY_ATTR_FOO1, 0x1010);
+ NLA_PUT_FLAG(msg, MY_ATTR_FOO3, 1);
+
+ return 0;
+
+nla_put_failure:
+ /* NLA_PUT* macros jump here in case of an error */
+ return -EMSGSIZE;
+}
+--------
+
+See <<core_attr_types>> for more information on the datatype specific
+exception based variants.
+
+[[core_attr_types]]
+=== Attribute Data Types
+
+A number of basic data types have been defined to simplify access and
+validation of attributes. The datatype is not encoded in the
+attribute, therefore bthe sender and receiver are required to use the
+same definition on what attribute is of what type.
+
+[options="header", cols="1m,5"]
+|================================================
+| Type | Description
+| NLA_UNSPEC | Unspecified attribute
+| NLA_U{8\|16\|32} | Integers
+| NLA_STRING | String
+| NLA_FLAG | Flag
+| NLA_NESTED | Nested attribute
+|================================================
+
+Besides simplified access to the payload of such datatypes, the major
+advantage is the automatic validation of each attribute based on a
+policy. The validation ensures safe access to the payload by checking
+for minimal payload size and can also be used to enforce maximum
+payload size for some datatypes.
+
+==== Integer Attributes
+
+The most frequently used datatypes are integers. Integers come in four
+different sizes:
+[horizontal]
+NLA_U8:: 8bit integer
+NLA_U16:: 16bit integer
+NLA_U32:: 32bit integer
+NLA_U64:: 64bit integer
+
+Note that due to the alignment requirements of attributes the integer
+attribtue +NLA_u8+ and +NLA_U16+ will not result in space savings in
+the netlink message. Their use is intended to limit the range of
+values.
+
+.Parsing Integer Attributes
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+uint8_t nla_get_u8(struct nlattr *hdr);
+uint16_t nla_get_u16(struct nlattr *hdr);
+uint32_t nla_get_u32(struct nlattr *hdr);
+uint64_t nla_get_u64(struct nlattr *hdr);
+--------
+
+Example:
+
+[source,c]
+--------
+if (attrs[MY_ATTR_FOO])
+ uint32_t val = nla_get_u32(attrs[MY_ATTR_FOO]);
+--------
+
+.Constructing Integer Attributes
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+int nla_put_u8(struct nl_msg *msg, int attrtype, uint8_t value);
+int nla_put_u16(struct nl_msg *msg, int attrtype, uint16_t value);
+int nla_put_u32(struct nl_msg *msg, int attrtype, uint32_t value);
+int nla_put_u64(struct nl_msg *msg, int attrtype, uint64_t value);
+--------
+
+Exception based:
+
+[source,c]
+--------
+NLA_PUT_U8(msg, attrtype, value)
+NLA_PUT_U16(msg, attrtype, value)
+NLA_PUT_U32(msg, attrtype, value)
+NLA_PUT_U64(msg, attrtype, value)
+--------
+
+.Validation
+
+Use +NLA_U8+, +NLA_U16+, +NLA_U32+, or +NLA_U64+ to define the type of
+integer when filling out a struct nla_policy array. It will
+automatically enforce the correct minimum payload length policy.
+
+Validation does not differ between signed and unsigned integers, only
+the size matters. If the appliaction wishes to enforce particular value
+ranges it must do so itself.
+
+[source,c]
+--------
+static struct nla_policy my_policy[ATTR_MAX+1] = {
+ [ATTR_FOO] = { .type = NLA_U32 },
+ [ATTR_BAR] = { .type = NLA_U8 },
+};
+--------
+
+The above is equivalent to:
+[source,c]
+--------
+static struct nla_policy my_policy[ATTR_MAX+1] = {
+ [ATTR_FOO] = { .minlen = sizeof(uint32_t) },
+ [ATTR_BAR] = { .minlen = sizeof(uint8_t) },
+};
+--------
+
+==== String Attributes
+
+The string datatype represents a NUL termianted character string of
+variable length. It is not intended for binary data streams.
+
+The payload of string attributes can be accessed with the function
+nla_get_string(). nla_strdup() calls strdup() on the payload and returns
+the newly allocated string.
+
+[source,c]
+--------
+#include <netlink/attr.h>
+
+char *nla_get_string(struct nlattr *hdr);
+char *nla_strdup(struct nlattr *hdr);
+--------
+
+String attributes are constructed with the function +nla_put_string()+
+respectively +NLA_PUT_STRING()+. The length of the payload will be
+strlen()+1, the trailing NUL byte is included.
+
+[source,c]
+--------
+int nla_put_string(struct nl_msg *msg, int attrtype, const char *data);
+
+NLA_PUT_STRING(msg, attrtype, data)
+--------
+
+For validation purposes the type +NLA_STRING+ can be used in
++struct nla_policy+ definitions. It implies a minimum payload length
+of 1 byte and checks for a trailing NUL byte. Optionally the +maxlen+
+member defines the maximum length of a character string (including the
+trailing NUL byte).
+
+[source,c]
+--------
+static struct nla_policy my_policy[] = {
+ [ATTR_FOO] = { .type = NLA_STRING,
+ .maxlen = IFNAMSIZ },
+};
+--------
+
+==== Flag Attributes
+
+The flag attribute represents a boolean datatype. The presence of the
+attribute implies a value of +true+, the absence of the attribute
+implies the value +false+. Therefore the payload length of flag
+attributes is always 0.
+
+[source,c]
+--------
+int nla_get_flag(struct nlattr *hdr);
+int nla_put_flag(struct nl_msg *msg, int attrtype);
+--------
+
+The type +NLA_FLAG+ is used for validation purposes. It implies a
++maxlen+ value of 0 and thus enforces a maximum payload length of 0.
+
+.Example:
+[source,c]
+--------
+/* nla_put_flag() appends a zero sized attribute to the message. */
+nla_put_flag(msg, ATTR_FLAG);
+
+/* There is no need for a receival function, the presence is the value. */
+if (attrs[ATTR_FLAG])
+ /* flag is present */
+--------
+
+[[core_attr_nested]]
+==== Nested Attributes
+
+As described in <<core_attr>>, attributes can be nested allowing for
+complex tree structures of attributes. It is commonly used to delegate
+the responsibility of a subsection of the message to a subsystem.
+Nested attributes are also commonly used for transmitting list of objects.
+
+When nesting attributes, the nested attributes are included as payload
+of a container attribute.
+
+NOTE: When validating the attributes using nlmsg_validate(),
+ nlmsg_parse(), nla_validate(), or nla_parse() only the
+ attributes on the first level are being validated. None of these
+ functions will validate attributes recursively. Therefore you
+ must explicitely call nla_validate() or use nla_parse_nested()
+ for each level of nested attributes.
+
+The type +NLA_NESTED+ should be used when defining nested attributes
+in a struct nla_policy definition. It will not enforce any minimum
+payload length unless +minlen+ is specified explicitely. This is
+because some netlink protocols implicitely allow empty container
+attributes.
+
+[source,c]
+--------
+static struct nla_policy my_policy[] = {
+ [ATTR_OPTS] = { .type = NLA_NESTED },
+};
+--------
+
+.Parsing of Nested Attributes
+
+The function nla_parse_nested() is used to parse nested attributes.
+Its behaviour is identical to nla_parse() except that it takes a
+struct nlattr as argument and will use the payload as stream of
+attributes.
+
+[source,c]
+--------
+if (attrs[ATTR_OPTS]) {
+ struct nlattr *nested[NESTED_MAX+1];
+ struct nla_policy nested_policy[] = {
+ [NESTED_FOO] = { .type = NLA_U32 },
+ };
+
+ if (nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_OPTS], nested_policy) < 0)
+ /* error */
+
+ if (nested[NESTED_FOO])
+ uint32_t val = nla_get_u32(nested[NESTED_FOO]);
+}
+--------
+
+.Construction of Nested Attributes
+
+Attributes are nested by surrounding them with calls to nla_nest_start()
+and nla_nest_end(). nla_nest_start() will add a attribute header to
+the message but no actual payload. All data added to the message from
+this point on will be part of the container attribute until nla_nest_end()
+is called which "closes" the attribute, correcting its payload length to
+include all data length.
+
+[source,c]
+--------
+int put_opts(struct nl_msg *msg)
+{
+ struct nlattr *opts;
+
+ if (!(opts = nla_nest_start(msg, ATTR_OPTS)))
+ goto nla_put_failure;
+
+ NLA_PUT_U32(msg, NESTED_FOO, 123);
+ NLA_PUT_STRING(msg, NESTED_BAR, "some text");
+
+ nla_nest_end(msg, opts);
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(msg, opts);
+ return -EMSGSIZE;
+}
+--------
+
+==== Unspecified Attribute
+
+This is the default attribute type and used when none of the basic
+datatypes is suitable. It represents data of arbitary type and length.
+
+See <<core_addr_alloc, Address Allocation>> for a more information on
+a special interface allowing the allocation of abstract address object
+based on netlink attributes which carry some form of network address.
+
+See <<core_data_alloc, Abstract Data Allocation>> for more information
+on how to allocate abstract data objects based on netlink attributes.
+
+Use the function nla_get() and nla_put() to access the payload and
+construct attributes. See <<core_attr_constr, Attribute Construction>>
+for an example.
+
+=== Examples
+
+==== Constructing a Netlink Message with Attributes
+
+[source,c]
+--------
+struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu)
+{
+ struct nl_msg *msg;
+ struct nlattr *info, *vlan;
+ struct ifinfomsg ifi = {
+ .ifi_family = AF_INET,
+ .ifi_index = ifindex,
+ };
+
+ /* Allocate a default sized netlink message */
+ if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, 0)))
+ return NULL;
+
+ /* Append the protocol specific header (struct ifinfomsg)*/
+ if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
+ goto nla_put_failure
+
+ /* Append a 32 bit integer attribute to carry the MTU */
+ NLA_PUT_U32(msg, IFLA_MTU, mtu);
+
+ /* Append a unspecific attribute to carry the link layer address */
+ NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr);
+
+ /* Append a container for nested attributes to carry link information */
+ if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
+ goto nla_put_failure;
+
+ /* Put a string attribute into the container */
+ NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan");
+
+ /*
+ * Append another container inside the open container to carry
+ * vlan specific attributes
+ */
+ if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA)))
+ goto nla_put_failure;
+
+ /* add vlan specific info attributes here... */
+
+ /* Finish nesting the vlan attributes and close the second container. */
+ nla_nest_end(msg, vlan);
+
+ /* Finish nesting the link info attribute and close the first container. */
+ nla_nest_end(msg, info);
+
+ return msg;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NULL;
+}
+------
+
+==== Parsing a Netlink Message with Attributes
+
+[source,c]
+--------
+int parse_message(struct nlmsghdr *hdr)
+{
+ /*
+ * The policy defines two attributes: a 32 bit integer and a container
+ * for nested attributes.
+ */
+ struct nla_policy attr_policy[] = {
+ [ATTR_FOO] = { .type = NLA_U32 },
+ [ATTR_BAR] = { .type = NLA_NESTED },
+ };
+ struct nlattr *attrs[ATTR_MAX+1];
+ int err;
+
+ /*
+ * The nlmsg_parse() function will make sure that the message contains
+ * enough payload to hold the header (struct my_hdr), validates any
+ * attributes attached to the messages and stores a pointer to each
+ * attribute in the attrs[] array accessable by attribute type.
+ */
+ if ((err = nlmsg_parse(hdr, sizeof(struct my_hdr), attrs, ATTR_MAX,
+ attr_policy)) < 0)
+ goto errout;
+
+ if (attrs[ATTR_FOO]) {
+ /*
+ * It is safe to directly access the attribute payload without
+ * any further checks since nlmsg_parse() enforced the policy.
+ */
+ uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
+ }
+
+ if (attrs[ATTR_BAR]) {
+ struct *nested[NESTED_MAX+1];
+
+ /*
+ * Attributes nested in a container can be parsed the same way
+ * as top level attributes.
+ */
+ err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR],
+ nested_policy);
+ if (err < 0)
+ goto errout;
+
+ // Process nested attributes here.
+ }
+
+ err = 0;
+errout:
+ return err;
+}
+--------
+
+[[core_cb]]
+== Callback Configurations
+
+Callback hooks and overwriting capabilities are provided in various places
+inside library to control the behaviour of several functions. All the
+callback and overwrite functions are packed together in struct nl_cb which
+is attached to a netlink socket or passed on to functions directly.
+
+=== Callback Hooks
+
+Callback hooks are spread across the library to provide entry points for
+message processing and to take action upon certain events.
+
+Callback functions may return the following return codes:
+[options="header", cols="1m,4"]
+|========================================================================
+| Return Code | Description
+| NL_OK | Proceed.
+| NL_SKIP | Skip message currently being processed and continue
+ parsing the receive buffer.
+| NL_STOP | Stop parsing and discard all remaining data in the
+ receive buffer.
+|========================================================================
+
+.Default Callback Implementations
+
+The library provides three sets of default callback implementations:
+* +NL_CB_DEFAULT+ This is the default set. It implets the default behaviour.
+ See the table below for more information on the return codes of each
+ function.
+* +NL_CB_VERBOSE+ This set is based on the default set but will cause an
+ error message to be printed to stderr for error messages, invalid
+ messages, message overruns and unhandled valid messages. The
+ +arg+ pointer in nl_cb_set() and nl_cb_err() can be used to
+ provide a FILE * which overwrites stderr.
+* +NL_CB_DEBUG+ This set is intended for debugging purposes. It is
+ based on the verbose set but will decode and dump each message sent
+ or received to the console.
+
+.Message Processing Callbacks
+
+.nl_sendmsg() callback hooks:
+[cols="2m,4e,1m", options="header"]
+|============================================================================
+| Callback ID | Description | Default Return Value
+| NL_CB_MSG_OUT | Each message sent | NL_OK
+|============================================================================
+
+Any function called by NL_CB_MSG_OUT may return a negative error code to
+prevent the message from being sent and the error code being returned.
+
+nl_recvmsgs() callback hooks (ordered by priority):
+[cols="2m,4e,1m", options="header"]
+|============================================================================
+| Callback ID | Description | Default Return Value
+| NL_CB_MSG_IN | Each message received | NL_OK
+| NL_CB_SEQ_CHECK | May overwrite sequence check algo | NL_OK
+| NL_CB_INVALID | Invalid messages | NL_STOP
+| NL_CB_SEND_ACK | Messages with NLM_F_ACK flag set | NL_OK
+| NL_CB_FINISH | Messages of type NLMSG_DONE | NL_STOP
+| NL_CB_SKIPPED | Messages of type NLMSG_NOOP | NL_SKIP
+| NL_CB_OVERRUN | Messages of type NLMSG_OVERRUN | NL_STOP
+| NL_CB_ACK | ACK Messages | NL_STOP
+| NL_CB_VALID | Each valid message | NL_OK
+|============================================================================
+
+Any of these functions may return NL_OK, NL_SKIP, or NL_STOP.
+
+Message processing callback functions are set with nl_cb_set():
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
+ nl_recvmsg_msg_cb_t func, void *arg);
+
+typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
+--------
+
+.Callback for Error Messages
+
+A special function prototype is used for the error message callback hook:
+
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, nl_recvmsg_err_cb_t func, void *arg);
+
+typedef int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg);
+--------
+
+.Example: Setting up a callback set
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+/* Allocate a callback set and initialize it to the verbose default set */
+struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
+
+/* Modify the set to call my_func() for all valid messages */
+nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
+
+/*
+ * Set the error message handler to the verbose default implementation
+ * and direct it to print all errors to the given file descriptor.
+ */
+FILE *file = fopen(...);
+nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);
+--------
+
+=== Overwriting of Internal Functions
+
+When the library needs to send or receive netlink messages in high level
+interfaces it does so by calling its own low level API. In the case the
+default characteristics are not sufficient for the application, it may
+overwrite several internal function calls with own implementations.
+
+.Overwriting recvmsgs()
+
+See <<core_recv, Receiving Netlink Messages>> for more information on
+how and when recvmsgs() is called internally.
+
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
+ int (*func)(struct nl_sock *sk, struct nl_cb *cb));
+--------
+
+The following criteras must be met if a recvmsgs() implementation is
+supposed to work with high level interfaces:
+
+- MUST respect the callback configuration +cb+, therefore:
+ - MUST call +NL_CB_VALID+ for all valid messages, passing on
+ - MUST call +NL_CB_ACK+ for all ACK messages
+ - MUST correctly handle multipart messages, calling NL_CB_VALID for
+ each message until a NLMSG_DONE message is received.
+- MUST report error code if a NLMSG_ERROR or NLMSG_OVERRUN mesasge is
+ received.
+
+.Overwriting nl_recv()
+
+Often it is sufficient to overwrite `nl_recv()` which is responsible
+from receiving the actual data from the socket instead of replacing
+the complete `recvmsgs()` logic.
+
+See <<core_recv_character, Receive Characteristics>> for more
+information on how and when `nl_recv()` is called internally.
+
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+void nl_cb_overwrite_recv(struct nl_cb *cb,
+ int (*func)(struct nl_sock * sk,
+ struct sockaddr_nl *addr,
+ unsigned char **buf,
+ struct ucred **cred));
+--------
+
+The following criteras must be met for an own `nl_recv()`
+implementation:
+
+ - *MUST* return the number of bytes read or a negative error code if
+ an error occured. The function may also return 0 to indicate that
+ no data has been read.
+ - *MUST* set `*buf` to a buffer containing the data read. It must be
+ safe for the caller to access the number of bytes read returned as
+ return code.
+ - *MAY* fill out `*addr` with the netlink address of the peer the
+ data has been received from.
+ - *MAY* set `*cred` to a newly allocated struct ucred containg
+ credentials.
+
+.Overwriting nl_send()
+
+See <<core_send, Sending Netlink Messages>> for more information on
+how and when nl_send() is called internally.
+
+[source,c]
+--------
+#include <netlink/handlers.h>
+
+void nl_cb_overwrite_send(struct nl_cb *cb, int (*func)(struct nl_sock *sk,
+ struct nl_msg *msg));
+--------
+
+Own implementations must send the netlink message and return 0 on success
+or a negative error code.
+
+[[core_cache]]
+== Cache System
+
+=== Allocation of Caches
+
+Almost all subsystem provide a function to allocate a new cache
+of some form. The function usually looks like this:
+[source,c]
+--------
+struct nl_cache *<object name>_alloc_cache(struct nl_sock *sk);
+--------
+
+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.
+
+=== Cache Manager
+
+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.
+
+
+----
+ 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)--------------+
+ | +------------+|
+ | | +------------+| |
+ <-------|---| ... ||
+ | | +------------+| |
+ +-----------------+
+ | |
+----
+
+.Creating a new cache manager
+
+[source,c]
+----
+struct nl_cache_mngr *mngr;
+
+// Allocate a new cache manager for RTNETLINK and automatically
+// provide the caches added to the manager.
+err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
+----
+
+.Keep track of a cache
+
+[source,c]
+----
+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");
+-----
+
+.Make the manager receive updates
+
+[source,c]
+----
+// 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, ...);
+}
+----
+
+.Release cache manager
+
+[source,c]
+----
+nl_cache_mngr_free(mngr);
+----
+
+== Abstract Data Types
+
+A few high level abstract data types which are used by a majority netlink
+protocols are implemented in the core library. More may be added in the
+future if the need arises.
+
+=== Abstract Address
+
+Most netlink protocols deal with networking related topics and thus
+dealing with network addresses is a common task.
+
+Currently the following address families are supported:
+
+[options="compact"]
+ * `AF_INET`
+ * `AF_INET6`
+ * `AF_LLC`
+ * `AF_DECnet`
+ * `AF_UNSPEC`
+
+[[core_addr_alloc]]
+.Address Allocation
+
+The function nl_addr_alloc() allocates a new empty address. The
++maxsize+ argument defines the maximum length of an address in bytes.
+The size of an address is address family specific. If the address
+family and address data are known at allocation time the function
+nl_addr_build() can be used alternatively. You may also clone
+an address by calling nl_addr_clone()
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+struct nl_addr *nl_addr_alloc(size_t maxsize);
+struct nl_addr *nl_addr_clone(struct nl_addr *addr);
+struct nl_addr *nl_addr_build(int family, void *addr, size_t size);
+--------
+
+If the address is transported in a netlink attribute, the function
+nl_addr_alloc_attr() allocates a new address based on the payload
+of the attribute provided. The +family+ argument is used to specify
+the address family of the address, set to +AF_UNSPEC+ if unknown.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+struct nl_addr *nl_addr_alloc_attr(struct nlattr *attr, int family);
+--------
+
+If the address is provided by a user, it is usually stored in a human
+readable format. The function nl_addr_parse() parses a character
+string representing an address and allocates a new address based on
+it.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_parse(const char *addr, int hint, struct nl_addr **result);
+--------
+
+If parsing succeeds the function returns 0 and the allocated address
+is stored in +*result+.
+
+NOTE: Make sure to return the reference to an address using
+ `nl_addr_put()` after usage to allow memory being freed.
+
+.Example: Transform character string to abstract address
+[source,c]
+-----
+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);
+-----
+
+.Address References
+
+Abstract addresses use reference counting to account for all users of
+a particular address. After the last user has returned the reference
+the address is freed.
+
+If you pass on a address object to another function and you are not
+sure how long it will be used, make sure to call nl_addr_get() to
+acquire an additional reference and have that function or code path
+call nl_addr_put() as soon as it has finished using the address.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+struct nl_addr *nl_addr_get(struct nl_addr *addr);
+void nl_addr_put(struct nl_addr *addr);
+int nl_addr_shared(struct nl_addr *addr);
+--------
+
+You may call nl_addr_shared() at any time to check if you are the only
+user of an address.
+
+.Address Attributes
+
+The address is usually set at allocation time. If it was unknown at that
+time it can be specified later by calling nl_addr_set_family() and is
+accessed with the function nl_addr_get_family().
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+void nl_addr_set_family(struct nl_addr *addr, int family);
+int nl_addr_get_family(struct nl_addr *addr);
+--------
+
+The same is true for the actual address data. It is typically present
+at allocation time. For exceptions it can be specified later or
+overwritten with the function `nl_addr_set_binary_addr()`. Beware that
+the length of the address may not exceed `maxlen` specified at
+allocation time. The address data is returned by the function
+`nl_addr_get_binary_addr()` and its length by the function
+`nl_addr_get_len()`.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_set_binary_addr(struct nl_addr *addr, void *data, size_t size);
+void *nl_addr_get_binary_addr(struct nl_addr *addr);
+unsigned int nl_addr_get_len(struct nl_addr *addr);
+--------
+
+If you only want to check if the address data consists of all zeros
+the function `nl_addr_iszero()` is a shortcut to that.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_iszero(struct nl_addr *addr);
+--------
+
+==== Address Prefix Length
+
+Although this functionality is somewhat specific to routing it has
+been implemented here. Addresses can have a prefix length assigned
+which implies that only the first n bits are of importance. This is
+f.e. used to implement subnets.
+
+Use set functions `nl_addr_set_prefixlen()` and
+`nl_addr_get_prefixlen()` to work with prefix lengths.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+void nl_addr_set_prefixlen(struct nl_addr *addr, int n);
+unsigned int nl_addr_get_prefixlen(struct nl_addr *addr);
+--------
+
+NOTE: The default prefix length is set to (address length * 8)
+
+.Address Helpers
+
+Several functions exist to help when dealing with addresses. The
+function `nl_addr_cmp()` compares two addresses and returns an integer
+less than, equal to or greater than zero without considering the
+prefix length at all. If you want to consider the prefix length, use
+the function `nl_addr_cmp_prefix()`.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_cmp(struct nl_addr *addr, struct nl_addr *addr);
+int nl_addr_cmp_prefix(struct nl_addr *addr, struct nl_addr *addr);
+--------
+
+If an abstract address needs to presented to the user it should be
+done in a human readable format which differs depending on the address
+family. The function `nl_addr2str()` takes care of this by calling the
+appropriate conversion functions internaly. It expects a `buf` of
+length `size` to write the character string into and returns a pointer
+to `buf` for easy `printf()` usage.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size);
+--------
+
+If the address family is unknown, the address data will be printed in
+hexadecimal format `AA:BB:CC:DD:...`
+
+Often the only way to figure out the address family is by looking at
+the length of the address. The function `nl_addr_guess_family()` does
+just this and returns the address family guessed based on the address
+size.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_guess_family(struct nl_addr *addr);
+--------
+
+Before allocating an address you may want to check if the character
+string actually represents a valid address of the address family you
+are expecting. The function `nl_addr_valid()` can be used for that, it
+returns 1 if the supplised `addr` is a valid address in the context of
+`family`. See `inet_pton(3)`, `dnet_pton(3)` for more information on
+valid adddress formats.
+
+[source,c]
+--------
+#include <netlink/addr.h>
+
+int nl_addr_valid(char *addr, int family);
+--------
+
+=== Abstract Data
+
+The abstract data type is a trivial datatype with the primary purpose
+to simplify usage of netlink attributes of arbitary length.
+
+[[core_data_alloc]]
+.Allocation of a Data Object
+The function `nl_data_alloc()` alloctes a new abstract data object and
+fill it with the provided data. `nl_data_alloc_attr()` does the same
+but bases the data on the payload of a netlink attribute. New data
+objects can also be allocated by cloning existing ones by using
+`nl_data_clone()`.
+
+[source,c]
+--------
+struct nl_data *nl_data_alloc(void *buf, size_t size);
+struct nl_data *nl_data_alloc_attr(struct nlattr *attr);
+struct nl_data *nl_data_clone(struct nl_data *data);
+void nl_data_free(struct nl_data *data);
+--------
+
+.Access to Data
+
+The function `nl_data_get()` returns a pointer to the data, the size
+of data is returned by `nl_data_get_size()`.
+
+[source,c]
+--------
+void *nl_data_get(struct nl_data *data);
+size_t nl_data_get_size(struct nl_data *data);
+--------
+
+.Data Helpers
+
+The function nl_data_append() reallocates the internal data buffers
+and appends the specified `buf` to the existing data.
+
+[source,c]
+--------
+int nl_data_append(struct nl_data *data, void *buf, size_t size);
+--------
+
+CAUTION: Any call to `nl_data_append()` invalidates all pointers
+ returned by `nl_data_get()` of the same data object.
+
+[source,c]
+--------
+int nl_data_cmp(struct nl_data *data, struct nl_data *data);
+--------
diff --git a/doc/doxygen-link.py b/doc/doxygen-link.py
new file mode 100755
index 00000000..910b8f8d
--- /dev/null
+++ b/doc/doxygen-link.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import fileinput
+import re
+import sys
+
+
+rc_script = re.compile(r'\s*(.*\S)?\s*')
+
+def parse_dict(filename):
+ links = {}
+ for line in open(filename, 'r'):
+ m = re.match('^([^=]+)=([^\n]+)$', line);
+ if not m:
+ continue
+ name = m.group(1)
+ value = m.group(2)
+
+ # strip leading and trailing whitespace
+ m = rc_script.match(name)
+ if m:
+ name = m.group(1)
+
+ # skip special names
+ if name == '':
+ continue
+ if name == '\\':
+ continue
+
+ links[name] = "<a href=\"" + value + "\" class=\"dg\">" + name + "</a>"
+ return links
+
+links = parse_dict(sys.argv[1])
+
+def translate(match):
+ return links[match.group(1)]
+
+# match for all names, with word boundaries \b
+rc = re.compile(r'\b(' + '|'.join(map(re.escape, sorted(links, reverse=True))) + r')\b')
+
+for line in open(sys.argv[2], 'r'):
+ print(rc.sub(translate, line), end='')
diff --git a/doc/gen-tags.sh b/doc/gen-tags.sh
new file mode 100755
index 00000000..862ec090
--- /dev/null
+++ b/doc/gen-tags.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+#
+# Based on a script found on the englinemtn-devel mailinglist
+# written by Carsten Haitzler <ras...@rasterman.com>
+#
+
+for f in api/group__*.html
+do
+ bf=$(basename $f)
+
+ grep -oE "href=\"$bf#[a-z0-9]+\">[^<]+</a>" $f |
+ sed 's/href="\([^"]*\)">\([^<]*\)<\/a>/\2=api\/\1/'
+done
diff --git a/doc/html/.gitignore b/doc/html/.gitignore
deleted file mode 100644
index 72e8ffc0..00000000
--- a/doc/html/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*
diff --git a/doc/images/.gitignore b/doc/images/.gitignore
new file mode 100644
index 00000000..efcc7e23
--- /dev/null
+++ b/doc/images/.gitignore
@@ -0,0 +1,3 @@
+core__*
+asciidoc__*.png
+*.odg
diff --git a/doc/images/addressing.png b/doc/images/addressing.png
new file mode 100644
index 00000000..9dcaaffd
--- /dev/null
+++ b/doc/images/addressing.png
Binary files differ
diff --git a/doc/images/attribute_hdr.png b/doc/images/attribute_hdr.png
new file mode 100644
index 00000000..0e6cfdad
--- /dev/null
+++ b/doc/images/attribute_hdr.png
Binary files differ
diff --git a/doc/images/classful_qdisc.png b/doc/images/classful_qdisc.png
new file mode 100644
index 00000000..7e77350f
--- /dev/null
+++ b/doc/images/classful_qdisc.png
Binary files differ
diff --git a/doc/images/classless_qdisc.png b/doc/images/classless_qdisc.png
new file mode 100644
index 00000000..bcf2c1ce
--- /dev/null
+++ b/doc/images/classless_qdisc.png
Binary files differ
diff --git a/doc/images/classless_qdisc_nbands.png b/doc/images/classless_qdisc_nbands.png
new file mode 100644
index 00000000..14cb0260
--- /dev/null
+++ b/doc/images/classless_qdisc_nbands.png
Binary files differ
diff --git a/doc/images/icons/README b/doc/images/icons/README
new file mode 100644
index 00000000..f12b2a73
--- /dev/null
+++ b/doc/images/icons/README
@@ -0,0 +1,5 @@
+Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook
+icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency
+from the Jimmac icons to get round MS IE and FOP PNG incompatibilies.
+
+Stuart Rackham
diff --git a/doc/images/icons/callouts/1.png b/doc/images/icons/callouts/1.png
new file mode 100644
index 00000000..7d473430
--- /dev/null
+++ b/doc/images/icons/callouts/1.png
Binary files differ
diff --git a/doc/images/icons/callouts/10.png b/doc/images/icons/callouts/10.png
new file mode 100644
index 00000000..997bbc82
--- /dev/null
+++ b/doc/images/icons/callouts/10.png
Binary files differ
diff --git a/doc/images/icons/callouts/11.png b/doc/images/icons/callouts/11.png
new file mode 100644
index 00000000..ce47dac3
--- /dev/null
+++ b/doc/images/icons/callouts/11.png
Binary files differ
diff --git a/doc/images/icons/callouts/12.png b/doc/images/icons/callouts/12.png
new file mode 100644
index 00000000..31daf4e2
--- /dev/null
+++ b/doc/images/icons/callouts/12.png
Binary files differ
diff --git a/doc/images/icons/callouts/13.png b/doc/images/icons/callouts/13.png
new file mode 100644
index 00000000..14021a89
--- /dev/null
+++ b/doc/images/icons/callouts/13.png
Binary files differ
diff --git a/doc/images/icons/callouts/14.png b/doc/images/icons/callouts/14.png
new file mode 100644
index 00000000..64014b75
--- /dev/null
+++ b/doc/images/icons/callouts/14.png
Binary files differ
diff --git a/doc/images/icons/callouts/15.png b/doc/images/icons/callouts/15.png
new file mode 100644
index 00000000..0d65765f
--- /dev/null
+++ b/doc/images/icons/callouts/15.png
Binary files differ
diff --git a/doc/images/icons/callouts/2.png b/doc/images/icons/callouts/2.png
new file mode 100644
index 00000000..5d09341b
--- /dev/null
+++ b/doc/images/icons/callouts/2.png
Binary files differ
diff --git a/doc/images/icons/callouts/3.png b/doc/images/icons/callouts/3.png
new file mode 100644
index 00000000..ef7b7004
--- /dev/null
+++ b/doc/images/icons/callouts/3.png
Binary files differ
diff --git a/doc/images/icons/callouts/4.png b/doc/images/icons/callouts/4.png
new file mode 100644
index 00000000..adb8364e
--- /dev/null
+++ b/doc/images/icons/callouts/4.png
Binary files differ
diff --git a/doc/images/icons/callouts/5.png b/doc/images/icons/callouts/5.png
new file mode 100644
index 00000000..4d7eb460
--- /dev/null
+++ b/doc/images/icons/callouts/5.png
Binary files differ
diff --git a/doc/images/icons/callouts/6.png b/doc/images/icons/callouts/6.png
new file mode 100644
index 00000000..0ba694af
--- /dev/null
+++ b/doc/images/icons/callouts/6.png
Binary files differ
diff --git a/doc/images/icons/callouts/7.png b/doc/images/icons/callouts/7.png
new file mode 100644
index 00000000..472e96f8
--- /dev/null
+++ b/doc/images/icons/callouts/7.png
Binary files differ
diff --git a/doc/images/icons/callouts/8.png b/doc/images/icons/callouts/8.png
new file mode 100644
index 00000000..5e60973c
--- /dev/null
+++ b/doc/images/icons/callouts/8.png
Binary files differ
diff --git a/doc/images/icons/callouts/9.png b/doc/images/icons/callouts/9.png
new file mode 100644
index 00000000..a0676d26
--- /dev/null
+++ b/doc/images/icons/callouts/9.png
Binary files differ
diff --git a/doc/images/icons/caution.png b/doc/images/icons/caution.png
new file mode 100644
index 00000000..9a8c515a
--- /dev/null
+++ b/doc/images/icons/caution.png
Binary files differ
diff --git a/doc/images/icons/example.png b/doc/images/icons/example.png
new file mode 100644
index 00000000..1199e864
--- /dev/null
+++ b/doc/images/icons/example.png
Binary files differ
diff --git a/doc/images/icons/home.png b/doc/images/icons/home.png
new file mode 100644
index 00000000..37a5231b
--- /dev/null
+++ b/doc/images/icons/home.png
Binary files differ
diff --git a/doc/images/icons/important.png b/doc/images/icons/important.png
new file mode 100644
index 00000000..be685cc4
--- /dev/null
+++ b/doc/images/icons/important.png
Binary files differ
diff --git a/doc/images/icons/next.png b/doc/images/icons/next.png
new file mode 100644
index 00000000..64e126bd
--- /dev/null
+++ b/doc/images/icons/next.png
Binary files differ
diff --git a/doc/images/icons/note.png b/doc/images/icons/note.png
new file mode 100644
index 00000000..7c1f3e2f
--- /dev/null
+++ b/doc/images/icons/note.png
Binary files differ
diff --git a/doc/images/icons/prev.png b/doc/images/icons/prev.png
new file mode 100644
index 00000000..3e8f12fe
--- /dev/null
+++ b/doc/images/icons/prev.png
Binary files differ
diff --git a/doc/images/icons/tip.png b/doc/images/icons/tip.png
new file mode 100644
index 00000000..f087c73b
--- /dev/null
+++ b/doc/images/icons/tip.png
Binary files differ
diff --git a/doc/images/icons/up.png b/doc/images/icons/up.png
new file mode 100644
index 00000000..2db1ce62
--- /dev/null
+++ b/doc/images/icons/up.png
Binary files differ
diff --git a/doc/images/icons/warning.png b/doc/images/icons/warning.png
new file mode 100644
index 00000000..d41edb9a
--- /dev/null
+++ b/doc/images/icons/warning.png
Binary files differ
diff --git a/doc/images/ifinfomsg.png b/doc/images/ifinfomsg.png
new file mode 100644
index 00000000..fb94cf7b
--- /dev/null
+++ b/doc/images/ifinfomsg.png
Binary files differ
diff --git a/doc/images/library_overview.png b/doc/images/library_overview.png
new file mode 100644
index 00000000..dd9d5fe9
--- /dev/null
+++ b/doc/images/library_overview.png
Binary files differ
diff --git a/doc/images/nlmsgerr.png b/doc/images/nlmsgerr.png
new file mode 100644
index 00000000..58e53d55
--- /dev/null
+++ b/doc/images/nlmsgerr.png
Binary files differ
diff --git a/doc/images/nlmsghdr.png b/doc/images/nlmsghdr.png
new file mode 100644
index 00000000..dd39b9ca
--- /dev/null
+++ b/doc/images/nlmsghdr.png
Binary files differ
diff --git a/doc/images/qdisc_default.png b/doc/images/qdisc_default.png
new file mode 100644
index 00000000..a7ba1678
--- /dev/null
+++ b/doc/images/qdisc_default.png
Binary files differ
diff --git a/doc/images/qdisc_mq.png b/doc/images/qdisc_mq.png
new file mode 100644
index 00000000..c6318b28
--- /dev/null
+++ b/doc/images/qdisc_mq.png
Binary files differ
diff --git a/doc/images/tc_obj.png b/doc/images/tc_obj.png
new file mode 100644
index 00000000..bfc81452
--- /dev/null
+++ b/doc/images/tc_obj.png
Binary files differ
diff --git a/doc/images/tc_overview.png b/doc/images/tc_overview.png
new file mode 100644
index 00000000..ce23e67b
--- /dev/null
+++ b/doc/images/tc_overview.png
Binary files differ
diff --git a/doc/index.txt b/doc/index.txt
new file mode 100644
index 00000000..c207b448
--- /dev/null
+++ b/doc/index.txt
@@ -0,0 +1,22 @@
+Documentation Overview - libnl Suite
+====================================
+
+== Libraries
+
+image:library_overview.png["Library Hierarchy"]
+
+link:core.html[Netlink Library] (libnl)::
+Socket handling, sending and receiving, message construction and parsing, ...
+
+link:route.html[Routing Family Library] (libnl-route)::
+Adresses, links, neighbours, routing, traffic control, neighbour tables, ...
+
+Netfilter Library (libnl-nf)::
+Connection tracking, logging, queueing
+
+Generic Netlink Library (libnl-genl)::
+Controller API, family and command registration
+
+== Python Packages
+ - netlink.core
+ - netlink.route.link
diff --git a/doc/libnl.css b/doc/libnl.css
index 22c48430..85894507 100644
--- a/doc/libnl.css
+++ b/doc/libnl.css
@@ -1,473 +1,1156 @@
-BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
- font-family: Geneva, Arial, Helvetica, sans-serif;
+/* The standard CSS for doxygen */
+
+body, table, div, p, dl {
+ font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+ font-size: 13px;
+ line-height: 1.3;
}
-BODY,TD {
- font-size: 90%;
+
+/* @group Heading Levels */
+
+h1 {
+ font-size: 150%;
}
-H1 {
- text-align: center;
- font-size: 160%;
+
+.title {
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
}
-H2 {
+
+h2 {
font-size: 120%;
}
-H3 {
+
+h3 {
font-size: 100%;
}
-CAPTION {
- font-weight: bold
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
}
-DIV.qindex {
- width: 100%;
- background-color: #e8eef2;
- border: 1px solid #84b0c7;
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd, p.starttd {
+ margin-top: 2px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
text-align: center;
- margin: 2px;
- padding: 2px;
- line-height: 140%;
}
-DIV.navpath {
+
+div.qindex, div.navpath {
width: 100%;
- background-color: #e8eef2;
- border: 1px solid #84b0c7;
- text-align: center;
- margin: 2px;
- padding: 2px;
line-height: 140%;
}
-DIV.navtab {
- background-color: #e8eef2;
- border: 1px solid #84b0c7;
- text-align: center;
- margin: 2px;
- margin-right: 15px;
- padding: 2px;
+
+div.navtab {
+ margin-right: 15px;
}
-TD.navtab {
- font-size: 70%;
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
}
-A.qindex {
- text-decoration: none;
- font-weight: bold;
- color: #1A419D;
+
+.contents a:visited {
+ color: #4665A2;
}
-A.qindex:visited {
- text-decoration: none;
- font-weight: bold;
- color: #1A419D
+
+a:hover {
+ text-decoration: underline;
}
-A.qindex:hover {
- text-decoration: none;
- background-color: #ddddff;
+
+a.qindex {
+ font-weight: bold;
}
-A.qindexHL {
- text-decoration: none;
+
+a.qindexHL {
font-weight: bold;
- background-color: #6666cc;
+ background-color: #9CAFD4;
color: #ffffff;
- border: 1px double #9295C2;
+ border: 1px double #869DCA;
}
-A.qindexHL:hover {
- text-decoration: none;
- background-color: #6666cc;
- color: #ffffff;
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
}
-A.qindexHL:visited {
- text-decoration: none;
- background-color: #6666cc;
- color: #ffffff
+
+a.elRef {
}
-A.el {
- text-decoration: none;
- font-weight: bold
+
+a.code, a.code:visited {
+ color: #4665A2;
}
-A.elRef {
- font-weight: bold
+
+a.codeRef, a.codeRef:visited {
+ color: #4665A2;
}
-A.code:link {
- text-decoration: none;
- font-weight: normal;
- color: #0000FF
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
}
-A.code:visited {
- text-decoration: none;
- font-weight: normal;
- color: #0000FF
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
}
-A.codeRef:link {
- font-weight: normal;
- color: #0000FF
+
+div.fragment {
+ padding: 4px;
+ margin: 4px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
}
-A.codeRef:visited {
- font-weight: normal;
- color: #0000FF
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
}
-A:hover {
- text-decoration: none;
- background-color: #f2f2ff
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
}
-DL.el {
- margin-left: -1cm
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
}
-.fragment {
- font-family: monospace, fixed;
- font-size: 95%;
+span.lineno a {
+ background-color: #D8D8D8;
}
-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;
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
}
-DIV.ah {
- background-color: black;
- font-weight: bold;
- color: #ffffff;
- margin-bottom: 3px;
- margin-top: 3px
+
+div.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
}
-DIV.groupHeader {
- margin-left: 16px;
- margin-top: 12px;
- margin-bottom: 6px;
- font-weight: bold;
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
}
-DIV.groupText {
- margin-left: 16px;
- font-style: italic;
- font-size: 90%
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
}
-BODY {
- background: white;
+
+body {
+ background-color: white;
color: black;
- margin-right: 20px;
- margin-left: 20px;
+ margin: 0;
}
-TD.indexkey {
- background-color: #e8eef2;
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
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: #e8eef2;
- 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 }
-SPAN.vhdldigit { color: #ff00ff }
-SPAN.vhdlchar { color: #000000 }
-SPAN.vhdlkeyword { color: #700070 }
-SPAN.vhdllogic { color: #ff0000 }
-
-.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;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
}
-.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;
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 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%;
+
+tr.memlist {
+ background-color: #EEF1F7;
}
-.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%;
+
+p.formulaDsp {
+ text-align: center;
}
-.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%;
+
+img.formulaDsp {
+
}
-.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%;
+
+img.formulaInl {
+ vertical-align: middle;
}
-.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%;
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+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
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
}
-.search {
+
+/* @end */
+
+/*
+.search {
color: #003399;
font-weight: bold;
}
-FORM.search {
+
+form.search {
margin-bottom: 0px;
margin-top: 0px;
}
-INPUT.search {
+
+input.search {
font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #e8eef2;
}
-TD.tiny {
+*/
+
+td.tiny {
font-size: 75%;
}
-a {
- color: #1A41A8;
-}
-a:visited {
- color: #2A3798;
-}
-.dirtab {
+
+.dirtab {
padding: 4px;
border-collapse: collapse;
- border: 1px solid #84b0c7;
+ border: 1px solid #A3B4D7;
}
-TH.dirtab {
- background: #e8eef2;
+
+th.dirtab {
+ background: #EBEFF6;
font-weight: bold;
}
-HR {
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
border: none;
- border-top: 1px solid black;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memItemLeft, .memItemRight, .memTemplParams {
+ border-top: 1px solid #C4CFE5;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
}
-/* Style for detailed member documentation */
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
.memtemplate {
font-size: 80%;
- color: #606060;
+ color: #4665A2;
font-weight: normal;
- margin-left: 3px;
-}
-.memnav {
- background-color: #e8eef2;
- border: 1px solid #84b0c7;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
+
+.mempage {
+ width: 100%;
+}
+
.memitem {
- padding: 4px;
- background-color: #eef3f5;
- border-width: 1px;
- border-style: solid;
- border-color: #dedeee;
- -moz-border-radius: 8px 8px 8px 8px;
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
}
+
.memname {
- white-space: nowrap;
- font-weight: bold;
+ font-weight: bold;
+ margin-left: 6px;
}
-.memdoc{
- padding-left: 10px;
+
+.memname td {
+ vertical-align: bottom;
}
-.memproto {
- background-color: #d5e1e8;
- width: 100%;
- border-width: 1px;
- border-style: solid;
- border-color: #84b0c7;
- font-weight: bold;
- -moz-border-radius: 8px 8px 8px 8px;
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+
}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
.paramkey {
text-align: right;
}
+
.paramtype {
white-space: nowrap;
}
+
.paramname {
color: #602020;
- font-style: italic;
white-space: nowrap;
}
-/* End Styling for detailed member documentation */
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
-/* for the tree view */
-.ftvtree {
- font-family: sans-serif;
- margin:0.5em;
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
}
-/* these are for tree view when used as main index */
-.directory {
- font-size: 9pt;
- font-weight: bold;
+
+table.mlabels {
+ border-spacing: 0px;
}
-.directory h3 {
- margin: 0px;
- margin-top: 1em;
- font-size: 11pt;
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
}
-/* The following two styles can be used to replace the root node title */
-/* with an image of your choice. Simply uncomment the next two styles, */
-/* specify the name of your image and be sure to set 'height' to the */
-/* proper pixel height of your image. */
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
-/* .directory h3.swap { */
-/* height: 61px; */
-/* background-repeat: no-repeat; */
-/* background-image: url("yourimage.gif"); */
-/* } */
-/* .directory h3.swap span { */
-/* display: none; */
-/* } */
+span.mlabels {
+ margin-left: 8px;
+}
-.directory > h3 {
- margin-top: 0;
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
}
-.directory p {
- margin: 0px;
- white-space: nowrap;
+
+
+
+/* @end */
+
+/* these are for tree view when not used as main index */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
}
-.directory div {
- display: none;
- margin: 0px;
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
}
-.directory img {
- vertical-align: -30%;
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
}
-/* these are for tree view when not used as main index */
-.directory-alt {
- font-size: 100%;
- font-weight: bold;
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ width: 100%;
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
}
-.directory-alt h3 {
- margin: 0px;
- margin-top: 1em;
- font-size: 11pt;
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ width: 100%;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
}
-.directory-alt > h3 {
- margin-top: 0;
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
}
-.directory-alt p {
- margin: 0px;
- white-space: nowrap;
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
}
-.directory-alt div {
- display: none;
- margin: 0px;
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
}
-.directory-alt img {
- vertical-align: -30%;
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 7px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectname
+{
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 120% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 50% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 20px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
}
diff --git a/doc/m4/ax_python.m4 b/doc/m4/ax_python.m4
new file mode 100644
index 00000000..f9a51359
--- /dev/null
+++ b/doc/m4/ax_python.m4
@@ -0,0 +1,97 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_python.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PYTHON
+#
+# DESCRIPTION
+#
+# This macro does a complete Python development environment check.
+#
+# It recurses through several python versions (from 2.1 to 2.6 in this
+# version), looking for an executable. When it finds an executable, it
+# looks to find the header files and library.
+#
+# It sets PYTHON_BIN to the name of the python executable,
+# PYTHON_INCLUDE_DIR to the directory holding the header files, and
+# PYTHON_LIB to the name of the Python library.
+#
+# This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG),
+# PYTHON_INCLUDE_DIR and PYTHON_LIB.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Michael Tindal
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 9
+
+AC_DEFUN([AX_PYTHON],
+[AC_MSG_CHECKING(for python build information)
+AC_MSG_RESULT([])
+for python in python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python; do
+AC_CHECK_PROGS(PYTHON_BIN, [$python])
+ax_python_bin=$PYTHON_BIN
+if test x$ax_python_bin != x; then
+ AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no)
+ AC_CHECK_HEADER([$ax_python_bin/Python.h],
+ [[ax_python_header=`locate $ax_python_bin/Python.h | sed -e s,/Python.h,,`]],
+ ax_python_header=no)
+ if test x$ax_python_lib != xno; then
+ if test x$ax_python_header != xno; then
+ break;
+ fi
+ fi
+fi
+done
+if test x$ax_python_bin = x; then
+ ax_python_bin=no
+fi
+if test x$ax_python_header = x; then
+ ax_python_header=no
+fi
+if test x$ax_python_lib = x; then
+ ax_python_lib=no
+fi
+
+AC_MSG_RESULT([ results of the Python check:])
+AC_MSG_RESULT([ Binary: $ax_python_bin])
+AC_MSG_RESULT([ Library: $ax_python_lib])
+AC_MSG_RESULT([ Include Dir: $ax_python_header])
+
+if test x$ax_python_header != xno; then
+ PYTHON_INCLUDE_DIR=$ax_python_header
+ AC_SUBST(PYTHON_INCLUDE_DIR)
+fi
+if test x$ax_python_lib != xno; then
+ PYTHON_LIB=$ax_python_lib
+ AC_SUBST(PYTHON_LIB)
+fi
+])dnl
diff --git a/doc/resolve-asciidoc-refs.py b/doc/resolve-asciidoc-refs.py
new file mode 100755
index 00000000..54187473
--- /dev/null
+++ b/doc/resolve-asciidoc-refs.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+import fileinput
+import re
+import sys
+
+refs = {}
+complete_file = ""
+
+for line in open(sys.argv[1], 'r'):
+ complete_file += line
+
+for m in re.findall('\[\[(.+)\]\]\n=+ ([^\n]+)', complete_file):
+ ref, title = m
+ refs["<<" + ref + ">>"] = "<<" + ref + ", " + title + ">>"
+
+def translate(match):
+ try:
+ return refs[match.group(0)]
+ except KeyError:
+ return ""
+
+rc = re.compile('|'.join(map(re.escape, sorted(refs, reverse=True))))
+for line in open(sys.argv[1], 'r'):
+ print rc.sub(translate, line),
diff --git a/doc/route.txt b/doc/route.txt
new file mode 100644
index 00000000..d9f88e13
--- /dev/null
+++ b/doc/route.txt
@@ -0,0 +1,1889 @@
+////
+ vim.syntax: asciidoc
+
+ Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
+////
+
+Routing Family Netlink Library (libnl-route)
+============================================
+Thomas Graf <tgraf@suug.ch>
+3.1, Aug 11 2011:
+
+== Introduction
+
+This library provides APIs to the kernel interfaces of the routing family.
+
+
+NOTE: Work in progress.
+
+== Addresses
+
+[[route_link]]
+== Links (Network Devices)
+
+The link configuration interface is part of the +NETLINK_ROUTE+ protocol
+family and implements the following netlink message types:
+
+- View and modify the configuration of physical and virtual network devices.
+- Create and delete virtual network devices (e.g. dummy devices, VLAN devices,
+ tun devices, bridging devices, ...)
+- View and modify per link network configuration settings (e.g.
+ +net.ipv6.conf.eth0.accept_ra+, +net.ipv4.conf.eth1.forwarding+, ...)
+
+.Naming Convention (network device, link, interface)
+
+In networking several terms are commonly used to refer to network devices.
+While they have distinct meanings they have been used interchangeably in
+the past. Within the Linux kernel, the term _network device_ or _netdev_ is
+commonly used In user space the term _network interface_ is very common.
+The routing netlink protocol uses the term _link_ and so does the _iproute2_
+utility and most routing daemons.
+
+=== Netlink Protocol
+
+This section describes the protocol semantics of the netlink based link
+configuration interface. The following messages are defined:
+
+[options="header", cols="1,2,2"]
+|==============================================================================
+| Message Type | User -> Kernel | Kernel -> User
+| +RTM_NEWLINK+ | Create or update virtual network device
+| Reply to +RTM_GETLINK+ request or notification of link added or updated
+| +RTM_DELLINK+ | Delete virtual network device
+| Notification of link deleted or disappeared
+| +RTM_GETLINK+ | Retrieve link configuration and statistics |
+| +RTM_SETLINK+ | Modify link configuration |
+|==============================================================================
+
+See link:core.html#core_msg_types[Netlink Library - Message Types] for more
+information on common semantics of these message types.
+
+==== Link Message Format
+
+All netlink link messages share a common header (+struct ifinfomsg+) which
+is appended after the netlink header (+struct nlmsghdr+).
+
+image:ifinfomsg.png["Link Message Header"]
+
+The meaning of each field may differ depending on the message type. A
++struct ifinfomsg+ is defined in +<linux/rtnetlink.h>+ to represent the
+header.
+
+Address Family (8bit)::
+The address family is usually set to +AF_UNSPEC+ but may be specified in
++RTM_GETLINK+ requests to limit the returned links to a specific address
+family.
+
+Link Layer Type (16bit)::
+Currently only used in kernel->user messages to report the link layer type
+of a link. The value corresponds to the +ARPHRD_*+ defines found in
++<linux/if_arp.h>+. Translation from/to strings can be done using the
+functions nl_llproto2str()/nl_str2llproto().
+
+Link Index (32bit)::
+Carries the interface index and is used to identify existing links.
+
+Flags (32bit)::
+In kernel->user messages the value of this field represents the current
+state of the link flags. In user->kernel messages this field is used to
+change flags or set the initial flag state of new links. Note that in order
+to change a flag, the flag must also be set in the _Flags Change Mask_ field.
+
+Flags Change Mask (32bit)::
+The primary use of this field is to specify a mask of flags that should be
+changed based on the value of the _Flags_ field. A special meaning is given
+to this field when present in link notifications, see TODO.
+
+Attributes (variable)::
+All link message types may carry netlink attributes. They are defined in the
+header file <linux/if_link.h> and share the prefix +IFLA_+.
+
+==== Link Message Types
+
+.RTM_GETLINK (user->kernel)
+
+Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and return
+a single +RTM_NEWLINK+ message containing the link configuration and statistics
+or a netlink error message if no such link was found.
+
+*Parameters:*
+
+* *Address family*
+** If the address family is set to +PF_BRIDGE+, only bridging devices will be
+ returned.
+** If the address family is set to +PF_INET6+, only ipv6 enabled devices will
+ be returned.
+
+*Flags:*
+
+* +NLM_F_DUMP+ If set, all links will be returned in form of a multipart
+ message.
+
+*Returns:*
+
+* +EINVAL+ if neither interface nor link name are set
+* +ENODEV+ if no link was found
+* +ENOBUFS+ if allocation failed
+
+.RTM_NEWLINK (user->kernel)
+
+Creates a new or updates an existing link. Only virtual links may be created
+but all links may be updated.
+
+*Flags:*
+
+- +NLM_F_CREATE+ Create link if it does not exist
+- +NLM_F_EXCL+ Return +EEXIST+ if link already exists
+
+*Returns:*
+
+- +EINVAL+ malformed message or invalid configuration parameters
+- +EAFNOSUPPORT+ if a address family specific configuration (+IFLA_AF_SPEC+)
+ is not supported.
+- +EOPNOTSUPP+ if the link does not support modification of parameters
+- +EEXIST+ if +NLM_F_EXCL+ was set and the link exists alraedy
+- +ENODEV+ if the link does not exist and +NLM_F_CREATE+ is not set
+
+.RTM_NEWLINK (kernel->user)
+
+This message type is used in reply to a +RTM_GETLINK+ request and carries
+the configuration and statistics of a link. If multiple links need to
+be sent, the messages will be sent in form of a multipart message.
+
+The message type is also used for notifications sent by the kernel to the
+multicast group +RTNLGRP_LINK+ to inform about various link events. It is
+therefore recommended to always use a separate link socket for link
+notifications in order to separate between the two message types.
+
+TODO: document how to detect different notifications
+
+.RTM_DELLINK (user->kernel)
+
+Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and delete
+the virtual link.
+
+*Returns:*
+
+* +EINVAL+ if neither interface nor link name are set
+* +ENODEV+ if no link was found
+* +ENOTSUPP+ if the operation is not supported (not a virtual link)
+
+.RTM_DELLINK (kernel->user)
+
+Notification sent by the kernel to the multicast group +RTNLGRP_LINK+ when
+
+a. a network device was unregistered (change == ~0)
+b. a bridging device was deleted (address family will be +PF_BRIDGE+)
+
+=== Get / List
+
+[[link_list]]
+==== Get list of links
+
+To retrieve the list of links in the kernel, allocate a new link cache
+using +rtnl_link_alloc_cache()+ to hold the links. It will automatically
+construct and send a +RTM_GETLINK+ message requesting a dump of all links
+from the kernel and feed the returned +RTM_NEWLINK+ to the internal link
+message parser which adds the returned links to the cache.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
+-----
+
+The cache will contain link objects (+struct rtnl_link+, see <<link_object>>)
+and can be accessed using the standard cache functions. By setting the
++family+ parameter to an address familly other than +AF_UNSPEC+, the resulting
+cache will only contain links supporting the specified address family.
+
+The following direct search functions are provided to search by interface
+index and by link name:
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex);
+struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, const char *name);
+-----
+
+.Example: Link Cache
+
+[source,c]
+-----
+struct nl_cache *cache;
+struct rtnl_link *link;
+
+if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache)) < 0)
+ /* error */
+
+if (!(link = rtnl_link_get_by_name(cache, "eth1")))
+ /* link does not exist */
+
+/* do something with link */
+
+rtnl_link_put(link);
+nl_cache_put(cache);
+-----
+
+[[link_direct_lookup]]
+==== Lookup Single Link (Direct Lookup)
+
+If only a single link is of interest, the link can be looked up directly
+without the use of a link cache using the function +rtnl_link_get_kernel()+.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result);
+-----
+
+It will construct and send a +RTM_GETLINK+ request using the parameters
+provided and wait for a +RTM_NEWLINK+ or netlink error message sent in
+return. If the link exists, the link is returned as link object
+(see <<link_object>>).
+
+.Example: Direct link lookup
+[source,c]
+-----
+struct rtnl_link *link;
+
+if (rtnl_link_get_kernel(sock, 0, "eth1", &link) < 0)
+ /* error */
+
+/* do something with link */
+
+rtnl_link_put(link);
+-----
+
+NOTE: While using this function can save a substantial amount of bandwidth
+ on the netlink socket, the result will not be cached, subsequent calls
+ to rtnl_link_get_kernel() will always trigger sending a +RTM_GETLINK+
+ request.
+
+[[link_translate_ifindex]]
+==== Translating interface index to link name
+
+Applications which require to translate interface index to a link name or
+vice verase may use the following functions to do so. Both functions require
+a filled link cache to work with.
+
+[source,c]
+-----
+char *rtnl_link_i2name (struct nl_cache *cache, int ifindex, char *dst, size_t len);
+int rtnl_link_name2i (struct nl_cache *cache, const char *name);
+-----
+
+=== Add / Modify
+
+Several types of virtual link can be added on the fly using the function
++rtnl_link_add()+.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags);
+-----
+
+=== Delete
+
+The deletion of virtual links such as VLAN devices or dummy devices is done
+using the function +rtnl_link_delete()+. The link passed on to the function
+can be a link from a link cache or it can be construct with the minimal
+attributes needed to identify the link.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link);
+-----
+
+The function will construct and send a +RTM_DELLINK+ request message and
+returns any errors returned by the kernel.
+
+.Example: Delete link by name
+[source,c]
+-----
+struct rtnl_link *link;
+
+if (!(link = rtnl_link_alloc()))
+ /* error */
+
+rtnl_link_set_name(link, "my_vlan");
+
+if (rtnl_link_delete(sock, link) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_object]]
+=== Link Object
+
+A link is represented by the structure +struct rtnl_link+. Instances may be
+created with the function +rtnl_link_alloc()+ or via a link cache (see
+<<link_list>>) and are freed again using the function +rtnl_link_put()+.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+struct rtnl_link *rtnl_link_alloc(void);
+void rtnl_link_put(struct rtnl_link *link);
+-----
+
+[[link_attr_name]]
+==== Name
+The name serves as unique, human readable description of the link. By
+default, links are named based on their type and then enumerated, e.g.
+eth0, eth1, ethn but they may be renamed at any time.
+
+Kernels >= 2.6.11 support identification by link name.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_name(struct rtnl_link *link, const char *name);
+char *rtnl_link_get_name(struct rtnl_link *link);
+-----
+
+*Accepted link name format:* +[^ /]*+ (maximum length: 15 characters)
+
+[[link_attr_ifindex]]
+==== Interface Index (Identifier)
+The interface index is an integer uniquely identifying a link. If present
+in any link message, it will be used to identify an existing link.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex);
+int rtnl_link_get_ifindex(struct rtnl_link *link);
+-----
+
+[[link_attr_group]]
+==== Group
+Each link can be assigned a numeric group identifier to group a bunch of links
+together and apply a set of changes to a group instead of just a single link.
+
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_group(struct rtnl_link *link, uint32_t group);
+uint32_t rtnl_link_get_group(struct rtnl_link *link);
+-----
+
+[[link_attr_address]]
+==== Link Layer Address
+The link layer address (e.g. MAC address).
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr);
+struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link);
+-----
+
+[[link_attr_broadcast]]
+==== Broadcast Address
+The link layer broadcast address
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr);
+struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link);
+-----
+
+[[link_attr_mtu]]
+==== MTU (Maximum Transmission Unit)
+The maximum transmission unit specifies the maximum packet size a network
+device can transmit or receive. This value may be lower than the capability
+of the physical network device.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu);
+unsigned int rtnl_link_get_mtu(struct rtnl_link *link);
+-----
+
+[[link_attr_flags]]
+==== Flags
+The flags of a link enable or disable various link features or inform about
+the state of the link.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags);
+void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags);
+unsigned int rtnl_link_get_flags(struct rtnl_link *link);
+-----
+
+[options="compact"]
+[horizontal]
+IFF_UP:: Link is up (administratively)
+IFF_RUNNING:: Link is up and carrier is OK (RFC2863 OPER_UP)
+IFF_LOWER_UP:: Link layer is operational
+IFF_DORMANT:: Driver signals dormant
+IFF_BROADCAST:: Link supports broadcasting
+IFF_MULTICAST:: Link supports multicasting
+IFF_ALLMULTI:: Link supports multicast routing
+IFF_DEBUG:: Tell driver to do debugging (currently unused)
+IFF_LOOPBACK:: Link loopback network
+IFF_POINTOPOINT:: Point-to-point link
+IFF_NOARP:: ARP is not supported
+IFF_PROMISC:: Status of promiscious mode
+IFF_MASTER:: Master of a load balancer (bonding)
+IFF_SLAVE:: Slave to a master link
+IFF_PORTSEL:: Driver supports setting media type (only used by ARM ethernet)
+IFF_AUTOMEDIA:: Link selects port automatically (only used by ARM ethernet)
+IFF_ECHO:: Echo sent packets (testing feature, CAN only)
+IFF_DYNAMIC:: Unused (BSD compatibility)
+IFF_NOTRAILERS:: Unused (BSD compatibility)
+
+To translate a link flag to a link flag name or vice versa:
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+char *rtnl_link_flags2str(int flags, char *buf, size_t size);
+int rtnl_link_str2flags(const char *flag_name);
+-----
+
+[[link_attr_txqlen]]
+==== Transmission Queue Length
+
+The transmission queue holds packets before packets are delivered to
+the driver for transmission. It is usually specified in number of
+packets but the unit may be specific to the link type.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen);
+unsigned int rtnl_link_get_txqlen(struct rtnl_link *link);
+-----
+
+[[link_attr_operstate]]
+==== Operational Status
+The operational status has been introduced to provide extended information
+on the link status. Traditionally the link state has been described using
+the link flags +IFF_UP, IFF_RUNNING, IFF_LOWER_UP+, and +IFF_DORMANT+ which
+was no longer sufficient for some link types.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t state);
+uint8_t rtnl_link_get_operstate(struct rtnl_link *link);
+-----
+
+[options="compact"]
+[horizontal]
+IF_OPER_UNKNOWN:: Unknown state
+IF_OPER_NOTPRESENT:: Link not present
+IF_OPER_DOWN:: Link down
+IF_OPER_LOWERLAYERDOWN:: L1 down
+IF_OPER_TESTING:: Testing
+IF_OPER_DORMANT:: Dormant
+IF_OPER_UP:: Link up
+
+Translation of operational status code to string and vice versa:
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+char *rtnl_link_operstate2str(uint8_t state, char *buf, size_t size);
+int rtnl_link_str2operstate(const char *name);
+-----
+
+[[link_attr_mode]]
+==== Mode
+Currently known link modes are:
+
+[options="compact"]
+[horizontal]
+IF_LINK_MODE_DEFAULT:: Default link mode
+IF_LINK_MODE_DORMANT:: Limit upward transition to dormant
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode);
+uint8_t rtnl_link_get_linkmode(struct rtnl_link *link);
+-----
+
+Translation of link mode to string and vice versa:
+
+[source,c]
+-----
+char *rtnl_link_mode2str(uint8_t mode, char *buf, size_t len);
+uint8_t rtnl_link_str2mode(const char *name);
+-----
+
+[[link_attr_alias]]
+==== IfAlias
+Alternative name for the link, primarly used for SNMP IfAlias.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+const char *rtnl_link_get_ifalias(struct rtnl_link *link);
+void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias);
+-----
+
+*Length limit:* 256
+
+[[link_attr_arptype]]
+==== Hardware Type
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+#include <linux/if_arp.h>
+
+void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype);
+unsigned int rtnl_link_get_arptype(struct rtnl_link *link);
+----
+
+Translation of hardware type to character string and vice versa:
+
+[source,c]
+-----
+#include <netlink/utils.h>
+
+char *nl_llproto2str(int arptype, char *buf, size_t len);
+int nl_str2llproto(const char *name);
+-----
+
+[[link_attr_qdisc]]
+==== Qdisc
+The name of the queueing discipline used by the link is of informational
+nature only. It is a read-only attribute provided by the kernel and cannot
+be modified. The set function is provided solely for the purpose of creating
+link objects to be used for comparison.
+
+For more information on how to modify the qdisc of a link, see section
+<<route_tc>>.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name);
+char *rtnl_link_get_qdisc(struct rtnl_link *link);
+-----
+
+[[link_attr_promiscuity]]
+==== Promiscuity
+The number of subsystem currently depending on the link being promiscuous mode.
+A value of 0 indicates that the link is not in promiscuous mode. It is a
+read-only attribute provided by the kernel and cannot be modified. The set
+function is provided solely for the purpose of creating link objects to be
+used for comparison.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count);
+uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link);
+-----
+
+[[link_num_rxtx_queues]]
+==== RX/TX Queues
+The number of RX/TX queues the link provides. The attribute is writable but
+will only be considered when creating a new network device via netlink.
+
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues);
+uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link);
+
+void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues);
+uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link);
+-----
+
+[[link_attr_weight]]
+==== Weight
+This attribute is unused and obsoleted in all recent kernels.
+
+
+[[link_modules]]
+=== Modules
+
+[[link_bonding]]
+==== Bonding
+
+.Example: Add bonding link
+[source,c]
+-----
+#include <netlink/route/link.h>
+
+struct rtnl_link *link;
+
+link = rtnl_link_bond_alloc();
+rtnl_link_set_name(link, "my_bond");
+
+/* requires admin privileges */
+if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_vlan]]
+==== VLAN
+
+[source,c]
+-----
+extern char * rtnl_link_vlan_flags2str(int, char *, size_t);
+extern int rtnl_link_vlan_str2flags(const char *);
+
+extern int rtnl_link_vlan_set_id(struct rtnl_link *, int);
+extern int rtnl_link_vlan_get_id(struct rtnl_link *);
+
+extern int rtnl_link_vlan_set_flags(struct rtnl_link *,
+ unsigned int);
+extern int rtnl_link_vlan_unset_flags(struct rtnl_link *,
+ unsigned int);
+extern unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *);
+
+extern int rtnl_link_vlan_set_ingress_map(struct rtnl_link *,
+ int, uint32_t);
+extern uint32_t * rtnl_link_vlan_get_ingress_map(struct rtnl_link *);
+
+extern int rtnl_link_vlan_set_egress_map(struct rtnl_link *,
+ uint32_t, int);
+extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *,
+ int *);
+-----
+
+.Example: Add a VLAN device
+[source,c]
+-----
+struct rtnl_link *link;
+int master_index;
+
+/* lookup interface index of eth0 */
+if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
+ /* error */
+
+/* allocate new link object of type vlan */
+link = rtnl_link_vlan_alloc();
+
+/* set eth0 to be our master device */
+rtnl_link_set_link(link, master_index);
+
+rtnl_link_vlan_set_id(link, 10);
+
+if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_macvlan]]
+==== MACVLAN
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_macvlan_alloc(void);
+
+extern int rtnl_link_is_macvlan(struct rtnl_link *);
+
+extern char * rtnl_link_macvlan_mode2str(int, char *, size_t);
+extern int rtnl_link_macvlan_str2mode(const char *);
+
+extern char * rtnl_link_macvlan_flags2str(int, char *, size_t);
+extern int rtnl_link_macvlan_str2flags(const char *);
+
+extern int rtnl_link_macvlan_set_mode(struct rtnl_link *,
+ uint32_t);
+extern uint32_t rtnl_link_macvlan_get_mode(struct rtnl_link *);
+
+extern int rtnl_link_macvlan_set_flags(struct rtnl_link *,
+ uint16_t);
+extern int rtnl_link_macvlan_unset_flags(struct rtnl_link *,
+ uint16_t);
+extern uint16_t rtnl_link_macvlan_get_flags(struct rtnl_link *);
+-----
+
+.Example: Add a MACVLAN device
+[source,c]
+-----
+struct rtnl_link *link;
+int master_index;
+struct nl_addr* addr;
+
+/* lookup interface index of eth0 */
+if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
+ /* error */
+
+/* allocate new link object of type macvlan */
+link = rtnl_link_macvlan_alloc();
+
+/* set eth0 to be our master device */
+rtnl_link_set_link(link, master_index);
+
+/* set address of virtual interface */
+addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN);
+rtnl_link_set_addr(link, addr);
+nl_addr_put(addr);
+
+/* set mode of virtual interface */
+rtnl_link_macvlan_set_mode(link, rtnl_link_macvlan_str2mode("bridge"));
+
+if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_vxlan]]
+==== VXLAN
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_vxlan_alloc(void);
+
+extern int rtnl_link_is_vxlan(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_id(struct rtnl_link *, uint32_t);
+extern int rtnl_link_vxlan_get_id(struct rtnl_link *, uint32_t *);
+
+extern int rtnl_link_vxlan_set_group(struct rtnl_link *, struct nl_addr *);
+extern int rtnl_link_vxlan_get_group(struct rtnl_link *, struct nl_addr **);
+
+extern int rtnl_link_vxlan_set_link(struct rtnl_link *, uint32_t);
+extern int rtnl_link_vxlan_get_link(struct rtnl_link *, uint32_t *);
+
+extern int rtnl_link_vxlan_set_local(struct rtnl_link *, struct nl_addr *);
+extern int rtnl_link_vxlan_get_local(struct rtnl_link *, struct nl_addr **);
+
+extern int rtnl_link_vxlan_set_ttl(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_ttl(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_tos(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_tos(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_learning(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_learning(struct rtnl_link *);
+extern int rtnl_link_vxlan_enable_learning(struct rtnl_link *);
+extern int rtnl_link_vxlan_disable_learning(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_ageing(struct rtnl_link *, uint32_t);
+extern int rtnl_link_vxlan_get_ageing(struct rtnl_link *, uint32_t *);
+
+extern int rtnl_link_vxlan_set_limit(struct rtnl_link *, uint32_t);
+extern int rtnl_link_vxlan_get_limit(struct rtnl_link *, uint32_t *);
+
+extern int rtnl_link_vxlan_set_port_range(struct rtnl_link *,
+ struct ifla_vxlan_port_range *);
+extern int rtnl_link_vxlan_get_port_range(struct rtnl_link *,
+ struct ifla_vxlan_port_range *);
+
+extern int rtnl_link_vxlan_set_proxy(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_proxy(struct rtnl_link *);
+extern int rtnl_link_vxlan_enable_proxy(struct rtnl_link *);
+extern int rtnl_link_vxlan_disable_proxy(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_rsc(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_rsc(struct rtnl_link *);
+extern int rtnl_link_vxlan_enable_rsc(struct rtnl_link *);
+extern int rtnl_link_vxlan_disable_rsc(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_l2miss(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_l2miss(struct rtnl_link *);
+extern int rtnl_link_vxlan_enable_l2miss(struct rtnl_link *);
+extern int rtnl_link_vxlan_disable_l2miss(struct rtnl_link *);
+
+extern int rtnl_link_vxlan_set_l3miss(struct rtnl_link *, uint8_t);
+extern int rtnl_link_vxlan_get_l3miss(struct rtnl_link *);
+extern int rtnl_link_vxlan_enable_l3miss(struct rtnl_link *);
+extern int rtnl_link_vxlan_disable_l3miss(struct rtnl_link *);
+-----
+
+.Example: Add a VXLAN device
+[source,c]
+-----
+struct rtnl_link *link;
+struct nl_addr* addr;
+
+/* allocate new link object of type vxlan */
+link = rtnl_link_vxlan_alloc();
+
+/* set interface name */
+rtnl_link_set_name(link, "vxlan128");
+
+/* set VXLAN network identifier */
+if ((err = rtnl_link_vxlan_set_id(link, 128)) < 0)
+ /* error */
+
+/* set multicast address to join */
+if ((err = nl_addr_parse("239.0.0.1", AF_INET, &addr)) < 0)
+ /* error */
+
+if ((err = rtnl_link_set_group(link, addr)) < 0)
+ /* error */
+
+nl_addr_put(addr);
+
+if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_ipip]]
+==== IPIP
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_ipip_alloc(void);
+extern int rtnl_link_ipip_add(struct nl_sock *sk, const char *name);
+
+extern int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index);
+extern uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link);
+
+extern int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link);
+
+extern int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link);
+
+extern int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl);
+extern uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link);
+
+extern int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos);
+extern uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link);
+
+extern int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
+extern uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link);
+
+-----
+
+.Example: Add a ipip tunnel device
+[source,c]
+-----
+struct rtnl_link *link
+struct in_addr addr
+
+/* allocate new link object of type vxlan */
+if(!(link = rtnl_link_ipip_alloc()))
+ /* error */
+
+/* set ipip tunnel name */
+if ((err = rtnl_link_set_name(link, "ipip-tun")) < 0)
+ /* error */
+
+/* set link index */
+if ((err = rtnl_link_ipip_set_link(link, if_index)) < 0)
+ /* error */
+
+/* set local address */
+inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
+if ((err = rtnl_link_ipip_set_local(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set remote address */
+inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
+if ((err = rtnl_link_ipip_set_remote(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set tunnel ttl */
+if ((err = rtnl_link_ipip_set_ttl(link, 64)) < 0)
+ /* error */
+
+if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_ipgre]]
+==== IPGRE
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_ipgre_alloc(void);
+extern int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name);
+
+extern int rtnl_link_ipgre_set_link(struct rtnl_link *link, uint32_t index);
+extern uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags);
+extern uint16_t rtnl_link_get_iflags(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags);
+extern uint16_t rtnl_link_get_oflags(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_ikey(struct rtnl_link *link, uint32_t ikey);
+extern uint32_t rtnl_link_get_ikey(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey);
+extern uint32_t rtnl_link_get_okey(struct rtnl_link *link)
+
+extern int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl);
+extern uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos);
+extern uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link);
+
+extern int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
+extern uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link);
+
+-----
+
+.Example: Add a ipgre tunnel device
+[source,c]
+-----
+struct rtnl_link *link
+struct in_addr addr
+
+/* allocate new link object of type vxlan */
+if(!(link = rtnl_link_ipgre_alloc()))
+ /* error */
+
+/* set ipgre tunnel name */
+if ((err = rtnl_link_set_name(link, "ipgre-tun")) < 0)
+ /* error */
+
+/* set link index */
+if ((err = rtnl_link_ipgre_set_link(link, if_index)) < 0)
+ /* error */
+
+/* set local address */
+inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
+if ((err = rtnl_link_ipgre_set_local(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set remote address */
+inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
+if ((err = rtnl_link_ipgre_set_remote(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set tunnel ttl */
+if ((err = rtnl_link_ipgre_set_ttl(link, 64)) < 0)
+ /* error */
+
+if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_sit]]
+==== SIT
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_sit_alloc(void);
+extern int rtnl_link_sit_add(struct nl_sock *sk, const char *name);
+
+extern int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index);
+extern uint32_t rtnl_link_sit_get_link(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_iflags(struct rtnl_link *link, uint16_t iflags);
+extern uint16_t rtnl_link_get_iflags(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_oflags(struct rtnl_link *link, uint16_t oflags);
+extern uint16_t rtnl_link_get_oflags(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_ikey(struct rtnl_link *link, uint32_t ikey);
+extern uint32_t rtnl_link_get_ikey(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_okey(struct rtnl_link *link, uint32_t okey);
+extern uint32_t rtnl_link_get_okey(struct rtnl_link *link)
+
+extern int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_sit_get_local(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl);
+extern uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos);
+extern uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link);
+
+extern int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
+extern uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link);
+
+-----
+
+.Example: Add a sit tunnel device
+[source,c]
+-----
+struct rtnl_link *link
+struct in_addr addr
+
+/* allocate new link object of type vxlan */
+if(!(link = rtnl_link_sit_alloc()))
+ /* error */
+
+/* set sit tunnel name */
+if ((err = rtnl_link_set_name(link, "sit-tun")) < 0)
+ /* error */
+
+/* set link index */
+if ((err = rtnl_link_sit_set_link(link, if_index)) < 0)
+ /* error */
+
+/* set local address */
+inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
+if ((err = rtnl_link_sit_set_local(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set remote address */
+inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
+if ((err = rtnl_link_sit_set_remote(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set tunnel ttl */
+if ((err = rtnl_link_sit_set_ttl(link, 64)) < 0)
+ /* error */
+
+if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+
+[[link_ipvti]]
+==== IPVTI
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_ipvti_alloc(void);
+extern int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name);
+
+extern int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index);
+extern uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link);
+
+extern int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey);
+extern uint32_t rtnl_link_get_ikey(struct rtnl_link *link);
+
+extern int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey);
+extern uint32_t rtnl_link_get_okey(struct rtnl_link *link)
+
+extern int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link);
+
+extern int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t addr);
+extern uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link);
+
+-----
+
+.Example: Add a ipvti tunnel device
+[source,c]
+-----
+struct rtnl_link *link
+struct in_addr addr
+
+/* allocate new link object of type vxlan */
+if(!(link = rtnl_link_ipvti_alloc()))
+ /* error */
+
+/* set ipvti tunnel name */
+if ((err = rtnl_link_set_name(link, "ipvti-tun")) < 0)
+ /* error */
+
+/* set link index */
+if ((err = rtnl_link_ipvti_set_link(link, if_index)) < 0)
+ /* error */
+
+/* set local address */
+inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
+if ((err = rtnl_link_ipvti_set_local(link, addr.s_addr)) < 0)
+ /* error */
+
+/* set remote address */
+inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
+if ((err = rtnl_link_ipvti_set_remote(link, addr.s_addr)) < 0)
+ /* error */
+
+if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
+ /* error */
+
+rtnl_link_put(link);
+-----
+
+[[link_ip6tnl]]
+==== IP6TNL
+
+[source,c]
+-----
+extern struct rtnl_link *rtnl_link_ip6_tnl_alloc(void);
+extern int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name);
+
+extern int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index);
+extern uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link);
+
+extern int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *);
+extern int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *);
+
+extern int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *);
+extern int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *);
+
+extern int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl);
+extern uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link);
+
+extern int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos);
+extern uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link);
+
+extern int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit);
+extern uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link);
+
+extern int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags);
+extern uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link);
+
+extern uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link);
+extern int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo);
+
+extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto);
+extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link);
+
+-----
+
+.Example: Add a ip6tnl tunnel device
+[source,c]
+-----
+struct rtnl_link *link
+struct in6_addr addr
+
+link = rtnl_link_ip6_tnl_alloc();
+
+rtnl_link_set_name(link, "ip6tnl-tun");
+rtnl_link_ip6_tnl_set_link(link, if_index);
+
+inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr);
+rtnl_link_ip6_tnl_set_local(link, &addr);
+
+inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr);
+rtnl_link_ip6_tnl_set_remote(link, &addr);
+
+rtnl_link_add(sk, link, NLM_F_CREATE);
+rtnl_link_put(link);
+
+-----
+
+
+== Neighbouring
+
+== Routing
+
+[[route_tc]]
+== Traffic Control
+
+The traffic control architecture allows the queueing and
+prioritization of packets before they are enqueued to the network
+driver. To a limited degree it is also possible to take control of
+network traffic as it enters the network stack.
+
+The architecture consists of three different types of modules:
+
+- *Queueing disciplines (qdisc)* provide a mechanism to enqueue packets
+ in different forms. They may be used to implement fair queueing,
+ prioritization of differentiated services, enforce bandwidth
+ limitations, or even to simulate network behaviour such as packet
+ loss and packet delay. Qdiscs can be classful in which case they
+ allow traffic classes described in the next paragraph to be attached
+ to them.
+
+- *Traffic classes (class)* are supported by several qdiscs to build
+ a tree structure for different types of traffic. Each class may be
+ assigned its own set of attributes such as bandwidth limits or
+ queueing priorities. Some qdiscs even allow borrowing of bandwidth
+ between classes.
+
+- *Classifiers (cls)* are used to decide which qdisc/class the packet
+ should be enqueued to. Different types of classifiers exists,
+ ranging from classification based on protocol header values to
+ classification based on packet priority or firewall marks.
+ Additionally most classifiers support *extended matches (ematch)*
+ which allow extending classifiers by a set of matcher modules, and
+ *actions* which allow classifiers to take actions such as mangling,
+ mirroring, or even rerouting of packets.
+
+.Default Qdisc
+
+The default qdisc used on all network devices is `pfifo_fast`.
+Network devices which do not require a transmit queue such as the
+loopback device do not have a default qdisc attached. The `pfifo_fast`
+qdisc provides three bands to prioritize interactive traffic over bulk
+traffic. Classification is based on the packet priority (diffserv).
+
+image:qdisc_default.png["Default Qdisc"]
+
+.Multiqueue Default Qdisc
+
+If the network device provides multiple transmit queues the `mq`
+qdisc is used by default. It will automatically create a separate
+class for each transmit queue available and will also replace
+the single per device tx lock with a per queue lock.
+
+image:qdisc_mq.png["Multiqueue default Qdisc"]
+
+.Example of a customized classful qdisc setup
+
+The following figure illustrates a possible combination of different
+queueing and classification modules to implement quality of service
+needs.
+
+image:tc_overview.png["Classful Qdisc diagram"]
+
+=== Traffic Control Object
+
+Each type traffic control module (qdisc, class, classifier) is
+represented by its own structure. All of them are based on the traffic
+control object represented by `struct rtnl_tc` which itself is based
+on the generic object `struct nl_object` to make it cacheable. The
+traffic control object contains all attributes, implementation details
+and statistics that are shared by all of the traffic control object
+types.
+
+image:tc_obj.png["struct rtnl_tc hierarchy"]
+
+It is not possible to allocate a `struct rtnl_tc` object, instead the
+actual tc object types must be allocated directly using
+`rtnl_qdisc_alloc()`, `rtnl_class_alloc()`, `rtnl_cls_alloc()` and
+then casted to `struct rtnl_tc` using the `TC_CAST()` macro.
+
+.Usage Example: Allocation, Casting, Freeing
+[source,c]
+-----
+#include <netlink/route/tc.h>
+#include <netlink/route/qdisc.h>
+
+struct rtnl_qdisc *qdisc;
+
+/* Allocation of a qdisc object */
+qdisc = rtnl_qdisc_alloc();
+
+/* Cast the qdisc to a tc object using TC_CAST() to use rtnl_tc_ functions. */
+rtnl_tc_set_mpu(TC_CAST(qdisc), 64);
+
+/* Free the qdisc object */
+rtnl_qdisc_put(qdisc);
+-----
+
+[[tc_attr]]
+==== Attributes
+
+Handle::
+The handle uniquely identifies a tc object and is used to refer
+to other tc objects when constructing tc trees.
++
+[source,c]
+-----
+void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t handle);
+uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc);
+-----
+
+Interface Index::
+The interface index specifies the network device the traffic object
+is attached to. The function `rtnl_tc_set_link()` should be preferred
+when setting the interface index. It stores the reference to the link
+object in the tc object and allows retrieving the `mtu` and `linktype`
+automatically.
++
+[source,c]
+-----
+void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex);
+void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link);
+int rtnl_tc_get_ifindex(struct rtnl_tc *tc);
+-----
+
+Link Type::
+The link type specifies the kind of link that is used by the network
+device (e.g. ethernet, ATM, ...). It is derived automatically when
+the network device is specified with `rtnl_tc_set_link()`.
+The default fallback is `ARPHRD_ETHER` (ethernet).
++
+[source,c]
+-----
+void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type);
+uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc);
+-----
+
+Kind::
+The kind character string specifies the type of qdisc, class,
+classifier. Setting the kind results in the module specific
+structure being allocated. Therefore it is imperative to call
+`rtnl_tc_set_kind()` before using any type specific API functions
+such as `rtnl_htb_set_rate()`.
++
+[source,c]
+-----
+int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind);
+char *rtnl_tc_get_kind(struct rtnl_tc *tc);
+-----
+
+MPU::
+The Minimum Packet Unit specifies the minimum packet size which will
+be transmitted
+ever be seen by this traffic control object. This value is used for
+rate calculations. Not all object implementations will make use of
+this value. The default value is 0.
++
+[source,c]
+-----
+void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu);
+uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc);
+-----
+
+MTU::
+The Maximum Transmission Unit specifies the maximum packet size which
+will be transmitted. The value is derived from the link specified
+with `rtnl_tc_set_link()` if not overwritten with `rtnl_tc_set_mtu()`.
+If no link and MTU is specified, the value defaults to 1500
+(ethernet).
++
+[source,c]
+-----
+void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu);
+uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc);
+-----
+
+Overhead::
+The overhead specifies the additional overhead per packet caused by
+the network layer. This value can be used to correct packet size
+calculations if the packet size on the wire does not match the packet
+size seen by the kernel. The default value is 0.
++
+[source,c]
+-----
+void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead);
+uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc);
+-----
+
+Parent::
+Specifies the parent traffic control object. The parent is identifier
+by its handle. Special values are:
+- `TC_H_ROOT`: attach tc object directly to network device (root
+ qdisc, root classifier)
+- `TC_H_INGRESS`: same as `TC_H_ROOT` but on the ingress side of the
+ network stack.
++
+[source,c]
+-----
+void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent);
+uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc);
+-----
+
+Statistics::
+Generic statistics, see <<tc_stats>> for additional information.
++
+[source,c]
+-----
+uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id);
+-----
+
+[[tc_stats]]
+==== Accessing Statistics
+
+The traffic control object holds a set of generic statistics. Not all
+traffic control modules will make use of all of these statistics. Some
+modules may provide additional statistics via their own APIs.
+
+.Statistic identifiers `(enum rtnl_tc_stat)`
+[cols="m,,", options="header", frame="topbot"]
+|====================================================================
+| ID | Type | Description
+| RTNL_TC_PACKETS | Counter | Total # of packets transmitted
+| RTNL_TC_BYTES | Counter | Total # of bytes transmitted
+| RTNL_TC_RATE_BPS | Rate | Current bytes/s rate
+| RTNL_TC_RATE_PPS | Rate | Current packets/s rate
+| RTNL_TC_QLEN | Rate | Current length of the queue
+| RTNL_TC_BACKLOG | Rate | # of packets currently backloged
+| RTNL_TC_DROPS | Counter | # of packets dropped
+| RTNL_TC_REQUEUES | Counter | # of packets requeued
+| RTNL_TC_OVERLIMITS | Counter | # of packets that exceeded the limit
+|====================================================================
+
+NOTE: `RTNL_TC_RATE_BPS` and `RTNL_TC_RATE_PPS` only return meaningful
+ values if a rate estimator has been configured.
+
+.Usage Example: Retrieving tc statistics
+[source,c]
+-------
+#include <netlink/route/tc.h>
+
+uint64_t drops, qlen;
+
+drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS);
+qlen = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_QLEN);
+-------
+
+==== Rate Table Calculations
+
+[[tc_qdisc]]
+=== Queueing Discipline (qdisc)
+
+.Classless Qdisc
+
+The queueing discipline (qdisc) is used to implement fair queueing,
+priorization or rate control. It provides a _enqueue()_ and
+_dequeue()_ operation. Whenever a network packet leaves the networking
+stack over a network device, be it a physical or virtual device, it
+will be enqueued to a qdisc unless the device is queueless. The
+_enqueue()_ operation is followed by an immediate call to _dequeue()_
+for the same qdisc to eventually retrieve a packet which can be
+scheduled for transmission by the driver. Additionally, the networking
+stack runs a watchdog which polls the qdisc regularly to dequeue and
+send packets even if no new packets are being enqueued.
+
+This additional watchdog is required due to the fact that qdiscs may
+hold on to packets and not return any packets upon _dequeue()_ in
+order to enforce bandwidth restrictions.
+
+image:classless_qdisc_nbands.png[alt="Multiband Qdisc", float="right"]
+
+The figure illustrates a trivial example of a classless qdisc
+consisting of three bands (queues). Use of multiple bands is a common
+technique in qdiscs to implement fair queueing between flows or
+prioritize differentiated services.
+
+Classless qdiscs can be regarded as a blackbox, their inner workings
+can only be steered using the configuration parameters provided by the
+qdisc. There is no way of taking influence on the structure of its
+internal queues itself.
+
+.Classful Qdisc
+
+Classful qdiscs allow for the queueing structure and classification
+process to be created by the user.
+
+image:classful_qdisc.png["Classful Qdisc"]
+
+The figure above shows a classful qdisc with a classifier attached to
+it which will make the decision whether to enqueue a packet to traffic
+class +1:1+ or +1:2+. Unlike with classless qdiscs, classful qdiscs
+allow the classification process and the structure of the queues to be
+defined by the user. This allows for complex traffic class rules to
+be applied.
+
+.List of Qdisc Implementations
+[options="header", frame="topbot", cols="2,1^,8"]
+|======================================================================
+| Qdisc | Classful | Description
+| ATM | Yes | FIXME
+| Blackhole | No | This qdisc will drop all packets passed to it.
+| CBQ | Yes |
+The CBQ (Class Based Queueing) is a classful qdisc which allows
+creating traffic classes and enforce bandwidth limitations for each
+class.
+| DRR | Yes |
+The DRR (Deficit Round Robin) scheduler is a classful qdisc
+impelemting fair queueing. Each class is assigned a quantum specyfing
+the maximum number of bytes that can be served per round. Unused
+quantum at the end of the round is carried over to the next round.
+| DSMARK | Yes | FIXME
+| FIFO | No | FIXME
+| GRED | No | FIXME
+| HFSC | Yes | FIXME
+| HTB | Yes | FIXME
+| mq | Yes | FIXME
+| multiq | Yes | FIXME
+| netem | No | FIXME
+| Prio | Yes | FIXME
+| RED | Yes | FIXME
+| SFQ | Yes | FIXME
+| TBF | Yes | FIXME
+| teql | No | FIXME
+|======================================================================
+
+
+.QDisc API Overview
+[cols="a,a", options="header", frame="topbot"]
+|====================================================================
+| Attribute | C Interface
+|
+Allocation / Freeing::
+|
+[source,c]
+-----
+struct rtnl_qdisc *rtnl_qdisc_alloc(void);
+void rtnl_qdisc_put(struct rtnl_qdisc *qdisc);
+-----
+|
+Addition::
+|
+[source,c]
+-----
+int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags,
+ struct nl_msg **result);
+int rtnl_qdisc_add(struct nl_sock *sock, struct rtnl_qdisc *qdisc,
+ int flags);
+-----
+|
+Modification::
+|
+[source,c]
+-----
+int rtnl_qdisc_build_change_request(struct rtnl_qdisc *old,
+ struct rtnl_qdisc *new,
+ struct nl_msg **result);
+int rtnl_qdisc_change(struct nl_sock *sock, struct rtnl_qdisc *old,
+ struct rtnl_qdisc *new);
+-----
+|
+Deletion::
+|
+[source,c]
+-----
+int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc,
+ struct nl_msg **result);
+int rtnl_qdisc_delete(struct nl_sock *sock, struct rtnl_qdisc *qdisc);
+-----
+|
+Cache::
+|
+[source,c]
+-----
+int rtnl_qdisc_alloc_cache(struct nl_sock *sock,
+ struct nl_cache **cache);
+struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int, uint32_t);
+
+struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t);
+-----
+|====================================================================
+
+[[qdisc_get]]
+==== Retrieving Qdisc Configuration
+
+The function rtnl_qdisc_alloc_cache() is used to retrieve the current
+qdisc configuration in the kernel. It will construct a +RTM_GETQDISC+
+netlink message, requesting the complete list of qdiscs configured in
+the kernel.
+
+[source,c]
+-------
+#include <netlink/route/qdisc.h>
+
+struct nl_cache *all_qdiscs;
+
+if (rtnl_link_alloc_cache(sock, &all_qdiscs) < 0)
+ /* error while retrieving qdisc cfg */
+-------
+
+The cache can be accessed using the following functions:
+
+- Search qdisc with matching ifindex and handle:
++
+[source,c]
+--------
+struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, uint32_t handle);
+--------
+- Search qdisc with matching ifindex and parent:
++
+[source,c]
+--------
+struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, int ifindex , uint32_t parent);
+--------
+- Or any of the generic cache functions (e.g. nl_cache_search(), nl_cache_dump(), etc.)
+
+.Example: Search and print qdisc
+[source,c]
+-------
+struct rtnl_qdisc *qdisc;
+int ifindex;
+
+ifindex = rtnl_link_get_ifindex(eth0_obj);
+
+/* search for qdisc on eth0 with handle 1:0 */
+if (!(qdisc = rtnl_qdisc_get(all_qdiscs, ifindex, TC_HANDLE(1, 0))))
+ /* no such qdisc found */
+
+nl_object_dump(OBJ_CAST(qdisc), NULL);
+
+rtnl_qdisc_put(qdisc);
+-------
+
+[[qdisc_add]]
+==== Adding a Qdisc
+
+In order to add a new qdisc to the kernel, a qdisc object needs to be
+allocated. It will hold all attributes of the new qdisc.
+
+[source,c]
+-----
+#include <netlink/route/qdisc.h>
+
+struct rtnl_qdisc *qdisc;
+
+if (!(qdisc = rtnl_qdisc_alloc()))
+ /* OOM error */
+-----
+
+The next step is to specify all generic qdisc attributes using the tc
+object interface described in the section <<tc_attr>>.
+
+The following attributes must be specified:
+- IfIndex
+- Parent
+- Kind
+
+[source,c]
+-----
+/* Attach qdisc to device eth0 */
+rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj);
+
+/* Make this the root qdisc */
+rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
+
+/* Set qdisc identifier to 1:0, if left unspecified, a handle will be generated by the kernel. */
+rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1, 0));
+
+/* Make this a HTB qdisc */
+rtnl_tc_set_kind(TC_CAST(qdisc), "htb");
+-----
+
+After specyfing the qdisc kind (rtnl_tc_set_kind()) the qdisc type
+specific interface can be used to set attributes which are specific
+to the respective qdisc implementations:
+
+[source,c]
+------
+/* HTB feature: Make unclassified packets go to traffic class 1:5 */
+rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, 5));
+------
+
+Finally, the qdisc is ready to be added and can be passed on to the
+function rntl_qdisc_add() which takes care of constructing a netlink
+message requesting the addition of the new qdisc, sends the message to
+the kernel and waits for the response by the kernel. The function
+returns 0 if the qdisc has been added or updated successfully or a
+negative error code if an error occured.
+
+CAUTION: The kernel operation for updating and adding a qdisc is the
+ same. Therefore when calling rtnl_qdisc_add() any existing
+ qdisc with matching handle will be updated unless the flag
+ NLM_F_EXCL is specified.
+
+The following flags may be specified:
+[horizontal]
+NLM_F_CREATE:: Create qdisc if it does not exist, otherwise
+ -NLE_OBJ_NOTFOUND is returned.
+NLM_F_REPLACE:: If another qdisc is already attached to the same
+ parent and their handles mismatch, replace the qdisc
+ instead of returning -EEXIST.
+NLM_F_EXCL:: Return -NLE_EXISTS if a qdisc with matching handles
+ exists already.
+
+WARNING: The function rtnl_qdisc_add() requires administrator
+ privileges.
+
+[source,c]
+------
+/* Submit request to kernel and wait for response */
+err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE);
+
+/* Return the qdisc object to free memory resources */
+rtnl_qdisc_put(qdisc);
+
+if (err < 0) {
+ fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err));
+ return err;
+}
+------
+
+==== Deleting a qdisc
+
+[source,c]
+------
+#include <netlink/route/qdisc.h>
+
+struct rtnl_qdisc *qdisc;
+
+qdisc = rtnl_qdisc_alloc();
+
+rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj);
+rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
+
+rtnl_qdisc_delete(sock, qdisc)
+
+rtnl_qdisc_put(qdisc);
+------
+
+WARNING: The function rtnl_qdisc_delete() requires administrator
+ privileges.
+
+
+[[qdisc_htb]]
+==== HTB - Hierarchical Token Bucket
+
+.HTB Qdisc Attributes
+
+Default Class::
+The default class is the fallback class to which all traffic which
+remained unclassified is directed to. If no default class or an
+invalid default class is specified, packets are transmitted directly
+to the next layer (direct transmissions).
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc);
+int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls);
+-----
+
+Rate to Quantum (r2q)::
+TODO
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc);
+int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum);
+-----
+
+
+.HTB Class Attributes
+
+Priority::
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_prio(struct rtnl_class *class);
+int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio);
+-----
+
+Rate::
+The rate (bytes/s) specifies the maximum bandwidth an invidivual class
+can use without borrowing. The rate of a class should always be greater
+or erqual than the rate of its children.
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_rate(struct rtnl_class *class);
+int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil);
+-----
+
+Ceil Rate::
+The ceil rate specifies the maximum bandwidth an invidivual class
+can use. This includes bandwidth that is being borrowed from other
+classes. Ceil defaults to the class rate implying that by default
+the class will not borrow. The ceil rate of a class should always
+be greater or erqual than the ceil rate of its children.
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_ceil(struct rtnl_class *class);
+int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil);
+-----
+
+Burst::
+TODO
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class);
+int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t burst);
+-----
+
+Ceil Burst::
+TODO
++
+[source,c]
+-----
+uint32_t rtnl_htb_get_bbuffer(struct rtnl_class *class);
+int rtnl_htb_set_bbuffer(struct rtnl_class *class, uint32_t burst);
+-----
+
+Quantum::
+TODO
++
+[source,c]
+-----
+int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum);
+-----
+
+extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t);
+
+
+
+
+[[tc_class]]
+=== Class
+
+[options="header", cols="s,a,a,a,a"]
+|=======================================================================
+| | UNSPEC | TC_H_ROOT | 0:pY | pX:pY
+| UNSPEC 3+^|
+[horizontal]
+qdisc =:: root-qdisc
+class =:: root-qdisc:0
+|
+[horizontal]
+qdisc =:: pX:0
+class =:: pX:0
+| 0:hY 3+^|
+[horizontal]
+qdisc =:: root-qdisc
+class =:: root-qdisc:hY
+|
+[horizontal]
+qdisc =:: pX:0
+class =:: pX:hY
+| hX:hY 3+^|
+[horizontal]
+qdisc =:: hX:
+class =:: hX:hY
+|
+if pX != hX
+ return -EINVAL
+[horizontal]
+qdisc =:: hX:
+class =:: hX:hY
+|=======================================================================
+
+[[tc_cls]]
+=== Classifier (cls)
+
+TODO
+
+[[tc_classid_mngt]]
+=== ClassID Management
+
+TODO
+
+[[tc_pktloc]]
+=== Packet Location Aliasing (pktloc)
+
+TODO
+
+[[tc_api]]
+=== Traffic Control Module API
+
+TODO
diff --git a/doc/src/hidden.c b/doc/src/hidden.c
new file mode 100644
index 00000000..a63621d7
--- /dev/null
+++ b/doc/src/hidden.c
@@ -0,0 +1,42 @@
+/**
+ * \cond skip
+ * vim:syntax=doxygen
+ * \endcond
+
+\page auto_ack_warning Disabling Auto-ACK
+
+\attention Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this
+ function to return immediately after sending the netlink message.
+ The function will not wait for an eventual error message. It is
+ the responsibility of the caller to handle any error messages or
+ ACKs returned.
+
+\page pointer_lifetime_warning Pointer Lifetime
+
+\attention The reference counter of the returned object is not incremented.
+ Therefore, the returned pointer is only valid during the lifetime
+ of the parent object. Increment the reference counter if the object
+ is supposed to stay around after the parent object was freed.
+
+\page private_struct Private Structure
+
+\note The definition of this structure is private to allow modification
+ without breaking API. Use the designated accessor functions to
+ access individual object attributes.
+
+\page read_only_attribute Read-Only Attribute
+
+\note The attribute this accessor is modifying is a read-only attribute
+ which can not be modified in the kernel. Any changes to the
+ attribute only have an effect on the local copy of the object. The
+ accessor function is provided solely for the purpose of creating
+ objects for comparison and filtering.
+
+\page low_level_api Low Level API
+
+\note This is a low level API function. A high level function implementing
+ the same functionality with a simplified usage pattern exists. This
+ function is available as an alternative if the default library
+ behaviour is not desirable.
+
+*/
diff --git a/doc/src/toc.c b/doc/src/toc.c
new file mode 100644
index 00000000..a91c2a71
--- /dev/null
+++ b/doc/src/toc.c
@@ -0,0 +1,54 @@
+/**
+ * \cond skip
+ * vim:syntax=doxygen
+ * \endcond
+
+\mainpage
+
+\section main_intro Introduction
+
+libnl is a set of libraries to deal with the netlink protocol and some
+of the high level protocols implemented on top of it. The goal is to
+provide APIs on different levels of abstraction. The core library libnl
+provides a fundamental set of functions to deal with sockets, construct
+messages, and send/receive those messages. Additional high level interfaces
+for several individual netlink protocols are provided in separate
+libraries (e.g. "nl-route", "nl-genl", ...).
+
+The library is designed to ensure that all components are optional, i.e.
+even though the core library provides a caching system which allows to
+easly manage objects of any kind, no application is required to use this
+caching system if it has no need for it.
+
+The library was developed and tested on 2.6.x and 3.x kernel releases. It
+may or may not work with older kernel series. Also, although all netlink
+protocols are required to maintain backwards compatibility, this has not
+always achieved and undesired side effects can occur if a recent libnl
+version is used with a considerably older kernel.
+
+\section main_toc Table of Contents
+
+\section main_trees GIT Trees
+
+\subsection tree_dev Development Tree
+
+@code
+git://git.infradead.org/users/tgr/libnl.git
+@endcode
+- Web: http://git.infradead.org/users/tgr/libnl.git
+
+\section main_website Website
+
+- http://www.infradead.org/~tgr/libnl/
+
+\section main_mailinglist Mailinglist
+
+Please post questions and patches to the libnl mailinglist:
+
+@code
+libnl@lists.infradead.org
+@endcode
+
+- Archives: http://canuck.infradead.org/pipermail/libnl/
+
+*/
diff --git a/doc/stylesheets/asciidoc-manpage.css b/doc/stylesheets/asciidoc-manpage.css
new file mode 100644
index 00000000..45eba236
--- /dev/null
+++ b/doc/stylesheets/asciidoc-manpage.css
@@ -0,0 +1,18 @@
+/* Overrides for manpage documents */
+h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+h2 {
+ border-style: none;
+}
+div.sectionbody {
+ margin-left: 3em;
+}
+
+@media print {
+ div#toc { display: none; }
+}
+
diff --git a/doc/stylesheets/asciidoc.css b/doc/stylesheets/asciidoc.css
new file mode 100644
index 00000000..2852168b
--- /dev/null
+++ b/doc/stylesheets/asciidoc.css
@@ -0,0 +1,526 @@
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ /* OLD: font-family: Arial,Helvetica,sans-serif; */
+ font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ /* color: blue; */
+ color: #990000;
+ text-decoration: none;
+}
+a:visited {
+ /* color: fuchsia; */
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+em {
+ font-style: italic;
+ /* color: navy; */
+}
+
+strong {
+ font-weight: bold;
+ color: black;
+ /* color: #083194; */
+}
+
+h1, h2, h3, h4, h5, h6 {
+ /* color: #527bbd; */
+ color: #990000;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+#author {
+ /* color: #527bbd; */
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ /* color: #606060; */
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ /* OLD: color: #527bbd; */
+ color: #990000;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ /* border-left: 5px solid #f0f0f0; */
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #777777;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ /* OLD: color: #527bbd; */
+ color: #990000;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ /* color: navy; */
+ color: #990000;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ /* color: #527bbd; */
+ color: #990000;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+tt {
+ font-family: monospace;
+ font-size: inherit;
+ /* color: navy; */
+ color: black;
+}
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ /* border: 3px solid #527bbd; */
+ border: 2px solid #990000;
+}
+thead, p.table.header {
+ font-weight: bold;
+ /* color: #527bbd; */
+ color: #990000;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+.monospaced {
+ font-family: monospace;
+ font-size: inherit;
+ color: navy;
+}
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ /* color: #527bbd; */
+ color: #990000;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ /* border-color: #527bbd; */
+ border-color: #990000;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ /* border-color: #527bbd; */
+ border-color: #990000;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
diff --git a/doc/stylesheets/docbook-xsl.css b/doc/stylesheets/docbook-xsl.css
new file mode 100644
index 00000000..6df2944f
--- /dev/null
+++ b/doc/stylesheets/docbook-xsl.css
@@ -0,0 +1,322 @@
+/*
+ CSS stylesheet for XHTML produced by DocBook XSL stylesheets.
+ Tested with XSL stylesheets 1.61.2, 1.67.2
+*/
+
+span.strong {
+ font-weight: bold;
+}
+
+body blockquote {
+ margin-top: .75em;
+ line-height: 1.5;
+ margin-bottom: .75em;
+}
+
+html body {
+ margin: 1em 5% 1em 5%;
+ line-height: 1.2;
+}
+
+body div {
+ margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6
+{
+ color: #527bbd;
+ font-family: tahoma, verdana, sans-serif;
+}
+
+div.toc p:first-child,
+div.list-of-figures p:first-child,
+div.list-of-tables p:first-child,
+div.list-of-examples p:first-child,
+div.example p.title,
+div.sidebar p.title
+{
+ font-weight: bold;
+ color: #527bbd;
+ font-family: tahoma, verdana, sans-serif;
+ margin-bottom: 0.2em;
+}
+
+body h1 {
+ margin: .0em 0 0 -4%;
+ line-height: 1.3;
+ border-bottom: 2px solid silver;
+}
+
+body h2 {
+ margin: 0.5em 0 0 -4%;
+ line-height: 1.3;
+ border-bottom: 2px solid silver;
+}
+
+body h3 {
+ margin: .8em 0 0 -3%;
+ line-height: 1.3;
+}
+
+body h4 {
+ margin: .8em 0 0 -3%;
+ line-height: 1.3;
+}
+
+body h5 {
+ margin: .8em 0 0 -2%;
+ line-height: 1.3;
+}
+
+body h6 {
+ margin: .8em 0 0 -1%;
+ line-height: 1.3;
+}
+
+body hr {
+ border: none; /* Broken on IE6 */
+}
+div.footnotes hr {
+ border: 1px solid silver;
+}
+
+div.navheader th, div.navheader td, div.navfooter td {
+ font-family: sans-serif;
+ font-size: 0.9em;
+ font-weight: bold;
+ color: #527bbd;
+}
+div.navheader img, div.navfooter img {
+ border-style: none;
+}
+div.navheader a, div.navfooter a {
+ font-weight: normal;
+}
+div.navfooter hr {
+ border: 1px solid silver;
+}
+
+body td {
+ line-height: 1.2
+}
+
+body th {
+ line-height: 1.2;
+}
+
+ol {
+ line-height: 1.2;
+}
+
+ul, body dir, body menu {
+ line-height: 1.2;
+}
+
+html {
+ margin: 0;
+ padding: 0;
+}
+
+body h1, body h2, body h3, body h4, body h5, body h6 {
+ margin-left: 0
+}
+
+body pre {
+ margin: 0.5em 10% 0.5em 1em;
+ line-height: 1.0;
+ color: navy;
+}
+
+tt.literal, code.literal {
+ color: navy;
+}
+
+.programlisting, .screen {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ margin: 0.5em 10% 0.5em 0;
+ padding: 0.5em 1em;
+}
+
+div.sidebar {
+ background: #ffffee;
+ margin: 1.0em 10% 0.5em 0;
+ padding: 0.5em 1em;
+ border: 1px solid silver;
+}
+div.sidebar * { padding: 0; }
+div.sidebar div { margin: 0; }
+div.sidebar p.title {
+ margin-top: 0.5em;
+ margin-bottom: 0.2em;
+}
+
+div.bibliomixed {
+ margin: 0.5em 5% 0.5em 1em;
+}
+
+div.glossary dt {
+ font-weight: bold;
+}
+div.glossary dd p {
+ margin-top: 0.2em;
+}
+
+dl {
+ margin: .8em 0;
+ line-height: 1.2;
+}
+
+dt {
+ margin-top: 0.5em;
+}
+
+dt span.term {
+ font-style: normal;
+ color: navy;
+}
+
+div.variablelist dd p {
+ margin-top: 0;
+}
+
+div.itemizedlist li, div.orderedlist li {
+ margin-left: -0.8em;
+ margin-top: 0.5em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+
+div.sidebar ul, div.sidebar ol {
+ margin-left: 2.8em;
+}
+
+div.itemizedlist p.title,
+div.orderedlist p.title,
+div.variablelist p.title
+{
+ margin-bottom: -0.8em;
+}
+
+div.revhistory table {
+ border-collapse: collapse;
+ border: none;
+}
+div.revhistory th {
+ border: none;
+ color: #527bbd;
+ font-family: tahoma, verdana, sans-serif;
+}
+div.revhistory td {
+ border: 1px solid silver;
+}
+
+/* Keep TOC and index lines close together. */
+div.toc dl, div.toc dt,
+div.list-of-figures dl, div.list-of-figures dt,
+div.list-of-tables dl, div.list-of-tables dt,
+div.indexdiv dl, div.indexdiv dt
+{
+ line-height: normal;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/*
+ Table styling does not work because of overriding attributes in
+ generated HTML.
+*/
+div.table table,
+div.informaltable table
+{
+ margin-left: 0;
+ margin-right: 5%;
+ margin-bottom: 0.8em;
+}
+div.informaltable table
+{
+ margin-top: 0.4em
+}
+div.table thead,
+div.table tfoot,
+div.table tbody,
+div.informaltable thead,
+div.informaltable tfoot,
+div.informaltable tbody
+{
+ /* No effect in IE6. */
+ border-top: 3px solid #527bbd;
+ border-bottom: 3px solid #527bbd;
+}
+div.table thead, div.table tfoot,
+div.informaltable thead, div.informaltable tfoot
+{
+ font-weight: bold;
+}
+
+div.mediaobject img {
+ margin-bottom: 0.8em;
+}
+div.figure p.title,
+div.table p.title
+{
+ margin-top: 1em;
+ margin-bottom: 0.4em;
+}
+
+div.calloutlist p
+{
+ margin-top: 0em;
+ margin-bottom: 0.4em;
+}
+
+a img {
+ border-style: none;
+}
+
+@media print {
+ div.navheader, div.navfooter { display: none; }
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
diff --git a/doc/stylesheets/flask-manpage.css b/doc/stylesheets/flask-manpage.css
new file mode 100644
index 00000000..75a2dda0
--- /dev/null
+++ b/doc/stylesheets/flask-manpage.css
@@ -0,0 +1 @@
+/* Empty placeholder file */
diff --git a/doc/stylesheets/flask.css b/doc/stylesheets/flask.css
new file mode 100644
index 00000000..8d33bc49
--- /dev/null
+++ b/doc/stylesheets/flask.css
@@ -0,0 +1,584 @@
+/*
+ * AsciiDoc 'flask' theme for xhtml11 and html5 backends. A shameless knock-off
+ * of the Flask website styling (http://flask.pocoo.org/docs/).
+ *
+ * The implementation is straight-forward, consisting of the asciidoc.css file
+ * followed by theme specific overrides.
+ *
+ * */
+
+
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #777777;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+tt {
+ font-family: monospace;
+ font-size: inherit;
+ color: navy;
+}
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+.monospaced {
+ font-family: monospace;
+ font-size: inherit;
+ color: navy;
+}
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * Theme specific overrides of the preceding (asciidoc.css) CSS.
+ *
+ */
+body {
+ font-family: Garamond, Georgia, serif;
+ font-size: 17px;
+ color: #3E4349;
+ line-height: 1.3em;
+}
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Garmond, Georgia, serif;
+ font-weight: normal;
+ border-bottom-width: 0;
+ color: #3E4349;
+}
+div.title, caption.title { color: #596673; font-weight: bold; }
+h1 { font-size: 240%; }
+h2 { font-size: 180%; }
+h3 { font-size: 150%; }
+h4 { font-size: 130%; }
+h5 { font-size: 100%; }
+h6 { font-size: 100%; }
+#header h1 { margin-top: 0; }
+#toc {
+ color: #444444;
+ line-height: 1.5;
+ padding-top: 1.5em;
+}
+#toctitle {
+ font-size: 20px;
+}
+#toc a {
+ border-bottom: 1px dotted #999999;
+ color: #444444 !important;
+ text-decoration: none !important;
+}
+#toc a:hover {
+ border-bottom: 1px solid #6D4100;
+ color: #6D4100 !important;
+ text-decoration: none !important;
+}
+div.toclevel1 { margin-top: 0.2em; font-size: 16px; }
+div.toclevel2 { margin-top: 0.15em; font-size: 14px; }
+em, dt, td.hdlist1 { color: black; }
+strong { color: #3E4349; }
+a { color: #004B6B; text-decoration: none; border-bottom: 1px dotted #004B6B; }
+a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; }
+a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; }
+div.tableblock > table, table.tableblock { border: 3px solid #E8E8E8; }
+th.tableblock, td.tableblock { border: 1px solid #E8E8E8; }
+ul > li > * { color: #3E4349; }
+pre, tt, .monospaced { font-family: Consolas,Menlo,'Deja Vu Sans Mono','Bitstream Vera Sans Mono',monospace; }
+tt, .monospaced { font-size: 0.9em; color: black;
+}
+div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock > div.content { border-width: 0 0 0 3px; border-color: #E8E8E8; }
+div.verseblock { border-left-width: 0; margin-left: 3em; }
+div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
+div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }
diff --git a/doc/stylesheets/pygments.css b/doc/stylesheets/pygments.css
new file mode 100644
index 00000000..9ca3659c
--- /dev/null
+++ b/doc/stylesheets/pygments.css
@@ -0,0 +1,66 @@
+/*
+ pygmentize filter
+*/
+.highlight .hll { background-color: #ffffcc }
+.highlight { background: #f4f4f4; }
+.highlight .c { color: #008800; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #008800 } /* Comment.Preproc */
+.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #808080 } /* Generic.Output */
+.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0040D0 } /* Generic.Traceback */
+.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
+.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
+.highlight .m { color: #666666 } /* Literal.Number */
+.highlight .s { color: #BB4444 } /* Literal.String */
+.highlight .na { color: #BB4444 } /* Name.Attribute */
+.highlight .nb { color: #AA22FF } /* Name.Builtin */
+.highlight .nc { color: #0000FF } /* Name.Class */
+.highlight .no { color: #880000 } /* Name.Constant */
+.highlight .nd { color: #AA22FF } /* Name.Decorator */
+.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #00A000 } /* Name.Function */
+.highlight .nl { color: #A0A000 } /* Name.Label */
+.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #B8860B } /* Name.Variable */
+.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mf { color: #666666 } /* Literal.Number.Float */
+.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
+.highlight .sc { color: #BB4444 } /* Literal.String.Char */
+.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
+.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
+.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.highlight .sx { color: #008000 } /* Literal.String.Other */
+.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
+.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
+.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #B8860B } /* Name.Variable.Class */
+.highlight .vg { color: #B8860B } /* Name.Variable.Global */
+.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
+.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
+
diff --git a/doc/stylesheets/slidy.css b/doc/stylesheets/slidy.css
new file mode 100644
index 00000000..bbb790e7
--- /dev/null
+++ b/doc/stylesheets/slidy.css
@@ -0,0 +1,445 @@
+/* slidy.css
+
+ Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ W3C liability, trademark, document use and software licensing
+ rules apply, see:
+
+ http://www.w3.org/Consortium/Legal/copyright-documents
+ http://www.w3.org/Consortium/Legal/copyright-software
+*/
+
+/*
+ SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
+ Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
+*/
+
+body
+{
+ margin: 0 0 0 0;
+ padding: 0 0 0 0;
+ width: 100%;
+ height: 100%;
+ color: black;
+ background-color: white;
+/*
+ font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
+*/
+ font-size: 14pt;
+}
+
+div.toolbar {
+ position: fixed; z-index: 200;
+ top: auto; bottom: 0; left: 0; right: 0;
+ height: 1.2em; text-align: right;
+ padding-left: 1em;
+ padding-right: 1em;
+ font-size: 60%;
+ color: red;
+ background-color: rgb(240,240,240);
+ border-top: solid 1px rgb(180,180,180);
+}
+
+div.toolbar span.copyright {
+ color: black;
+ margin-left: 0.5em;
+}
+
+div.initial_prompt {
+ position: absolute;
+ z-index: 1000;
+ bottom: 1.2em;
+ width: 90%;
+ background-color: rgb(200,200,200);
+ opacity: 0.35;
+ background-color: rgb(200,200,200, 0.35);
+ cursor: pointer;
+}
+
+div.initial_prompt p.help {
+ text-align: center;
+}
+
+div.initial_prompt p.close {
+ text-align: right;
+ font-style: italic;
+}
+
+div.slidy_toc {
+ position: absolute;
+ z-index: 300;
+ width: 60%;
+ max-width: 30em;
+ height: 30em;
+ overflow: auto;
+ top: auto;
+ right: auto;
+ left: 4em;
+ bottom: 4em;
+ padding: 1em;
+ background: rgb(240,240,240);
+ border-style: solid;
+ border-width: 2px;
+ font-size: 60%;
+}
+
+div.slidy_toc .toc_heading {
+ text-align: center;
+ width: 100%;
+ margin: 0;
+ margin-bottom: 1em;
+ border-bottom-style: solid;
+ border-bottom-color: rgb(180,180,180);
+ border-bottom-width: 1px;
+}
+
+div.slide {
+ z-index: 20;
+ margin: 0 0 0 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-left: 20px;
+ padding-right: 20px;
+ border-width: 0;
+ clear: both;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ line-height: 120%;
+ background-color: transparent;
+}
+
+div.background {
+ display: none;
+}
+
+div.handout {
+ margin-left: 20px;
+ margin-right: 20px;
+}
+
+div.slide.titlepage {
+ text-align: center;
+}
+
+div.slide.titlepage.h1 {
+ padding-top: 10%;
+}
+
+div.slide h1 {
+ padding-left: 0;
+ padding-right: 20pt;
+ padding-top: 4pt;
+ padding-bottom: 4pt;
+ margin-top: 0;
+ margin-left: 0;
+ margin-right: 60pt;
+ margin-bottom: 0.5em;
+ display: block;
+ font-size: 160%;
+ line-height: 1.2em;
+ background: transparent;
+}
+
+div.toc {
+ position: absolute;
+ top: auto;
+ bottom: 4em;
+ left: 4em;
+ right: auto;
+ width: 60%;
+ max-width: 30em;
+ height: 30em;
+ border: solid thin black;
+ padding: 1em;
+ background: rgb(240,240,240);
+ color: black;
+ z-index: 300;
+ overflow: auto;
+ display: block;
+ visibility: visible;
+}
+
+div.toc-heading {
+ width: 100%;
+ border-bottom: solid 1px rgb(180,180,180);
+ margin-bottom: 1em;
+ text-align: center;
+}
+
+/*
+pre {
+ font-size: 80%;
+ font-weight: bold;
+ line-height: 120%;
+ padding-top: 0.2em;
+ padding-bottom: 0.2em;
+ padding-left: 1em;
+ padding-right: 1em;
+ border-style: solid;
+ border-left-width: 1em;
+ border-top-width: thin;
+ border-right-width: thin;
+ border-bottom-width: thin;
+ border-color: #95ABD0;
+ color: #00428C;
+ background-color: #E4E5E7;
+}
+*/
+
+/*
+li pre { margin-left: 0; }
+
+blockquote { font-style: italic }
+
+img { background-color: transparent }
+
+p.copyright { font-size: smaller }
+*/
+
+.center { text-align: center }
+.footnote { font-size: smaller; margin-left: 2em; }
+
+/*
+a img { border-width: 0; border-style: none }
+*/
+
+a:visited { color: navy }
+a:link { color: navy }
+a:hover { color: red; text-decoration: underline }
+a:active { color: red; text-decoration: underline }
+
+a {text-decoration: none}
+.navbar a:link {color: white}
+.navbar a:visited {color: yellow}
+.navbar a:active {color: red}
+.navbar a:hover {color: red}
+
+/*
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+li { margin-left: 0.5em; margin-top: 0.5em; }
+li li { font-size: 85%; font-style: italic }
+li li li { font-size: 85%; font-style: normal }
+*/
+
+div dt
+{
+ margin-left: 0;
+ margin-top: 1em;
+ margin-bottom: 0.5em;
+ font-weight: bold;
+}
+div dd
+{
+ margin-left: 2em;
+ margin-bottom: 0.5em;
+}
+
+
+/*
+p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
+ margin-left: 1em;
+ margin-right: 1em;
+}
+*/
+
+p.subhead { font-weight: bold; margin-top: 2em; }
+
+.smaller { font-size: smaller }
+.bigger { font-size: 130% }
+
+/*
+td,th { padding: 0.2em }
+*/
+
+ul {
+ margin: 0.5em 1.5em 0.5em 1.5em;
+ padding: 0;
+}
+
+ol {
+ margin: 0.5em 1.5em 0.5em 1.5em;
+ padding: 0;
+}
+
+ul { list-style-type: square; }
+ul ul { list-style-type: disc; }
+ul ul ul { list-style-type: circle; }
+ul ul ul ul { list-style-type: disc; }
+
+/*
+ul li {
+ list-style: square;
+ margin: 0.1em 0em 0.6em 0;
+ padding: 0 0 0 0;
+ line-height: 140%;
+}
+
+ol li {
+ margin: 0.1em 0em 0.6em 1.5em;
+ padding: 0 0 0 0px;
+ line-height: 140%;
+ list-style-type: decimal;
+}
+
+li ul li {
+ font-size: 85%;
+ font-style: italic;
+ list-style-type: disc;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+li li ul li {
+ font-size: 85%;
+ font-style: normal;
+ list-style-type: circle;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+li li li ul li {
+ list-style-type: disc;
+ background: transparent;
+ padding: 0 0 0 0;
+}
+
+li ol li {
+ list-style-type: decimal;
+}
+
+
+li li ol li {
+ list-style-type: decimal;
+}
+*/
+
+/*
+ setting class="outline" on ol or ul makes it behave as an
+ ouline list where blocklevel content in li elements is
+ hidden by default and can be expanded or collapsed with
+ mouse click. Set class="expand" on li to override default
+*/
+
+ol.outline li:hover { cursor: pointer }
+ol.outline li.nofold:hover { cursor: default }
+
+ul.outline li:hover { cursor: pointer }
+ul.outline li.nofold:hover { cursor: default }
+
+ol.outline { list-style:decimal; }
+ol.outline ol { list-style-type:lower-alpha }
+
+ol.outline li.nofold {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.folded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.unfolded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
+}
+ol.outline li.folded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
+}
+
+ul.outline li.nofold {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.folded {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.unfolded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
+}
+ul.outline li.folded:hover {
+ padding: 0 0 0 20px;
+ background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
+}
+
+/* for slides with class "title" in table of contents */
+a.titleslide { font-weight: bold; font-style: italic }
+
+/*
+ hide images for work around for save as bug
+ where browsers fail to save images used by CSS
+*/
+img.hidden { display: none; visibility: hidden }
+div.initial_prompt { display: none; visibility: hidden }
+
+ div.slide {
+ visibility: visible;
+ position: inherit;
+ }
+ div.handout {
+ border-top-style: solid;
+ border-top-width: thin;
+ border-top-color: black;
+ }
+
+@media screen {
+ .hidden { display: none; visibility: visible }
+
+ div.slide.hidden { display: block; visibility: visible }
+ div.handout.hidden { display: block; visibility: visible }
+ div.background { display: none; visibility: hidden }
+ body.single_slide div.initial_prompt { display: block; visibility: visible }
+ body.single_slide div.background { display: block; visibility: visible }
+ body.single_slide div.background.hidden { display: none; visibility: hidden }
+ body.single_slide .invisible { visibility: hidden }
+ body.single_slide .hidden { display: none; visibility: hidden }
+ body.single_slide div.slide { position: absolute }
+ body.single_slide div.handout { display: none; visibility: hidden }
+}
+
+@media print {
+ .hidden { display: block; visibility: visible }
+
+/*
+ div.slide pre { font-size: 60%; padding-left: 0.5em; }
+*/
+ div.toolbar { display: none; visibility: hidden; }
+ div.slidy_toc { display: none; visibility: hidden; }
+ div.background { display: none; visibility: hidden; }
+ div.slide { page-break-before: always }
+ /* :first-child isn't reliable for print media */
+ div.slide.first-slide { page-break-before: avoid }
+}
+
+
+/* SJR: AsciiDoc slidy backend tweaks */
+
+ol, ul {
+ margin: 0.8em 1.5em 0.8em 1.8em;
+}
+li > ul, li > ol {
+ margin-top: 0.5em;
+}
+
+.outline > li.folded,
+.outline > li.unfolded {
+ color: #527bbd;
+}
+ul > li{ color: #aaa; }
+ul > li > *, ol > li > * { color: black; }
+
+li {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
diff --git a/doc/stylesheets/toc2.css b/doc/stylesheets/toc2.css
new file mode 100644
index 00000000..a1e368bc
--- /dev/null
+++ b/doc/stylesheets/toc2.css
@@ -0,0 +1,34 @@
+@media screen {
+ body {
+ max-width: 50em; /* approximately 80 characters wide */
+ margin-left: 16em;
+ }
+
+ #toc {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 13em;
+ padding: 0.5em;
+ padding-bottom: 1.5em;
+ margin: 0;
+ overflow: auto;
+ border-right: 3px solid #f8f8f8;
+ }
+
+ #toc .toclevel1 {
+ margin-top: 0.5em;
+ }
+
+ #toc .toclevel2 {
+ margin-top: 0.25em;
+ display: list-item;
+ /* OLD color: #aaaaaa; */
+ color: #990000;
+ }
+
+ #toctitle {
+ margin-top: 0.5em;
+ }
+}
diff --git a/doc/stylesheets/volnitsky-manpage.css b/doc/stylesheets/volnitsky-manpage.css
new file mode 100644
index 00000000..75a2dda0
--- /dev/null
+++ b/doc/stylesheets/volnitsky-manpage.css
@@ -0,0 +1 @@
+/* Empty placeholder file */
diff --git a/doc/stylesheets/volnitsky.css b/doc/stylesheets/volnitsky.css
new file mode 100644
index 00000000..b6c4a156
--- /dev/null
+++ b/doc/stylesheets/volnitsky.css
@@ -0,0 +1,435 @@
+/*
+ * AsciiDoc 'volnitsky' theme for xhtml11 and html5 backends.
+ * Based on css from http://volnitsky.com, which was in turn based on default
+ * theme from AsciiDoc
+ *
+ * FIXME: The stlying is still a bit rough in places.
+ *
+ */
+
+/* Default font. */
+body {
+ font-family: Georgia,"Times New Roman",Times,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Candara,Arial,sans-serif;
+}
+
+
+#toc a {
+ border-bottom: 1px dotted #999999;
+ color: #3A3A4D !important;
+ text-decoration: none !important;
+}
+#toc a:hover {
+ border-bottom: 1px solid #6D4100;
+ color: #6D4100 !important;
+ text-decoration: none !important;
+}
+a { color: #666688; text-decoration: none; border-bottom: 1px dotted #666688; }
+a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; }
+a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; }
+
+em {
+ font-style: italic;
+ color: #444466;
+}
+
+strong {
+ font-weight: bold;
+ color: #444466;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #666688;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+ letter-spacing:+0.15em;
+}
+
+h1, h2, h3 { border-bottom: 2px solid #ccd; }
+h2 { padding-top: 0.5em; }
+h3 { float: left; }
+h3 + * { clear: left; }
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid #444466;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+#author {
+ color: #444466;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+
+div.admonitionblock {
+ margin-top: 2.5em;
+ margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #444466;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock {
+ padding-left: 2.0em;
+ margin-right: 10%;
+}
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock {
+ padding-left: 2.0em;
+ margin-right: 10%;
+}
+div.verseblock > pre.content {
+ font-family: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #444466;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+ border-left: 2px solid silver;
+ padding: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: #444466;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+ border: 3px solid #444466;
+}
+thead {
+ font-weight: bold;
+ color: #444466;
+}
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: #444466;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+@media print {
+ #footer-badges { display: none; }
+}
+
+#toctitle {
+ color: #666688;
+ font-size: 1.2em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { margin-top: 0; margin-bottom: 0; }
+div.toclevel1 { margin-top: 0.3em; margin-left: 0; font-size: 1.0em; }
+div.toclevel2 { margin-top: 0.25em; margin-left: 2em; font-size: 0.9em; }
+div.toclevel3 { margin-left: 4em; font-size: 0.8em; }
+div.toclevel4 { margin-left: 6em; font-size: 0.8em; }
+
+body {
+ margin: 1em 5%;
+ max-width: 55em;
+ padding-left: 0;
+
+}
+
+.monospaced, tt, div.listingblock > div.content {
+ font-family: Consolas, "Andale Mono", "Courier New", monospace;
+ color: #004400;
+ background: #f4f4f4;
+ max-width: 80em;
+ line-height: 1.2em;
+}
+
+.paragraph p {
+ line-height: 1.5em;
+ margin-top: 1em;
+}
+
+.paragraph p, li, dd, .content { max-width: 45em; }
+.admonitionblock { max-width: 35em; }
+
+div.sectionbody div.ulist > ul > li {
+ list-style-type: square;
+ color: #aaa;
+}
+ div.sectionbody div.ulist > ul > li > * {
+ color: black;
+ /*font-size: 50%;*/
+ }
+
+
+div.sectionbody div.ulist > ul > li div.ulist > ul > li {
+ color: #ccd ;
+}
+ div.sectionbody div.ulist > ul > li div.ulist > ul > li > * {
+ color: black ;
+ }
+
+em {
+ font-style: normal ! important;
+ font-weight: bold ! important;
+ color: #662222 ! important;
+ letter-spacing:+0.08em ! important;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #666688;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #444466;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #444466;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
diff --git a/doc/stylesheets/xhtml11-quirks.css b/doc/stylesheets/xhtml11-quirks.css
new file mode 100644
index 00000000..b3b46d2a
--- /dev/null
+++ b/doc/stylesheets/xhtml11-quirks.css
@@ -0,0 +1,43 @@
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ margin-top: 0.0em;
+ margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock-attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+pre.verseblock-content {
+ font-family: inherit;
+}
+div.verseblock-attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+
+div.exampleblock-content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock.latex div.image-title { margin-top: 0.5em; }
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
diff --git a/doc/stylesheets/xhtml11.css b/doc/stylesheets/xhtml11.css
new file mode 100644
index 00000000..1e6bf5a4
--- /dev/null
+++ b/doc/stylesheets/xhtml11.css
@@ -0,0 +1,333 @@
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+ border: 1px solid red;
+*/
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+tt {
+ color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ font-family: sans-serif;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+
+div.sectionbody {
+ font-family: serif;
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+
+pre {
+ padding: 0;
+ margin: 0;
+}
+
+span#author {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+span#email {
+}
+span#revnumber, span#revdate, span#revremark {
+ font-family: sans-serif;
+}
+
+div#footer {
+ font-family: sans-serif;
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+div#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+div#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+div#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.5em;
+ margin-bottom: 2.5em;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid silver;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid silver;
+ background: #f4f4f4;
+ padding: 0.5em;
+}
+
+div.quoteblock {
+ padding-left: 2.0em;
+ margin-right: 10%;
+}
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock {
+ padding-left: 2.0em;
+ margin-right: 10%;
+}
+div.verseblock > div.content {
+ white-space: pre;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 2px solid silver;
+}
+
+div.exampleblock > div.content {
+ border-left: 2px solid silver;
+ padding: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead {
+ font-family: sans-serif;
+ font-weight: bold;
+}
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+@media print {
+ div#footer-badges { display: none; }
+}
+
+div#toctitle {
+ color: #527bbd;
+ font-family: sans-serif;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}