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.
 
void nl_close (struct nl_handle *handle)
 Close/Disconnect netlink socket.
 

Send

int nl_sendto (struct nl_handle *handle, void *buf, size_t size)
 Send raw data over netlink socket.
 
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_send (struct nl_handle *handle, struct nl_msg *msg)
 Send netlink message.
 
int nl_send_auto_complete (struct nl_handle *handle, struct nl_msg *msg)
 Send netlink message and check & extend header values as needed.
 
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()
 

Receive

int nl_recv (struct nl_handle *handle, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds)
 Receive data from netlink socket.
 
int nl_recvmsgs (struct nl_handle *handle, struct nl_cb *cb)
 Receive a set of messages from a netlink socket.
 
int nl_recvmsgs_default (struct nl_handle *handle)
 Receive a set of message from a netlink socket using handlers in nl_handle.
 
int nl_wait_for_ack (struct nl_handle *handle)
 Wait for ACK.
 
#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)
@ NL_STOP
Stop parsing altogether and discard remaining messages.
Definition: handlers.h:65
@ NL_SKIP
Skip this message.
Definition: handlers.h:63
@ NL_CB_SKIPPED
Message wants to be skipped.
Definition: handlers.h:102
@ NL_CB_FINISH
Last message in a series of multi part messages received.
Definition: handlers.h:98
@ NL_CB_MSG_IN
Called for every message received.
Definition: handlers.h:106
@ NL_CB_OVERRUN
Report received that data was lost.
Definition: handlers.h:100
@ NL_CB_VALID
Message is valid.
Definition: handlers.h:96
@ NL_CB_ACK
Message is an acknowledge.
Definition: handlers.h:104
@ NL_CB_SEQ_CHECK
Called instead of internal sequence number checking.
Definition: handlers.h:112
@ NL_CB_SEND_ACK
Sending of an acknowledge message has been requested.
Definition: handlers.h:114
@ NL_CB_INVALID
Message is malformed and invalid.
Definition: handlers.h:110
#define NLM_F_ACK
Request for an acknowledgment on success.
int nl_recv(struct nl_handle *handle, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds)
Receive data from netlink socket.
Definition: nl.c:460
int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
Definition: nl.c:768
int nl_recvmsgs_default(struct nl_handle *handle)
Receive a set of message from a netlink socket using handlers in nl_handle.
Definition: nl.c:782
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()
@ NL_CB_MSG_OUT
Called for every message sent out except for nl_sendto()
Definition: handlers.h:108
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 nl_send(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message.
Definition: nl.c:325
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
1) Connecting the socket
// Bind and connect the socket to a protocol, NETLINK_ROUTE in this example.
nl_connect(handle, NETLINK_ROUTE);
int nl_connect(struct nl_handle *handle, int protocol)
Create and connect netlink socket.
Definition: nl.c:191
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));
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
Definition: msg.c:643
int nl_sendto(struct nl_handle *handle, void *buf, size_t size)
Send raw data over netlink socket.
Definition: nl.c:271
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()
Definition: nl.c:410
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()
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:801
Netlink socket address.
Definition: netlink-kernel.h:9
4) Closing
// Close the socket first to release kernel memory
nl_close(handle);
void nl_close(struct nl_handle *handle)
Close/Disconnect netlink socket.
Definition: nl.c:247

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)
@ NL_OK
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.

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;
236errout:
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

References nl_set_buffer_size().

Referenced by nfnl_connect(), and nl_cache_mngr_alloc().

◆ nl_close()

void nl_close ( struct nl_handle *  handle)
Parameters
handleNetlink handle

Definition at line 247 of file nl.c.

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}

Referenced by nl_cache_mngr_free().

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

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}
uint32_t nlmsg_len
Length of message including header.

References NL_CB_MSG_OUT, NL_OK, nlmsg_hdr(), and nlmsghdr::nlmsg_len.

Referenced by nl_send().

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

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}
sa_family_t nl_family
socket family (AF_NETLINK)

References sockaddr_nl::nl_family, and nl_sendmsg().

Referenced by nl_send_auto_complete().

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

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
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_REQUEST
Must be set on all request messages (typically from user space to kernel space).
Netlink message header.
uint32_t nlmsg_pid
Netlink PID of the proccess sending the message.
uint16_t nlmsg_flags
Message flags.
uint32_t nlmsg_seq
Sequence number.

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_addr_add(), rtnl_addr_delete(), 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 
)
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.

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);
428errout:
429 nlmsg_free(msg);
430
431 return err;
432}
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:448
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
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

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

◆ 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 }
491retry:
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
546abort:
547 free(msg.msg_control);
548 free(*buf);
549 return 0;
550}

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

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

Referenced by nl_recvmsgs_default(), and nl_wait_for_ack().

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

783{
784 return nl_recvmsgs(handle, handle->h_cb);
785
786}

References nl_recvmsgs().

Referenced by nl_cache_mngr_data_ready().

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

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}
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
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
Definition: handlers.c:286
@ NL_CB_CUSTOM
Customized handler specified by the user.
Definition: handlers.h:84

References NL_CB_ACK, nl_cb_clone(), NL_CB_CUSTOM, nl_cb_set(), and nl_recvmsgs().

Referenced by rtnl_addr_add(), rtnl_addr_delete(), 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().