summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorPaul Stewart <pstew@google.com>2016-11-04 10:50:31 -0700
committerPaul Stewart <pstew@google.com>2016-11-11 12:31:50 -0800
commit054c80d775f2ae9b8f50260bdfcb821e99c0da2a (patch)
tree9749e9fc8313b0745b2b96e0102d41a63b2a2db4 /doc
parent3f563dcf99d53a43799e5bd75d7761fcd9716c5a (diff)
downloadlibnl-054c80d775f2ae9b8f50260bdfcb821e99c0da2a.tar.gz
Update libnl to 3.2.25
Commits: 2dbc1ca Generic Netlink multicast groups support 3229b32 - Prepare for 2.1.x tree - Bump interface number, we will break API in the development tree c0cd587 nl-qdisc-add tool fa89403 HTB: Append TCA_OPTIONS even if no options are set 757592e classid database 23c6191 remove obsolete nl-qdisc-add code 1884809 pfifo/bfifo qdisc support for cli libs 27883b0 nl-class-add tool a670ee5 make nl-qdisc-list installable 420438c Remove NL_DUMP_ENV code cefe7db Make nl-qdisc-delete installable 8699ba8 nl-class-delete tool 2a9c3ef nl-class-list tool 3a96527 nl-qdisc-add(8), nl-qdisc-delete(8), nl-qdisc-list(8) b9d965b Update include/linux header copies 4c6d1c5 Unified TC attributes interface b57a697 nl-cls-* tools 65e386c Packet location updates 0fe5b29 Extended pktloc to support nbyte locations for ipv6, etc. d0e5645 Avoid memcpy()/memset() when reserving space for nested attributes e1eacd6 Fix use of uninitialized data at the end of netlink message d7a561a Tons of ematch work 2f86768 basic: Only add ematches to message if available 691905b cgroup classifier improvements - enabled again - ematch support - cli tools module 897828d src/nf-queue: revert nonsensical change ee88c71 routing rules: mark support 6862c65 Include RTA_MARK in routing rule messages 6d43441 Updated arp and ethernet codes 873a64e Support for 64bit link counters IFLA_STATS64 2e6d497 Support neighbour flag NTF_USE 48cdb1f Support RT_TABLE_COMPAT 8585276 Revert "Include RTA_MARK in routing rule messages" 1eccb7b Revert "routing rules: mark support" f703192 routing rules: adapt to unified routing rules cc22992 Improved debugging messages while constructing messages/attributes 93f992e attr: Add padding if nested data does not end at an alignment boundry c7a6737 text ematch support 7903d6a Support for meta match 4267d8f classid auto generation if provided tc name does not exist 4e48d90 Correctly parse and generate classids 54e2539 nl-qdisc-list: --recursive - print tc objects recursively df36c25 nl-classid-lookup: Added --raw option to print classid without pretty printing it d95a419 ematch/meta: id definitions 738ee7f nl-qdisc-delete: Do not attempt to delete default qdiscs d283c8e Correctly state the process of sending a netlink message. A message passes through nl_send_iovec() before hitting nl_sendmsg() 59880cb pktloc: support to specify a shift operator for packet locations 8970c5c link: Support IFLA_IFALIAS attribute fd857ee link: Support IFLA_NUM_VF attribute - parses attribute if available - provides API to access value rtnl_link_get_num_vf(link, num_vf) 3fa6a6b link: API for address family specific link data 280d457 link/api: Check for null pointer in rtnl_link_af_ops_put() 800013b link: Support for AF_BRIDGE address family 67aeb74 link/api: Convert link info ops to use nl_list_head 12b82e4 link/api: Improve API documentation. 2847cf0 Make nl_str2af return a negative value if parsing fails 7ff4dee Extend rtnl_link_alloc_cache() to support address families f64ebab Add all libraries for libtool to improve linkage 407e9eb Add local copies of linux/ipv6.h and linux/snmp.h e69efad Add support for per interface ICMPv6 statistics a4efc65 link: Add support for IPv6 specific link data - parses IFLA_PROTINFO - dumps flags, cacheinfo, devconf and all statistics 2e3ca4d link: Support for IFLA_AF_SPEC 53015f8 link: AF_INET link module b6592cb link: Fix typo, use rtnl_link_af_alloc() to make sure data buffer is allocated e209971 link/inet: Fix array access 2575d03 link: Add missing IFLA_AF_SPEC container attribute ee57cc7 link: define RTM_SETLINK to allow pretty printing 01bc3c5 link/inet: documentation: add examples a3ea8a6 Make syntax of nl-link-list consistent and install it f56317f update Doxyfile to latest version 4d28cc5 link/inet: pretty printing, make output more readable 3a95620 sfq: perturb period is in seconds, not jiffies 10424b2 Rename nl_get_hz() to nl_get_user_hz() to indicate it's not the in-kernel HZ value d8eeb0a New function nl_size2str() 98ffede link/inet6: pretty printing cf5577d constify struct trans_tbl c32c3f3 socket: constify interface 09daef3 Don't build doc.c, there is no real code in it 063a2eb only perform automatic sequence checking if auto-ack mode is enabled 8a365db rename nl_send_auto_complete() -> nl_send_auto(), nl_auto_complete -> nl_complete_msg() 5a08c8f Inherit return code of NL_CB_MSG_OUT in nl_sendmsg() 6545206 Documentation updates - moved documentation from lib/doc.c to doc/src/ - splitted pages into separate files - worked over core sections, explaining the receiving and sending behaviour in much more details including the the available mechanisms to customize the behaviour - updated the html stylesheet file for increased readability, probably needs some doxygen patching to achieve what I am looking for. - enabled call graphs, not expanded by default e52a09c nl: rename nlmsg_msg_size() to nlmsg_size(), nlmsg_len() -> nlmsg_datalen() 9fbdf6c nl_recv(): Make passing creds pointer optional 4fb528b nl_recv(): Zero out sockaddr in case the caller forgot 9513d4c Rename nlmsg_for_each_msg() to nlmsg_for_each() c158d06 rename NL_AUTO_PID to NL_AUTO_PORT 7105aea addr: hide nl_addr_destroy() 5644578 Tons of documentation 82fe785 use linux/netlink.h instead of netlink/netlink-kernel.h 4b0126b prefix ipv6 link statistics identifiers with IP6 2d1626b Include <linux/pkt_cls.h> and <linux/pkt_sched.h> in <netlink/route/tc.h> for convenience 5f3dbf8 Fix function nfnl_ct_del name b5c474e allowing silent rules in build d8d67c0 Provide numeric version defines 59c3474 Add missing argument in rtnl_link_change example ae5dfb1 Make struct nl_object public, NLHDR_COMMON has been public anyway 5a9f50b __nlmsg_alloc(): Guarantee minimal message size of at least the header 2c75886 Fix off-by-one when reading IFLA_INET6_CONF and IFLA_INET6_STATS 33e9403 Print debugging info while iterating a cache based on a filter 552c85c Hold reference to obj while calling callback of cache iterator 5dc897d provide function to retrieve htb rate 8eb5b55 Unified TC API 45941f9 rename sch -> qdisc 722a227 fix module parent references 55f803c libnl-3.0 c1073d6 Documentation updates f0603a4 add missing checks for ROUTE_ATTR_MULTIPATH 38db636 add missing nl_cache_search in cache.h a0fe7a1 Omit empty nested attributes 913579b Fix out-of-tree build. 9f1abdd Fix "make distcheck". 14fa557 Set default MTU to 1500 93b6c11 Add NLE_NODEV error a62bfdb Check if all mandatory attributes are present in rtnl_tc_msg_build() 8d54934 Cleanup <netlink/route/qdisc.h> - remove dead prototypes - reformat f523f29 Allow NLSYSCONFDIR environment variable to overwrite built-in sysconfdir e4b507e Deprecate rtnl_qdisc_foreach_child() and rtnl_qdisc_foreach_cls() 7e9d5f6 correctly handle the object not found case 23845e9 Add nl_send_sync() 747b892 Qdisc API improvements and documentation 7c62050 trafic class/classifer API improvements and documentation 350b15f Move to asciidoc 475dffa Provide TC_HANDLE(maj, min) macro to generate tc handles 2dbe7d7 Initialize dump buffer in case caller missed it ef327ff Provide nl_object_dump_buf() to easily dump to buffers 23c27b4 Provide nl_cache_set_arg{1,2}() to specify cache args 0893aaf link: Make return and argument type match 41fb241 link: Provide rtnl_link_delete() to delete virtual links 48d543c API to issue direct GET requests to the kernel b5918b5 fix line removed by mistake 96bc6d6 Improve rtnl_link_change() behaviour e81814a Support for rtnl_link_add() 5a66101 dummy interface support 8ffab45 export rtnl_link_add() and rtnl_link_build_add_request() 3d70697 Add support for ARPHRD_NONE 36b0474 Support link info types with no payload 4c6dd3a Expose <netlink/route/link/inet.h> fac4885 Improve readability of classid string representation c18730d Set tc->tc_link if link cache is available 83f1411 Fix clone() of AF specific link data daefa76 Provide rtnl_tc_get_link() and fix link refcnt cc33b09 Add missing declaration of rtnl_tc_get_link() cb6a089 Adding rule with "From" option doesn't work d44c31d addr: store link object and provide rtnl_addr_get() 023c662 Use name "global" instead of "universe" for largest scope f443be6 python interface to netlink protocols 4cb1666 Provide silent variation of nl_cache_require() ed69b2a Add rtnl_tc_data_check() 58e0e1e Add nl_rate2str() aba3689 Provide documentation for rtnl_tc_data() and rtnl_tc_data_check() 053c93f Update local copies of include/linux 09210d9 HTB: Add support for level and direct pkt stats, complete access functions e56eb06 Work on libnl-python 4806c5c Don't redefine offsetof when already defined by e.g. stddef.h c881908 neigh: include ndm flags while building message ca0fc75 socket: Set SOCK_CLOEXEC if available 21d52ea Support for NLM_F_INTR 63548f5 documentation updates 7d48455 Documentation updates dea6de4 Include IFLA_LINK in link messages 5007473 more documentation updates - improved stylesheets for both doxygen and asciidoc - use of xml doxygen layout - python script to resolve <<foo>> asciidoc references to <<foo, title>> based on the target caption - graphics for netlink and netlink error headers - more link documentation 4d23836 bonding link module c79ab52 ignore various generated files 49d29e9 ignore python build directory 16d38a4 Use 'link type' instead of 'link info type' 8219cc7 VLAN: rtnl_link_is_vlan() function and API documentation bf1b5d2 removed autogenerated swig interface files from git tree 20e9797 use rtnl_link_set/get_type() f3ee216 include <linux/if.h> from <netlink/route/link.h> to export IFF_* flags 915a23f Hack doxygen CSS to avoid stupid margins in modules listing 70c9371 Updated link documentation f1c8d5b 3.1 release f999383 Remove write-only variables in lib/cache.c 7701c85 Make some functions and global variables static bbe5e94 Put "break" inside the "if" block in route_compare() d886de5 Allow building documentation out of the tree b5d081d Avoid freeing memory if vasprintf() failed 569bec5 make port map thread safe 7a46ef0 Include all files necessary to build documentation in distribution d8d96bb link: fix unaligned access to 64bit link stats 23333e5 python: Include python/ in distribution and provide a README on how to build & install cc9ae9b doc: need to include @srcdir@/src not @top_srcdir@/src 4be7adb htb: fix misplaced memset() overwriting already set htb prio option b367024 Local port leak on nl_socket_alloc/nl_socket_set_local_port(, 0) eabb753 nl-link-name2ifindex: fix usage text 6faeffe socket: introduce nl_socket_modify_err_cb 17781e4 socket: fix two typos 7adaad7 genl: genl_ctrl_grp_by_name: fix retval in case group id not found f1d9e9d 64bit unaligned access b4b853e Do not require python and swig to be present db6de56 fix license of lib/route/pktloc.c 7ac948c Remove GPL-3.0 license file. 80569bb remove dist lines for non existing files 2a37ab5 prepare for 3.2 release 5a59cf8 asciidoc xhtml stylesheet 7b0d063 lib: Use @MAJ_VERSION and @MAJ_MINOR@ for -version-info 226b387 Install headers in ${includedir}/libnl3 6e5332b Inform users about changed include location at end of configure script a73cb2f build: always install files into /etc/libnl 4c210ad Switch to libtool versioning system b50195c addr: Add missing header to <netlink/route/addr.h> 6d93b83 route: Remove dead link_cache variable 109ea68 tools: Use LDADD and link against .la files instead of LDFLAGS and -llib 67bd56f Fix a73cb2f26 fallout to allow building in separate directory 5151cbc link: Eat ACK followed by RTM_NEWLINK when requesting single link 96f17ce bonding: API to create/enslave/release 15b13dd bonding: Install <netlink/route/link/bonding.h> 076909a Bonding: Fix header guard of <netlink/route/link/bonding.h> 0d9958e Ingnore src/nl-link-enslave and nl-link-release 1c9b175 Provide micro version in <netlink/version.h> d3bb7c9 3.2.1 release f90dc63 Add libnl-cli-3.0 to pkg-config tool d17379d Fix rtnl_link object memory leak when freeing rtnl_addr objects. 6c70cf7 Don't install CLI header files when --disable-cli has been configured. 790966d Only use the MULTIPATH attribute when adding routes with more than one next hop. 30d3f8c utils: Initialize list head after freeing translation list 2bcd8ec cache: event_filter() cache operation to filter notifications 7f20c57 link: Ignore bridging notifications in link cache manager 9c7593c python: Link against nl-3 and nl-route-3 8104b52 Fix typo in debug message 659b6d6 bump to 3.2.2 03f3a58 link: generic link enslaving API bd70009 add missing IFLA_MASTER fillup 32f30b7 release 3.2.3 88940b7 build: simplify optional dirs/files in Makefile.am processing ef75c4e link: allow to add/get linkinfo of unknown type 847e269 rtnl_link_bond_add: allow to allocate bond name in case NULL is given 4a7791e dsmark: Add missing declarations for rtnl_class_dsmark_(get|set)_bitmask() 9819717 avoid dangling co_major_cache reference to NL_AUTO_PROVIDE caches d7222e5 3.2.4 release 794ac78 nl_addr_cmp(): handle prefix length during address comparison 4035e5b link: fix regression in link message parser 9015d11 3.2.5 release d111b1d cli: Use -avoid-version to link cli modules c857625 Update COPYING to fix FSF address 83ab0ae man: Remove bogus .LO macro in manpages 4cc1daa 3.2.6 release 9cbcbca 3.2.7 release a39bb56 add new function to provide neighbour event parsing a17970b Support plug qdisc - queue traffic until explicit release 0b40364 Add new nl_cache_clone() function. f7d0661 doc: Fix typos in autoconf example 965fd78 missing extended Table attribute for lib/route/ 7d47666 doc: Fix incorrect nl_socket_add_memberships() example f54ac3d Memory leak in classid.c 073ef6a genl-ctrl-list: Introduce -d|--details as a shortcut for --format=details 5399b3d genl-ctrl-list: Provide manual page 4a2962d genl-ctrl-list: fix copyright and summary 5f4d4d3 genl-ctrl-list: Mark for installation 653ea34 cache_mngr: document uncommon error codes 9af5469 tests: Convert tests/Makefile to use automake e78975a tests: fix test programs to compile again b320112 cache_mngr: Don't modify callback setup of socket c55acc4 cache_manager: Move documentation to doc/core.txt e34ed95 cache_mngr: Automatically allocate socket if needed a143037 test-cache-mngr: Let the cache manager allocate the socket adbc568 cache_mngr: Fix memory corruption after resizing e048279 nl: Make nl_recvmsgs() return the number of netlink messages processed a518a31 cache_mngr: Let nl_cache_mngr_data_ready() read multiple messages 743756f cache_mngr: API doc updates 5165366 cache_mngr: Provide nl_cache_mngr_info() to pring cache manager details 2ed371e test-cache-mngr: Allow for management of arbitary caches via argument string 2e93940 cache_mngr: Make providing the result pointer to nl_cache_mngr_add() optional 8bbcd22 genl: Make genl_unregister() a NOP if NULL pointer is passed 2e23491 cache: improve documentation of co_event_filter bd1e4d0 cache: Add co_include_event allowing caches to provide their own nl_cache_include() implementation ff3e9e3 object: Add functions to access the object type, cache and object ops ad5d2b7 3.2.8 release d726ecd Fix two bugs in 3.2.8/doc/ 6f156a7 nl: Fix return value of nl_recvmsgs() f8b4f92 3.2.9 release beb40e2 u32: add support for hashing 7b503a1 u32: example/test code for u32 hashing with HTB 183e869 doc: Check documentation generation requirements with autoconf 2fbab02 doc: add section about addressing 100403a route: Add FIXME to rtnl_route_nh_set_gateway() to fix return value 32057bc __str2flags fix fec10a2 doc: documentation restructuring 996b502 FTBFS with musl libc: Missing includes 6627ec3 tc: fix included headers 24d577c u32: fix various u32 hashing related warnings ca883b6 Fix for dumping objects to a buffer instead of file descriptor 9bb30a5 add fwmark mask support 970f5d0 correct HTB rtable/HZ calculations d733f8a use MSG_TRUNC flag to get recv message size at once 0b70de5 genl: updates to API reference documentation 71b442b genl: Add genlmsg_hdr() 3656b6f genl: Add genlmsg_user_hdr(), genlmsg_user_data(), and genlmsg_user_datalen() faef2fa genl: Support registration of families without depending on caches 8fad2e3 genl: Export genl_ops_resolve() and genl_mngt_resolve() in header 43eab46 genl: Update genl-ctrl-list(8) 0c408aa genl: modify genl_ctrl_resolve and friends to allow for module auto-loading 405d168 libnl 3.2.10 2275bb0 Fix compilation with clang d3dcde2 rtnl_netem_set_delay_distribution: fix possible segfault d8a25e4 netem: Use ARRAY_SIZE() bf54d6d Fixed address deletion 9d60ef0 Removed generated .pyc files from repository 1e75bd0 Make syntax highlighters happy f55ea7f Fix typo in still unused function that generate colored message 4be1ae2 Introduce Python's absolute_imports b369d22 Fix whitespaces at EOL 38fefc5 Fixed various str-related logick c1547d9 Flags properties description and implementation fixed fb890a5 Code cleanups 83f06bf Fix indentation (spaces vs tabs) 8959d95 Using only single quotes now and multi-line lists 454ea4a pylint's first review and trivial fixes 482c602 Refine some places 08e8b35 Remove unnecessary comments 139e3d3 nl_pickup removed from python binding 87d3709 netlink.nlattr re-implemented in more pythonic way dca358c rtnl_link_(get|set)_weight is deprecated in libnl. ffa461d Fixed memory leak in Cache destructor 3c53265 Add 'ingress' to the list of recognized TC handles. 84037be Correct missing fwmark mask proto. 69da6af genl: Wait for ACK after successful ctrl reply 49fe936 genl: cleanup genl_ctrl_resolve() 4f93364 link: rtnl_link_get_kernel() should only wait for ACK if AUTO-ACK is on 2bdcde7 Fix types-related warnings based on clang diagnostics 941ba95 libnl 3.2.11 9426d03 tbf: fix false missing attr 052a131 nl_cli_route_parse_table fixed typo in code a0f1c0e ct_dump_stats: detect when stats are not available 25d640d lib/utils.c: One kilobit now is a 1000bits (instead of 1024) 8222519 Fix the always false if (a->rt_nr_nh != a->rt_nr_nh) test 376a0e2 Fix build warning after const char ** convert 97d2460 route_clone : fix segmentation fault using nl_cache_subset to filter routes de28daf nl_addr_parse handling of 'default', 'any', and 'all' b62e019 single nexthop flags bug d10d963 Added lex.yy.c to .gitignore 582a324 Run-time version information is now available ab15d06 "%llu" replaced with "%" PRIu64 8cd2f57 Fix typo in textual description in ct_dump_stats() a2b23ff Fix warning "not checking return value of fscanf" in lib/utils.c: get_psched_settings 5eee974 Prevent potential socket file descriptor leak 717fabc configure: Check for graphviz and source-highlight before building documentation b377ab1 route: Document ROUTE_CACHE_CONTENT flag 5eeb3d3 doc: Update Doxyfile config to latest release 929bd01 configure: Check for pygmentize when building docs 3bf8712 3.2.12 release 8f2ce4d More clean NL_AUTO_PORT and NL_AUTO_SEQ usage in nl_complete_msg 0026125 Address comparison bug fixed 49c94c3 genl_ctrl_probe_by_name: fix checking of genlmsg_put() return value 49be8cd doc: Update Doxyfile.in to latest syntax b1e0a0c Remove auto-generated Doxyfile from git a820222 asprintf related fixed in yy parser fddba71 libnl-3.2.12 - ./configure --disable-doc: error: conditional "LINK_DOC" was never defined. \ Usually this means the macro was only invoked conditionally. ce72837 3.2.13 release 72c2cb9 Enabled the use of Links as context managers. e4192ff nl: Provide API to specify the default buffer size when receiving netlink messages 6ac0717 link: Support IFLA_PROMISCUITY link attribute d2876f8 link: correctly set LINK_ATTR_PROMISCUITY 36ed882 link: Support IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES 7f6880c link: Only print "promisc-mode" if users > 0 f2e2e7f link: Include IFLA_NUM_TX_QUEUES and IFLA_NUM_RX_QUEUES when building messages 36139cf doc: Provide documentation for link promis counter and rx/tx queues a35287a link: Support link grouping c3376e7 Conntrack Dump ICMP 2d674fe doc: mark route.txt as WIP db13843 doc: Split doc/ into separate packages 65c3919 Only include doc/ in dist 1fa61d1 3.2.14 release 5535f59 Don't include doc/ in toplevel dist 787f14d genl/family flags can be damaged during the auto-indentation. fedb862 ROUTE_DIFF result was not used in some place in route_compare e1b67fb Clang diagnostics e7ec197 nf-log example: correct copy-range parsing 9d6b104 nl_recv(): "else if" logick simplified and refined 6946851 nl_recv(): Memory allocation errors are handled properly now 2249eae nl_recv(): EWOULDBLOCK return value also checked da694e6 nl_recv(): small code cleanups 420e462 nl_recv(): work with credentials only if "creds" given and NL_SOCK_PASSCRED set 3c1ab42 add missing '}' in __cplusplus namespaces 40457db Exp checkpoint 20035ce Checkpoint: compare function e8b3356 "checkpoint" c675bf0 Checkpoint before compilation attempt f111efd Successful compilation of libnl-nf with expectation 4a702e6 Starting CLI work daf5f93 Compile CLI 453492c Expectation get cli tool 3cb581d update gitignore d3bec59 bugfixes 547c8f6 reinit port numers on tuple dump 4164595 Bugfixes 0741865 define advanced attributes out 2d70751 Updated nfnetlink includes; removed ifdefs; added delete exp program d2fff93 Source cleanup for upstream a8ef352 Add configure option to disable pthreads support 503270c Remove unreachable code 16e54c4 Add missing va_end() calls 3750e2a Set err and free ntbl when leaving neightbl_msg_parser 690264a Add new object op oo_id_attrs_get bc7c822 Add support for updating objects in the cache ceb8fb9 Document buffer size limitations of nl_recv() 6d52ae6 nl_recv: Don't update *buf in error path fb42f19 nl_recv: improve function documentation eb36066 nl_recv: return NLE_INVAL if buf is NULL 220d8e1 nl_recv: return NLE_INVAL if socket address pointer is NULL 65f97de nl_recv: fix indent style b25f26b socket: document nl_socket_get_fd() 8f47501 nl: improve nl_sendto() docs and error checks a721c1d doc: increase dot max graph nodes to 100 b132ee7 nl: improve API doc of transmit functions fd6f205 nl: Allow to overwrite nl_send() b28c25e nl: Improve API doc of nl_connect() and nl_close() 665464c nl: Improve API doc of nl_send_simple() a8741fa Add hash function c6f89ed Add nl hashtable structures and access functions 55c0e03 Add hash support in cache mngr e16e8fd Add hash support to link cache 6f24cf1 Add hash support to neigh cache a2207c7 Add hash support to route cache 5641c0e Hash: Properly prefix hash functions ae1e236 hashtable: Add API reference documentation 59a6b00 hashtable: Fix reference leak in nl_hashtable_free() b66d267 hashtable: remove doc section crashing doxygen 7e075c6 doc: update Doxygen layout file to latest format 5a04760 addr: Return -NLE_AF_NOSUPPORT when trying to set unsupported attributes 3132db5 addr: rtnl_addr_set_peer() is limited to IPv4 c83ecb3 doc: Revert to default stylesheet dd8a87d Add support for per cache flags 30d8626 New cache manager add cache api 0bd14aa Add NL_CACHE_AF_ITER support during refill and resync ce72565 cache: Move NL_CACHE_AF_ITER to <netlink/cache.h> 5734011 cache: Fix typo in API doc of nl_cache_set_flags() 8ffa257 cache: Move nl_cache_ops_set_flags() to cache_mngt.c ea79a76 addr: Support setting local/peer/anycast/multicast/broadcast address to NULL 125119a Add AF_BRIDGE support to link cache 64fcb47 Add AF_BRIDGE support to neigh cache cb25338 Add master support to rtnl_neigh for AF_BRIDGE objects c658a6e cache: Add reference counter to caches 3ed1f9a cache: Hold cache reference while a cache is being provided 20efa14 lock abstraction layer f5af5c5 cache: rwlock accesses to cache operations 74926f9 link: Protect registration of af and link ops with rwlock 1a2c3e3 cache: Add reference counter to cache operations 2b3912a cache: Provide safe versions of nl_cache_ops_associate() and nl_cache_ops_lookup() cb82c2a use safe cache lookup variants internally 235aa7f cache: hold a reference to the cache ops while a cache is provided over it 23c4ef6 Use NL_DBG() instead of printing warnings and errors to stderr 00132b4 cache: provide safe variant of nl_cache_mngt_require() and use it 4d94ed5 Bug Fix: Add new fill socket to cache manager a2c4bd8 Updated configure.in to make sure bison and lex are installed. 0a9d5fc configure: Replace broken AM_PROG_LEX with AC_CHECK_PROGS 3163fa7 cache: reserve room in cache_ops to avoid breaking module ABI too frequently ed3d706 Include the newly added header files in next release 05a6723 3.2.15 release 4149154 cache: only continue iterating over co_groups if it is available f535de3 3.2.16 release a96a3b6 build: rename configure.in -> .ac 9d92564 build: resolve automake-1.12 warnings f3cd3fe build: use AC_CONFIG_AUX_DIR 0ba9e99 build: use foreign mode ab7f42e build: resolve lex failure 5251188 link: basic socket-CAN support c86088f link: socket-CAN helper functions 68967eb Fix python detection code de14136 Fix make check when using --disable-cli 913a689 can: provide local copy of <linux/can/netlink.h> 7c85b8a netfilter: update local header files 89e1b30 Included defs.h so DISABLE_PTHREADS is visible. 25c407c Re-adding #defines for __aligned_be64 for older kernels 29b7137 route cache: Fix handling of ipv6 multipath routes 20a0512 Bug Fix: cache_include: Fix object ref release after successful object update 91ab1be make: automake provides a cscope target these days 96bb7c9 cache pickup: Avoid duplicates during cache pickup de21332 cache: Take cache_ops lock when modifying cache ops flags 6971932 Fix file descriptor leak on error 5d53626 nlmsg_ok comparison between signed and unsigned 6369e1f 3.2.17 release 00a5879 Add <netlink/route/link/can.h> to dist target ba38f39 cache: make sure the user has specified a callback de5744f build: Fix distribution to include 'nfnetlink_conntrack.h' 383ff94 fix include/Makefile.am f123795 3.2.18 release 3540e44 link: add carrier support b1ebda9 cache: Add new nl_cache_find api 09213ee link af ops: Add new ao_compare op to compare link af_data 310ec86 Add ao_compare support to bridge family af_data 6b4a2cb 3.2.19 release 99399ca Add new rtnl_link_af_data_compare function to compare af_data 5c3f2f0 link: Add af data compare to link objects 5291af6 link: fix reference leak in rtnl_link_af_data_compare() 7559157 Undo soname bump f20bbe1 No longer install module API headers 2b96c33 Remove obsolete release notes at end of configure 1481f97 route cache: This patch adds route priority to route object oo_id_attrs 26e22d8 3.2.20 release 1419851 fix includes after removing some headers 9680f91 Move private header files to <netlink-private/*> 1b9de9a Provide compat headers for removed private API c6abb44 Fix test-cache-mngr test c4f8033 Fix build warnings of nl-(qdisc|class|cls)-add 776cde0 Remove obsolete warning from <netlink/object-api.h> as it breaks NM build b6afd0b Provide better help text when bumping CURRENT,AGE,REVISION 83c762d 3.2.21 release 56352ab netfilter: expectation NAT direction is 32 bit attribute 87244f7 netfilter: keep 8-bit API for 32-bit NAT dir attribute 6cc5fdc can: add helper function to get CAN bus state b06c23a link cache: remove AF_UNSPEC check in rtnl_get_link and rtnl_get_link_by_name 4f088d3 netfilter: correct error in construction of NAT tuple 87458ab Fix mask calculation in nl_addr_cmp_prefix() 2005c2e cache: Make NL_ACT_* and nl_cache_ops_(get|put)() available 8571f58 neigh: Remove check for AF_UNSPEC in rtnl_neigh_get() 1c24480 can: Include "linux/can/netlink.h" in the distribution 506020a can: Fix nested message creation in can_put_attrs() 8b8e26b link: Fix af_ops leak on ENOMEM 2d36371 link: Keep reference to af_ops during lifetime of link object e576768 link: Modify link policy on the stack 4a793a4 link: Hold af_ops reference for each AF_SPEC block during lifetime of link object 8026fe2 link: Free and realloc af specific data upon rtnl_link_set_family() 9f8548b attr: Provide nla_is_nested() function fd19dae bridge: Support the new bridging attributes 5a5aa73 bridge: Provide rtnl_link_bridge_alloc() bb9911b netlink: Forward declare frequent libnl types to ease inclusion deps ee4122a vlan: Provide rtnl_link_vlan_alloc() 1ecf98a bond: Provide rtnl_link_bond_alloc() 8f151fa link: move af_data_compare to the end ded2048 link: Fix rtnl_link_af_data_compare return value 4d7680c Use thread-safe strerror_r() instead of strerror() 9e6cdbf attr: Add nla_nest_cancel() to remove partially added nested attributes 60b370d attr: Do not enforce maximum length for NLA_FLAG attributes 64315f7 attr: No longer warn about attribute of type 0 1395c69 attr: Warn application if nla_parse() observes same attribute multiple times c608b4d msg: Pretty print padding attributes in nl_msg_dump() f72bfc7 msg: Pretty print error message header even if incomplete f0f33c3 addr: Reset unused portion of binary address in nl_addr_set_binary_addr() 8852753 addr: improve API reference documentation for nl_addr_*() 780a042 addr: Update to latest address familiy definition for translation e09e7f1 tests: Add check based unit test system 549d26d rtnl-addr: Inherit prefix length to nl_addr objs in rtnl_addr_set_prefixlen() b39c9f7 rtnl-addr: Fix invalid call to nl_addr_set_prefixlen() if neither local or peer address are present 4db1151 Remove superfluous declaration of rtnl_route_put() 23e26e9 Remove rtnl_link_free() declaration from the header file. 6c9be5a nl-route-add: Add NLM_F_EXCL flag to route add aad041c genl: Provide internal function to resolve name to id ad545f2 genl: Update mt_id of cache ops when resolving genl id f9241d5 cache: Improve debugging messages of cache operations ff56710 nl: Print file:line:func in debugging messages and provide --disable-debug to disable debugging 18152ca ct: add ICMPv6 type,code and ID df66b0f genl: Fix cb reference leak in genl_ctrl_probe_by_name() 375a629 nl: Return -NLE_AGAIN if non-blocking socket would block 56eb22f msg: Pretty print generic netlink header in nl_msg_dump() ea43644 Perform no operation on nl_object_free(NULL). d3cf89e addr: only translate more recent address family names and ARP types if defined d505165 autoconf: Use PKG_CHECK_MODULES() instead of AM_PATH_CHECK() ead4cde tests: Make unit test building optional c07a6a3 attr: nla_is_nested() must access nla_type directly 59db7fb dump_attrs: "NLA_F_NESTED" => nla_is_nested(nla) 33396fa Fix leak of cb if nl_socket_alloc_cb() failed to allocate socket 3a6d256 attr: Fix typo in nla_is_nested() 979ea33 Wrong calcultation in nla_reserve ffc0ee3 configure: Convert ENABLE_UNIT_TESTS to a mere AM conditional 4e9aa6a tests: Add basic attribute unit tests ed1f4cb tests: Include util.h in dist 183052d Prepare for 3.2.22-rc1 release 8983fa9 rtnl_link_af_unregister: fix locking 807fddc nl: Increase receive buffer size to 4 pages c4d846f 3.2.22 release c76393e Add macvlan support 87bbfb6 Default to comparing all attributes if no oo_id_attrs defined 53ac502 Handle -NLE_AGAIN in nl_cache_mngr_data_ready 34a96ba netfilter/queue: generalize nfnl_queue_msg_build_verdict() d612180 netfilter/queue: introduce nfnl_queue_msg_send_verdict_batch() 01cfa9c msg: Avoid returning a negative value for nlmsg_attrlen() cd1c1e1 tests: use AM_CFLAGS instead of CFLAGS directly 2d0810e socket: Warn via debug message if local port namespace is exhausted 408a1b8 cache: Return -NLE_PROTO_MISMATCH if socket provided mismatches cache protocol c08aacc handle the case where 0 is passed to nl_size2str e77ea93 add support functions for attributes and callback handlers 7dc033f add python module for generic netlink library 89b0011 add generic netlink functions to swig 81d2b1d Add support for inet diag Netlink protocol. b3fb89f Handle the case where nl_msec2str is passed 0 msecs 162c906 Add VXLAN support. 57f1d9f link: add support for IFLA_PHYS_PORT_ID c97c8c2 Add idiag-socket-details 2ef91da More safely parse vegas info and mem info. 0eb665c Enable linker versioning 6f37b43 fix double free caused by freeing link af_data in rtnl_link_set_family() c31467e Priority of the '<' operator is higher than that of the '=' operator 8a4f16b Call to_msg_fill_raw when defined to_msg_fill is NULL 56d2bbe netfilter/ct: support optional CTA_TIMESTAMP attribute db08ef4 netfilter/ct: support optional CTA_ZONE attribute 9828326 add python examples using swig provided api 9346269 nl_cb: store nl_cb_type in struct nl_cb 86207d4 python: rework netlink callback handling 2d55872 use Callback object constructing Socket 522cf98 python: allow callback function to be a class method fa23414 python: remove unnecessary callback type definitions 6726895 python: fix typo in Socket::__str__() function b9284bc python: add send and receive functions to Socket class ae7f8cc python: remove use of PyArg_ParseTuple() for callback result f2e6f50 python: fixup VLANLink() initialization a4e588d Fixed ObjIterator for python3, fixed output of _color and added missing parameter to nl_cache_resync 1daa48c nl: Fix comment typo on recvmsgs 27019c5 nl-link-set: Add --state option fdd1ba2 route/link: fixup link->l_af_ops must be set for some kind of links cb034e1 test: add bridge creation sample defebe3 python: add basic netlink protocol bridge interface support 07669b0 test: add python bridge testing sample 978bb85 python: add bridge flags API d976e2e obj: Check for NULL pointer in nl_object_clone() 549010c rtnl-addr: set ifa_flags when creating/updating address 74db300 libnl-3.2.23-rc1 release 72bf363 doxygen-link: Be python3 compatible 3151eda doc: Add instructions on how to build docs 7f066d0 Fix up -rc1 versioning to not be included in libnl_micro_version 71ad234 include: Provide <netlink/route/link/vxlan.h> in distribution f44b82f libnl-3.2.23-rc2 release ac344b9 tests: fix make test-create-vxlan 60ceeef 3.2.23 release 43e9438 add ingress qdisc 1f3511c factor out rtnl_link_fill_info() 4263106 add veth link support 760bfab add link netns support 678753b factor out rtnl_link_info_parse() 2ae5298 python: Include all files in distribution 2d20d09 Remove extra memset from __nlmsg_alloc 4f075a4 do not compile some address families when not available d6cfd04 add initial tc action support 9073aaf add mirred tc action 6cdc32d add u32 action support 2e90ed5 add u32 action test 24e8b52 basic: add action support ff94045 add veth.h into include/Makefile.am 0404011 link: Fall back to global provisioned link cache if object is not a cache resident 3ddecb3 fix linux/pkt_act.h inclusion d969a19 add fq_codel qdisc ae19ac0 add fq_codel cli module bda0f66 build: separate compiler and linker flags 6a8d90f attr: Allow attribute type 0 b50a36b The commit 6a8d90f5fec4 "attr: Allow attribute type 0" intended to allow the parsing of {netlink,packet,unix}_diag, even if they are using type 0 for valid attributes. 8b87ae5 fix rtnl_link_info_parse() and rtnl_link_fill_info() aa1c562 add a parameter to rtnl_link_veth_add() 2b7d1d5 add declaration for rtnl_cls_change() b5309e1 fix a bug in rtnl_act_fill() 017c971 rename rtnl_mirred_set_index() to rtnl_mirred_set_ifindex() ffbfe92 add rtnl_mirred_get* functions 507897a u32: add action removal API efdde42 basic: add action removal API 4b84836 basic: Add missing declaration for rtnl_basic_add_action() 438e3ff fix some typo in lib/route/act.c a858d99 basic: Declare rtnl_act in basic.h to silence warning ea0eec9 add an assertion in rtnl_tc_set_link() 7744a5a Revert "basic: Declare rtnl_act in basic.h to silence warning" 85c0192 Revert "basic: Add missing declaration for rtnl_basic_add_action()" c855e4f add declaration for rtnl_basic_add_action() bc717a9 cache: Add missing declaration for nl_cache_find() d7aca17 u32: add rtnl_u32_get_key() 02c9c25 build: fix build failure when using different build dir (make distcheck) 62c37fa libnl-3.2.24-rc1 release 2cf635b route: add libnl name prefix to global variable link_policy 42c4133 add support for IFA_FLAGS nl attribute dcc0baa addr: add address flag IFA_F_MANAGETEMPADDR 8dabf9f bridge: add rtnl_link_add_bridge() function aa8877d act: remove rtnl_act_alloc_cache() b203c89 addr: add address flag IFA_F_NOPREFIXROUTE 815e192 python: fix build error for missing library_path in setup.py 894acf7 doc: fix typo in documentation 1a510c5 libnl-3.2.24 release 4c7a307 build: fix error when running `configure --disable-doc` b701746 route: fix return value of nl_rtgen_request() 7dbf4d5 remove the obsolete src/cls directory b3b8d72 remove nl_cache_lookup() from cache.h 3fb0aae utils: fix nl_msec2str() which always returned '0msec' for whole second durations 85ec9c7 route: rtnl_route_build_msg() should not overwrite the route scope 20aa732 basic: make BASIC_ATTR_TARGET optional 59547d2 fix comments for rtnl_act_add() cdfdfb1 remove some useless code in lib/route/cls/u32.c a126d66 fill prio and protocol attr bits when parsing cls message 68d6bd7 utils: add nl_has_capability() function 015c4ee utils: indicate capability NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE 67a7046 link: document sk == NULL case for rtnl_link_alloc_cache() c0a5b39 u32: add const to rtnl_u32_add_key_in*_addr() dfd0a80 route: don't enforce minlen in inet6_parse_protinfo() (IFLA_PROTINFO) and inet_parse_af() (IFLA_AF_SPEC) 3584a7a route: detect missing cfgid in rtnl_link_inet_get_conf() 5981a39 route: update kernel header snmp.h and fix inet6_parse_protinfo() after kernel API breakage 1048a61 route: rename internal copy of kernel header file 'inetdevice.h' to 'ip.h' a593803 route: update copy of kernel header 'ip.h' baa2cad route: fix off-by-one in rtnl_act_parse() 34bfce6 link: Catch missing io_free() implementations 5206c05 route/addr: only sent IFA_FLAGS when needed to workaround picky older kernels 690545a act: fix policy range check ab55ea8 link: call rtnl_link_set_type() in link_msg_parser() 12bd035 veth: implement ->io_alloc 6c8f67b veth: implement ->io_free 3700bf5 veth: use nl_object_clone() to deep copy rtnl_link object 65f218b add NLM_F_EXCL to rtnl_link_veth_add() cb319e2 python: fix wrongly passing argument to function in ObjIterator.next() 8ff1999 netfilter/ct: expand CT parameters that can be used in add/delete operations 69f4a03 gitignore: ignore ctags file 6722853 doc/core: reply message should send from kernel to app f55ef93 gitignore: ignore patch files 0ba7e66 veth: grab a reference for rtnl_link_veth_get_peer() e5d9b82 act: grab a reference when adding an action to a filter a5917da gitignore: ignore 'nf-ct-add' (netfilter/ct) 6d70d83 docs: add code comment to explain the meaning of the fields in rtnl_addr_cacheinfo b8d90d9 act: fix a pointer in rtnl_act_msg_parse() 35f4473 act: fix memory leak in rtnl_act_parse() a1c9915 doc: fix wrong name in documentation for rtnl_link_bridge_alloc() 0482cdc gitignore: ignore test binaries and artifacts in "tests/" 3a95fad introduce ipip tunnel support 57bdc4f introduce gre tunnel support d715b8a introduce sit tunnel support 737d5f0 ipgre: fix attribute IPGRE_ATTR_OKEY in ipgre_put_attrs() adb9f5d ipgre: rename new public API to avoid confusion 8f63014 ipvti: introduce vti tunnel support 657e257 gitignore: ignore test binaries and artifacts in "tests/" 0fd510b lib/socket: use proper typed constant UINT32_MAX for uint32_t typed port 0271578 lib/socket: don't fail if no more local ports can be assigned in nl_socket_alloc 4dd5fdd lib/socket: retry generate local port in nl_connect on ADDRINUSE 1f734a8 lib/socket: randomize the generated local port c797542 tunnel: add a copy of include/linux/if_tunnel.h 430eb40 vlan: add support for IFLA_VLAN_PROTOCOL 4dc7246 Explicitly create output directories for flex/yacc output. 425d3d6 Use paths relative to srcdir in setup.py. 1087eb5 obj: Fix dereference before NULL check 872544c msg: Remove unnecessary call of nlmsg_free on known NULL pointer 6608cd5 act: fix the logic of parsing actions bb44548 route/link: pass proper type to sizeof() for calloc() in vlan_parse() 29a3894 lib: reorder free() after printf("%p") statements d50758c route: remove unnecessary non-null check in pktloc and ematch 87682a0 cli: add error checking to nl-route-get about out-of-memory 8532ac5 cls: fix array overrun in rtnl_ematch_opnd2txt() dae0a23 cache: fix crash in nl_cache_dump_filter() when omitting the params argument d7a9e74 route/link: fix dangling pointer after rtnl_link_get_ifalias(link, NULL) 90cfeee netfilter/ct: fix calling nfnl_*_put() on uninitialized memory after nfnlmsg_*_parse() 3d5e488 route/pktloc: read_pktlocs() always returned success status 11f9cc0 ip6tnl: introduce ip6 tunnel support f8144b1 build: fix error in include/Makefile.am feda705 cli: Fix typo in error message 8f82270 cache_mngr: Return proper error code if nl_socket_alloc() fails b6cadfe cache_mngr: Fix assignment of error code in nl_cache_mngr_alloc() e4c94ea doc: fix error in core documentation for nl_cache_mngr_alloc() 2ca01af u32: prevent memcpy from NULL 8e052f5 attr: prevent garbage return value for NULL param a8b352a attr: fix compile warning in headers 853c045 cache: add missing declaration of nl_cache_move() in include/netlink/cache.h 940e5d5 doc: fix doxygen-link.py by skipping invalid entries in libnl.dict 558df52 attr: nla_get_u64() should return 0 if the attribute does not fully contain 64 bit 0446731 libnl-3.2.25-rc1 release 9e0960c doc: state in documentation that libnl3 is supposed to work with 3.x kernels 9c2dbdf ip6tnl: Use <netinet/in.h> for in6_addr and stuff c62cda9 build: let autogen.sh script change into top source directory 94e1345 build: embed the git commit id of HEAD in the configure script c4d7000 tc: add co_groups for tc qdisc and filter dcc5375 libnl-3.2.25 release Change-Id: I5c46e7d2b808ad7baf037a49523ad69191450cbf Bug: 32255299 Test: Compile (fails)
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;
+}