|
| | Callbacks/Customization |
| | Callbacks and overwriting capabilities are provided to take influence in various control flows inside the library.
|
| |
| | Messages |
| | Netlink Message Construction/Parsing Interface.
|
| |
| | Socket |
| | Handle representing a netlink socket.
|
| |
|
| int | nl_connect (struct nl_handle *handle, int protocol) |
| | Create and connect netlink socket. More...
|
| |
| void | nl_close (struct nl_handle *handle) |
| | Close/Disconnect netlink socket. More...
|
| |
|
| int | nl_sendto (struct nl_handle *handle, void *buf, size_t size) |
| | Send raw data over netlink socket. More...
|
| |
| int | nl_sendmsg (struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr) |
| | Send netlink message with control over sendmsg() message header. More...
|
| |
| int | nl_send (struct nl_handle *handle, struct nl_msg *msg) |
| | Send netlink message. More...
|
| |
| int | nl_send_auto_complete (struct nl_handle *handle, struct nl_msg *msg) |
| | Send netlink message and check & extend header values as needed. More...
|
| |
| int | nl_send_simple (struct nl_handle *handle, int type, int flags, void *buf, size_t size) |
| | Send simple netlink message using nl_send_auto_complete() More...
|
| |
|
| int | nl_recv (struct nl_handle *handle, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds) |
| | Receive data from netlink socket. More...
|
| |
| int | nl_recvmsgs (struct nl_handle *handle, struct nl_cb *cb) |
| | Receive a set of messages from a netlink socket. More...
|
| |
| int | nl_recvmsgs_default (struct nl_handle *handle) |
| | Receive a set of message from a netlink socket using handlers in nl_handle. More...
|
| |
| int | nl_wait_for_ack (struct nl_handle *handle) |
| | Wait for ACK. More...
|
| |
| #define | NL_CB_CALL(cb, type, msg) |
| |
- Receiving Semantics
|
| cb = nl_socket_get_cb(socket)
v
|- - - - - - - - - - - - - - - v
| cb->cb_recvmsgs_ow()
|
| [Application provides
nl_recv() replacement]
+-------------->|- - - - - - - - - - - - - - - v
| +----------->|<- - - - - - - - - - - - - - -+
| | v
| | Parse Message
| | |- - - - - - - - - - - - - - - v
| | |<- - - - - - - - - - - - - - -+
| | |
| | |- - - - - - - - - - - - - - - v
| | |<- - - - - - - - - - - - - - -+
| | |
| | |- - - - - - - - - - - - - - - v [
NLM_F_ACK is set ]
| | |<- - - - - - - - - - - - - - -+
| | |
| | +-----+------+--------------+----------------+--------------+
| | v v v v v
| | Valid Message ACK NOOP Message End of Multipart Error Message
| | | | | | |
| | v v v v v
| | | | | | |
| | +------------+--------------+----------------+ v
| | | (FAILURE)
| | [More messages to be parsed] |<-----------
| +----------------------------------|
| |
| [Multipart message] |
+-------------------------------------| [Callback returned
NL_STOP]
|<-----------
v
(SUCCESS)
At any time:
Message Format Error
|- - - - - - - - - - - - v
(FAILURE)
Message Overrun (Kernel Lost Data)
|- - - - - - - - - - - - v
(FAILURE)
Callback returned negative error code
(FAILURE)
- Sending Semantics
|
| Automatically fill in PID and/or sequence number
|
| [Application provides
nl_send() replacement]
|- - - - - - - - - - - - - - - - - - - - v
v cb->cb_send_ow()
| Add destination address and credentials
v
| Set source address
|
|- - - - - - - - - - - - - - - - - - - - v
|<- - - - - - - - - - - - - - - - - - - -+
v
sendmsg()
- 1) Connecting the socket
- 2) Sending data
const char buf[] = { 0x01, 0x02, 0x03, 0x04 };
struct nl_msg *msg = my_msg_builder();
struct msghdr hdr = { ... };
- 3) Receiving data
- 4) Closing
-
◆ NL_CB_CALL
| #define NL_CB_CALL |
( |
|
cb, |
|
|
|
type, |
|
|
|
msg |
|
) |
| |
Value:do { \
err = nl_cb_call(cb, type, msg); \
switch (err) { \
err = 0; \
break; \
goto skip; \
goto stop; \
default: \
goto out; \
} \
} while (0)
Definition at line 552 of file nl.c.
◆ nl_connect()
| int nl_connect |
( |
struct nl_handle * |
handle, |
|
|
int |
protocol |
|
) |
| |
- Parameters
-
| handle | Netlink handle. |
| protocol | Netlink protocol to use. |
Creates a netlink socket using the specified protocol, binds the socket and issues a connection attempt.
- Returns
- 0 on success or a negative error code.
Definition at line 191 of file nl.c.
196 handle->h_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
197 if (handle->h_fd < 0) {
198 err = nl_error(1,
"socket(AF_NETLINK, ...) failed");
202 if (!(handle->h_flags & NL_SOCK_BUFSIZE_SET)) {
208 err = bind(handle->h_fd, (
struct sockaddr*) &handle->h_local,
209 sizeof(handle->h_local));
211 err = nl_error(1,
"bind() failed");
215 addrlen =
sizeof(handle->h_local);
216 err = getsockname(handle->h_fd, (
struct sockaddr *) &handle->h_local,
219 err = nl_error(1,
"getsockname failed");
223 if (addrlen !=
sizeof(handle->h_local)) {
224 err = nl_error(EADDRNOTAVAIL,
"Invalid address length");
228 if (handle->h_local.nl_family != AF_NETLINK) {
229 err = nl_error(EPFNOSUPPORT,
"Address format not supported");
233 handle->h_proto = protocol;
References nl_set_buffer_size().
Referenced by nfnl_connect().
◆ nl_close()
| void nl_close |
( |
struct nl_handle * |
handle | ) |
|
◆ nl_sendto()
| int nl_sendto |
( |
struct nl_handle * |
handle, |
|
|
void * |
buf, |
|
|
size_t |
size |
|
) |
| |
- Parameters
-
| handle | Netlink handle. |
| buf | Data buffer. |
| size | Size of data buffer. |
- Returns
- Number of characters written on success or a negative error code.
Definition at line 271 of file nl.c.
275 ret = sendto(handle->h_fd, buf, size, 0, (
struct sockaddr *)
276 &handle->h_peer,
sizeof(handle->h_peer));
278 return nl_errno(errno);
◆ nl_sendmsg()
| int nl_sendmsg |
( |
struct nl_handle * |
handle, |
|
|
struct nl_msg * |
msg, |
|
|
struct msghdr * |
hdr |
|
) |
| |
- Parameters
-
| handle | Netlink handle. |
| msg | Netlink message to be sent. |
| hdr | Sendmsg() message header. |
- Returns
- Number of characters sent on sucess or a negative error code.
Definition at line 290 of file nl.c.
303 nlmsg_set_src(msg, &handle->h_local);
310 ret = sendmsg(handle->h_fd, hdr, 0);
312 return nl_errno(errno);
References nlmsg_hdr(), and nlmsghdr::nlmsg_len.
◆ nl_send()
| int nl_send |
( |
struct nl_handle * |
handle, |
|
|
struct nl_msg * |
msg |
|
) |
| |
- Parameters
-
| handle | Netlink handle |
| msg | Netlink message to be sent. |
- See also
- nl_sendmsg()
- Returns
- Number of characters sent on success or a negative error code.
Definition at line 325 of file nl.c.
330 struct msghdr hdr = {
331 .msg_name = (
void *) &handle->h_peer,
338 dst = nlmsg_get_dst(msg);
343 creds = nlmsg_get_creds(msg);
345 char buf[CMSG_SPACE(
sizeof(
struct ucred))];
346 struct cmsghdr *cmsg;
348 hdr.msg_control = buf;
349 hdr.msg_controllen =
sizeof(buf);
351 cmsg = CMSG_FIRSTHDR(&hdr);
352 cmsg->cmsg_level = SOL_SOCKET;
353 cmsg->cmsg_type = SCM_CREDENTIALS;
354 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct ucred));
355 memcpy(CMSG_DATA(cmsg), creds,
sizeof(
struct ucred));
Referenced by nl_send_auto_complete().
◆ nl_send_auto_complete()
| int nl_send_auto_complete |
( |
struct nl_handle * |
handle, |
|
|
struct nl_msg * |
msg |
|
) |
| |
- Parameters
-
| handle | Netlink handle. |
| msg | Netlink message to be sent. |
Checks the netlink message nlh for completness and extends it as required before sending it out. Checked fields include pid, sequence nr, and flags.
- See also
- nl_send()
- Returns
- Number of characters sent or a negative error code.
Definition at line 373 of file nl.c.
376 struct nl_cb *cb = handle->h_cb;
385 if (msg->nm_protocol == -1)
386 msg->nm_protocol = handle->h_proto;
391 return cb->cb_send_ow(handle, msg);
References nl_send(), NLM_F_ACK, NLM_F_REQUEST, nlmsghdr::nlmsg_flags, nlmsg_hdr(), nlmsghdr::nlmsg_pid, and nlmsghdr::nlmsg_seq.
Referenced by flnl_lookup(), nl_send_simple(), rtnl_class_add(), rtnl_cls_add(), rtnl_cls_change(), rtnl_cls_delete(), rtnl_link_change(), rtnl_neigh_add(), rtnl_neigh_change(), rtnl_neigh_delete(), rtnl_neightbl_change(), rtnl_qdisc_add(), rtnl_qdisc_change(), rtnl_qdisc_delete(), rtnl_rule_add(), and rtnl_rule_delete().
◆ nl_send_simple()
| int nl_send_simple |
( |
struct nl_handle * |
handle, |
|
|
int |
type, |
|
|
int |
flags, |
|
|
void * |
buf, |
|
|
size_t |
size |
|
) |
| |
◆ nl_recv()
| int nl_recv |
( |
struct nl_handle * |
handle, |
|
|
struct sockaddr_nl * |
nla, |
|
|
unsigned char ** |
buf, |
|
|
struct ucred ** |
creds |
|
) |
| |
- Parameters
-
| handle | Netlink handle. |
| nla | Destination pointer for peer's netlink address. |
| buf | Destination pointer for message content. |
| creds | Destination pointer for credentials. |
Receives a netlink message, allocates a buffer in *buf and stores the message content. The peer's netlink address is stored in *nla. The caller is responsible for freeing the buffer allocated in *buf if a positive value is returned. Interruped system calls are handled by repeating the read. The input buffer size is determined by peeking before the actual read is done.
A non-blocking sockets causes the function to return immediately with a return value of 0 if no data is available.
- Returns
- Number of octets read, 0 on EOF or a negative error code.
Definition at line 460 of file nl.c.
465 static int page_size = 0;
467 struct msghdr msg = {
468 .msg_name = (
void *) nla,
476 struct cmsghdr *cmsg;
478 if (handle->h_flags & NL_MSG_PEEK)
479 flags |= MSG_PEEK | MSG_TRUNC;
482 page_size = getpagesize() * 4;
484 iov.iov_len = page_size;
485 iov.iov_base = *buf = calloc(1, iov.iov_len);
487 if (handle->h_flags & NL_SOCK_PASSCRED) {
488 msg.msg_controllen = CMSG_SPACE(
sizeof(
struct ucred));
489 msg.msg_control = calloc(1, msg.msg_controllen);
493 n = recvmsg(handle->h_fd, &msg, flags);
497 if (errno == EINTR) {
498 NL_DBG(3,
"recvmsg() returned EINTR, retrying\n");
500 }
else if (errno == EAGAIN) {
501 NL_DBG(3,
"recvmsg() returned EAGAIN, aborting\n");
504 free(msg.msg_control);
506 return nl_error(errno,
"recvmsg failed");
510 if (msg.msg_flags & MSG_CTRUNC) {
511 msg.msg_controllen *= 2;
512 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
514 }
else if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) {
519 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
522 }
else if (flags != 0) {
528 if (msg.msg_namelen !=
sizeof(
struct sockaddr_nl)) {
529 free(msg.msg_control);
531 return nl_error(EADDRNOTAVAIL,
"socket address size mismatch");
534 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
535 if (cmsg->cmsg_level == SOL_SOCKET &&
536 cmsg->cmsg_type == SCM_CREDENTIALS) {
537 *creds = calloc(1,
sizeof(
struct ucred));
538 memcpy(*creds, CMSG_DATA(cmsg),
sizeof(
struct ucred));
543 free(msg.msg_control);
547 free(msg.msg_control);
◆ nl_recvmsgs()
| int nl_recvmsgs |
( |
struct nl_handle * |
handle, |
|
|
struct nl_cb * |
cb |
|
) |
| |
- Parameters
-
| handle | netlink handle |
| cb | set of callbacks to control behaviour. |
Repeatedly calls nl_recv() or the respective replacement if provided by the application (see nl_cb_overwrite_recv()) and parses the received data as netlink messages. Stops reading if one of the callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code.
A non-blocking sockets causes the function to return immediately if no data is available.
- Returns
- 0 on success or a negative error code from nl_recv().
Definition at line 768 of file nl.c.
770 if (cb->cb_recvmsgs_ow)
771 return cb->cb_recvmsgs_ow(handle, cb);
773 return recvmsgs(handle, cb);
Referenced by nl_recvmsgs_default().
◆ nl_recvmsgs_default()
| int nl_recvmsgs_default |
( |
struct nl_handle * |
handle | ) |
|
◆ nl_wait_for_ack()
| int nl_wait_for_ack |
( |
struct nl_handle * |
handle | ) |
|
- Parameters
-
- Precondition
- The netlink socket must be in blocking state.
Waits until an ACK is received for the latest not yet acknowledged netlink message.
Definition at line 801 of file nl.c.
808 return nl_get_errno();
References nl_cb_clone().
Referenced by rtnl_class_add(), rtnl_cls_add(), rtnl_cls_change(), rtnl_cls_delete(), rtnl_link_change(), rtnl_neigh_add(), rtnl_neigh_change(), rtnl_neigh_delete(), rtnl_neightbl_change(), rtnl_qdisc_add(), rtnl_qdisc_change(), rtnl_qdisc_delete(), rtnl_rule_add(), and rtnl_rule_delete().
sa_family_t nl_family
socket family (AF_NETLINK)
int nl_send(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message.
int nl_sendmsg(struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr)
Send netlink message with control over sendmsg() message header.
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
#define NLM_F_ACK
Request for an acknowledgment on success.
int nl_recvmsgs_default(struct nl_handle *handle)
Receive a set of message from a netlink socket using handlers in nl_handle.
@ NL_CB_SEQ_CHECK
Called instead of internal sequence number checking.
#define NLM_F_REQUEST
Must be set on all request messages (typically from user space to kernel space).
uint16_t nlmsg_flags
Message flags.
@ NL_CB_ACK
Message is an acknowledge.
uint32_t nlmsg_len
Length of message including header.
int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
Set socket buffer size of netlink handle.
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
@ NL_CB_CUSTOM
Customized handler specified by the user.
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
@ NL_CB_SEND_ACK
Sending of an acknowledge message has been requested.
uint32_t nlmsg_seq
Sequence number.
@ NL_CB_SKIPPED
Message wants to be skipped.
int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf, size_t size)
Send simple netlink message using nl_send_auto_complete()
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
uint32_t nlmsg_pid
Netlink PID of the proccess sending the message.
@ NL_CB_MSG_IN
Called for every message received.
@ NL_STOP
Stop parsing altogether and discard remaining messages.
@ NL_SKIP
Skip this message.
@ NL_CB_FINISH
Last message in a series of multi part messages received.
@ NL_CB_OVERRUN
Report received that data was lost.
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
int nl_connect(struct nl_handle *handle, int protocol)
Create and connect netlink socket.
@ NL_CB_INVALID
Message is malformed and invalid.
@ NL_OK
Proceed with wathever would come next.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
void nl_close(struct nl_handle *handle)
Close/Disconnect netlink socket.
@ NL_CB_MSG_OUT
Called for every message sent out except for nl_sendto()
int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
@ NL_CB_VALID
Message is valid.
int nl_recv(struct nl_handle *handle, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds)
Receive data from netlink socket.
int nl_sendto(struct nl_handle *handle, void *buf, size_t size)
Send raw data over netlink socket.