Unverified Commit 72abae9e by Stéphane Graber Committed by GitHub

Merge pull request #3312 from brauner/2020-03-20/fixes

network: use cleanup macros
parents d42ec829 a5f5cb41
...@@ -71,7 +71,7 @@ static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *de ...@@ -71,7 +71,7 @@ static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *de
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
err = -ENOMEM; return -ENOMEM;
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags =
NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
...@@ -79,7 +79,7 @@ static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *de ...@@ -79,7 +79,7 @@ static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *de
rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg)); rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
if (!rt) if (!rt)
err = -ENOMEM; return -ENOMEM;
rt->rtm_family = family; rt->rtm_family = family;
rt->rtm_table = RT_TABLE_MAIN; rt->rtm_table = RT_TABLE_MAIN;
...@@ -1511,25 +1511,25 @@ int lxc_netdev_isup(const char *name) ...@@ -1511,25 +1511,25 @@ int lxc_netdev_isup(const char *name)
int netdev_get_mtu(int ifindex) int netdev_get_mtu(int ifindex)
{ {
int answer_len, err, res; call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh; struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int readmore = 0, recv_len = 0;
int answer_len, err, res;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct nlmsghdr *msg; struct nlmsghdr *msg;
int readmore = 0, recv_len = 0;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
/* Save the answer buffer length, since it will be overwritten /* Save the answer buffer length, since it will be overwritten
* on the first receive (and we might need to receive more than * on the first receive (and we might need to receive more than
...@@ -1542,14 +1542,15 @@ int netdev_get_mtu(int ifindex) ...@@ -1542,14 +1542,15 @@ int netdev_get_mtu(int ifindex)
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) if (!ifi)
goto out; return ret_errno(ENOMEM);
ifi->ifi_family = AF_UNSPEC; ifi->ifi_family = AF_UNSPEC;
/* Send the request for addresses, which returns all addresses /* Send the request for addresses, which returns all addresses
* on all interfaces. */ * on all interfaces. */
err = netlink_send(&nlh, nlmsg); err = netlink_send(nlh_ptr, nlmsg);
if (err < 0) if (err < 0)
goto out; return ret_set_errno(-1, errno);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
...@@ -1561,9 +1562,9 @@ int netdev_get_mtu(int ifindex) ...@@ -1561,9 +1562,9 @@ int netdev_get_mtu(int ifindex)
answer->nlmsghdr->nlmsg_len = answer_len; answer->nlmsghdr->nlmsg_len = answer_len;
/* Get the (next) batch of reply messages */ /* Get the (next) batch of reply messages */
err = netlink_rcv(&nlh, answer); err = netlink_rcv(nlh_ptr, answer);
if (err < 0) if (err < 0)
goto out; return ret_set_errno(-1, errno);
recv_len = err; recv_len = err;
...@@ -1573,10 +1574,8 @@ int netdev_get_mtu(int ifindex) ...@@ -1573,10 +1574,8 @@ int netdev_get_mtu(int ifindex)
while (NLMSG_OK(msg, recv_len)) { while (NLMSG_OK(msg, recv_len)) {
/* Stop reading if we see an error message */ /* Stop reading if we see an error message */
if (msg->nlmsg_type == NLMSG_ERROR) { if (msg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *errmsg = struct nlmsgerr *errmsg = (struct nlmsgerr *)NLMSG_DATA(msg);
(struct nlmsgerr *)NLMSG_DATA(msg); return ret_set_errno(errmsg->error, errno);
err = errmsg->error;
goto out;
} }
/* Stop reading if we see a NLMSG_DONE message */ /* Stop reading if we see a NLMSG_DONE message */
...@@ -1588,20 +1587,19 @@ int netdev_get_mtu(int ifindex) ...@@ -1588,20 +1587,19 @@ int netdev_get_mtu(int ifindex)
ifi = NLMSG_DATA(msg); ifi = NLMSG_DATA(msg);
if (ifi->ifi_index == ifindex) { if (ifi->ifi_index == ifindex) {
struct rtattr *rta = IFLA_RTA(ifi); struct rtattr *rta = IFLA_RTA(ifi);
int attr_len = int attr_len = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
res = 0; res = 0;
while (RTA_OK(rta, attr_len)) { while (RTA_OK(rta, attr_len)) {
/* /*
Found a local address for the * Found a local address for the
* requested interface, return it. * requested interface, return it.
*/ */
if (rta->rta_type == IFLA_MTU) { if (rta->rta_type == IFLA_MTU) {
memcpy(&res, RTA_DATA(rta), memcpy(&res, RTA_DATA(rta), sizeof(int));
sizeof(int)); return res;
err = res;
goto out;
} }
rta = RTA_NEXT(rta, attr_len); rta = RTA_NEXT(rta, attr_len);
} }
} }
...@@ -1619,62 +1617,49 @@ int netdev_get_mtu(int ifindex) ...@@ -1619,62 +1617,49 @@ int netdev_get_mtu(int ifindex)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
/* If we end up here, we didn't find any result, so signal an error. */ /* If we end up here, we didn't find any result, so signal an error. */
err = -1; return -1;
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
int lxc_netdev_set_mtu(const char *name, int mtu) int lxc_netdev_set_mtu(const char *name, int mtu)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int err, len; int err, len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct nl_handler nlh;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -EINVAL;
len = strlen(name); len = strlen(name);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto out; return ret_errno(EINVAL);
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) { if (!ifi)
err = -ENOMEM; return ret_errno(ENOMEM);
goto out;
}
ifi->ifi_family = AF_UNSPEC; ifi->ifi_family = AF_UNSPEC;
if (nla_put_string(nlmsg, IFLA_IFNAME, name)) if (nla_put_string(nlmsg, IFLA_IFNAME, name))
goto out; return ret_errno(ENOMEM);
if (nla_put_u32(nlmsg, IFLA_MTU, mtu)) if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
goto out; return ret_errno(ENOMEM);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
out:
netlink_close(&nlh);
nlmsg_free(nlmsg);
nlmsg_free(answer);
return err;
} }
int lxc_netdev_up(const char *name) int lxc_netdev_up(const char *name)
...@@ -1689,229 +1674,205 @@ int lxc_netdev_down(const char *name) ...@@ -1689,229 +1674,205 @@ int lxc_netdev_down(const char *name)
int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu) int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int err, len; int err, len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct nl_handler nlh;
struct rtattr *nest1, *nest2, *nest3; struct rtattr *nest1, *nest2, *nest3;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -EINVAL;
len = strlen(name1); len = strlen(name1);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto out; return ret_errno(EINVAL);
len = strlen(name2); len = strlen(name2);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto out; return ret_errno(EINVAL);
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) if (!ifi)
goto out; return ret_errno(ENOMEM);
ifi->ifi_family = AF_UNSPEC; ifi->ifi_family = AF_UNSPEC;
err = -EINVAL;
nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO);
if (!nest1) if (!nest1)
goto out; return ret_errno(EINVAL);
if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth")) if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth"))
goto out; return ret_errno(ENOMEM);
nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA); nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
if (!nest2) if (!nest2)
goto out; return ret_errno(ENOMEM);
nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER); nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER);
if (!nest3) if (!nest3)
goto out; return ret_errno(ENOMEM);
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) { if (!ifi)
err = -ENOMEM; return ret_errno(ENOMEM);
goto out;
}
if (nla_put_string(nlmsg, IFLA_IFNAME, name2)) if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
goto out; return ret_errno(ENOMEM);
if (mtu > 0 && nla_put_u32(nlmsg, IFLA_MTU, mtu)) if (mtu > 0 && nla_put_u32(nlmsg, IFLA_MTU, mtu))
goto out; return ret_errno(ENOMEM);
if (pid > 0 && nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid)) if (pid > 0 && nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
goto out; return ret_errno(ENOMEM);
nla_end_nested(nlmsg, nest3); nla_end_nested(nlmsg, nest3);
nla_end_nested(nlmsg, nest2); nla_end_nested(nlmsg, nest2);
nla_end_nested(nlmsg, nest1); nla_end_nested(nlmsg, nest1);
if (nla_put_string(nlmsg, IFLA_IFNAME, name1)) if (nla_put_string(nlmsg, IFLA_IFNAME, name1))
goto out; return ret_errno(ENOMEM);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
/* TODO: merge with lxc_macvlan_create */ /* TODO: merge with lxc_macvlan_create */
int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid) int lxc_vlan_create(const char *master, const char *name, unsigned short vlanid)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int err, len, lindex; int err, len, lindex;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct nl_handler nlh;
struct rtattr *nest, *nest2; struct rtattr *nest, *nest2;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -EINVAL;
len = strlen(master); len = strlen(master);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto err3; return ret_errno(EINVAL);
len = strlen(name); len = strlen(name);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto err3; return ret_errno(EINVAL);
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto err3; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto err2; return ret_errno(ENOMEM);
err = -EINVAL;
lindex = if_nametoindex(master); lindex = if_nametoindex(master);
if (!lindex) if (!lindex)
goto err1; return ret_errno(EINVAL);
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) { if (!ifi)
err = -ENOMEM; return ret_errno(ENOMEM);
goto err1;
}
ifi->ifi_family = AF_UNSPEC; ifi->ifi_family = AF_UNSPEC;
nest = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
if (!nest) if (!nest)
goto err1; return ret_errno(ENOMEM);
if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan")) if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
goto err1; return ret_errno(ENOMEM);
nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA); nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
if (!nest2) if (!nest2)
goto err1; return ret_errno(ENOMEM);
if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid)) if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
goto err1; return ret_errno(ENOMEM);
nla_end_nested(nlmsg, nest2); nla_end_nested(nlmsg, nest2);
nla_end_nested(nlmsg, nest); nla_end_nested(nlmsg, nest);
if (nla_put_u32(nlmsg, IFLA_LINK, lindex)) if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
goto err1; return ret_errno(ENOMEM);
if (nla_put_string(nlmsg, IFLA_IFNAME, name)) if (nla_put_string(nlmsg, IFLA_IFNAME, name))
goto err1; return ret_errno(ENOMEM);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
err1:
nlmsg_free(answer);
err2:
nlmsg_free(nlmsg);
err3:
netlink_close(&nlh);
return err;
} }
int lxc_macvlan_create(const char *master, const char *name, int mode) int lxc_macvlan_create(const char *master, const char *name, int mode)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int err, index, len; int err, index, len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
struct nl_handler nlh;
struct rtattr *nest, *nest2; struct rtattr *nest, *nest2;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -EINVAL;
len = strlen(master); len = strlen(master);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto out; return ret_errno(EINVAL);
len = strlen(name); len = strlen(name);
if (len == 1 || len >= IFNAMSIZ) if (len == 1 || len >= IFNAMSIZ)
goto out; return ret_errno(EINVAL);
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
err = -EINVAL;
index = if_nametoindex(master); index = if_nametoindex(master);
if (!index) if (!index)
goto out; return ret_errno(EINVAL);
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg));
if (!ifi) { if (!ifi)
err = -ENOMEM; return ret_errno(ENOMEM);
goto out;
}
ifi->ifi_family = AF_UNSPEC; ifi->ifi_family = AF_UNSPEC;
nest = nla_begin_nested(nlmsg, IFLA_LINKINFO); nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
if (!nest) if (!nest)
goto out; return ret_errno(ENOMEM);
if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan")) if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
goto out; return ret_errno(ENOMEM);
if (mode) { if (mode) {
nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA); nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
if (!nest2) if (!nest2)
goto out; return ret_errno(ENOMEM);
if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode)) if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
goto out; return ret_errno(ENOMEM);
nla_end_nested(nlmsg, nest2); nla_end_nested(nlmsg, nest2);
} }
...@@ -1919,17 +1880,12 @@ int lxc_macvlan_create(const char *master, const char *name, int mode) ...@@ -1919,17 +1880,12 @@ int lxc_macvlan_create(const char *master, const char *name, int mode)
nla_end_nested(nlmsg, nest); nla_end_nested(nlmsg, nest);
if (nla_put_u32(nlmsg, IFLA_LINK, index)) if (nla_put_u32(nlmsg, IFLA_LINK, index))
goto out; return ret_errno(ENOMEM);
if (nla_put_string(nlmsg, IFLA_IFNAME, name)) if (nla_put_string(nlmsg, IFLA_IFNAME, name))
goto out; return ret_errno(ENOMEM);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
static int proc_sys_net_write(const char *path, const char *value) static int proc_sys_net_write(const char *path, const char *value)
...@@ -2067,62 +2023,55 @@ int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr) ...@@ -2067,62 +2023,55 @@ int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
static int ip_addr_add(int family, int ifindex, void *addr, void *bcast, static int ip_addr_add(int family, int ifindex, void *addr, void *bcast,
void *acast, int prefix) void *acast, int prefix)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int addrlen, err; int addrlen, err;
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
struct nl_handler nlh;
struct nlmsg *answer = NULL, *nlmsg = NULL;
addrlen = family == AF_INET ? sizeof(struct in_addr) addrlen = family == AF_INET ? sizeof(struct in_addr)
: sizeof(struct in6_addr); : sizeof(struct in6_addr);
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWADDR;
ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg)); ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
if (!ifa) if (!ifa)
goto out; return ret_errno(ENOMEM);
ifa->ifa_prefixlen = prefix; ifa->ifa_prefixlen = prefix;
ifa->ifa_index = ifindex; ifa->ifa_index = ifindex;
ifa->ifa_family = family; ifa->ifa_family = family;
ifa->ifa_scope = 0; ifa->ifa_scope = 0;
err = -EINVAL;
if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen)) if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen))
goto out; return ret_errno(EINVAL);
if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen)) if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen))
goto out; return ret_errno(EINVAL);
if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen)) if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen))
goto out; return ret_errno(EINVAL);
/* TODO: multicast, anycast with ipv6 */ /* TODO: multicast, anycast with ipv6 */
err = -EPROTONOSUPPORT;
if (family == AF_INET6 && if (family == AF_INET6 &&
(memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) || (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) ||
memcmp(acast, &in6addr_any, sizeof(in6addr_any)))) memcmp(acast, &in6addr_any, sizeof(in6addr_any))))
goto out; return ret_errno(EPROTONOSUPPORT);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr, int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
...@@ -2194,25 +2143,25 @@ static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res) ...@@ -2194,25 +2143,25 @@ static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res)
static int ip_addr_get(int family, int ifindex, void **res) static int ip_addr_get(int family, int ifindex, void **res)
{ {
call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int answer_len, err; int answer_len, err;
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
struct nl_handler nlh;
struct nlmsghdr *msg; struct nlmsghdr *msg;
int readmore = 0, recv_len = 0; int readmore = 0, recv_len = 0;
struct nlmsg *answer = NULL, *nlmsg = NULL;
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
/* Save the answer buffer length, since it will be overwritten on the /* Save the answer buffer length, since it will be overwritten on the
* first receive (and we might need to receive more than once). * first receive (and we might need to receive more than once).
...@@ -2224,15 +2173,16 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -2224,15 +2173,16 @@ static int ip_addr_get(int family, int ifindex, void **res)
ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg)); ifa = nlmsg_reserve(nlmsg, sizeof(struct ifaddrmsg));
if (!ifa) if (!ifa)
goto out; return ret_errno(ENOMEM);
ifa->ifa_family = family; ifa->ifa_family = family;
/* Send the request for addresses, which returns all addresses on all /* Send the request for addresses, which returns all addresses on all
* interfaces. * interfaces.
*/ */
err = netlink_send(&nlh, nlmsg); err = netlink_send(nlh_ptr, nlmsg);
if (err < 0) if (err < 0)
goto out; return ret_set_errno(err, errno);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
...@@ -2244,9 +2194,9 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -2244,9 +2194,9 @@ static int ip_addr_get(int family, int ifindex, void **res)
answer->nlmsghdr->nlmsg_len = answer_len; answer->nlmsghdr->nlmsg_len = answer_len;
/* Get the (next) batch of reply messages. */ /* Get the (next) batch of reply messages. */
err = netlink_rcv(&nlh, answer); err = netlink_rcv(nlh_ptr, answer);
if (err < 0) if (err < 0)
goto out; return ret_set_errno(err, errno);
recv_len = err; recv_len = err;
err = 0; err = 0;
...@@ -2257,10 +2207,8 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -2257,10 +2207,8 @@ static int ip_addr_get(int family, int ifindex, void **res)
while (NLMSG_OK(msg, recv_len)) { while (NLMSG_OK(msg, recv_len)) {
/* Stop reading if we see an error message. */ /* Stop reading if we see an error message. */
if (msg->nlmsg_type == NLMSG_ERROR) { if (msg->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *errmsg = struct nlmsgerr *errmsg = (struct nlmsgerr *)NLMSG_DATA(msg);
(struct nlmsgerr *)NLMSG_DATA(msg); return ret_set_errno(errmsg->error, errno);
err = errmsg->error;
goto out;
} }
/* Stop reading if we see a NLMSG_DONE message. */ /* Stop reading if we see a NLMSG_DONE message. */
...@@ -2269,21 +2217,17 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -2269,21 +2217,17 @@ static int ip_addr_get(int family, int ifindex, void **res)
break; break;
} }
if (msg->nlmsg_type != RTM_NEWADDR) { if (msg->nlmsg_type != RTM_NEWADDR)
err = -1; return ret_errno(EINVAL);
goto out;
}
ifa = (struct ifaddrmsg *)NLMSG_DATA(msg); ifa = (struct ifaddrmsg *)NLMSG_DATA(msg);
if (ifa->ifa_index == ifindex) { if (ifa->ifa_index == ifindex) {
if (ifa_get_local_ip(family, msg, res) < 0) { if (ifa_get_local_ip(family, msg, res) < 0)
err = -1; return ret_errno(EINVAL);
goto out;
}
/* Found a result, stop searching. */ /* Found a result, stop searching. */
if (*res) if (*res)
goto out; return 0;
} }
/* Keep reading more data from the socket if the last /* Keep reading more data from the socket if the last
...@@ -2301,13 +2245,7 @@ static int ip_addr_get(int family, int ifindex, void **res) ...@@ -2301,13 +2245,7 @@ static int ip_addr_get(int family, int ifindex, void **res)
/* If we end up here, we didn't find any result, so signal an /* If we end up here, we didn't find any result, so signal an
* error. * error.
*/ */
err = -1; return -1;
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res) int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res)
...@@ -2322,34 +2260,34 @@ int lxc_ipv4_addr_get(int ifindex, struct in_addr **res) ...@@ -2322,34 +2260,34 @@ int lxc_ipv4_addr_get(int ifindex, struct in_addr **res)
static int ip_gateway_add(int family, int ifindex, void *gw) static int ip_gateway_add(int family, int ifindex, void *gw)
{ {
int addrlen, err; call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL;
struct nl_handler nlh; struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int addrlen, err;
struct rtmsg *rt; struct rtmsg *rt;
struct nlmsg *answer = NULL, *nlmsg = NULL;
addrlen = family == AF_INET ? sizeof(struct in_addr) addrlen = family == AF_INET ? sizeof(struct in_addr)
: sizeof(struct in6_addr); : sizeof(struct in6_addr);
err = netlink_open(&nlh, NETLINK_ROUTE); err = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (err) if (err)
return err; return err;
err = -ENOMEM;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; return ret_errno(ENOMEM);
answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE);
if (!answer) if (!answer)
goto out; return ret_errno(ENOMEM);
nlmsg->nlmsghdr->nlmsg_flags = nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWROUTE;
rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg)); rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg));
if (!rt) if (!rt)
goto out; return ret_errno(ENOMEM);
rt->rtm_family = family; rt->rtm_family = family;
rt->rtm_table = RT_TABLE_MAIN; rt->rtm_table = RT_TABLE_MAIN;
rt->rtm_scope = RT_SCOPE_UNIVERSE; rt->rtm_scope = RT_SCOPE_UNIVERSE;
...@@ -2358,26 +2296,17 @@ static int ip_gateway_add(int family, int ifindex, void *gw) ...@@ -2358,26 +2296,17 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
/* "default" destination */ /* "default" destination */
rt->rtm_dst_len = 0; rt->rtm_dst_len = 0;
err = -EINVAL;
/* If gateway address not supplied, then a device route will be created instead */ /* If gateway address not supplied, then a device route will be created instead */
if (gw != NULL) { if (gw && nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen)) return ret_errno(ENOMEM);
goto out;
}
/* Adding the interface index enables the use of link-local /* Adding the interface index enables the use of link-local
* addresses for the gateway. * addresses for the gateway.
*/ */
if (nla_put_u32(nlmsg, RTA_OIF, ifindex)) if (nla_put_u32(nlmsg, RTA_OIF, ifindex))
goto out; return ret_errno(EINVAL);
err = netlink_transaction(&nlh, nlmsg, answer); return netlink_transaction(nlh_ptr, nlmsg, answer);
out:
netlink_close(&nlh);
nlmsg_free(answer);
nlmsg_free(nlmsg);
return err;
} }
int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw) int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw)
...@@ -3768,13 +3697,13 @@ int lxc_netns_set_nsid(int fd) ...@@ -3768,13 +3697,13 @@ int lxc_netns_set_nsid(int fd)
NLMSG_ALIGN(sizeof(struct rtgenmsg)) + NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
NLMSG_ALIGN(1024)]; NLMSG_ALIGN(1024)];
struct nl_handler nlh; struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
struct rtgenmsg *msg; struct rtgenmsg *msg;
int saved_errno;
const __s32 ns_id = -1; const __s32 ns_id = -1;
const __u32 netns_fd = fd; const __u32 netns_fd = fd;
ret = netlink_open(&nlh, NETLINK_ROUTE); ret = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (ret < 0) if (ret < 0)
return -1; return -1;
...@@ -3795,20 +3724,13 @@ int lxc_netns_set_nsid(int fd) ...@@ -3795,20 +3724,13 @@ int lxc_netns_set_nsid(int fd)
ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
if (ret < 0) if (ret < 0)
goto on_error; return ret_errno(ENOMEM);
ret = addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id)); ret = addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
if (ret < 0) if (ret < 0)
goto on_error; return ret_errno(ENOMEM);
ret = __netlink_transaction(&nlh, hdr, hdr);
on_error:
saved_errno = errno;
netlink_close(&nlh);
errno = saved_errno;
return ret; return __netlink_transaction(nlh_ptr, hdr, hdr);
} }
static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
...@@ -3843,19 +3765,19 @@ static inline __s32 rta_getattr_s32(const struct rtattr *rta) ...@@ -3843,19 +3765,19 @@ static inline __s32 rta_getattr_s32(const struct rtattr *rta)
int lxc_netns_get_nsid(int fd) int lxc_netns_get_nsid(int fd)
{ {
struct nl_handler nlh;
call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh;
int ret; int ret;
ssize_t len; ssize_t len;
char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
NLMSG_ALIGN(sizeof(struct rtgenmsg)) + NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
NLMSG_ALIGN(1024)]; NLMSG_ALIGN(1024)];
struct rtattr *tb[__LXC_NETNSA_MAX + 1]; struct rtattr *tb[__LXC_NETNSA_MAX + 1];
struct nl_handler nlh;
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
struct rtgenmsg *msg; struct rtgenmsg *msg;
int saved_errno;
__u32 netns_fd = fd; __u32 netns_fd = fd;
ret = netlink_open(&nlh, NETLINK_ROUTE); ret = netlink_open(nlh_ptr, NETLINK_ROUTE);
if (ret < 0) if (ret < 0)
return -1; return -1;
...@@ -3875,20 +3797,17 @@ int lxc_netns_get_nsid(int fd) ...@@ -3875,20 +3797,17 @@ int lxc_netns_get_nsid(int fd)
msg->rtgen_family = AF_UNSPEC; msg->rtgen_family = AF_UNSPEC;
ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd)); ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
if (ret == 0) if (ret < 0)
ret = __netlink_transaction(&nlh, hdr, hdr); return ret_errno(ENOMEM);
saved_errno = errno; ret = __netlink_transaction(nlh_ptr, hdr, hdr);
netlink_close(&nlh);
errno = saved_errno;
if (ret < 0) if (ret < 0)
return -1; return -1;
errno = EINVAL;
msg = NLMSG_DATA(hdr); msg = NLMSG_DATA(hdr);
len = hdr->nlmsg_len - NLMSG_SPACE(sizeof(*msg)); len = hdr->nlmsg_len - NLMSG_SPACE(sizeof(*msg));
if (len < 0) if (len < 0)
return -1; return ret_errno(EINVAL);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment