libnl  1.1.4
Modules | Data Structures
Core Netlink API

Modules

 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.
 

Data Structures

struct  sockaddr_nl
 Netlink socket address. More...
 

Connection Management

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...
 

Send

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...
 

Receive

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)
 

Detailed Description

Receiving Semantics
|
| cb = nl_socket_get_cb(socket)
v
nl_recvmsgs(socket, 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 ]
| | |<- - - - - - - - - - - - - - -+
| | |
| | +-----+------+--------------+----------------+--------------+
| | v v v v v
| | Valid Message ACK NOOP Message End of Multipart Error Message
| | | | | | |
| | v v v v v
| | | | | | |
| | +------------+--------------+----------------+ v
| | | (FAILURE)
| | | [Callback returned NL_SKIP]
| | [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
// Bind and connect the socket to a protocol, NETLINK_ROUTE in this example.
nl_connect(handle, NETLINK_ROUTE);
2) Sending data
// The most rudimentary method is to use nl_sendto() simply pushing
// a piece of data to the other netlink peer. This method is not
// recommended.
const char buf[] = { 0x01, 0x02, 0x03, 0x04 };
nl_sendto(handle, buf, sizeof(buf));
// A more comfortable interface is nl_send() taking a pointer to
// a netlink message.
struct nl_msg *msg = my_msg_builder();
nl_send(handle, nlmsg_hdr(msg));
// nl_sendmsg() provides additional control over the sendmsg() message
// header in order to allow more specific addressing of multiple peers etc.
struct msghdr hdr = { ... };
nl_sendmsg(handle, nlmsg_hdr(msg), &hdr);
// You're probably too lazy to fill out the netlink pid, sequence number
// and message flags all the time. nl_send_auto_complete() automatically
// extends your message header as needed with an appropriate sequence
// number, the netlink pid stored in the netlink handle and the message
// flags NLM_F_REQUEST and NLM_F_ACK
// Simple protocols don't require the complex message construction interface
// and may favour nl_send_simple() to easly send a bunch of payload
// encapsulated in a netlink message header.
nl_send_simple(handle, MY_MSG_TYPE, 0, buf, sizeof(buf));
3) Receiving data
// nl_recv() receives a single message allocating a buffer for the message
// content and gives back the pointer to you.
struct sockaddr_nl peer;
unsigned char *msg;
nl_recv(handle, &peer, &msg);
// nl_recvmsgs() receives a bunch of messages until the callback system
// orders it to state, usually after receving a compolete multi part
// message series.
nl_recvmsgs(handle, my_callback_configuration);
// nl_recvmsgs_default() acts just like nl_recvmsg() but uses the callback
// configuration stored in the handle.
// In case you want to wait for the ACK to be recieved that you requested
// with your latest message, you can call nl_wait_for_ack()
4) Closing
// Close the socket first to release kernel memory
nl_close(handle);

Macro Definition Documentation

◆ NL_CB_CALL

#define NL_CB_CALL (   cb,
  type,
  msg 
)
Value:
do { \
err = nl_cb_call(cb, type, msg); \
switch (err) { \
case NL_OK: \
err = 0; \
break; \
case NL_SKIP: \
goto skip; \
case NL_STOP: \
goto stop; \
default: \
goto out; \
} \
} while (0)
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:65
Skip this message.
Definition: handlers.h:63
Proceed with wathever would come next.
Definition: handlers.h:61

Definition at line 552 of file nl.c.

Function Documentation

◆ nl_connect()

int nl_connect ( struct nl_handle *  handle,
int  protocol 
)
Parameters
handleNetlink handle.
protocolNetlink 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.

References nl_set_buffer_size().

Referenced by nfnl_connect().

