system-linux: extend link mode speed definitions
[oweals/netifd.git] / system-linux.c
index 9b654d16c2117d263cd325e7cff4a65d2744f380..c7bdf5b9befef8ac00326d1db7624b104c14dd29 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2013 Steven Barth <steven@midlink.org>
  * Copyright (C) 2014 Gioacchino Mazzurco <gio@eigenlab.org>
  * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
+ * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2
@@ -665,7 +666,7 @@ static int system_bridge_if(const char *bridge, struct device *dev, int cmd, voi
                ifr.ifr_ifindex = dev->ifindex;
        else
                ifr.ifr_data = data;
-       strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name) - 1);
        return ioctl(sock_ioctl, cmd, &ifr);
 }
 
@@ -768,7 +769,7 @@ int system_bridge_delif(struct device *bridge, struct device *dev)
 int system_if_resolve(struct device *dev)
 {
        struct ifreq ifr;
-       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
        if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
                return ifr.ifr_ifindex;
        else
@@ -780,7 +781,7 @@ static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
        struct ifreq ifr;
 
        memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
        if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
                return -1;
 
@@ -1333,7 +1334,7 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
        char buf[10];
 
        memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
 
        if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
                s->mtu = ifr.ifr_mtu;
@@ -1430,7 +1431,7 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
        char buf[12];
 
        memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
        if (s->flags & DEV_OPT_MTU & apply_mask) {
                ifr.ifr_mtu = s->mtu;
                if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
@@ -1682,12 +1683,27 @@ static const struct {
        uint32_t mask;
        const char *name;
 } ethtool_link_modes[] = {
-       { ADVERTISED_10baseT_Half, "10H" },
-       { ADVERTISED_10baseT_Full, "10F" },
-       { ADVERTISED_100baseT_Half, "100H" },
-       { ADVERTISED_100baseT_Full, "100F" },
-       { ADVERTISED_1000baseT_Half, "1000H" },
-       { ADVERTISED_1000baseT_Full, "1000F" },
+       { ADVERTISED_10baseT_Half, "10baseT-H" },
+       { ADVERTISED_10baseT_Full, "10baseT-F" },
+       { ADVERTISED_100baseT_Half, "100baseT-H" },
+       { ADVERTISED_100baseT_Full, "100baseT-F" },
+       { ADVERTISED_1000baseT_Half, "1000baseT-H" },
+       { ADVERTISED_1000baseT_Full, "1000baseT-F" },
+       { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
+       { ADVERTISED_2500baseX_Full, "2500baseX-F" },
+       { ADVERTISED_10000baseT_Full, "10000baseT-F" },
+       { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
+       { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
+       { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
+       { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
+       { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
+       { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
+       { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
+       { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
+       { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
+       { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
+       { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
+       { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
 };
 
 static void system_add_link_modes(struct blob_buf *b, __u32 mask)
@@ -1719,7 +1735,7 @@ system_if_dump_info(struct device *dev, struct blob_buf *b)
 
        memset(&ecmd, 0, sizeof(ecmd));
        memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
        ifr.ifr_data = (caddr_t) &ecmd;
        ecmd.cmd = ETHTOOL_GSET;
 
@@ -1728,6 +1744,10 @@ system_if_dump_info(struct device *dev, struct blob_buf *b)
                system_add_link_modes(b, ecmd.advertising);
                blobmsg_close_array(b, c);
 
+               c = blobmsg_open_array(b, "link-partner-advertising");
+               system_add_link_modes(b, ecmd.lp_advertising);
+               blobmsg_close_array(b, c);
+
                c = blobmsg_open_array(b, "link-supported");
                system_add_link_modes(b, ecmd.supported);
                blobmsg_close_array(b, c);
@@ -1736,6 +1756,8 @@ system_if_dump_info(struct device *dev, struct blob_buf *b)
                snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
                        ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
                blobmsg_add_string_buffer(b);
+
+               blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
        }
 
        return 0;
@@ -2255,7 +2277,7 @@ static int tunnel_ioctl(const char *name, int cmd, void *p)
        struct ifreq ifr;
 
        memset(&ifr, 0, sizeof(ifr));
-       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
        ifr.ifr_ifru.ifru_data = p;
        return ioctl(sock_ioctl, cmd, &ifr);
 }
@@ -2300,7 +2322,6 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int link,
 
        nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
        nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
-       nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
 
        struct in6_addr in6buf;
        if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
@@ -2319,26 +2340,41 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int link,
                nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
        }
 
-#ifdef IFLA_IPTUN_FMR_MAX
        if ((cur = tb[TUNNEL_ATTR_DATA])) {
-               struct blob_attr *dcur;
-               unsigned drem, fmrcnt = 0;
-               struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
+               struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
 
-               if (!fmrs) {
-                       ret = -ENOMEM;
-                       goto failure;
-               }
+               blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
+                       blobmsg_data(cur), blobmsg_len(cur));
 
-               blobmsg_for_each_attr(dcur, cur, drem) {
-                       if (blobmsg_type(dcur) != BLOBMSG_TYPE_ARRAY ||
-                                       strcmp(blobmsg_name(dcur), "fmrs") ||
-                                       blobmsg_check_array(dcur, BLOBMSG_TYPE_UNSPEC) <= 0)
-                               continue;
+               if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) {
+                       char *str = blobmsg_get_string(cur);
+
+                       if (strcmp(str, "ignore")) {
+                               char *e;
+                               unsigned encap_limit = strtoul(str, &e, 0);
 
+                               if (e == str || *e || encap_limit > 255) {
+                                       ret = -EINVAL;
+                                       goto failure;
+                               }
+
+                               nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
+                       } else
+                               nla_put_u32(nlm, IFLA_IPTUN_FLAGS, IP6_TNL_F_IGN_ENCAP_LIMIT);
+               }
+
+#ifdef IFLA_IPTUN_FMR_MAX
+               if ((cur = tb_data[IPIP6_DATA_FMRS])) {
                        struct blob_attr *rcur;
-                       unsigned rrem;
-                       blobmsg_for_each_attr(rcur, dcur, rrem) {
+                       unsigned rrem, fmrcnt = 0;
+                       struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
+
+                       if (!fmrs) {
+                               ret = -ENOMEM;
+                               goto failure;
+                       }
+
+                       blobmsg_for_each_attr(rcur, cur, rrem) {
                                struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur;
                                struct in6_addr ip6prefix;
                                struct in_addr ip4prefix;
@@ -2390,10 +2426,11 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int link,
 
                                nla_nest_end(nlm, rule);
                        }
+
+                       nla_nest_end(nlm, fmrs);
                }
-               nla_nest_end(nlm, fmrs);
-       }
 #endif
+       }
 
        nla_nest_end(nlm, infodata);
        nla_nest_end(nlm, linkinfo);
@@ -2966,7 +3003,7 @@ static int system_add_proto_tunnel(const char *name, const uint8_t proto, const
        if (p.iph.ttl && p.iph.frag_off == 0)
                return -EINVAL;
 
-       strncpy(p.name, name, sizeof(p.name));
+       strncpy(p.name, name, sizeof(p.name) - 1);
 
        switch (p.iph.protocol) {
        case IPPROTO_IPIP: