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) |
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)
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()
// Bind and connect the socket to a protocol, NETLINK_ROUTE in this example. nl_connect(handle, NETLINK_ROUTE);
// 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));
// 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);
// Close the socket first to release kernel memory nl_close(handle);
#define NL_CB_CALL | ( | cb, | |||
type, | |||||
msg | ) |
int nl_connect | ( | struct nl_handle * | handle, | |
int | protocol | |||
) |
handle | Netlink handle. | |
protocol | Netlink protocol to use. |
Creates a netlink socket using the specified protocol, binds the socket and issues a connection attempt.
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 | ) |
handle | Netlink handle |
Definition at line 247 of file nl.c.
Referenced by nl_cache_mngr_free().
int nl_sendto | ( | struct nl_handle * | handle, | |
void * | buf, | |||
size_t | size | |||
) |
handle | Netlink handle. | |
buf | Data buffer. | |
size | Size of data buffer. |
int nl_sendmsg | ( | struct nl_handle * | handle, | |
struct nl_msg * | msg, | |||
struct msghdr * | hdr | |||
) |
handle | Netlink handle. | |
msg | Netlink message to be sent. | |
hdr | Sendmsg() message header. |
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 | |||
) |
handle | Netlink handle | |
msg | Netlink message to be sent. |
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 | |||
) |
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.
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 | |||
) |
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.
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 | |||
) |
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.
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 | |||
) |
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.
Definition at line 767 of file nl.c.
Referenced by nl_recvmsgs_default(), and nl_wait_for_ack().
int nl_recvmsgs_default | ( | struct nl_handle * | handle | ) |
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 | ) |
handle | netlink handle |
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 }