Core Netlink API

Data Structures

struct  sockaddr_nl
 Netlink socket address. More...

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.


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
          nl_recvmsgs_default(socket)
                 |
                 | 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 ]
 |  |            |                      NL_CB_SEND_ACK()
 |  |            |<- - - - - - - - - - - - - - -+
 |  |            |
 |  |      +-----+------+--------------+----------------+--------------+
 |  |      v            v              v                v              v
 |  | Valid Message    ACK        NOOP Message  End of Multipart  Error Message
 |  |      |            |              |                |              |
 |  |      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]    |<-----------
 |  +----------------------------------|
 |                                     |
 |         [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)
Sending Semantics
     nl_send_auto_complete()
             |
             | Automatically fill in PID and/or sequence number
             |
             |                   [Application provides nl_send() replacement]
             |- - - - - - - - - - - - - - - - - - - - v
             v                                 cb->cb_send_ow()
         nl_send()
             | Add destination address and credentials
             v
        nl_sendmsg()
             | Set source address
             |
             |- - - - - - - - - - - - - - - - - - - - v
             |                                 NL_CB_MSG_OUT()
             |<- - - - - - - - - - - - - - - - - - - -+
             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
 nl_send_auto_complete(handle, nlmsg_hdr(msg));

 // 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.
 nl_recvmsgs_default(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()
 nl_wait_for_ack(handle);
4) Closing
 // Close the socket first to release kernel memory
 nl_close(handle);

Define Documentation

#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)

Definition at line 551 of file nl.c.


Function Documentation

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.

References nl_set_buffer_size().

Referenced by nfnl_connect(), and nl_cache_mngr_alloc().

00192 {
00193         int err;
00194         socklen_t addrlen;
00195 
00196         handle->h_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
00197         if (handle->h_fd < 0) {
00198                 err = nl_error(1, "socket(AF_NETLINK, ...) failed");
00199                 goto errout;
00200         }
00201 
00202         if (!(handle->h_flags & NL_SOCK_BUFSIZE_SET)) {
00203                 err = nl_set_buffer_size(handle, 0, 0);
00204                 if (err < 0)
00205                         goto errout;
00206         }
00207 
00208         err = bind(handle->h_fd, (struct sockaddr*) &handle->h_local,
00209                    sizeof(handle->h_local));
00210         if (err < 0) {
00211                 err = nl_error(1, "bind() failed");
00212                 goto errout;
00213         }
00214 
00215         addrlen = sizeof(handle->h_local);
00216         err = getsockname(handle->h_fd, (struct sockaddr *) &handle->h_local,
00217                           &addrlen);
00218         if (err < 0) {
00219                 err = nl_error(1, "getsockname failed");
00220                 goto errout;
00221         }
00222 
00223         if (addrlen != sizeof(handle->h_local)) {
00224                 err = nl_error(EADDRNOTAVAIL, "Invalid address length");
00225                 goto errout;
00226         }
00227 
00228         if (handle->h_local.nl_family != AF_NETLINK) {
00229                 err = nl_error(EPFNOSUPPORT, "Address format not supported");
00230                 goto errout;
00231         }
00232 
00233         handle->h_proto = protocol;
00234 
00235         return 0;
00236 errout:
00237         close(handle->h_fd);
00238         handle->h_fd = -1;
00239 
00240         return err;
00241 }

void nl_close ( struct nl_handle *  handle  ) 
Parameters:
handle Netlink handle

Definition at line 247 of file nl.c.

Referenced by nl_cache_mngr_free().

00248 {
00249         if (handle->h_fd >= 0) {
00250                 close(handle->h_fd);
00251                 handle->h_fd = -1;
00252         }
00253 
00254         handle->h_proto = 0;
00255 }

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.

00272 {
00273         int ret;
00274 
00275         ret = sendto(handle->h_fd, buf, size, 0, (struct sockaddr *)
00276                      &handle->h_peer, sizeof(handle->h_peer));
00277         if (ret < 0)
00278                 return nl_errno(errno);
00279 
00280         return ret;
00281 }

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.

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

