169 #include <netlink-local.h>
170 #include <netlink/netlink.h>
171 #include <netlink/utils.h>
172 #include <netlink/handlers.h>
173 #include <netlink/msg.h>
174 #include <netlink/attr.h>
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;
249 if (handle->h_fd >= 0) {
271 int nl_sendto(
struct nl_handle *handle,
void *buf,
size_t size)
275 ret = sendto(handle->h_fd, buf, size, 0, (
struct sockaddr *)
276 &handle->h_peer,
sizeof(handle->h_peer));
278 return nl_errno(errno);
290 int nl_sendmsg(
struct nl_handle *handle,
struct nl_msg *msg,
struct msghdr *hdr)
303 nlmsg_set_src(msg, &handle->h_local);
310 ret = sendmsg(handle->h_fd, hdr, 0);
312 return nl_errno(errno);
325 int nl_send(
struct nl_handle *handle,
struct nl_msg *msg)
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));
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);
418 return nl_errno(ENOMEM);
461 unsigned char **buf,
struct ucred **creds)
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)
482 page_size = getpagesize();
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 (iov.iov_len < n ||
511 msg.msg_flags & MSG_TRUNC) {
515 iov.iov_base = *buf = realloc(*buf, iov.iov_len);
517 }
else if (msg.msg_flags & MSG_CTRUNC) {
518 msg.msg_controllen *= 2;
519 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen);
521 }
else if (flags != 0) {
527 if (msg.msg_namelen !=
sizeof(
struct sockaddr_nl)) {
528 free(msg.msg_control);
530 return nl_error(EADDRNOTAVAIL,
"socket address size mismatch");
533 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
534 if (cmsg->cmsg_level == SOL_SOCKET &&
535 cmsg->cmsg_type == SCM_CREDENTIALS) {
536 *creds = calloc(1,
sizeof(
struct ucred));
537 memcpy(*creds, CMSG_DATA(cmsg),
sizeof(
struct ucred));
542 free(msg.msg_control);
546 free(msg.msg_control);
551 #define NL_CB_CALL(cb, type, msg) \
553 err = nl_cb_call(cb, type, msg); \
567 static int recvmsgs(
struct nl_handle *handle,
struct nl_cb *cb)
569 int n, err = 0, multipart = 0;
570 unsigned char *buf = NULL;
573 struct nl_msg *msg = NULL;
574 struct ucred *creds = NULL;
577 NL_DBG(3,
"Attempting to read from %p\n", handle);
579 n = cb->cb_recv_ow(handle, &nla, &buf, &creds);
581 n =
nl_recv(handle, &nla, &buf, &creds);
586 NL_DBG(3,
"recvmsgs(%p): Read %d bytes\n", handle, n);
590 NL_DBG(3,
"recgmsgs(%p): Processing valid message...\n",
596 err = nl_errno(ENOMEM);
600 nlmsg_set_proto(msg, handle->h_proto);
601 nlmsg_set_src(msg, &nla);
603 nlmsg_set_creds(msg, creds);
615 else if (hdr->
nlmsg_seq != handle->h_seq_expect) {
619 err = nl_error(EINVAL,
620 "Sequence number mismatch");
631 handle->h_seq_expect++;
632 NL_DBG(3,
"recvmsgs(%p): Increased expected " \
633 "sequence number to %d\n",
634 handle, handle->h_seq_expect);
677 err = nl_error(EOVERFLOW,
"Overrun");
694 err = nl_error(EINVAL,
695 "Truncated error message");
698 }
else if (e->
error) {
701 err = cb->cb_err(&nla, e,
708 err = nl_error(-e->
error,
713 err = nl_error(-e->
error,
740 goto continue_reading;
769 if (cb->cb_recvmsgs_ow)
770 return cb->cb_recvmsgs_ow(handle, cb);
772 return recvmsgs(handle, cb);
787 static int ack_wait_handler(
struct nl_msg *msg,
void *arg)
807 return nl_get_errno();
Report received that data was lost.
Called for every message sent out except for nl_sendto()
Message is an acknowledge.
int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
int nl_sendto(struct nl_handle *handle, void *buf, size_t size)
Send raw data over netlink socket.
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
Sending of an acknowledge message has been requested.
uint16_t nlmsg_type
Message type (content type)
int nl_sendmsg(struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr)
Send netlink message with control over sendmsg() message header.
#define NLM_F_ACK
Request for an acknowledgment on success.
Customized handler specified by the user.
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
int nl_send(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message.
uint32_t nlmsg_seq
Sequence number.
Message wants to be skipped.
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
int error
Error code (errno number)
int nl_recvmsgs_default(struct nl_handle *handle)
Receive a set of message from a netlink socket using handlers in nl_handle.
int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
check if the netlink message fits into the remaining bytes
Stop parsing altogether and discard remaining messages.
Called for every message received.
#define NLMSG_OVERRUN
The message signals that data got lost.
uint32_t nlmsg_len
Length of message including header.
#define NLM_F_REQUEST
Must be set on all request messages (typically from user space to kernel space).
#define NLMSG_ERROR
The message signals an error and the payload contains a nlmsgerr structure.
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
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.
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_next(struct nlmsghdr *nlh, int *remaining)
next netlink message in message stream
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()
uint32_t nlmsg_pid
Netlink PID of the proccess sending the message.
Message is malformed and invalid.
Last message in a series of multi part messages received.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
int nl_set_buffer_size(struct nl_handle *handle, int rxbuf, int txbuf)
Set socket buffer size of netlink handle.
Called instead of internal sequence number checking.
#define NLM_F_MULTI
Indicates the message is part of a multipart message terminated by NLMSG_DONE.
uint16_t nlmsg_flags
Message flags.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
int nl_connect(struct nl_handle *handle, int protocol)
Create and connect netlink socket.
Proceed with wathever would come next.
#define NLMSG_DONE
Message terminates a multipart message.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
#define NLMSG_NOOP
No operation, message must be ignored.
struct nl_msg * nlmsg_convert(struct nlmsghdr *hdr)
Convert a netlink message received from a netlink socket to a nl_msg.
int nlmsg_msg_size(int payload)
length of netlink message not including padding
int nl_recv(struct nl_handle *handle, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds)
Receive data from netlink socket.
sa_family_t nl_family
socket family (AF_NETLINK)
void nl_close(struct nl_handle *handle)
Close/Disconnect netlink socket.