system-linux: fix PATH_MAX undeclared compilation error
[oweals/netifd.git] / system-linux.c
index 6a0105e304c391a82419cfa12fe72cfde989534b..775b448e56f17e35c106cb37a2a76ee0b0dc8623 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/if.h>
 #include <net/if_arp.h>
 
+#include <limits.h>
 #include <arpa/inet.h>
 #include <netinet/ether.h>
 #include <netinet/in.h>
@@ -45,6 +46,8 @@
 #include <linux/veth.h>
 #include <linux/version.h>
 
+#include <sched.h>
+
 #ifndef RTN_FAILED_POLICY
 #define RTN_FAILED_POLICY 12
 #endif
@@ -139,8 +142,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 +909,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 +946,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 +988,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 +1011,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 +1024,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 +1246,25 @@ nla_put_failure:
        return -ENOMEM;
 }
 
+int system_link_netns_move(const char *ifname, int netns_fd)
+{
+       struct nl_msg *msg;
+       struct ifinfomsg iim = {
+               .ifi_family = AF_UNSPEC,
+               .ifi_index = 0,
+       };
+
+       msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
+
+       if (!msg)
+               return -1;
+
+       nlmsg_append(msg, &iim, sizeof(iim), 0);
+       nla_put_string(msg, IFLA_IFNAME, 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 +1288,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;
@@ -1656,7 +1708,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);
 
@@ -1945,9 +2000,6 @@ static int system_neigh(struct device *dev, struct device_neighbor *neighbor, in
        };
        struct nl_msg *msg;
 
-       if (!dev)
-               return 1;
-
        if (cmd == RTM_NEWNEIGH)
                flags |= NLM_F_CREATE | NLM_F_REPLACE;
 
@@ -1973,9 +2025,7 @@ int system_add_neighbor(struct device *dev, struct device_neighbor *neighbor)
 
 int system_del_neighbor(struct device *dev, struct device_neighbor *neighbor)
 {
-       int rval = system_neigh(dev, neighbor, RTM_DELNEIGH);
-       netifd_log_message(L_NOTICE,"return delete %d", rval);
-       return rval;
+       return system_neigh(dev, neighbor, RTM_DELNEIGH);
 }
 
 static int system_rt(struct device *dev, struct device_route *route, int cmd)
@@ -2372,7 +2422,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)
@@ -2879,6 +2929,63 @@ failure:
 }
 #endif
 
+#ifdef IFLA_XFRM_MAX
+static int system_add_xfrm_tunnel(const char *name, const char *kind,
+                                const unsigned int link, struct blob_attr **tb)
+{
+       struct nl_msg *nlm;
+       struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
+       struct blob_attr *cur;
+       int ret = 0;
+
+       nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
+       if (!nlm)
+               return -1;
+
+       nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
+       nla_put_string(nlm, IFLA_IFNAME, name);
+
+       struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
+       if (!linkinfo) {
+               ret = -ENOMEM;
+               goto failure;
+       }
+
+       nla_put_string(nlm, IFLA_INFO_KIND, kind);
+       struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
+       if (!infodata) {
+               ret = -ENOMEM;
+               goto failure;
+       }
+
+       if (link)
+               nla_put_u32(nlm, IFLA_XFRM_LINK, link);
+
+       if ((cur = tb[TUNNEL_ATTR_DATA])) {
+               struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
+               uint32_t if_id = 0;
+
+               blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
+                       blobmsg_data(cur), blobmsg_len(cur));
+
+               if ((cur = tb_data[XFRM_DATA_IF_ID])) {
+                       if ((if_id = blobmsg_get_u32(cur)))
+                               nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
+               }
+
+       }
+
+       nla_nest_end(nlm, infodata);
+       nla_nest_end(nlm, linkinfo);
+
+       return system_rtnl_call(nlm);
+
+failure:
+       nlmsg_free(nlm);
+       return ret;
+}
+#endif
+
 #ifdef IFLA_VXLAN_MAX
 static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
 {
@@ -3164,7 +3271,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);
@@ -3261,6 +3369,10 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
        } else if (!strcmp(str, "vtiip6")) {
                return system_add_vti_tunnel(name, "vti6", link, tb, true);
 #endif
+#ifdef IFLA_XFRM_MAX
+       } else if (!strcmp(str, "xfrm")) {
+               return system_add_xfrm_tunnel(name, "xfrm", link, tb);
+#endif
 #ifdef IFLA_VXLAN_MAX
        } else if(!strcmp(str, "vxlan")) {
                return system_add_vxlan(name, link, tb, false);