Referenced by nl_send().

00291 {
00292         struct nl_cb *cb;
00293         int ret;
00294 
00295         struct iovec iov = {
00296                 .iov_base = (void *) nlmsg_hdr(msg),
00297                 .iov_len = nlmsg_hdr(msg)->nlmsg_len,
00298         };
00299 
00300         hdr->msg_iov = &iov;
00301         hdr->msg_iovlen = 1;
00302 
00303         nlmsg_set_src(msg, &handle->h_local);
00304 
00305         cb = handle->h_cb;
00306         if (cb->cb_set[NL_CB_MSG_OUT])
00307                 if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
00308                         return 0;
00309 
00310         ret = sendmsg(handle->h_fd, hdr, 0);
00311         if (ret < 0)
00312                 return nl_errno(errno);
00313 
00314         return ret;
00315 }

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.

References sockaddr_nl::nl_family, and nl_sendmsg().

Referenced by nl_send_auto_complete().

00326 {
00327         struct sockaddr_nl *dst;
00328         struct ucred *creds;
00329         
00330         struct msghdr hdr = {
00331                 .msg_name = (void *) &handle->h_peer,
00332                 .msg_namelen = sizeof(struct sockaddr_nl),
00333         };
00334 
00335         /* Overwrite destination if specified in the message itself, defaults
00336          * to the peer address of the handle.
00337          */
00338         dst = nlmsg_get_dst(msg);
00339         if (dst->nl_family == AF_NETLINK)
00340                 hdr.msg_name = dst;
00341 
00342         /* Add credentials if present. */
00343         creds = nlmsg_get_creds(msg);
00344         if (creds != NULL) {
00345                 char buf[CMSG_SPACE(sizeof(struct ucred))];
00346                 struct cmsghdr *cmsg;
00347 
00348                 hdr.msg_control = buf;
00349                 hdr.msg_controllen = sizeof(buf);
00350 
00351                 cmsg = CMSG_FIRSTHDR(&hdr);
00352                 cmsg->cmsg_level = SOL_SOCKET;
00353                 cmsg->cmsg_type = SCM_CREDENTIALS;
00354                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
00355                 memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
00356         }
00357 
00358         return nl_sendmsg(handle, msg, &hdr);
00359 }

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.

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

00374 {
00375         struct nlmsghdr *nlh;
00376         struct nl_cb *cb = handle->h_cb;
00377 
00378         nlh = nlmsg_hdr(msg);
00379         if (nlh->nlmsg_pid == 0)
00380                 nlh->nlmsg_pid = handle->h_local.nl_pid;
00381 
00382         if (nlh->nlmsg_seq == 0)
00383                 nlh->nlmsg_seq = handle->h_seq_next++;
00384 
00385         if (msg->nm_protocol == -1)
00386                 msg->nm_protocol = handle->h_proto;
00387         
00388         nlh->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK);
00389 
00390         if (cb->cb_send_ow)
00391                 return cb->cb_send_ow(handle, msg);
00392         else
00393                 return nl_send(handle, msg);
00394 }

int nl_send_simple ( struct nl_handle *  handle,
int  type,
int  flags,
void *  buf,
size_t  size 
)
Parameters:
handle Netlink handle.
type Netlink message type.
flags Netlink message flags.
buf Data buffer.
size Size 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().

00412 {
00413         int err;
00414         struct nl_msg *msg;
00415 
00416         msg = nlmsg_alloc_simple(type, flags);
00417         if (!msg)
00418                 return nl_errno(ENOMEM);
00419 
00420         if (buf && size) {
00421                 err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO);
00422                 if (err < 0)
00423                         goto errout;
00424         }
00425         
00426 
00427         err = nl_send_auto_complete(handle, msg);
00428 errout:
00429         nlmsg_free(msg);
00430 
00431         return err;
00432 }

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.

