Tons of documentation

This commit is contained in:
Thomas Graf 2010-11-27 10:18:07 +01:00
parent 7105aea116
commit 5644578190
20 changed files with 2219 additions and 402 deletions

View file

@ -642,7 +642,7 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
EXAMPLE_PATH = src/examples
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@ -662,7 +662,7 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
IMAGE_PATH = src/img
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
#include <netlink/msg.h>
#include <netlink/attr.h>
void construct_attrs(struct nl_msg *msg)
{
NLA_PUT_STRING(msg, MY_ATTR_FOO1, "some text");
NLA_PUT_U32(msg, MY_ATTR_FOO1, 0x1010);
NLA_PUT_FLAG(msg, MY_ATTR_FOO3, 1);
return 0;
nla_put_failure:
/* NLA_PUT* macros jump here in case of an error */
return -EMSGSIZE;
}

View file

@ -0,0 +1,51 @@
struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu)
{
struct nl_msg *msg;
struct nlattr *info, *vlan;
struct ifinfomsg ifi = {
.ifi_family = AF_INET,
.ifi_index = ifindex,
};
/* Allocate a default sized netlink message */
if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, 0)))
return NULL;
/* Append the protocol specific header (struct ifinfomsg)*/
if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
goto nla_put_failure
/* Append a 32 bit integer attribute to carry the MTU */
NLA_PUT_U32(msg, IFLA_MTU, mtu);
/* Append a unspecific attribute to carry the link layer address */
NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr);
/* Append a container for nested attributes to carry link information */
if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
goto nla_put_failure;
/* Put a string attribute into the container */
NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan");
/*
* Append another container inside the open container to carry
* vlan specific attributes
*/
if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA)))
goto nla_put_failure;
/* add vlan specific info attributes here... */
/* Finish nesting the vlan attributes and close the second container. */
nla_nest_end(msg, vlan);
/* Finish nesting the link info attribute and close the first container. */
nla_nest_end(msg, info);
return msg;
nla_put_failure:
nlmsg_free(msg);
return NULL;
}

View file

@ -0,0 +1,50 @@
int parse_message(struct nlmsghdr *hdr)
{
/*
* The policy defines two attributes: a 32 bit integer and a container
* for nested attributes.
*/
struct nla_policy attr_policy[] = {
[ATTR_FOO] = { .type = NLA_U32 },
[ATTR_BAR] = { .type = NLA_NESTED },
};
struct nlattr *attrs[ATTR_MAX+1];
int err;
/*
* The nlmsg_parse() function will make sure that the message contains
* enough payload to hold the header (struct my_hdr), validates any
* attributes attached to the messages and stores a pointer to each
* attribute in the attrs[] array accessable by attribute type.
*/
if ((err = nlmsg_parse(hdr, sizeof(struct my_hdr), attrs, ATTR_MAX,
attr_policy)) < 0)
goto errout;
if (attrs[ATTR_FOO]) {
/*
* It is safe to directly access the attribute payload without
* any further checks since nlmsg_parse() enforced the policy.
*/
uint32_t foo = nla_get_u32(attrs[ATTR_FOO]);
}
if (attrs[ATTR_BAR]) {
struct *nested[NESTED_MAX+1];
/*
* Attributes nested in a container can be parsed the same way
* as top level attributes.
*/
err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR],
nested_policy);
if (err < 0)
goto errout;
// Process nested attributes here.
}
err = 0;
errout:
return err;
}

View file

@ -0,0 +1,11 @@
#include <netlink/msg.h>
void my_parse(void *stream, int length)
{
struct nlmsghdr *hdr = stream;
while (nlmsg_ok(hdr, length)) {
// Parse message here
hdr = nlmsg_next(hdr, &length);
}
}

View file

@ -0,0 +1,14 @@
#include <netlink/handlers.h>
/* Allocate a callback set and initialize it to the verbose default set */
struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
/* Modify the set to call my_func() for all valid messages */
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
/*
* Set the error message handler to the verbose default implementation
* and direct it to print all errors to the given file descriptor.
*/
FILE *file = fopen(...);
nl_cb_err(cb, NL_CB_VERBOSE, NULL, file);

View file

@ -0,0 +1,11 @@
#include <netlink/netlink.h>
struct nl_sock *sk;
struct rtgenmsg rt_hdr = {
.rtgen_family = AF_UNSPEC,
};
sk = nl_socket_alloc();
nl_connect(sk, NETLINK_ROUTE);
nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));

View file

@ -0,0 +1,7 @@
/* nla_put_flag() appends a zero sized attribute to the message. */
nla_put_flag(msg, ATTR_FLAG);
/* There is no need for a receival function, the presence is the value. */
if (attrs[ATTR_FLAG])
/* flag is present */

View file

@ -0,0 +1,11 @@
#include <netlink/attr.h>
struct nalttr *nla;
int rem;
nla_for_each_attr(nla, attrstream, streamlen, rem) {
/* validate & parse attribute */
}
if (rem > 0)
/* unparsed attribute data */

View file

