diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index ed78bfe..5deba44 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -519,7 +519,7 @@ FILE_VERSION_FILTER = # 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 = +LAYOUT_FILE = DoxygenLayout.xml #--------------------------------------------------------------------------- # configuration options related to warning and progress messages diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml new file mode 100644 index 0000000..29049d1 --- /dev/null +++ b/doc/DoxygenLayout.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/Makefile.am b/doc/Makefile.am index 165660b..149daba 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -4,14 +4,16 @@ ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a toc2 \ + -a numbered \ -a imagesdir="./images/" \ -a iconsdir="./images/icons" \ -a stylesdir="${abs_srcdir}/stylesheets/" %.html: %.txt - asciidoc $(ASCIIDOCOPTS) $< - ./doxygen-link.py libnl.dict $@ > doxygen-link.tmp - mv doxygen-link.tmp $@ + ./resolve-asciidoc-refs.py $< > asciidoc.tmp + asciidoc $(ASCIIDOCOPTS) -o $@ asciidoc.tmp + ./doxygen-link.py libnl.dict $@ > asciidoc.tmp + mv asciidoc.tmp $@ asciidoc: core.html route.html index.html diff --git a/doc/core.txt b/doc/core.txt index 42f1035..0ab32ec 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -20,25 +20,42 @@ 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. -.Sub Libraries +.Library Hierarchy -Several sub libraries exist which provide APIs to several netlink -protocols: +The suite is split into multiple libraries: -- link:route.html[libnl-route] Adresses, Links, Neighbours, Routing & Traffic Control -- Netfilter -- Generic Netlink +image:library_overview.png["Library Hierarchy"] -+FIXME+: Add links +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 documentation consists of this manual and the API reference pages. -Both contain references to each other and as many examples as -possible. +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. + +- <> + +The low level APIs are described in: + +- <> +- <> -+FIXME+ === Linking to this Library @@ -48,9 +65,10 @@ The main header is ``. Additional headers need to be included in your sources depending on the subsystems your program makes use of. +.Version Checking [source,c] ----- -#include +#include #if LIBNL_VER_NUM >= LIBNL_VER(3,0) /* include code if compiled with libnl version >= 3.0 */ @@ -64,8 +82,9 @@ $ gcc myprogram.c -o myprogram -lnl === Debugging -The library contains debugging statements which are printed to -+stderr+ if the environment variable +NLDBG+ is set to > 0. +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 @@ -130,7 +149,7 @@ $ NLCB=debug ./myprogram ----- -[[core_prot_fund]] +[[core_netlink_fundamentals]] == Netlink Protocol Fundamentals The netlink protocol is a socket based IPC mechanism used for @@ -147,19 +166,36 @@ each peer. 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 arbitary data but usually contains +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+) -[cols="^s,^s", width="40%", align="center"] -|============================================================== -2+| Length -| Type | Flags -2+| Sequence Number -2+| Port (Address) -|============================================================== +.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 +<> for additional information. + +Message Flags (16bit):: +The message flags may be used to modify the behaviour of a message type. +See section <> 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 @@ -193,10 +229,9 @@ 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 <>, respectively <> -- +NLMSG_DONE+ - End of multipart sequence, see <> +- +NLMSG_ERROR+ - Error message or ACK, see <> + respectively <> +- +NLMSG_DONE+ - End of multipart sequence, see <> - +NLMSG_OVERRUN+ - Overrun notification (Error) Every netlink protocol is free to define own message types. Note that @@ -231,8 +266,8 @@ msc { -------- The configuration may be changed by sending a +MSG_SETCFG+ which will -be responded to with either a ACK (see <>) -or a error message (see <>). +be responded to with either a ACK (see <>) +or a error message (see <>). ["mscgen"] -------- @@ -294,16 +329,7 @@ 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. -.Netlink Error Message Header (+struct nlmsggerr+) -[cols="^,^", width="50%"] -|============================================================== -2+| Length -|.nlmsg_type = NLMSG_ERROR | .nlmsg_flags = 0 -2+| Sequence number of the orig request -2+| Port number of the orig request -2+| Error Code (e.g. EINVAL) -2+| Netlink Message Header of orig. 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. @@ -337,6 +363,7 @@ msc { 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 @@ -349,19 +376,16 @@ The following standard flags are defined #define NLM_F_ECHO 8 -------- -- `NLM_F_REQUEST` - Message is a request, see <>. -- `NLM_F_MULTI` - Multipart message, see <> -- `NLM_F_ACK` - ACK message requested, see <>. +- `NLM_F_REQUEST` - Message is a request, see <>. +- `NLM_F_MULTI` - Multipart message, see <> +- `NLM_F_ACK` - ACK message requested, see <>. - `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 <> +multicast group or not. See <> Additional universal message flags are defined which only apply for +GET+ requests: @@ -383,8 +407,7 @@ Additional universal message flags are defined which only apply for 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 <>). +sequence of multipart messages (see <>). Another set of flags exist related to `NEW` or `SET` requests. These flags are mutually exclusive to the `GET` flags: @@ -411,20 +434,19 @@ 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 <> for more -information. +corresponding requests. See <> for more information. Sequence numbers are managed on a per socket basis, see -<> for more information on -how to use sequence numbers. +<> for more information on how to use sequence numbers. [[core_multicast]] === Multicast Groups TODO -See <> +See <> +[[core_sockets]] == Netlink Sockets In order to use the netlink protocol, a netlink socket is required. @@ -434,10 +456,10 @@ same netlink protocol, e.g. one socket to send requests and receive replies and another socket subscribed to a multicast group to receive notifications. -=== Socket Allocation & Freeing +=== Allocation & Freeing The netlink socket and all its related attributes are represented by -=struct nl_sock=. ++struct nl_sock+. [source,c] -------- @@ -470,8 +492,7 @@ 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 out automatically and matched again on the receiving side. See -<> for more -information. +<> 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 @@ -567,7 +588,7 @@ while (1) [[core_sk_cb]] === Modifiying Socket Callback Configuration -See <> for more information on +See <> for more information on callback hooks and overwriting capabilities. Each socket is assigned a callback configuration which controls the @@ -696,9 +717,9 @@ 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 <> for more information on -what implications that has. Auto-ACK mode is enabled by default. +The following functions allow to enable/disable Auto-ACK mode on a socket. +See <> for more information on what implications that has. +Auto-ACK mode is enabled by default. [source,c] -------- @@ -742,7 +763,7 @@ NOTE: Processing of NETLINK_PKTINFO has not been implemented yet. == Sending and Receiving of Messages / Data [[core_send]] -=== Sending Netlink Messages +=== 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 @@ -800,7 +821,7 @@ it will try to fall back to the peer address specified in the socket unaddressed and it is left to the kernel to find the correct peer. nl_send_iovec() also adds credentials if present and enabled -(see <>). +(see <>). The message is then passed on to nl_sendmsg(). @@ -838,8 +859,8 @@ 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 <> for more information on how to set callbacks. +callback function is returned. See <> for more information +on how to set callbacks. .Sending Raw Data with nl_sendto() @@ -889,7 +910,7 @@ nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); -------- [[core_recv]] -=== Receiving Netlink Messages +=== 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 @@ -917,12 +938,11 @@ 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 <>) the application may provide a -complete own implementation of it and overwrite all calls to -nl_recvmsgs() with the function nl_cb_overwrite_recvmsgs(). +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 <>) 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] -------- @@ -972,21 +992,21 @@ 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 <>) and the parser did not +(see <>) 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 <> for information on -how to extract valid netlink messages from the parser and on how to -control the behaviour of it. +See <> 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 -<>). +<>). The parser will first ensure that the length of the data stream provided is sufficient to contain a netlink message header and that @@ -1010,8 +1030,7 @@ 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 <>). +an ACK message back to the sender (see <>). [source,c] -------- @@ -1041,12 +1060,12 @@ Messages>>). TODO -== Netlink Message Parsing & Construction +== Message Parsing & Construction === Message Format -See <> for an introduction to -the netlink protocol and its message format. +See <> for an introduction to the netlink +protocol and its message format. .Alignment @@ -1097,8 +1116,7 @@ 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 <> +This high level interface is described in <>. .Splitting a byte stream into separate messages @@ -1234,8 +1252,7 @@ struct nlattr *nlmsg_attrdata(const struct nlmsghdr *hdr, int hdrlen); int nlmsg_attrlen(const struct nlmsghdr *hdr, int hdrlen); -------- -See <> for more information on how to use netlink -attributes. +See <> for more information on how to use netlink attributes. .Parsing a Message the Easy Way @@ -1244,8 +1261,7 @@ 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 <>. +parsing attributes, see <>. [source,c] -------- @@ -1263,13 +1279,13 @@ int nlmsg_validate(struct nlmsghdr *hdr, int hdrlen, intmaxtype, struct nla_policy *policy); -------- -See <> for an -example and more information on attribute parsing. +See <> for an example and more information on +attribute parsing. === Construction of a Message -See <> for information on the netlink -message format and alignment requirements. +See <> 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+ @@ -1374,14 +1390,13 @@ 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 <> for more information on how to fill the header. +you are replying to a request. See <> +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 <> for more information on reserving room for + equivalent to calling +nlmsg_reserve(msg, payload, NLMSG_ALIGNTO)+. + See <> for more information on reserving room for data. .Example @@ -1477,10 +1492,10 @@ NOTE: `nlmsg_append()` will *not* align the start of the data. Any .Adding attribtues to a message Construction of attributes and addition of attribtues to the message is -covereted in section <>. +covereted in section <>. [[core_attr]] -== Netlink Attributes +== Attributes Any form of payload should be encoded as netlink attributes whenever possible. Use of attributes allows to extend any netlink protocol in @@ -1510,9 +1525,8 @@ the message format will never ever change in the future. === Attribute Format Netlink attributes allow for any number of data chunks of arbitary -length to be attached to a netlink message. See <> for more information on where attributes are -stored in the message. +length to be attached to a netlink message. See <> +for more information on where attributes are stored in the message. The format of the attributes data returned by nlmsg_attrdata() is as follows: @@ -1532,17 +1546,7 @@ Every attribute must start at an offset which is a multiple of to be padded at the end, the function nla_padlen() returns the number of padding bytes that will or need to be added. --------- -0 1 2 3 -0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+-------------------------------------------------------------+ -| Length | Type | -+------------------------------+------------------------------+ -| Attribute Payload | -. . -. . -+-------------------------------------------------------------+ --------- +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 @@ -1556,16 +1560,14 @@ the next attribute. .Splitting an Attributes Stream into Attributes Although most applications will use one of the functions from the -nlmsg_parse() family (See <>) an interface exists to split the attributes stream -manually. +nlmsg_parse() family (See <>) an interface exists +to split the attributes stream manually. -As described in <> the attributes -section contains a infinite sequence or stream of attributes. The -pointer returned by nlmsg_attrdata() (See <>) points to the first attribute header. Any subsequent -attribute is accessed with the function nla_next() based on the -previous header. +As described in <> the attributes section contains a +infinite sequence or stream of attributes. The pointer returned by +nlmsg_attrdata() (See <>) points to the first attribute +header. Any subsequent attribute is accessed with the function nla_next() +based on the previous header. [source,c] -------- @@ -1654,7 +1656,7 @@ 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 <>. +expectations. See <> [[core_attr_validation]] .Attribute Validation @@ -1702,8 +1704,7 @@ introduced attributes to continue functioning. -------- #include -int nla_validate(struct nlattr *head, int len, int maxtype, - struct nla_policy *policy); +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, @@ -1712,26 +1713,24 @@ 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 -<> for an -example and more information. +<> 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 - <> --# If all is ok, 0 is returned. -[[core_attr_nla_parse]] +. 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 <> +. 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 <>. A much easier method is to use -nla_parse(). +streams themselves as described in <> +A much easier method is to use nla_parse(). [source,c] -------- @@ -1742,15 +1741,13 @@ int nla_parse(struct nlattr **attrs, int maxtype, struct nlattr *head, -------- The function nla_parse() will iterate over a stream of attributes, -validate each attribute as described in <>. If the validation of all attributes succeeds, -a pointer to each attribute is stored in the +attrs+ array at -`attrs[nla_type(attr)]`. +validate each attribute as described in <> +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 -<> for -information on how to use these functions. +<> for information on how to use these functions. .Example: @@ -1815,8 +1812,7 @@ 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 <>. + attributes recursively, see <>. ==== Iterating over a Stream of Attributes @@ -1901,8 +1897,8 @@ int my_put(struct nl_msg *msg) } -------- -See <> for datatype specific -attribute construction functions. +See <> for datatype specific attribute construction +functions. .Exception Based Attribute Construction @@ -1931,8 +1927,8 @@ nla_put_failure: } -------- -See <> for more information on the -datatype specific exception based variants. +See <> for more information on the datatype specific +exception based variants. [[core_attr_types]] === Attribute Data Types @@ -2114,11 +2110,10 @@ if (attrs[ATTR_FLAG]) [[core_attr_nested]] ==== Nested Attributes -As described in <>, 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. +As described in <>, 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. diff --git a/doc/images/attribute_hdr.png b/doc/images/attribute_hdr.png new file mode 100644 index 0000000..0e6cfda Binary files /dev/null and b/doc/images/attribute_hdr.png differ diff --git a/doc/images/ifinfomsg.png b/doc/images/ifinfomsg.png new file mode 100644 index 0000000..fb94cf7 Binary files /dev/null and b/doc/images/ifinfomsg.png differ diff --git a/doc/images/library_overview.png b/doc/images/library_overview.png new file mode 100644 index 0000000..dd9d5fe Binary files /dev/null and b/doc/images/library_overview.png differ diff --git a/doc/images/nlmsgerr.png b/doc/images/nlmsgerr.png new file mode 100644 index 0000000..58e53d5 Binary files /dev/null and b/doc/images/nlmsgerr.png differ diff --git a/doc/images/nlmsghdr.png b/doc/images/nlmsghdr.png new file mode 100644 index 0000000..dd39b9c Binary files /dev/null and b/doc/images/nlmsghdr.png differ diff --git a/doc/index.txt b/doc/index.txt index c59be0e..c207b44 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -1,16 +1,22 @@ -libnl -===== -Thomas Graf -3.0, April 12 2011: +Documentation Overview - libnl Suite +==================================== -== Table of Contents -=== Libraries - - link:core.html[Core Library] - - link:route.html[Routing Family] +== Libraries -=== Tools - - link:link.html[Link Utility] +image:library_overview.png["Library Hierarchy"] -=== Python Packages +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 b92bafc..ddc6ac3 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -2,21 +2,31 @@ body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 12px; + font-size: 13px; } /* @group Heading Levels */ +h1, h2, h3 { + color: #990000; +} + h1 { - font-size: 180%; + font-size: 150%; +} + +.title { + font-size: 150%; + font-weight: bold; + margin: 10px 2px; } h2 { - font-size: 140%; + font-size: 120%; } h3 { - font-size: 120%; + font-size: 100%; } dt { @@ -82,13 +92,15 @@ div.navtab { /* @group Link Styling */ a { - color: #3D578C; + /* color: #3D578C; */ + color: #990000; font-weight: normal; text-decoration: none; } .contents a:visited { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; } a:hover { @@ -118,7 +130,8 @@ a.elRef { } a.code { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; } a.codeRef { @@ -158,6 +171,7 @@ div.ah { 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)); @@ -167,7 +181,6 @@ div.ah { div.groupHeader { margin-left: 16px; margin-top: 12px; - margin-bottom: 6px; font-weight: bold; } @@ -185,16 +198,7 @@ body { div.contents { margin-top: 10px; margin-left: 10px; - margin-right: 10px; -} - -div.contents p { - margin-left: 30px; -} - -div.contents .fragment { - margin-left: 30px; - margin-right: 20px; + margin-right: 5px; } td.indexkey { @@ -370,8 +374,13 @@ table.memberdecls { white-space: nowrap; } +.memItemRight { + width: 100%; +} + .memTemplParams { - color: #4665A2; + /* color: #4665A2; */ + color: #990000; white-space: nowrap; } @@ -382,10 +391,11 @@ table.memberdecls { /* Styles for detailed member documentation */ .memtemplate { - font-size: 100%; - color: #4665A2; + font-size: 80%; + /* color: #4665A2; */ + color: #990000; font-weight: normal; - margin-left: 3px; + margin-left: 9px; } .memnav { @@ -397,10 +407,14 @@ table.memberdecls { padding: 2px; } +.mempage { + width: 100%; +} + .memitem { padding: 0; - border: 1px solid #C4CFE5; - margin-bottom: 30px; + margin-bottom: 10px; + margin-right: 5px; } .memname { @@ -410,17 +424,53 @@ table.memberdecls { } .memproto { - background-color: #F9FAFC; - border-bottom: 1px solid #A3B4D7; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; - color: #000000; + color: #253555; font-weight: bold; + /* text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); */ + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 8px; + border-top-left-radius: 8px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; } .memdoc { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; padding: 2px 5px; - margin-left: 30px; + background-color: #FBFCFD; + border-top-width: 0; + /* opera specific markup */ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); } .paramkey { @@ -432,13 +482,36 @@ table.memberdecls { } .paramname { - color: #602020; + /* color: #602020; */ + color: black; white-space: nowrap; } .paramname em { font-style: normal; } +.params, .retval, .exception, .tparams { + border-spacing: 6px 2px; +} + +.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; +} + + + + /* @end */ /* @group Directory (tree) */ @@ -589,14 +662,14 @@ table.doxtable th { list-style-type:none; float:left; padding-left:10px; - padding-right: 15px; + padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } -.navpath a +.navpath li.navelem a { height:32px; display:block; @@ -604,11 +677,25 @@ table.doxtable th { outline: none; } -.navpath a:hover +.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; @@ -623,6 +710,19 @@ div.summary a white-space: nowrap; } +div.ingroups +{ + font-size: 8pt; + padding-left: 5px; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + div.header { background-image:url('nav_h.png'); @@ -637,3 +737,110 @@ div.headertitle padding: 5px 5px 5px 10px; } +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 +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} + +#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; +} + diff --git a/doc/resolve-asciidoc-refs.py b/doc/resolve-asciidoc-refs.py new file mode 100755 index 0000000..5418747 --- /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 index 1f68116..b9b50b6 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -35,50 +35,316 @@ 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. -=== Protocol Definition +=== Netlink Protocol -This section describes the protocol semantics of the netlink link configuration -interface. The following netlink message types are defined: +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 new virtual network device | Notification: Link changed or added -| +RTM_DELLINK+ | Delete virtual network device | Notification: Link deleted or disappeared +| +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 the link:core.html#core_msg_types[Message Types] section of the Netlink -Library documentation for more information on common semantics of these message -types. +See link:core.html#core_msg_types[Netlink Library - Message Types] for more +information on common semantics of these message types. -.Link Message Header +==== Link Message Format -All netlink link messages share the following common header which is appended -after the netlink message header (+struct nlmsghdr+). It is defined in the -header ++ +All netlink link messages share a common header (+struct ifinfomsg+) which +is appended after the netlink header (+struct nlmsghdr+). -[source,c] ------ -struct ifinfomsg { - unsigned char ifi_family; - unsigned char __ifi_pad; - unsigned short ifi_type; /* ARPHRD_* */ - int ifi_index; /* Link index */ - unsigned ifi_flags; /* IFF_* flags */ - unsigned ifi_change; /* IFF_* change mask */ -}; ------ +image:ifinfomsg.png["Link Message Header"] -The meaning of each field may differ depending on the message type. +The meaning of each field may differ depending on the message type. A ++struct ifinfomsg+ is defined in ++ to represent the +header. -.Attributes +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 +++. 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 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+) + +[source,c] +----- +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_DEBUG 0x4 /* turn on debugging */ +#define IFF_LOOPBACK 0x8 /* is a loopback net */ +#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ +#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ +#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ +#define IFF_NOARP 0x80 /* no ARP protocol */ +#define IFF_PROMISC 0x100 /* receive all packets */ +#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ + +#define IFF_MASTER 0x400 /* master of a load balancer */ +#define IFF_SLAVE 0x800 /* slave of a load balancer */ + +#define IFF_MULTICAST 0x1000 /* Supports multicast */ + +#define IFF_PORTSEL 0x2000 /* can set media type */ +#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ +#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ + +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#define IFF_DORMANT 0x20000 /* driver signals dormant */ + +#define IFF_ECHO 0x40000 /* echo sent packets */ +----- + +=== 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 + +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 <>) +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 + +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); +----- + +==== 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 + +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 <>). + +.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. + +==== 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 + +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 + +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 Name:: @@ -86,6 +352,8 @@ The name of a network device is the human readable representation of a network device and secondary identification parameter besides the interface index. + +Kernels >= 2.6.11 support identification by link name. ++ [source,c] ----- void rtnl_link_set_name(struct rtnl_link *link, const char *name); @@ -141,8 +409,81 @@ void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight); unsigned int rtnl_link_get_weight(struct rtnl_link *link); ----- -=== Link Cache +=== Modules +[[link_bonding]] +==== Bonding + +.Example: Add bonding link +[source,c] +----- +#include + +struct rtnl_link *link; + +link = rtnl_link_alloc(); +rtnl_link_set_name(link, "my_bond"); +rtnl_link_set_type(link, "bond"); + +/* requires admin privileges */ +if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0) + /* error */ + +rtnl_link_put(link); +----- + +==== 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 to configure the vlan device */ +link = rtnl_link_alloc(); + +/* set eth0 to be our master device */ +rtnl_link_set_link(link, master_index); + +if ((err = rtnl_link_set_type(link, "vlan")) < 0) + /* error */ + +rtnl_link_vlan_set_id(link, 10); + +if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) + /* error */ + +rtnl_link_put(link); +----- == Neighbouring @@ -347,8 +688,7 @@ uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc); ----- Statistics:: -Generic statistics, see <> for -additional information. +Generic statistics, see <> for additional information. + [source,c] ----- @@ -593,8 +933,7 @@ if (!(qdisc = rtnl_qdisc_alloc())) ----- The next step is to specify all generic qdisc attributes using the tc -object interface described in the section <>. +object interface described in the section <>. The following attributes must be specified: - IfIndex diff --git a/doc/stylesheets/asciidoc.css b/doc/stylesheets/asciidoc.css index 19796dd..8ded7c9 100644 --- a/doc/stylesheets/asciidoc.css +++ b/doc/stylesheets/asciidoc.css @@ -23,12 +23,16 @@ body { a { /* color: blue; */ color: #990000; - text-decoration: underline; + text-decoration: none; } a:visited { /* color: fuchsia; */ } +a:hover { + text-decoration: underline; +} + em { font-style: italic; /* color: navy; */