X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=system-linux.c;h=c225175b7f4ee10151df4cbf8b445f7caafdeb79;hb=3392046d51959b228133e69f54893898df75635e;hp=6e5ca2861cd4b09804ba3ac2f5bd9c5f1e0e6e31;hpb=c1964d8eaf612d997e81474eb75071bedb2b914a;p=oweals%2Fnetifd.git diff --git a/system-linux.c b/system-linux.c index 6e5ca28..c225175 100644 --- a/system-linux.c +++ b/system-linux.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,8 @@ #include #include +#include + #ifndef RTN_FAILED_POLICY #define RTN_FAILED_POLICY 12 #endif @@ -71,6 +74,7 @@ #include "netifd.h" #include "device.h" #include "system.h" +#include "utils.h" struct event_socket { struct uloop_fd uloop; @@ -139,8 +143,10 @@ create_socket(int protocol, int groups) if (groups) nl_join_groups(sock, groups); - if (nl_connect(sock, protocol)) + if (nl_connect(sock, protocol)) { + nl_socket_free(sock); return NULL; + } return sock; } @@ -904,7 +910,7 @@ static int cb_clear_event(struct nl_msg *msg, void *arg) struct clear_data *clr = arg; struct nlmsghdr *hdr = nlmsg_hdr(msg); bool (*cb)(struct nlmsghdr *, int ifindex); - int type; + int type, ret; switch(clr->type) { case RTM_GETADDR: @@ -941,13 +947,23 @@ static int cb_clear_event(struct nl_msg *msg, void *arg) D(SYSTEM, "Remove %s from device %s\n", type == RTM_DELADDR ? "an address" : "a route", clr->dev->ifname); + memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len); hdr = nlmsg_hdr(clr->msg); hdr->nlmsg_type = type; hdr->nlmsg_flags = NLM_F_REQUEST; nl_socket_disable_auto_ack(sock_rtnl); - nl_send_auto_complete(sock_rtnl, clr->msg); + ret = nl_send_auto_complete(sock_rtnl, clr->msg); + if (ret < 0) { + if (type == RTM_DELRULE) + D(SYSTEM, "Error deleting a rule: %d\n", ret); + else + D(SYSTEM, "Error deleting %s from device '%s': %d\n", + type == RTM_DELADDR ? "an address" : "a route", + clr->dev->ifname, ret); + } + nl_socket_enable_auto_ack(sock_rtnl); return NL_SKIP; @@ -973,7 +989,7 @@ static void system_if_clear_entries(struct device *dev, int type, int af) { struct clear_data clr; - struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); + struct nl_cb *cb; struct rtmsg rtm = { .rtm_family = af, .rtm_flags = RTM_F_CLONED, @@ -996,6 +1012,7 @@ system_if_clear_entries(struct device *dev, int type, int af) return; } + cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) return; @@ -1008,10 +1025,13 @@ system_if_clear_entries(struct device *dev, int type, int af) nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending); nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending); - nl_send_auto_complete(sock_rtnl, clr.msg); + if (nl_send_auto_complete(sock_rtnl, clr.msg) < 0) + goto free; + while (pending > 0) nl_recvmsgs(sock_rtnl, cb); +free: nlmsg_free(clr.msg); out: nl_cb_put(cb); @@ -1227,6 +1247,30 @@ nla_put_failure: return -ENOMEM; } +int system_link_netns_move(struct device *dev, int netns_fd, const char *target_ifname) +{ + struct nl_msg *msg; + struct ifinfomsg iim = { + .ifi_family = AF_UNSPEC, + }; + + if (!dev) + return -1; + + iim.ifi_index = system_if_resolve(dev); + msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST); + + if (!msg) + return -1; + + nlmsg_append(msg, &iim, sizeof(iim), 0); + if (target_ifname) + nla_put_string(msg, IFLA_IFNAME, target_ifname); + + nla_put_u32(msg, IFLA_NET_NS_FD, netns_fd); + return system_rtnl_call(msg); +} + static int system_link_del(const char *ifname) { struct nl_msg *msg; @@ -1250,6 +1294,20 @@ int system_macvlan_del(struct device *macvlan) return system_link_del(macvlan->ifname); } +int system_netns_open(const pid_t target_ns) +{ + char pid_net_path[PATH_MAX]; + + snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%u/ns/net", target_ns); + + return open(pid_net_path, O_RDONLY); +} + +int system_netns_set(int netns_fd) +{ + return setns(netns_fd, CLONE_NEWNET); +} + int system_veth_add(struct device *veth, struct veth_config *cfg) { struct nl_msg *msg; @@ -1344,8 +1402,10 @@ int system_vlan_del(struct device *dev) int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg) { struct nl_msg *msg; - struct nlattr *linkinfo, *data; + struct nlattr *linkinfo, *data, *qos; struct ifinfomsg iim = { .ifi_family = AF_UNSPEC }; + struct vlan_qos_mapping *elem; + struct ifla_vlan_qos_mapping nl_qos_map; int rv; msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); @@ -1374,6 +1434,26 @@ int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlande netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name); #endif + if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) + goto nla_put_failure; + + vlist_simple_for_each_element(&cfg->ingress_qos_mapping_list, elem, node) { + nl_qos_map.from = elem->from; + nl_qos_map.to = elem->to; + nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map); + } + nla_nest_end(msg, qos); + + if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) + goto nla_put_failure; + + vlist_simple_for_each_element(&cfg->egress_qos_mapping_list, elem, node) { + nl_qos_map.from = elem->from; + nl_qos_map.to = elem->to; + nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map); + } + nla_nest_end(msg, qos); + nla_nest_end(msg, data); nla_nest_end(msg, linkinfo); @@ -1656,7 +1736,10 @@ int system_if_check(struct device *dev) nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk); nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk); - nl_send_auto_complete(sock_rtnl, msg); + ret = nl_send_auto_complete(sock_rtnl, msg); + if (ret < 0) + goto free; + while (chk.pending > 0) nl_recvmsgs(sock_rtnl, cb); @@ -2367,7 +2450,7 @@ time_t system_get_rtime(void) struct timespec ts; struct timeval tv; - if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) return ts.tv_sec; if (gettimeofday(&tv, NULL) == 0) @@ -2883,7 +2966,7 @@ static int system_add_xfrm_tunnel(const char *name, const char *kind, struct blob_attr *cur; int ret = 0; - nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL); + nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); if (!nlm) return -1; @@ -3216,7 +3299,8 @@ static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb) if (!strcmp(str, "greip") || !strcmp(str, "gretapip") || !strcmp(str, "greip6") || !strcmp(str, "gretapip6") || !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") || - !strcmp(str, "vxlan") || !strcmp(str, "vxlan6")) + !strcmp(str, "vxlan") || !strcmp(str, "vxlan6") || + !strcmp(str, "xfrm")) return system_link_del(name); else return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);