192 {
193  int err;
194  socklen_t addrlen;
195 
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");
199  goto errout;
200  }
201 
202  if (!(handle->h_flags & NL_SOCK_BUFSIZE_SET)) {
203  err = nl_set_buffer_size(handle, 0, 0);
204  if (err < 0)
205  goto errout;
206  }
207 
208  err = bind(handle->h_fd, (struct sockaddr*) &handle->h_local,
209  sizeof(handle->h_local));
210  if (err < 0) {
211  err = nl_error(1, "bind() failed");
212  goto errout;
213  }
214 
215  addrlen = sizeof(handle->h_local);
216  err = getsockname(handle->h_fd, (struct sockaddr *) &handle->h_local,
217  &addrlen);
218  if (err < 0) {
219  err = nl_error(1, "getsockname failed");
220  goto errout;
221  }
222 
223  if (addrlen != sizeof(handle->h_local)) {
224  err = nl_error(EADDRNOTAVAIL, "Invalid address length");
225  goto errout;
226  }
227 
228  if (handle->h_local.nl_family != AF_NETLINK) {
229  err = nl_error(EPFNOSUPPORT, "Address format not supported");
230  goto errout;
231  }
232 
233  handle->h_proto = protocol;
234 
235  return 0;
236 errout:
237  close(handle->h_fd);
238  handle->h_fd = -1;
239 
240  return err;
241 }
int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
Set socket buffer size of netlink handle.
Definition: socket.c:541

◆ nl_close()

void nl_close ( struct nl_handle *  handle)
Parameters
handleNetlink handle

Definition at line 247 of file nl.c.

Referenced by nl_cache_mngr_free().

248 {
249  if (handle->h_fd >= 0) {
250  close(handle->h_fd);
251  handle->h_fd = -1;
252  }
253 
254  handle->h_proto = 0;
255 }

◆ nl_sendto()

int nl_sendto ( struct nl_handle *  handle,
void *  buf,
size_t  size 
)
Parameters
handleNetlink handle.
bufData buffer.
sizeSize of data buffer.
Returns
Number of characters written on success or a negative error code.

Definition at line 271 of file nl.c.

272 {
273  int ret;
274 
275  ret = sendto(handle->h_fd, buf, size, 0, (struct sockaddr *)
276  &handle->h_peer, sizeof(handle->h_peer));
277  if (ret < 0)
278  return nl_errno(errno);
279 
280  return ret;
281 }

◆ nl_sendmsg()

int nl_sendmsg ( struct nl_handle *  handle,
struct nl_msg *  msg,
struct msghdr *  hdr 
)
Parameters
handleNetlink handle.
msgNetlink message to be sent.
hdrSendmsg() message header.
Returns
Number of characters sent on sucess or a negative error code.

Definition at line 290 of file nl.c.

References nlmsg_hdr(), and nlmsghdr::nlmsg_len.

291 {
292  struct nl_cb *cb;
293  int ret;
294 
295  struct iovec iov = {
296  .iov_base = (void *) nlmsg_hdr(msg),
297  .iov_len = nlmsg_hdr(msg)->nlmsg_len,
298  };
299 
300  hdr->msg_iov = &iov;
301  hdr->msg_iovlen = 1;
302 
303  nlmsg_set_src(msg, &handle->h_local);
304 
305  cb = handle->h_cb;
306  if (cb->cb_set[NL_CB_MSG_OUT])
307  if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
308  return 0;
309 
310  ret = sendmsg(handle->h_fd, hdr, 0);
311  if (ret < 0)
312  return nl_errno(errno);
313 
314  return ret;
315 }
Called for every message sent out except for nl_sendto()
Definition: handlers.h:108
uint32_t nlmsg_len
Length of message including header.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:643
Proceed with wathever would come next.
Definition: handlers.h:61

◆ nl_send()

int nl_send ( struct nl_handle *  handle,
struct nl_msg *  msg 
)
Parameters
handleNetlink handle
msgNetlink 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.

Referenced by nl_send_auto_complete().

