util: introduce {send,receive}_one_fd()

Introduce two new helpers that send/receive a single fd via a unix
transport. Also make nspawn use them instead of hard-coding it.

Based on a patch by Krzesimir Nowak.
This commit is contained in:
David Herrmann
2015-09-22 14:09:54 +02:00
parent 8e112c803c
commit d960371482
4 changed files with 83 additions and 62 deletions
+7 -41
View File
@@ -183,17 +183,8 @@ int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *ex
}
int expose_port_send_rtnl(int send_fd) {
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
} control = {};
struct msghdr mh = {
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
_cleanup_close_ int fd = -1;
ssize_t k;
int r;
assert(send_fd >= 0);
@@ -201,19 +192,11 @@ int expose_port_send_rtnl(int send_fd) {
if (fd < 0)
return log_error_errno(errno, "Failed to allocate container netlink: %m");
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
mh.msg_controllen = cmsg->cmsg_len;
/* Store away the fd in the socket, so that it stays open as
* long as we run the child */
k = sendmsg(send_fd, &mh, MSG_NOSIGNAL);
if (k < 0)
return log_error_errno(errno, "Failed to send netlink fd: %m");
r = send_one_fd(send_fd, fd);
if (r < 0)
return log_error_errno(r, "Failed to send netlink fd: %m");
return 0;
}
@@ -224,33 +207,16 @@ int expose_port_watch_rtnl(
sd_netlink_message_handler_t handler,
union in_addr_union *exposed,
sd_netlink **ret) {
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
} control = {};
struct msghdr mh = {
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
_cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
int fd, r;
ssize_t k;
assert(event);
assert(recv_fd >= 0);
assert(ret);
k = recvmsg(recv_fd, &mh, MSG_NOSIGNAL);
if (k < 0)
return log_error_errno(errno, "Failed to recv netlink fd: %m");
cmsg = CMSG_FIRSTHDR(&mh);
assert(cmsg->cmsg_level == SOL_SOCKET);
assert(cmsg->cmsg_type == SCM_RIGHTS);
assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
fd = receive_one_fd(recv_fd);
if (fd < 0)
return log_error_errno(fd, "Failed to recv netlink fd: %m");
r = sd_netlink_open_fd(&rtnl, fd);
if (r < 0) {
+4 -21
View File
@@ -1264,16 +1264,7 @@ static int setup_dev_console(const char *dest, const char *console) {
static int setup_kmsg(const char *dest, int kmsg_socket) {
const char *from, *to;
_cleanup_umask_ mode_t u;
int fd, k;
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
} control = {};
struct msghdr mh = {
.msg_control = &control,
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
int fd, r;
assert(kmsg_socket >= 0);
@@ -1298,21 +1289,13 @@ static int setup_kmsg(const char *dest, int kmsg_socket) {
if (fd < 0)
return log_error_errno(errno, "Failed to open fifo: %m");
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
mh.msg_controllen = cmsg->cmsg_len;
/* Store away the fd in the socket, so that it stays open as
* long as we run the child */
k = sendmsg(kmsg_socket, &mh, MSG_NOSIGNAL);
r = send_one_fd(kmsg_socket, fd);
safe_close(fd);
if (k < 0)
return log_error_errno(errno, "Failed to send FIFO fd: %m");
if (r < 0)
return log_error_errno(r, "Failed to send FIFO fd: %m");
/* And now make the FIFO unavailable as /run/kmsg... */
(void) unlink(from);