From: Christian Brauner Date: Sat, 11 Aug 2018 00:21:34 +0000 (+0200) Subject: netns: improve netnsid allocation X-Git-Tag: lxc-3.1.0~168^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ce60f0d5f3d53d554572c144ca0c5c2fec742f9;p=thirdparty%2Flxc.git netns: improve netnsid allocation Signed-off-by: Christian Brauner --- diff --git a/src/lxc/network.c b/src/lxc/network.c index d0824690f..53bc58111 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -3192,16 +3192,102 @@ enum { __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) { ssize_t ret; - char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + - NLMSG_ALIGN(sizeof(struct rtgenmsg)) + - NLMSG_ALIGN(1024)]; + char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + + NLMSG_ALIGN(sizeof(struct rtgenmsg)) + + NLMSG_ALIGN(1024)]; struct nl_handler nlh; - struct nlmsghdr *l_hdr; - struct rtgenmsg *l_msg; - struct sockaddr_nl l_addr; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; __s32 ns_id = -1; __u32 netns_fd = fd; @@ -3209,25 +3295,21 @@ int lxc_netns_set_nsid(int fd) if (ret < 0) return ret; - memset(l_buffer, 0, sizeof(l_buffer)); - l_hdr = (struct nlmsghdr *)l_buffer; - l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); - - l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); - l_hdr->nlmsg_type = RTM_NEWNSID; - l_hdr->nlmsg_flags = NLM_F_REQUEST; - l_hdr->nlmsg_pid = 0; - l_hdr->nlmsg_seq = RTM_NEWNSID; - l_msg->rtgen_family = AF_UNSPEC; + memset(buf, 0, sizeof(buf)); + hdr = (struct nlmsghdr *)buf; + msg = (struct rtgenmsg *)NLMSG_DATA(hdr); - addattr(l_hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); - addattr(l_hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id)); + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg)); + hdr->nlmsg_type = RTM_NEWNSID; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = RTM_NEWNSID; + msg->rtgen_family = AF_UNSPEC; - memset(&l_addr, 0, sizeof(l_addr)); - l_addr.nl_family = AF_NETLINK; + addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); + addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id)); - ret = sendto(nlh.fd, l_hdr, l_hdr->nlmsg_len, 0, - (struct sockaddr *)&l_addr, sizeof(l_addr)); + ret = nl_transaction(&nlh, hdr, hdr); netlink_close(&nlh); if (ret < 0) return -1;