326 {
327  struct sockaddr_nl *dst;
328  struct ucred *creds;
329 
330  struct msghdr hdr = {
331  .msg_name = (void *) &handle->h_peer,
332  .msg_namelen = sizeof(struct sockaddr_nl),
333  };
334 
335  /* Overwrite destination if specified in the message itself, defaults
336  * to the peer address of the handle.
337  */
338  dst = nlmsg_get_dst(msg);
339  if (dst->nl_family == AF_NETLINK)
340  hdr.msg_name = dst;
341 
342  /* Add credentials if present. */
343  creds = nlmsg_get_creds(msg);
344  if (creds != NULL) {
345  char buf[CMSG_SPACE(sizeof(struct ucred))];
346  struct cmsghdr *cmsg;
347 
348  hdr.msg_control = buf;
349  hdr.msg_controllen = sizeof(buf);
350 
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));
356  }
357 
358  return nl_sendmsg(handle, msg, &hdr);
359 }
int nl_sendmsg(struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr)
Send netlink message with control over sendmsg() message header.
Definition: nl.c:290
Netlink socket address.
Definition: netlink-kernel.h:8
sa_family_t nl_family
socket family (AF_NETLINK)

◆ nl_send_auto_complete()

int nl_send_auto_complete ( struct nl_handle *  handle,
struct nl_msg *  msg 
)
Parameters
handleNetlink handle.
msgNetlink 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.

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().

374 {
375  struct nlmsghdr *nlh;
376  struct nl_cb *cb = handle->h_cb;
377 
378  nlh = nlmsg_hdr(msg);
379  if (nlh->nlmsg_pid == 0)
380  nlh->nlmsg_pid = handle->h_local.nl_pid;
381 
382  if (nlh->nlmsg_seq == 0)
383  nlh->nlmsg_seq = handle->h_seq_next++;
384 
385  if (msg->nm_protocol == -1)
386  msg->nm_protocol = handle->h_proto;
387 
388  nlh->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK);
389 
390  if (cb->cb_send_ow)
391  return cb->cb_send_ow(handle, msg);
392  else
393  return nl_send(handle, msg);
394 }
#define NLM_F_ACK
Request for an acknowledgment on success.
int nl_send(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message.
Definition: nl.c:325
uint32_t nlmsg_seq
Sequence number.
Netlink message header.
#define NLM_F_REQUEST
Must be set on all request messages (typically from user space to kernel space).
uint32_t nlmsg_pid
Netlink PID of the proccess sending the message.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:643
uint16_t nlmsg_flags
Message flags.

◆ nl_send_simple()

int nl_send_simple ( struct nl_handle *  handle,
int  type,
int  flags,
void *  buf,
size_t  size 
)
Parameters
handleNetlink handle.
typeNetlink message type.
flagsNetlink message flags.
bufData buffer.
sizeSize of data buffer.

Builds a netlink message with the specified type and flags and appends the specified data as payload to the message.

See also
nl_send_auto_complete()
Returns
Number of characters sent on success or a negative error code.

Definition at line 410 of file nl.c.

References nl_send_auto_complete(), nlmsg_alloc_simple(), nlmsg_append(), and nlmsg_free().

Referenced by genl_send_simple(), nfnl_send_simple(), and nl_rtgen_request().

412 {
413  int err;
414  struct nl_msg *msg;
415 
416  msg = nlmsg_alloc_simple(type, flags);
417  if (!msg)
418  return nl_errno(ENOMEM);
419 
420  if (buf && size) {
421  err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
422  if (err < 0)
423  goto errout;
424  }
425 
426 
427  err = nl_send_auto_complete(handle, msg);
428 errout:
429  nlmsg_free(msg);
430 
431  return err;
432 }
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
Definition: nl.c:373
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:549
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:448

◆ nl_recv()

int nl_recv ( struct nl_handle *  handle,
struct sockaddr_nl nla,
unsigned char **  buf,
struct ucred **  creds 
)
Parameters
handleNetlink handle.
nlaDestination pointer for peer's netlink address.
bufDestination pointer for message content.
credsDestination 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.

462 {
463  int n;
464  int flags = 0;
465  static int page_size = 0;
466  struct iovec iov;
467  struct msghdr msg = {
468  .msg_name = (void *) nla,
469  .msg_namelen = sizeof(struct sockaddr_nl),
470  .msg_iov = &iov,
471  .msg_iovlen = 1,
472  .msg_control = NULL,
473  .msg_controllen = 0,
474  .msg_flags = 0,
475  };
476  struct cmsghdr *cmsg;
477 
478  if (handle->h_flags & NL_MSG_PEEK)
479  flags |= MSG_PEEK | MSG_TRUNC;
480 
481  if (page_size == 0)
482  page_size = getpagesize() * 4;
483 
484  iov.iov_len = page_size;
485  iov.iov_base = *buf = calloc(1, iov.iov_len);
486 
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);
490  }
491 retry:
492 
493  n = recvmsg(handle->h_fd, &msg, flags);
494  if (!n)
495  goto abort;
496  else if (n < 0) {
497  if (errno == EINTR) {
498  NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
499  goto retry;
500  } else if (errno == EAGAIN) {
501  NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
502  goto abort;
503  } else {
504  free(msg.msg_control);
505  free(*buf);
506  return nl_error(errno, "recvmsg failed");
507  }
508  }
509 
510  if (msg.msg_flags & MSG_CTRUNC) {
511  msg.msg_controllen *= 2;
512  msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
513  goto retry;
514  } else if (iov.iov_len < n || msg.msg_flags & MSG_TRUNC) {
515  /* Provided buffer is not long enough, enlarge it
516  * to size of n (which should be total length of the message)
517  * and try again. */
518  iov.iov_len = n;
519  iov.iov_base = *buf = realloc(*buf, iov.iov_len);
520  flags = 0;
521  goto retry;
522  } else if (flags != 0) {
523  /* Buffer is big enough, do the actual reading */
524  flags = 0;
525  goto retry;
526  }
527 
528  if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
529  free(msg.msg_control);
530  free(*buf);
531  return nl_error(EADDRNOTAVAIL, "socket address size mismatch");
532  }
533 
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));
539  break;
540  }
541  }
542 
543  free(msg.msg_control);
544  return n;
545 
546 abort:
547  free(msg.msg_control);
548  free(*buf);
549  return 0;
550 }
Netlink socket address.
Definition: netlink-kernel.h:8