@ -0,0 +1,16 @@
int put_opts(struct nl_msg *msg)
{
struct nlattr *opts;
if (!(opts = nla_nest_start(msg, ATTR_OPTS)))
goto nla_put_failure;
NLA_PUT_U32(msg, NESTED_FOO, 123);
NLA_PUT_STRING(msg, NESTED_BAR, "some text");
nla_nest_end(msg, opts);
return 0;
nla_put_failure:
return -EMSGSIZE;
}

10
doc/src/examples/nla_ok.c Normal file
View file

@ -0,0 +1,10 @@
#include <netlink/msg.h>
#include <netlink/attr.h>
struct nlattr *hdr = nlmsg_attrdata(msg, 0);
int remaining = nlmsg_attrlen(msg, 0);
while (nla_ok(hdr, remaining)) {
/* parse attribute here */
hdr = nla_next(hdr, &remaining);
};

View file

@ -0,0 +1,12 @@
if (attrs[ATTR_OPTS]) {
struct nlattr *nested[NESTED_MAX+1];
struct nla_policy nested_policy[] = {
[NESTED_FOO] = { .type = NLA_U32 },
};
if (nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_OPTS], nested_policy) < 0)
/* error */
if (nested[NESTED_FOO])
uint32_t val = nla_get_u32(nested[NESTED_FOO]);
}

View file

@ -0,0 +1,14 @@
struct my_attr_struct {
uint32_t a;
uint32_t b;
};
int my_put(struct nl_msg *msg)
{
struct my_attr_struct obj = {
.a = 10,
.b = 20,
};
return nla_put(msg, ATTR_MY_STRUCT, sizeof(obj), &obj);
}

View file

@ -0,0 +1,7 @@
#include <netlink/msg.h>
struct nlmsghdr *hdr;
nlmsg_for_each(hdr, stream, length) {
/* do something with message */
}

View file

@ -0,0 +1,29 @@
#include <netlink/msg.h>
#include <netlink/attr.h>
enum {
MY_ATTR_FOO = 1,
MY_ATTR_BAR,
__MY_ATTR_MAX,
};
#define MY_ATTR_MAX (__MY_ATTR_MAX - 1)
static struct nla_policy my_policy[MY_ATTR_MAX+1] = {
[MY_ATTR_FOO] = { .type = NLA_U32 },
[MY_ATTR_BAR] = { .type = NLA_STRING,
.maxlen = 16 },
};
void parse_msg(struct nlmsghdr *nlh)
{
struct nlattr *attrs[MY_ATTR_MAX+1];
if (nlmsg_parse(nlh, 0, attrs, MY_ATTR_MAX, my_policy) < 0)
/* error */
if (attrs[MY_ATTR_FOO]) {
/* MY_ATTR_FOO is present in message */
printf("value: %u\n", nla_get_u32(attrs[MY_ATTR_FOO]));
}
}

View file

@ -0,0 +1,31 @@
#include <netlink/msg.h>
struct nlmsghdr *hdr;
struct nl_msg *msg;
struct myhdr {
uint32_t foo1, foo2;
} hdr = { 10, 20 };
/* Allocate a message with the default maximum message size */
msg = nlmsg_alloc();
/*
* Add header with message type MY_MSGTYPE, the flag NLM_F_CREATE,
* let library fill port and sequence number, and reserve room for
* struct myhdr
*/
hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, MY_MSGTYPE, sizeof(hdr), NLM_F_CREATE);
/* Copy own header into newly reserved payload section */
memcpy(nlmsg_data(hdr), &hdr, sizeof(hdr));
/*
* The message will now look like this:
* +-------------------+- - -+----------------+- - -+
* | struct nlmsghdr | Pad | struct myhdr | Pad |
* +-------------------+-----+----------------+- - -+
* nlh -^ / \
* +--------+---------+
* | foo1 | foo2 |
* +--------+---------+
*/

View file

