diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 190fe39..8c87c64 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -92,7 +92,7 @@ ABBREVIATE_BRIEF = # 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 @@ -583,7 +583,8 @@ WARN_LOGFILE = INPUT = ../lib \ ../src/lib \ - ../include/netlink + ../include/netlink \ + 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 @@ -815,7 +816,7 @@ HTML_TIMESTAMP = NO # 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! -HTML_STYLESHEET = +HTML_STYLESHEET = libnl.css # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images @@ -1022,7 +1023,7 @@ 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. -ENUM_VALUES_PER_LINE = 4 +ENUM_VALUES_PER_LINE = 1 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. @@ -1037,7 +1038,7 @@ GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. -USE_INLINE_TREES = NO +USE_INLINE_TREES = YES # 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 @@ -1571,7 +1572,7 @@ GRAPHICAL_HIERARCHY = YES # 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 diff --git a/doc/libnl.css b/doc/libnl.css index 22c4843..b92bafc 100644 --- a/doc/libnl.css +++ b/doc/libnl.css @@ -1,473 +1,639 @@ -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: 12px; } -BODY,TD { - font-size: 90%; + +/* @group Heading Levels */ + +h1 { + font-size: 180%; } -H1 { - text-align: center; - font-size: 160%; + +h2 { + font-size: 140%; } -H2 { + +h3 { font-size: 120%; } -H3 { - font-size: 100%; -} -CAPTION { - font-weight: bold -} -DIV.qindex { - width: 100%; - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} -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; -} -TD.navtab { - font-size: 70%; -} -A.qindex { - text-decoration: none; - font-weight: bold; - color: #1A419D; -} -A.qindex:visited { - text-decoration: none; - font-weight: bold; - color: #1A419D -} -A.qindex:hover { - text-decoration: none; - background-color: #ddddff; -} -A.qindexHL { - text-decoration: none; + +dt { font-weight: bold; - background-color: #6666cc; - color: #ffffff; - border: 1px double #9295C2; -} -A.qindexHL:hover { - text-decoration: none; - background-color: #6666cc; - color: #ffffff; -} -A.qindexHL:visited { - text-decoration: none; - background-color: #6666cc; - color: #ffffff -} -A.el { - text-decoration: none; - font-weight: bold -} -A.elRef { - font-weight: bold -} -A.code:link { - text-decoration: none; - font-weight: normal; - color: #0000FF -} -A.code:visited { - text-decoration: none; - font-weight: normal; - color: #0000FF -} -A.codeRef:link { - font-weight: normal; - color: #0000FF -} -A.codeRef:visited { - font-weight: normal; - color: #0000FF -} -A:hover { - text-decoration: none; - background-color: #f2f2ff -} -DL.el { - margin-left: -1cm -} -.fragment { - font-family: monospace, fixed; - font-size: 95%; -} -PRE.fragment { - border: 1px solid #CCCCCC; - background-color: #f5f5f5; - margin-top: 4px; - margin-bottom: 4px; - margin-left: 2px; - margin-right: 8px; - padding-left: 6px; - padding-right: 6px; - padding-top: 4px; - padding-bottom: 4px; -} -DIV.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px } -DIV.groupHeader { - margin-left: 16px; - margin-top: 12px; - margin-bottom: 6px; - font-weight: bold; +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; } -DIV.groupText { - margin-left: 16px; - font-style: italic; - font-size: 90% + +p.startli, p.startdd, p.starttd { + margin-top: 2px; } -BODY { + +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; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { + color: #4665A2; +} + +a.codeRef { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +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%; +} + +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; + -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.groupText { + margin-left: 16px; + font-style: italic; +} + +body { background: white; color: black; - margin-right: 20px; - margin-left: 20px; + margin: 0; } -TD.indexkey { - background-color: #e8eef2; - 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; +div.contents { + margin-top: 10px; + margin-left: 10px; + margin-right: 10px; } -.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; + +div.contents p { + margin-left: 30px; } -.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%; + +div.contents .fragment { + margin-left: 30px; + margin-right: 20px; } -.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%; + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; } -.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%; + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; } -.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%; + +tr.memlist { + background-color: #EEF1F7; } -.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%; + +p.formulaDsp { + text-align: center; } -.search { + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +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 +} + +/* @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; -} -TH.dirtab { - background: #e8eef2; - font-weight: bold; -} -HR { - height: 1px; - border: none; - border-top: 1px solid black; + border: 1px solid #A3B4D7; } -/* Style for detailed member documentation */ +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + 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; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + .memtemplate { - font-size: 80%; - color: #606060; + font-size: 100%; + color: #4665A2; font-weight: normal; margin-left: 3px; -} -.memnav { - background-color: #e8eef2; - border: 1px solid #84b0c7; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } + .memitem { - padding: 4px; - background-color: #eef3f5; - border-width: 1px; - border-style: solid; - border-color: #dedeee; - -moz-border-radius: 8px 8px 8px 8px; + padding: 0; + border: 1px solid #C4CFE5; + margin-bottom: 30px; } + .memname { - white-space: nowrap; - font-weight: bold; -} -.memdoc{ - padding-left: 10px; + white-space: nowrap; + font-weight: bold; + margin-left: 6px; } + .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; + background-color: #F9FAFC; + border-bottom: 1px solid #A3B4D7; + padding: 6px 0px 6px 0px; + color: #000000; + font-weight: bold; + } + +.memdoc { + padding: 2px 5px; + margin-left: 30px; +} + .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; +} + +/* @end */ + +/* @group Directory (tree) */ /* for the tree view */ + .ftvtree { font-family: sans-serif; - margin:0.5em; + margin: 0px; } + /* these are for tree view when used as main index */ -.directory { - font-size: 9pt; - font-weight: bold; -} -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; + +.directory { + font-size: 9pt; + font-weight: bold; + margin: 5px; } -/* 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. */ +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} -/* .directory h3.swap { */ -/* height: 61px; */ -/* background-repeat: no-repeat; */ -/* background-image: url("yourimage.gif"); */ -/* } */ -/* .directory h3.swap span { */ -/* display: none; */ -/* } */ +/* +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. +*/ -.directory > h3 { - margin-top: 0; +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); } -.directory p { - margin: 0px; - white-space: nowrap; +.directory h3.swap span { + display: none; } -.directory div { - display: none; - margin: 0px; +*/ + +.directory > h3 { + margin-top: 0; } -.directory img { - vertical-align: -30%; + +.directory p { + margin: 0px; + white-space: nowrap; } + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + /* these are for tree view when not used as main index */ -.directory-alt { - font-size: 100%; - font-weight: bold; -} -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} -.directory-alt > h3 { - margin-top: 0; -} -.directory-alt p { - margin: 0px; - white-space: nowrap; -} -.directory-alt div { - display: none; - margin: 0px; -} -.directory-alt img { - vertical-align: -30%; + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; +} + +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; + text-align:left; +} + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.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; +} + +.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; +} + +.navpath a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; +} + +.navpath a:hover +{ + color:#6884BD; +} + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary 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 10px; } diff --git a/doc/src/core.c b/doc/src/core.c new file mode 100644 index 0000000..9520730 --- /dev/null +++ b/doc/src/core.c @@ -0,0 +1,812 @@ +/** + * \cond skip + * vim:syntax=doxygen + * \endcond + +\page core_doc Netlink Core Library (-lnl) + +\section core_intro 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, 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 with the help of netlink messages. + +\section core_toc Table of Contents + +- \ref proto_fund + - \ref core_format + - \ref core_msgtype + - \ref core_multipart + - \ref core_errmsg + - \ref core_ack +- \ref sk_doc + - \ref core_sk_alloc + - \ref core_sk_local_port + - \ref core_sk_peer_port + - \ref core_sk_fd + - \ref core_sk_buffer_size + - \ref core_sk_groups +- \ref core_send_recv + - \ref core_send + - \ref core_recv +- \ref core_msg +- \ref core_cb + +\section proto_fund 1. Netlink Protocol Fundamentals + +The netlink protocol is a socket based IPC mechanism used for communication +between any number of userspace processes and the kernel. The netlink +protocol is based on BSD sockets and uses the \c AF_NETLINK address family. +It uses a protocol type for each subsystem protocol (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. + +\subsection core_format 1.1 Message Format + +A netlink protocol is typicall 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 a fixed +size protocol specific header followed by a stream of attributes. + +The netlink message header (struct nlmsghdr) has the following format: +\code +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 | Flags | ++------------------------------+------------------------------+ +| Sequence Number | ++-------------------------------------------------------------+ +| Port (Address) | ++-------------------------------------------------------------+ +\endcode + +\subsection core_msgtype 1.2 Message Types + +Netlink differs between requests, notifications, and replies. Requests +are messages which have the \c 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. 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. + +\msc +A,B; +A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; +A<=B [label="PUT (seq=1)"]; +...; +A<=B [label="NOTIFY (seq=0)"]; +\endmsc + +\subsection core_multipart 1.3 Multipart Messages (NLM_F_MULTI) + +If the size of a reply exceeds the size of a memory page and thus exceeds +the maximum message size, the reply can be split into a series of multipart +messages. A multipart message has the \c flag NLM_F_MULTI set and the +receiver is expected to continue parsing the reply until the special +message type \c 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. + +\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)"]; +\endmsc + +\subsection core_errmsg 1.4 Error Message + +Error messages can be sent in response to a request. Error messages must +use the standard message type \c NLMSG_ERROR. The payload consists of a +error code and the original netlink mesage header of the request. Error +messages should set the sequence number to the sequence number of the +request which caused the error. + +\msc +A,B; +A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; +A<=B [label="NLMSG_ERROR code=EINVAL (seq=1)"]; +\endmsc + +\subsection core_ack 1.5 ACKs + +A sender can request an ACK message to be sent back for each request +processed by setting the \c 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. + +ACK messages also use the message type \c NLMSG_ERROR and payload format +but the error code is set to 0. + +\msc +A,B; +A=>B [label="GET (seq=1, NLM_F_REQUEST | NLM_F_ACK)"]; +A<=B [label="ACK (seq=1)"]; +\endmsc + +\section sk_doc 2. Netlink Sockets + +In order to use the netlink protocol, a netlink socket is required. Each +socket defines a completely independent context for sending and receiving +of messages. An application may use multiple sockets for the same netlink +protocol, e.g. one socket to send requests and receive replies and another +socket subscribed to a multicast group to receive notifications. + +\subsection core_sk_alloc 2.1 Socket Allocation & Freeing + +The netlink socket and all its related attributes are represented by +struct nl_sock. + +\code +struct nl_sock *nl_socket_alloc(void) +void nl_socket_free(struct nl_sock *sk) +\endcode + + +\subsection core_sk_local_port 2.2 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. + +\code +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); +\endcode + +\b Note: 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. + +\subsection core_sk_peer_port 2.3 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. + +\code +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); +\endcode + +\subsection core_sk_fd 2.4 File Descriptor + +Netlink uses the BSD socket interface, therefore a file descriptor +is behind each socket and you may use it directly. + +\code +int nl_socket_get_fd(const struct nl_sock *sk); +\endcode + +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. + +\code +int nl_socket_set_nonblocking(const struct nl_sock *sk); +\endcode + +\subsection core_sk_buffer_size 2.5 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. + +\code +int nl_socket_set_buffer_size(struct nl_sock *sk, int rx, int tx); +\endcode + +\subsection core_sk_seq_num 2.6 Sequence Numbers + +The library will automatically take care of sequence number handling for +the application. A sequence number counter is stored in struct nl_sock which +is meant to be used when sending messages which will produce a reply. + +The following function will return the sequence number counter and increment +it afterwards. + +\code +unsigned int nl_socket_use_seq(struct nl_sock *sk); +\endcode + + +if nl_send_auto_complete() is used to send messages. + +See \ref core_send_recv. + + + +It will return the current sequence number and increment the counter +afterwards. + +When receiving netlink messages on a socket, the sequence number of +each received message will be automatically compared to the last +sequence number used, therefore ensuring that each reply relates to +a request. + +This behaviour can and must be disabled if the netlink protocol +implemented does not use a request/reply model: + +\code +void nl_socket_disable_seq_check(struct nl_sock *sk); +\endcode + +\subsection core_sk_groups 2.6 Multicast Groups + +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. + +\code +void nl_join_groups(struct nl_sock *sk, int bitmask); /* obsolete */ +\endcode + +Starting with 2.6.14 a new method was introduced which supports subscribing +to an almost infinite number of multicast groups. + +\code +int nl_socket_add_memberships(struct nl_sock *sk, int group, ...); +int nl_socket_drop_memberships(struct nl_sock *sk, int group, ...); +\endcode + +\subsubsection core_sk_group_example 2.6.1 Multicast Example + +\code +// 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); + +// 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); +\endcode + + +\subsection core_sk_cb 2.7 Callback Configuration +Every socket is associated a callback configuration which enables the +applications to hook into various internal functions and control the +receiving and sendings semantics. For more information, see section +\ref core_cb. + +\code +nl_socket_alloc_cb(cb) Allocate socket based on callback set. +nl_socket_get_cb(sk) Return callback configuration. +nl_socket_set_cb(sk, cb) Replace callback configuration. +nl_socket_modify_cb(sk, ...) Modify a specific callback function. +\endcode + +\subsection core_sk_cred 2.8 Credentials + +\subsection sk_other Other Functions +\code +nl_socket_enable_auto_ack(sock) Enable automatic request of ACK. +nl_socket_disable_auto_ack(sock) Disable automatic request of ACK. +nl_socket_enable_msg_peek(sock) Enable message peeking. +nl_socket_disable_msg_peek(sock) Disable message peeking. +nl_socket_set_passcred(sk, state) Enable/disable credential passing. +nl_socket_recv_pktinfo(sk, state) Enable/disable packet information. +\endcode + +\section core_send_recv 3. Sending and Receiving of Messages / Data + +- \ref core_send + - \ref core_nl_send + - \ref core_nl_send_iovec + - \ref core_nl_sendmsg + - \ref core_send_raw + - \ref core_send_simple +- \ref core_recv + - \ref core_nl_recvmsgs + - \ref core_recvmsgs + - \ref core_recv_parse + +\subsection core_send 3.1 Sending Netlink 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 based +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(). + +\code + 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() +\endcode + +\subsubsection core_nl_send 3.1.1 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(). + +\code + nl_send(sk, msg) + | + v + nl_send_iovec(sk, msg, iov, iovlen) +\endcode + +\subsubsection core_nl_send_iovec 3.1.2 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 \ref core_sk_cred). + +The message is then passed on to nl_sendmsg(). + +\code + nl_send_iovec(sk, msg, iov, iovlen) + | + v + nl_sendmsg(sk, msg, msghdr) + |- - - - - - - - - - - - - - - - - - - - v + | NL_CB_MSG_OUT() + |<- - - - - - - - - - - - - - - - - - - -+ + v + sendmsg() +\endcode + +\subsubsection core_nl_sendmsg 3.1.3 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. + +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 +\ref core_sk_cb for more information on how to set callbacks. + +\subsubsection core_send_raw 3.1.4 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(): + +\code +int nl_sendto(struct nl_sock *sk, void *buf, size_t size); +\endcode + +\subsubsection core_send_simple 3.1.5 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. +\code +int nl_send_simple(struct nl_sock *sk, int type, int flags, + void *buf, size_t size); +\endcode + +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: +\code +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)); +\endcode + +\subsection core_recv 3.2 Receiving Netlink 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(): + +\code + nl_recvmsgs_default(sk) + | + | cb = nl_socket_get_cb(sk) + v + nl_recvmsgs(sk, cb) +\endcode + +\subsubsection core_nl_recvmsgs 3.2.1 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. + +See \ref core_recvmsgs for more information on the behaviour of +nl_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 \ref 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(). + +\code + nl_recvmsgs(sk, cb) + | + | Own recvmsgs function specified via nl_cb_overwrite_recvmsgs() + |- - - - - - - - - - - - - - - - - - - - + v v + internal_recvmsgs() my_recvmsgs() +\endcode + +\subsubsection core_recvmsgs 3.2.2 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: + +\code + 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) +\endcode + +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 +(see \ref core_recv_parse). 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 \ref 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 \ref core_recv_parse for information on how to extract valid netlink +messages from the parser and on how to control the behaviour of it. + +\subsubsection core_recv_parse 3.2.3 Parsing Characteristics + +The internal parser is invoked for each netlink message received from a +netlink socket. It is typically fed by nl_recv() (see \ref core_recvmsgs). + +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 \ref core_ack). + +\code + 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 +\endcode + +\section core_msg 4. Message Construction & Parsing + +\subsection core_msg_format 4.1 Message Format + +\section core_cb 5. Callback Configurations + +Callback hooks and overwriting capabilities are provided in various places +inside library code 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. + +\subsection cb_func 5.1 Callback Function Formats + +\subsubsection cb_func_recvmsgs 5.1.1 Callbacks for nl_recvmsgs() and nl_sendmsg() + +Both nl_recvmsgs() and nl_sendmsg() provide callback hooks for functions to +control their behaviour. Every callback function must have the following +prototype: + +\code +typedef int(* nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); +\endcode + +nl_sendmsg() callback hooks: +\code +Callback ID | Description | Default Return Value +----------------------------------------------------------------------------- +NL_CB_MSG_OUT | Each message sent | NL_OK +\endcode + +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): +\code +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 +\endcode + +All these callback hooks can control the flow of the callee by returning +appropriate error codes: +\code +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. +\endcode + +\subsubsection cb_func_error 5.1.2 Callback for Error Messages + +A special function prototype is used for the error message callback hook: + +\code +typedef int(* nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg); +\endcode + +\subsubsection cb_cb_set 5.1.3 Setting Callback Functions + +In order to simplify typical usages of the library, different sets of +default callback implementations exist: +\code +NL_CB_DEFAULT: No additional actions +NL_CB_VERBOSE: Automatically print warning and error messages to a file + descriptor as appropriate. This is useful for CLI based + applications. +NL_CB_DEBUG: Print informal debugging information for each message + received. This will result in every message beint sent or + received to be printed to the screen in a decoded, + human-readable format. +\endcode + +\subsubsection core_cb_example 5.1.4 Example: Setting up a callback set +\code +// 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); +\endcode + +\section remarks Remarks + +\subsection cache_alloc Allocation of Caches + +Almost all subsystem provide a function to allocate a new cache +of some form. The function usually looks like this: +\code +struct nl_cache *_alloc_cache(struct nl_sock *sk); +\endcode + +These functions allocate a new cache for the own object type, +initializes it properly and updates it to represent the current +state of their master, e.g. a link cache would include all +links currently configured in the kernel. + +Some of the allocation functions may take additional arguments +to further specify what will be part of the cache. + +All such functions return a newly allocated cache or NULL +in case of an error. + +\subsection addr Setting of Addresses +\code +int _set_addr(struct nl_object *, struct nl_addr *) +\endcode + +All attribute functions avaiable for assigning addresses to objects +take a struct nl_addr argument. The provided address object is +validated against the address family of the object if known already. +The assignment fails if the address families mismatch. In case the +address family has not been specified yet, the address family of +the new address is elected to be the new requirement. + +The function will acquire a new reference on the address object +before assignment, the caller is NOT responsible for this. + +All functions return 0 on success or a negative error code. + +\subsection flags Flags to Character StringTranslations +All functions converting a set of flags to a character string follow +the same principles, therefore, the following information applies +to all functions convertings flags to a character string and vice versa. + +\subsubsection flags2str Flags to Character String +\code +char *_flags2str(int flags, char *buf, size_t len) +\endcode +\arg flags Flags. +\arg buf Destination buffer. +\arg len Buffer length. + +Converts the specified flags to a character string separated by +commas and stores it in the specified destination buffer. + +\return The destination buffer + +\subsubsection str2flags Character String to Flags +\code +int _str2flags(const char *name) +\endcode +\arg name Name of flag. + +Converts the provided character string specifying a flag +to the corresponding numeric value. + +\return Link flag or a negative value if none was found. + +\subsubsection type2str Type to Character String +\code +char *_2str(int type, char *buf, size_t len) +\endcode +\arg type Type as numeric value +\arg buf Destination buffer. +\arg len Buffer length. + +Converts an identifier (type) to a character string and stores +it in the specified destination buffer. + +\return The destination buffer or the type encoded in hexidecimal + form if the identifier is unknown. + +\subsubsection str2type Character String to Type +\code +int _str2(const char *name) +\endcode +\arg name Name of identifier (type). + +Converts the provided character string specifying a identifier +to the corresponding numeric value. + +\return Identifier as numeric value or a negative value if none was found. + + +*/ diff --git a/doc/src/genl.c b/doc/src/genl.c new file mode 100644 index 0000000..8585c62 --- /dev/null +++ b/doc/src/genl.c @@ -0,0 +1,10 @@ +/** + * \cond skip + * vim:syntax=doxygen + * \endcond + +\page genl_doc Generic Netlink Library (-lnl-genl) + +\section genl_intro Introduction + +*/ diff --git a/doc/src/nf.c b/doc/src/nf.c new file mode 100644 index 0000000..006500d --- /dev/null +++ b/doc/src/nf.c @@ -0,0 +1,10 @@ +/** + * \cond skip + * vim:syntax=doxygen + * \endcond + +\page nf_doc Netfilter Netlink Library (-lnl-nf) + +\section nf_intro Introduction + +*/ diff --git a/doc/src/route.c b/doc/src/route.c new file mode 100644 index 0000000..2c042db --- /dev/null +++ b/doc/src/route.c @@ -0,0 +1,10 @@ +/** + * \cond skip + * vim:syntax=doxygen + * \endcond + +\page route_doc Routing Netlink Library (-lnl-route) + +\section route_intro Introduction + +*/ diff --git a/doc/src/toc.c b/doc/src/toc.c new file mode 100644 index 0000000..c33727c --- /dev/null +++ b/doc/src/toc.c @@ -0,0 +1,66 @@ +/** + * \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.so +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. \ref route_doc "nl-route.so", \ref genl_doc "nl-genl.so", ...). + +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 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 + +- \subpage core_doc "1. Netlink Core Library (-lnl)" +- \subpage route_doc "2. Routing Netlink Library (-lnl-route)" +- \subpage genl_doc "3. Generic Netlink Library (-lnl-genl)" +- \subpage nf_doc "4. Netfilter Netlink Library (-lnl-nf)" + +\section main_trees GIT Trees + +\subsection tree_dev Development Tree + +@code +git://git.kernel.org/pub/scm/libs/netlink/libnl.git +@endcode +- Web: http://www.kernel.org/pub/scm/libs/netlink/libnl.git + +\subsection tree_stable Stable Tree + +@code +git://git.kernel.org/pub/scm/libs/netlink/libnl-stable.git +@endcode +- Web: http://www.kernel.org/pub/scm/libs/netlink/libnl-stable.git + +\section main_website Website + +- http://www.infradead.org/~tgr/libnl/ + +\section main_mailinglist Mailinglist + +Please post question and patches to the libnl mailinglist: + +@code +libnl@lists.infradead.org +@endcode + +- Archives: http://canuck.infradead.org/pipermail/libnl/ + +*/ diff --git a/lib/doc.c b/lib/doc.c deleted file mode 100644 index 4272a59..0000000 --- a/lib/doc.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * lib/doc.c Documentation Purpose - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2008 Thomas Graf - */ - -/** - * @mainpage - * - * @section 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. Its goal is to - * simplify netlink protocol usage and to create an abstraction layer using - * object based interfaces for various netlink based subsystems.The library - * was developed and tested on the 2.6.x kernel releases but it may work with - * older kernel series. - * - * @section toc Table of Contents - * - * - \subpage core_doc - * - \subpage route_doc - * - \subpage genl_doc - * - \subpage nf_doc - * - * @section remarks Remarks - * - * @subsection cache_alloc Allocation of Caches - * - * Almost all subsystem provide a function to allocate a new cache - * of some form. The function usually looks like this: - * @code - * struct nl_cache *_alloc_cache(struct nl_sock *sk); - * @endcode - * - * These functions allocate a new cache for the own object type, - * initializes it properly and updates it to represent the current - * state of their master, e.g. a link cache would include all - * links currently configured in the kernel. - * - * Some of the allocation functions may take additional arguments - * to further specify what will be part of the cache. - * - * All such functions return a newly allocated cache or NULL - * in case of an error. - * - * @subsection addr Setting of Addresses - * @code - * int _set_addr(struct nl_object *, struct nl_addr *) - * @endcode - * - * All attribute functions avaiable for assigning addresses to objects - * take a struct nl_addr argument. The provided address object is - * validated against the address family of the object if known already. - * The assignment fails if the address families mismatch. In case the - * address family has not been specified yet, the address family of - * the new address is elected to be the new requirement. - * - * The function will acquire a new reference on the address object - * before assignment, the caller is NOT responsible for this. - * - * All functions return 0 on success or a negative error code. - * - * @subsection flags Flags to Character StringTranslations - * All functions converting a set of flags to a character string follow - * the same principles, therefore, the following information applies - * to all functions convertings flags to a character string and vice versa. - * - * @subsubsection flags2str Flags to Character String - * @code - * char *_flags2str(int flags, char *buf, size_t len) - * @endcode - * @arg flags Flags. - * @arg buf Destination buffer. - * @arg len Buffer length. - * - * Converts the specified flags to a character string separated by - * commas and stores it in the specified destination buffer. - * - * @return The destination buffer - * - * @subsubsection str2flags Character String to Flags - * @code - * int _str2flags(const char *name) - * @endcode - * @arg name Name of flag. - * - * Converts the provided character string specifying a flag - * to the corresponding numeric value. - * - * @return Link flag or a negative value if none was found. - * - * @subsubsection type2str Type to Character String - * @code - * char *_2str(int type, char *buf, size_t len) - * @endcode - * @arg type Type as numeric value - * @arg buf Destination buffer. - * @arg len Buffer length. - * - * Converts an identifier (type) to a character string and stores - * it in the specified destination buffer. - * - * @return The destination buffer or the type encoded in hexidecimal - * form if the identifier is unknown. - * - * @subsubsection str2type Character String to Type - * @code - * int _str2(const char *name) - * @endcode - * @arg name Name of identifier (type). - * - * Converts the provided character string specifying a identifier - * to the corresponding numeric value. - * - * @return Identifier as numeric value or a negative value if none was found. - * - * @page core_doc Core Library (-lnl) - * - * @section core_intro Introduction - * - * The core library contains the fundamentals required to communicate over - * netlink sockets. It deals with connecting and unconnecting of sockets, - * sending and receiving of data, 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 with the help of netlink messages. - * - * @section core_toc Table of Contents - * - * - \ref proto_fund - * - \ref sk_doc - * - \ref rxtx_doc - * - \ref cb_doc - * - * @section proto_fund Netlink Protocol Fundamentals - * - * The netlink protocol is a socket based IPC mechanism used for communication - * between userspace processes and the kernel. The netlink protocol uses the - * \c AF_NETLINK address family and defines a protocol type for each subsystem - * protocol (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. - * - * The netlink protocol is based on messages each limited to the size of a - * memory page and consists of the netlink message header (struct nlmsghdr) - * plus the payload attached to it. The payload can consist of arbitary data - * but often contains a fixed sized family specifc header followed by a - * stream of \ref attr_doc. The use of attributes dramatically increases - * the flexibility of the protocol and allows for the protocol to be - * extended while maintaining backwards compatibility. - * - * The netlink message header (struct nlmsghdr): - * @code - * 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 | Flags | - * +------------------------------+------------------------------+ - * | Sequence Number | - * +-------------------------------------------------------------+ - * | Port (Address) | - * +-------------------------------------------------------------+ - * @endcode - * - * Netlink differs between requests, notifications, and replies. Requests - * are messages which have the \c 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. Every request should be assigned a - * sequence number which should be incremented for each request sent on the - * sending side. Depending on the nature of the request, the receiver may - * reply to the request with regular netlink messages which should contain - * the same sequence number as the request it relates to. Notifications are - * of informal nature and don't expect a reply, therefore the sequence number - * is typically set to 0. 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. - * - * @msc - * A,B; - * A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; - * A<=B [label="PUT (seq=1)"]; - * ...; - * A<=B [label="NOTIFY (seq=0)"]; - * @endmsc - * - * If the size of a reply exceeds the size of a memory page and thus exceeds - * the maximum message size, the reply can be split into a series of multipart - * messages. A multipart message has the \c flag NLM_F_MULTI set and the - * receiver is expected to continue parsing the reply until the special - * message type \c NLMSG_DONE is received. - * - * @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)"]; - * @endmsc - * - * Errors can be reported using the standard message type \c NLMSG_ERROR which - * can carry an error code and the netlink mesage header of the request. - * Error messages should set their sequence number to the sequence number - * of the message which caused the error. - * - * @msc - * A,B; - * A=>B [label="GET (seq=1, NLM_F_REQUEST)"]; - * A<=B [label="NLMSG_ERROR code=EINVAL (seq=1)"]; - * @endmsc - * - * The \c NLMSG_ERROR message type is also used to send acknowledge messages. - * An acknowledge message can be requested by setting the \c NLM_F_ACK flag - * message except that the error code is set to 0. - * - * @msc - * A,B; - * A=>B [label="GET (seq=1, NLM_F_REQUEST | NLM_F_ACK)"]; - * A<=B [label="ACK (seq=1)"]; - * @endmsc - * - * @section sk_doc Dealing with Netlink Sockets - * - * In order to use the netlink protocol, a netlink socket is required. Each - * socket defines a completely independent context for sending and receiving - * of messages. The netlink socket and all its related attributes are - * represented by struct nl_sock. - * - * @code - * nl_socket_alloc() Allocate new socket structure. - * nl_socket_free(s) Free socket structure. - * @endcode - * - * @subsection local_port 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) to allow up to 1024 sockets per process. - * - * @code - * nl_socket_get_local_port(sk) Return the peer's port number. - * nl_socket_set_local_port(sk, port) Set the peer's port number. - * @endcode - * - * @subsection peer_port 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 corresponding peer. If - * no peer is specified, the kernel 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. - * - * @code - * nl_socket_get_peer_port(sk) Return the local port number. - * nl_socket_set_peer_port(sk, port) Set the local port number. - * @endcode - * - * @subsection sock_fd File Descriptor - * The file descriptor of the socket(2). - * - * @code - * nl_socket_get_fd(sk) Return file descriptor. - * nl_socket_set_buffer_size(sk, rx, tx) Set buffer size of socket. - * nl_socket_set_nonblocking(sk) Set socket to non-blocking state. - * @endcode - * - * @subsection group_sub Group Subscriptions - * Each socket can subscribe to multicast groups of the netlink protocol - * family it is bound 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. Starting with 2.6.14 a new method was introduced which - * supports subscribing to an almost unlimited number of multicast groups. - * - * @code - * nl_socket_add_membership(sk, group) Become a member of a multicast group. - * nl_socket_drop_membership(sk, group) Drop multicast group membership. - * nl_join_groups(sk, groupmask) Join a multicast group (obsolete). - * @endcode - * - * @subsection seq_num Sequence Numbers - * The socket keeps track of the sequence numbers used. The library will - * automatically verify the sequence number of messages received unless - * the check was disabled using the function nl_socket_disable_seq_check(). - * When a message is sent using nl_send_auto_complete(), the sequence number - * is automatically filled in, and replies will be verified correctly. - * - * @code - * nl_socket_disable_seq_check(sk) Disable checking of sequece numbers. - * nl_socket_use_seq(sk) Use sequence number and bump to next. - * @endcode - * - * @subsection sock_cb Callback Configuration - * Every socket is associated a callback configuration which enables the - * applications to hook into various internal functions and control the - * receiving and sendings semantics. For more information, see section - * \ref cb_doc. - * - * @code - * nl_socket_alloc_cb(cb) Allocate socket based on callback set. - * nl_socket_get_cb(sk) Return callback configuration. - * nl_socket_set_cb(sk, cb) Replace callback configuration. - * nl_socket_modify_cb(sk, ...) Modify a specific callback function. - * @endcode - * - * @subsection sk_other Other Functions - * @code - * nl_socket_enable_auto_ack(sock) Enable automatic request of ACK. - * nl_socket_disable_auto_ack(sock) Disable automatic request of ACK. - * nl_socket_enable_msg_peek(sock) Enable message peeking. - * nl_socket_disable_msg_peek(sock) Disable message peeking. - * nl_socket_set_passcred(sk, state) Enable/disable credential passing. - * nl_socket_recv_pktinfo(sk, state) Enable/disable packet information. - * @endcode - * - * @section rxtx_doc Sending and Receiving of Data - * - * @subsection recv_semantisc Receiving Semantics - * @code - * nl_recvmsgs_default(set) - * | cb = nl_socket_get_cb(sk) - * v - * nl_recvmsgs(sk, cb) - * | [Application provides nl_recvmsgs() replacement] - * |- - - - - - - - - - - - - - - v - * | cb->cb_recvmsgs_ow() - * | - * | [Application provides nl_recv() replacement] - * +-------------->|- - - - - - - - - - - - - - - v - * | nl_recv() cb->cb_recv_ow() - * | +----------->|<- - - - - - - - - - - - - - -+ - * | | v - * | | Parse Message - * | | |- - - - - - - - - - - - - - - v - * | | | NL_CB_MSG_IN() - * | | |<- - - - - - - - - - - - - - -+ - * | | | - * | | |- - - - - - - - - - - - - - - v - * | | Sequence Check NL_CB_SEQ_CHECK() - * | | |<- - - - - - - - - - - - - - -+ - * | | | - * | | |- - - - - - - - - - - - - - - v [ NLM_F_ACK is set ] - * | | | NL_CB_SEND_ACK() - * | | |<- - - - - - - - - - - - - - -+ - * | | | - * | | +-----+------+--------------+----------------+--------------+ - * | | v v v v v - * | | Valid Message ACK NO-OP Message End of Multipart Error - * | | | | | | | - * | | v v v v v - * | |NL_CB_VALID() NL_CB_ACK() NL_CB_SKIPPED() NL_CB_FINISH() cb->cb_err() - * | | | | | | | - * | | +------------+--------------+----------------+ v - * | | | (FAILURE) - * | | | [Callback returned NL_SKIP] - * | | [More messages to be parsed] |<----------- - * | +----------------------------------| - * | | - * | [is Multipart message] | - * +-------------------------------------| [Callback returned NL_STOP] - * |<----------- - * v - * (SUCCESS) - * - * At any time: - * Message Format Error - * |- - - - - - - - - - - - v - * v NL_CB_INVALID() - * (FAILURE) - * - * Message Overrun (Kernel Lost Data) - * |- - - - - - - - - - - - v - * v NL_CB_OVERRUN() - * (FAILURE) - * - * Callback returned negative error code - * (FAILURE) - * @endcode - * - * @subsection send_semantics Sending Semantisc - * - * @code - * nl_send_auto_complete(sk, msg) - * | [Automatically completes netlink message header] - * | [(local port, sequence number) ] - * | - * | [Application provies nl_send() replacement] - * |- - - - - - - - - - - - - - - - - - - - v - * v cb->cb_send_ow() - * nl_send(sk, msg) - * | - * v - * nl_send_iovec() - * | [If available, add peer port and credentials] - * v - * nl_sendmsg(sk, msg, msghdr) - * |- - - - - - - - - - - - - - - - - - - - v - * | NL_CB_MSG_OUT() - * |<- - - - - - - - - - - - - - - - - - - -+ - * v - * sendmsg() - * @endcode - * - * @section cb_doc Callback Configurations - * Callbacks and overwriting capabilities are provided to control various - * semantics of the library. All callback functions are packed together in - * struct nl_cb which is attached to a netlink socket or passed on to - * the respective functions directly. - * - * @subsection cb_ret_doc Callback Return Values - * Callback functions can control the flow of the calling layer by returning - * appropriate error codes: - * @code - * Action ID | Description - * -----------------+------------------------------------------------------- - * NL_OK | Proceed with whatever comes next. - * NL_SKIP | Skip message currently being processed and continue - * | with next message. - * NL_STOP | Stop parsing and discard all remaining messages in - * | this set of messages. - * @endcode - * - * All callbacks are optional and a default action is performed if no - * application specific implementation is provided: - * - * @code - * Callback ID | Default Return Value - * ------------------+---------------------- - * NL_CB_VALID | NL_OK - * NL_CB_FINISH | NL_STOP - * NL_CB_OVERRUN | NL_STOP - * NL_CB_SKIPPED | NL_SKIP - * NL_CB_ACK | NL_STOP - * NL_CB_MSG_IN | NL_OK - * NL_CB_MSG_OUT | NL_OK - * NL_CB_INVALID | NL_STOP - * NL_CB_SEQ_CHECK | NL_OK - * NL_CB_SEND_ACK | NL_OK - * | - * Error Callback | NL_STOP - * @endcode - * - * In order to simplify typical usages of the library, different sets of - * default callback implementations exist: - * @code - * NL_CB_DEFAULT: No additional actions - * NL_CB_VERBOSE: Automatically print warning and error messages to a file - * descriptor as appropriate. This is useful for CLI based - * applications. - * NL_CB_DEBUG: Print informal debugging information for each message - * received. This will result in every message beint sent or - * received to be printed to the screen in a decoded, - * human-readable format. - * @endcode - * - * @par 1) Setting up a callback set - * @code - * // 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); - * @endcode - * - * @page route_doc Routing Family - * - * @page genl_doc Generic Netlink Family - * - * @page nf_doc Netfilter Subsystem - */