◆ nl_recvmsgs()

int nl_recvmsgs ( struct nl_handle *  handle,
struct nl_cb *  cb 
)
Parameters
handlenetlink handle
cbset 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.

Referenced by nl_recvmsgs_default().

769 {
770  if (cb->cb_recvmsgs_ow)
771  return cb->cb_recvmsgs_ow(handle, cb);
772  else
773  return recvmsgs(handle, cb);
774 }

◆ nl_recvmsgs_default()

int nl_recvmsgs_default ( struct nl_handle *  handle)
Parameters
handlenetlink handle

Calls nl_recvmsgs() with the handlers configured in the netlink handle.

Definition at line 782 of file nl.c.

References nl_recvmsgs().

Referenced by nl_cache_mngr_data_ready().

783 {
784  return nl_recvmsgs(handle, handle->h_cb);
785 
786 }
int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
Definition: nl.c:768

◆ nl_wait_for_ack()

int nl_wait_for_ack ( struct nl_handle *  handle)
Parameters
handlenetlink handle
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.

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().

802 {
803  int err;
804  struct nl_cb *cb;
805 
806  cb = nl_cb_clone(handle->h_cb);
807  if (cb == NULL)
808  return nl_get_errno();
809 
810  nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
811  err = nl_recvmsgs(handle, cb);
812  nl_cb_put(cb);
813 
814  return err;
815 }
Message is an acknowledge.
Definition: handlers.h:104
int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
Definition: nl.c:768
Customized handler specified by the user.
Definition: handlers.h:84
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:286
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.
Definition: handlers.c:338