00462 {
00463         int n;
00464         int flags = 0;
00465         static int page_size = 0;
00466         struct iovec iov;
00467         struct msghdr msg = {
00468                 .msg_name = (void *) nla,
00469                 .msg_namelen = sizeof(struct sockaddr_nl),
00470                 .msg_iov = &iov,
00471                 .msg_iovlen = 1,
00472                 .msg_control = NULL,
00473                 .msg_controllen = 0,
00474                 .msg_flags = 0,
00475         };
00476         struct cmsghdr *cmsg;
00477 
00478         if (handle->h_flags & NL_MSG_PEEK)
00479                 flags |= MSG_PEEK;
00480 
00481         if (page_size == 0)
00482                 page_size = getpagesize();
00483 
00484         iov.iov_len = page_size;
00485         iov.iov_base = *buf = calloc(1, iov.iov_len);
00486 
00487         if (handle->h_flags & NL_SOCK_PASSCRED) {
00488                 msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
00489                 msg.msg_control = calloc(1, msg.msg_controllen);
00490         }
00491 retry:
00492 
00493         n = recvmsg(handle->h_fd, &msg, flags);
00494         if (!n)
00495                 goto abort;
00496         else if (n < 0) {
00497                 if (errno == EINTR) {
00498                         NL_DBG(3, "recvmsg() returned EINTR, retrying\n");
00499                         goto retry;
00500                 } else if (errno == EAGAIN) {
00501                         NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n");
00502                         goto abort;
00503                 } else {
00504                         free(msg.msg_control);
00505                         free(*buf);
00506                         return nl_error(errno, "recvmsg failed");
00507                 }
00508         }
00509 
00510         if (iov.iov_len < n ||
00511             msg.msg_flags & MSG_TRUNC) {
00512                 /* Provided buffer is not long enough, enlarge it
00513                  * and try again. */
00514                 iov.iov_len *= 2;
00515                 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
00516                 goto retry;
00517         } else if (msg.msg_flags & MSG_CTRUNC) {
00518                 msg.msg_controllen *= 2;
00519                 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
00520                 goto retry;
00521         } else if (flags != 0) {
00522                 /* Buffer is big enough, do the actual reading */
00523                 flags = 0;
00524                 goto retry;
00525         }
00526 
00527         if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00528                 free(msg.msg_control);
00529                 free(*buf);
00530                 return nl_error(EADDRNOTAVAIL, "socket address size mismatch");
00531         }
00532 
00533         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00534                 if (cmsg->cmsg_level == SOL_SOCKET &&
00535                     cmsg->cmsg_type == SCM_CREDENTIALS) {
00536                         *creds = calloc(1, sizeof(struct ucred));
00537                         memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred));
00538                         break;
00539                 }
00540         }
00541 
00542         free(msg.msg_control);
00543         return n;
00544 
00545 abort:
00546         free(msg.msg_control);
00547         free(*buf);
00548         return 0;
00549 }

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 767 of file nl.c.

Referenced by nl_recvmsgs_default(), and nl_wait_for_ack().

00768 {
00769         if (cb->cb_recvmsgs_ow)
00770                 return cb->cb_recvmsgs_ow(handle, cb);
00771         else
00772                 return recvmsgs(handle, cb);
00773 }

int nl_recvmsgs_default ( struct nl_handle *  handle  ) 
Parameters:
handle netlink handle

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

Definition at line 781 of file nl.c.

References nl_recvmsgs().

Referenced by nl_cache_mngr_data_ready().

00782 {
00783         return nl_recvmsgs(handle, handle->h_cb);
00784 
00785 }

int nl_wait_for_ack ( struct nl_handle *  handle  ) 
Parameters:
handle netlink 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 800 of file nl.c.

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

00801 {
00802         int err;
00803         struct nl_cb *cb;
00804 
00805         cb = nl_cb_clone(handle->h_cb);
00806         if (cb == NULL)
00807                 return nl_get_errno();
00808 
00809         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL);
00810         err = nl_recvmsgs(handle, cb);
00811         nl_cb_put(cb);
00812 
00813         return err;
00814 }


Generated on 30 Oct 2009 for libnl by  doxygen 1.6.1