@ -0,0 +1,43 @@
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
/*
* This function will be called for each valid netlink message received
* in nl_recvmsgs_default()
*/
static int my_func(struct nl_msg *msg, void *arg)
{
return 0;
}
struct nl_sock *sk;
/* Allocate a new socket */
sk = nl_socket_alloc();
/*
* Notifications do not use sequence numbers, disable sequence number
* checking.
*/
nl_socket_disable_seq_check(sk);
/*
* Define a callback function, which will be called for each notification
* received
*/
nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL);
/* Connect to routing netlink protocol */
nl_connect(sk, NETLINK_ROUTE);
/* Subscribe to link notifications group */
nl_socket_add_memberships(sk, RTNLGRP_LINK);
/*
* 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);

View file

@ -29,52 +29,6 @@
struct net;
struct sockaddr_nl {
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};
struct nlmsghdr {
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process port ID */
};
/* Flags values */
#define NLM_F_REQUEST 1 /* It is request message. */
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
#define NLM_F_MATCH 0x200 /* return all matching */
#define NLM_F_ATOMIC 0x400 /* atomic GET */
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
/* Modifiers to NEW request */
#define NLM_F_REPLACE 0x100 /* Override existing */
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
#define NLM_F_APPEND 0x800 /* Add to end of list */
/*
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
4.4BSD CHANGE NLM_F_REPLACE
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
Append NLM_F_CREATE
Check NLM_F_EXCL
*/
#define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
@ -85,28 +39,12 @@ struct nlmsghdr {
(nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_NOOP 0x1 /* Nothing. */
#define NLMSG_ERROR 0x2 /* Error */
#define NLMSG_DONE 0x3 /* End of a dump */
#define NLMSG_OVERRUN 0x4 /* Data lost */
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
struct nlmsgerr {
int error;
struct nlmsghdr msg;
};
#define NETLINK_ADD_MEMBERSHIP 1
#define NETLINK_DROP_MEMBERSHIP 2
#define NETLINK_PKTINFO 3
#define NETLINK_BROADCAST_ERROR 4
#define NETLINK_NO_ENOBUFS 5
struct nl_pktinfo {
__u32 group;
};
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
enum {
@ -114,36 +52,4 @@ enum {
NETLINK_CONNECTED,
};
/*
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
*/
struct nlattr {
__u16 nla_len;
__u16 nla_type;
};
/*
* nla_type (16 bits)
* +---+---+-------------------------------+
* | N | O | Attribute Type |
* +---+---+-------------------------------+
* N := Carries nested attributes
* O := Payload stored in network byte order
*
* Note: The N and O flag are mutually exclusive.
*/
#define NLA_F_NESTED (1 << 15)
#define NLA_F_NET_BYTEORDER (1 << 14)
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
#define NLA_ALIGNTO 4
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
#endif /* __LINUX_NETLINK_H */

View file

@ -1,5 +1,5 @@
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
#ifndef __NETLINK_KERNEL_H_
#define __NETLINK_KERNEL_H_
/**
* Netlink socket address
@ -20,35 +20,30 @@ struct sockaddr_nl
uint32_t nl_groups;
};
/**
* @addtogroup msg
* @{
*/
/**
* Netlink message header
* @ingroup msg
*/
struct nlmsghdr
{
/**
* Length of message including header.
*/
/** Length of message including header and padding. */
uint32_t nlmsg_len;
/**
* Message type (content type)
*/
/** Message type (content type) */
uint16_t nlmsg_type;
/**
* Message flags
*/
/** Message flags */
uint16_t nlmsg_flags;
/**
* Sequence number
*/
/** Sequence number of message \see core_sk_seq_num. */
uint32_t nlmsg_seq;
/**
* Netlink PID of the proccess sending the message.
*/
/** Netlink port */
uint32_t nlmsg_pid;
};
@ -60,7 +55,6 @@ struct nlmsghdr
/**
* Must be set on all request messages (typically from user space to
* kernel space).
* @ingroup msg
*/
#define NLM_F_REQUEST 1
@ -89,7 +83,6 @@ struct nlmsghdr
/**
* Return the complete table instead of a single entry.
* @ingroup msg
*/
#define NLM_F_ROOT 0x100
@ -119,7 +112,6 @@ struct nlmsghdr
/**
* Replace existing matching config object with this request.
* @ingroup msg
*/
#define NLM_F_REPLACE 0x100
@ -147,7 +139,6 @@ struct nlmsghdr
/**
* No operation, message must be ignored
* @ingroup msg
*/
#define NLMSG_NOOP 0x1
@ -176,8 +167,7 @@ struct nlmsghdr
/** @} */
/**
* Netlink error message
* @ingroup msg
* Netlink error message header
*/
struct nlmsgerr
{
@ -193,4 +183,102 @@ struct nl_pktinfo
__u32 group;
};
/**
* Netlink alignment constant, all boundries within messages must be align to this.
*
* See \ref core_msg_fmt_align for more information on message alignment.
*/
#define NLMSG_ALIGNTO 4
/**
* Returns \p len properly aligned to NLMSG_ALIGNTO.
*
* See \ref core_msg_fmt_align for more information on message alignment.
*/
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
/**
* Length of a netlink message header including padding.
*
* See \ref core_msg_fmt_align for more information on message alignment.
*/
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
/** @} */
/**
* @addtogroup attr
* @{
*/
/*
*/
/**
* Netlink attribute structure
*
* @code
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
* @endcode
*/
struct nlattr {
/**
* Attribute length in bytes including header
*/
__u16 nla_len;
/**
* Netlink attribute type
*/
__u16 nla_type;
};
/**
* @name Attribute Type Flags
*
* @code
* nla_type (16 bits)
* +---+---+-------------------------------+
* | N | O | Attribute Type |
* +---+---+-------------------------------+
* N := Carries nested attributes
* O := Payload stored in network byte order
* @endcode
*
* @note The N and O flag are mutually exclusive.
*
* @{
*/
/*
*/
#define NLA_F_NESTED (1 << 15)
#define NLA_F_NET_BYTEORDER (1 << 14)
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
/** @} */
#define NLA_ALIGNTO 4
/**
* Returns \p len properly aligned to NLA_ALIGNTO.
*
* See \ref core_msg_fmt_align for more information on message alignment.
*/
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
/**
* Length of a netlink attribute header including padding.
*
* See \ref core_msg_fmt_align for more information on message alignment.
*/
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
/** @} */
#endif /* __LINUX_NETLINK_H */