netlink: add __netlink_{send,recv,transaction}

These allow to pass a struct nlmsghdr directly and are used in the higher level
netlink_{send,rcv,transaction}.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2018-08-11 16:25:14 +02:00
parent d813c8edf8
commit 9fbbc42791
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
3 changed files with 58 additions and 123 deletions

View File

@ -3192,93 +3192,6 @@ enum {
__LXC_NETNSA_MAX, __LXC_NETNSA_MAX,
}; };
static int nl_send(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = nlmsghdr,
.iov_len = nlmsghdr->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
ret = sendmsg(handler->fd, &msg, MSG_NOSIGNAL);
if (ret < 0)
return -errno;
return ret;
}
static int nl_recv(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{
int ret;
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = nlmsghdr,
.iov_len = nlmsghdr->nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
again:
ret = recvmsg(handler->fd, &msg, 0);
if (ret < 0) {
if (errno == EINTR)
goto again;
return -1;
}
if (!ret)
return 0;
if (msg.msg_flags & MSG_TRUNC && (ret == nlmsghdr->nlmsg_len))
return -EMSGSIZE;
return ret;
}
extern int nl_transaction(struct nl_handler *handler, struct nlmsghdr *request,
struct nlmsghdr *answer)
{
int ret;
ret = nl_send(handler, request);
if (ret < 0)
return ret;
ret = nl_recv(handler, answer);
if (ret < 0)
return ret;
if (answer->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(answer);
return err->error;
}
return 0;
}
int lxc_netns_set_nsid(int fd) int lxc_netns_set_nsid(int fd)
{ {
ssize_t ret; ssize_t ret;
@ -3309,7 +3222,7 @@ int lxc_netns_set_nsid(int fd)
addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id)); addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
ret = nl_transaction(&nlh, hdr, hdr); ret = __netlink_transaction(&nlh, hdr, hdr);
netlink_close(&nlh); netlink_close(&nlh);
if (ret < 0) if (ret < 0)
return -1; return -1;

View File

@ -171,20 +171,20 @@ extern void nlmsg_free(struct nlmsg *nlmsg)
free(nlmsg); free(nlmsg);
} }
extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer) extern int __netlink_recv(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{ {
int ret; int ret;
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov = { struct iovec iov = {
.iov_base = answer->nlmsghdr, .iov_base = nlmsghdr,
.iov_len = answer->nlmsghdr->nlmsg_len, .iov_len = nlmsghdr->nlmsg_len,
}; };
struct msghdr msg = { struct msghdr msg = {
.msg_name = &nladdr, .msg_name = &nladdr,
.msg_namelen = sizeof(nladdr), .msg_namelen = sizeof(nladdr),
.msg_iov = &iov, .msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
}; };
memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr));
@ -197,33 +197,38 @@ again:
if (ret < 0) { if (ret < 0) {
if (errno == EINTR) if (errno == EINTR)
goto again; goto again;
return -errno;
return -1;
} }
if (!ret) if (!ret)
return 0; return 0;
if (msg.msg_flags & MSG_TRUNC && if (msg.msg_flags & MSG_TRUNC && (ret == nlmsghdr->nlmsg_len))
ret == answer->nlmsghdr->nlmsg_len)
return -EMSGSIZE; return -EMSGSIZE;
return ret; return ret;
} }
extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg) extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer)
{ {
return __netlink_recv(handler, answer->nlmsghdr);
}
extern int __netlink_send(struct nl_handler *handler, struct nlmsghdr *nlmsghdr)
{
int ret;
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct iovec iov = { struct iovec iov = {
.iov_base = nlmsg->nlmsghdr, .iov_base = nlmsghdr,
.iov_len = nlmsg->nlmsghdr->nlmsg_len, .iov_len = nlmsghdr->nlmsg_len,
}; };
struct msghdr msg = { struct msghdr msg = {
.msg_name = &nladdr, .msg_name = &nladdr,
.msg_namelen = sizeof(nladdr), .msg_namelen = sizeof(nladdr),
.msg_iov = &iov, .msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
}; };
int ret;
memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK; nladdr.nl_family = AF_NETLINK;
@ -232,30 +237,43 @@ extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
ret = sendmsg(handler->fd, &msg, MSG_NOSIGNAL); ret = sendmsg(handler->fd, &msg, MSG_NOSIGNAL);
if (ret < 0) if (ret < 0)
return -errno; return -1;
return ret; return ret;
} }
extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
{
return __netlink_send(handler, nlmsg->nlmsghdr);
}
extern int __netlink_transaction(struct nl_handler *handler,
struct nlmsghdr *request,
struct nlmsghdr *answer)
{
int ret;
ret = __netlink_send(handler, request);
if (ret < 0)
return ret;
ret = __netlink_recv(handler, answer);
if (ret < 0)
return ret;
if (answer->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(answer);
return err->error;
}
return 0;
}
extern int netlink_transaction(struct nl_handler *handler, extern int netlink_transaction(struct nl_handler *handler,
struct nlmsg *request, struct nlmsg *answer) struct nlmsg *request, struct nlmsg *answer)
{ {
int ret; return __netlink_transaction(handler, request->nlmsghdr,
answer->nlmsghdr);
ret = netlink_send(handler, request);
if (ret < 0)
return ret;
ret = netlink_rcv(handler, answer);
if (ret < 0)
return ret;
if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr);
return err->error;
}
return 0;
} }
extern int netlink_open(struct nl_handler *handler, int protocol) extern int netlink_open(struct nl_handler *handler, int protocol)

View File

@ -98,6 +98,7 @@ int netlink_close(struct nl_handler *handler);
* Returns 0 on success, < 0 otherwise * Returns 0 on success, < 0 otherwise
*/ */
int netlink_rcv(struct nl_handler *handler, struct nlmsg *nlmsg); int netlink_rcv(struct nl_handler *handler, struct nlmsg *nlmsg);
int __netlink_recv(struct nl_handler *handler, struct nlmsghdr *nlmsg);
/* /*
* netlink_send: send a netlink message to the kernel. It is up * netlink_send: send a netlink message to the kernel. It is up
@ -109,6 +110,7 @@ int netlink_rcv(struct nl_handler *handler, struct nlmsg *nlmsg);
* Returns 0 on success, < 0 otherwise * Returns 0 on success, < 0 otherwise
*/ */
int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg); int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg);
int __netlink_send(struct nl_handler *handler, struct nlmsghdr *nlmsg);
/* /*
* netlink_transaction: send a request to the kernel and read the response. * netlink_transaction: send a request to the kernel and read the response.
@ -123,6 +125,8 @@ int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg);
*/ */
int netlink_transaction(struct nl_handler *handler, int netlink_transaction(struct nl_handler *handler,
struct nlmsg *request, struct nlmsg *anwser); struct nlmsg *request, struct nlmsg *anwser);
int __netlink_transaction(struct nl_handler *handler, struct nlmsghdr *request,
struct nlmsghdr *anwser);
/* /*
* nla_put_string: copy a null terminated string to a netlink message * nla_put_string: copy a null terminated string to a netlink message