diff options
Diffstat (limited to 'src/lxc/network.c')
-rw-r--r-- | src/lxc/network.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/lxc/network.c b/src/lxc/network.c index 420117a..b1d60f2 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -89,6 +89,11 @@ struct ip_req { struct ifaddrmsg ifa; }; +struct rt_req { + struct nlmsg nlmsg; + struct rtmsg rt; +}; + int lxc_netdev_move_by_index(int ifindex, pid_t pid) { struct nl_handler nlh; @@ -741,6 +746,71 @@ int lxc_ipv4_addr_add(int ifindex, struct in_addr *addr, return ip_addr_add(AF_INET, ifindex, addr, bcast, NULL, prefix); } +static int ip_gateway_add(int family, int ifindex, void *gw) +{ + struct nl_handler nlh; + struct nlmsg *nlmsg = NULL, *answer = NULL; + struct rt_req *rt_req; + int addrlen; + int err; + + addrlen = family == AF_INET ? sizeof(struct in_addr) : + sizeof(struct in6_addr); + + err = netlink_open(&nlh, NETLINK_ROUTE); + if (err) + return err; + + err = -ENOMEM; + nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); + if (!nlmsg) + goto out; + + answer = nlmsg_alloc(NLMSG_GOOD_SIZE); + if (!answer) + goto out; + + rt_req = (struct rt_req *)nlmsg; + rt_req->nlmsg.nlmsghdr.nlmsg_len = + NLMSG_LENGTH(sizeof(struct rtmsg)); + rt_req->nlmsg.nlmsghdr.nlmsg_flags = + NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; + rt_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWROUTE; + rt_req->rt.rtm_family = family; + rt_req->rt.rtm_table = RT_TABLE_MAIN; + rt_req->rt.rtm_scope = RT_SCOPE_UNIVERSE; + rt_req->rt.rtm_protocol = RTPROT_BOOT; + rt_req->rt.rtm_type = RTN_UNICAST; + /* "default" destination */ + rt_req->rt.rtm_dst_len = 0; + + err = -EINVAL; + if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen)) + goto out; + + /* Adding the interface index enables the use of link-local + * addresses for the gateway */ + if (nla_put_u32(nlmsg, RTA_OIF, ifindex)) + goto out; + + err = netlink_transaction(&nlh, 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) +{ + return ip_gateway_add(AF_INET, ifindex, gw); +} + +int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw) +{ + return ip_gateway_add(AF_INET6, ifindex, gw); +} + /* * There is a lxc_bridge_attach, but no need of a bridge detach * as automatically done by kernel when a netdev is deleted. |