int lxc_netdev_delete_by_index(int ifindex) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct link_req *link_req; int err; 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; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_index = ifindex; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST; nlmsg->nlmsghdr.nlmsg_type = RTM_DELLINK; err = netlink_transaction(&nlh, nlmsg, answer); out: netlink_close(&nlh); nlmsg_free(answer); nlmsg_free(nlmsg); return err; }
static int ip_addr_add(int family, int ifindex, void *addr, void *bcast, void *acast, int prefix) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct ip_req *ip_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; ip_req = (struct ip_req *)nlmsg; ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); ip_req->nlmsg.nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; ip_req->nlmsg.nlmsghdr.nlmsg_type = RTM_NEWADDR; ip_req->ifa.ifa_prefixlen = prefix; ip_req->ifa.ifa_index = ifindex; ip_req->ifa.ifa_family = family; ip_req->ifa.ifa_scope = 0; err = -EINVAL; if (nla_put_buffer(nlmsg, IFA_LOCAL, addr, addrlen)) goto out; if (nla_put_buffer(nlmsg, IFA_ADDRESS, addr, addrlen)) goto out; if (nla_put_buffer(nlmsg, IFA_BROADCAST, bcast, addrlen)) goto out; /* TODO : multicast, anycast with ipv6 */ err = -EPROTONOSUPPORT; if (family == AF_INET6 && (memcmp(bcast, &in6addr_any, sizeof(in6addr_any)) || memcmp(acast, &in6addr_any, sizeof(in6addr_any)))) goto out; err = netlink_transaction(&nlh, nlmsg, answer); out: netlink_close(&nlh); nlmsg_free(answer); nlmsg_free(nlmsg); return err; }
extern int rtnetlink_transaction(struct rtnl_handler *handler, struct rtnlmsg *request, struct rtnlmsg *answer) { return netlink_transaction(&handler->nlh, (struct nlmsg *)&request->nlmsghdr, (struct nlmsg *)&answer->nlmsghdr); }
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_device_rename(const char *oldname, const char *newname) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct link_req *link_req; int index, len, err = -1; if (netlink_open(&nlh, NETLINK_ROUTE)) return -1; len = strlen(oldname); if (len == 1 || len > IFNAMSIZ) goto out; len = strlen(newname); if (len == 1 || len > IFNAMSIZ) goto out; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; answer = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!answer) goto out; index = if_nametoindex(oldname); if (!index) goto out; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_index = index; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; if (nla_put_string(nlmsg, IFLA_IFNAME, newname)) goto out; if (netlink_transaction(&nlh, nlmsg, answer)) goto out; err = 0; out: netlink_close(&nlh); nlmsg_free(answer); nlmsg_free(nlmsg); return err; }
static int netdev_set_flag(const char *name, int flag) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct link_req *link_req; int index, len, err; err = netlink_open(&nlh, NETLINK_ROUTE); if (err) return err; err = -EINVAL; len = strlen(name); if (len == 1 || len >= IFNAMSIZ) goto out; err = -ENOMEM; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; answer = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!answer) goto out; err = -EINVAL; index = if_nametoindex(name); if (!index) goto out; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_index = index; link_req->ifinfomsg.ifi_change |= IFF_UP; link_req->ifinfomsg.ifi_flags |= flag; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; err = netlink_transaction(&nlh, nlmsg, answer); out: netlink_close(&nlh); nlmsg_free(nlmsg); nlmsg_free(answer); return err; }
int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL; struct ifinfomsg *ifi; int err; err = netlink_open(&nlh, NETLINK_ROUTE); if (err) return err; err = -ENOMEM; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); if (!ifi) goto out; ifi->ifi_family = AF_UNSPEC; ifi->ifi_index = ifindex; if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid)) goto out; if (ifname != NULL) { if (nla_put_string(nlmsg, IFLA_IFNAME, ifname)) goto out; } err = netlink_transaction(&nlh, nlmsg, nlmsg); out: netlink_close(&nlh); nlmsg_free(nlmsg); return err; }
int lxc_netdev_move(char *ifname, pid_t pid) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL; struct link_req *link_req; int err, index; index = if_nametoindex(ifname); if (!ifname) return -EINVAL; err = netlink_open(&nlh, NETLINK_ROUTE); if (err) return err; err = -ENOMEM; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_index = index; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid)) goto out; err = netlink_transaction(&nlh, nlmsg, nlmsg); out: netlink_close(&nlh); nlmsg_free(nlmsg); return err; }
static int genetlink_resolve_family(const char *family) { struct nl_handler handler; struct nlattr *attr; struct genlmsg *request, *reply; struct genlmsghdr *genlmsghdr; int len, ret; request = genlmsg_alloc(GENLMSG_GOOD_SIZE); if (!request) return -ENOMEM; reply = genlmsg_alloc(GENLMSG_GOOD_SIZE); if (!reply) { genlmsg_free(request); return -ENOMEM; } request->nlmsghdr.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); request->nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; request->nlmsghdr.nlmsg_type = GENL_ID_CTRL; genlmsghdr = NLMSG_DATA(&request->nlmsghdr); genlmsghdr->cmd = CTRL_CMD_GETFAMILY; ret = netlink_open(&handler, NETLINK_GENERIC); if (ret) goto out; ret = nla_put_string((struct nlmsg *)&request->nlmsghdr, CTRL_ATTR_FAMILY_NAME, family); if (ret) goto out_close; ret = netlink_transaction(&handler, (struct nlmsg *)&request->nlmsghdr, (struct nlmsg *)&reply->nlmsghdr); if (ret < 0) goto out_close; genlmsghdr = NLMSG_DATA(&reply->nlmsghdr); len = reply->nlmsghdr.nlmsg_len; ret = -ENOMSG; if (reply->nlmsghdr.nlmsg_type != GENL_ID_CTRL) goto out_close; if (genlmsghdr->cmd != CTRL_CMD_NEWFAMILY) goto out_close; ret = -EMSGSIZE; len -= NLMSG_LENGTH(GENL_HDRLEN); if (len < 0) goto out_close; attr = (struct nlattr *)GENLMSG_DATA(reply); attr = (struct nlattr *)((char *)attr + NLA_ALIGN(attr->nla_len)); ret = -ENOMSG; if (attr->nla_type != CTRL_ATTR_FAMILY_ID) goto out_close; ret = *(__u16 *) NLA_DATA(attr); out_close: netlink_close(&handler); out: genlmsg_free(request); genlmsg_free(reply); return ret; }
int lxc_veth_create(const char *name1, const char *name2) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct link_req *link_req; struct rtattr *nest1, *nest2, *nest3; int len, err; err = netlink_open(&nlh, NETLINK_ROUTE); if (err) return err; err = -EINVAL; len = strlen(name1); if (len == 1 || len >= IFNAMSIZ) goto out; len = strlen(name2); if (len == 1 || len >= IFNAMSIZ) goto out; err = -ENOMEM; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; answer = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!answer) goto out; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; err = -EINVAL; nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO); if (!nest1) goto out; if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth")) goto out; nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA); if (!nest2) goto out; nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER); if (!nest3) goto out; nlmsg->nlmsghdr.nlmsg_len += sizeof(struct ifinfomsg); if (nla_put_string(nlmsg, IFLA_IFNAME, name2)) goto out; nla_end_nested(nlmsg, nest3); nla_end_nested(nlmsg, nest2); nla_end_nested(nlmsg, nest1); if (nla_put_string(nlmsg, IFLA_IFNAME, name1)) goto out; err = netlink_transaction(&nlh, nlmsg, answer); out: netlink_close(&nlh); nlmsg_free(answer); nlmsg_free(nlmsg); return err; }