* 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
system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val);
}
-static void system_bridge_set_isolate_mode(struct device *dev, const char *val)
+static void system_bridge_set_isolated(struct device *dev, const char *val)
{
- system_set_dev_sysctl("/sys/class/net/%s/brport/isolate_mode", dev->ifname, val);
+ system_set_dev_sysctl("/sys/class/net/%s/brport/isolated", dev->ifname, val);
}
static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
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);
}
if (dev->settings.flags & DEV_OPT_ISOLATE &&
dev->settings.isolate)
- system_bridge_set_isolate_mode(dev, "1");
+ system_bridge_set_isolated(dev, "1");
return ret;
}
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
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
+ if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) < 0)
+ return -1;
+
ifr.ifr_flags |= add;
ifr.ifr_flags &= ~rem;
return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
.u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
};
- ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
+ if (ioctl(sock_ioctl, SIOCSIFVLAN, &ifr) < 0)
+ return -1;
if (id < 0) {
ifr.cmd = DEL_VLAN_CMD;
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;
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)
};
int ret = 1;
+ if (!cb)
+ return ret;
+
msg = nlmsg_alloc_simple(RTM_GETLINK, 0);
if (!msg)
goto out;
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" },
+#ifdef ADVERTISED_56000baseKR4_Full
+ { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
+ { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
+ { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
+ { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
+#endif
};
static void system_add_link_modes(struct blob_buf *b, __u32 mask)
{
struct ethtool_cmd ecmd;
struct ifreq ifr;
- char buf[64], *s;
+ char *s;
void *c;
- int dir_fd;
-
- snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
- dir_fd = open(buf, O_DIRECTORY);
memset(&ecmd, 0, sizeof(ecmd));
memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, dev->ifname);
+ strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
ifr.ifr_data = (caddr_t) &ecmd;
ecmd.cmd = ETHTOOL_GSET;
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);
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);
}
- close(dir_fd);
return 0;
}
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);
}
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])) {
nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
}
-#ifdef IFLA_IPTUN_FMR_MAX
if ((cur = tb[TUNNEL_ATTR_DATA])) {
- struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
- struct blob_attr *dcur;
- unsigned drem, fmrcnt = 0;
-
- 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;
+ struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX];
+
+ blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data,
+ blobmsg_data(cur), blobmsg_len(cur));
+ 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;
offset = blobmsg_get_u32(tb_cur);
struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
+ if (!rule) {
+ ret = -ENOMEM;
+ goto failure;
+ }
nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
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);
unsigned tos = 1;
if (strcmp(str, "inherit")) {
- if (!system_tos_aton(str, &tos))
- return -EINVAL;
+ if (!system_tos_aton(str, &tos)) {
+ ret = -EINVAL;
+ goto failure;
+ }
}
nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
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: