static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
{
- snprintf(dev_buf, sizeof(dev_buf), path, val);
+ snprintf(dev_buf, sizeof(dev_buf), path, device);
system_set_sysctl(dev_buf, val);
}
if (dev->type != &simple_device_type)
return;
+ if (add && system_if_force_external(dev->ifname))
+ return;
+
device_set_present(dev, add);
}
static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
{
struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
if (dev)
ifr.ifr_ifindex = dev->ifindex;
else
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));
ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags |= add;
static bool check_route(struct nlmsghdr *hdr, int ifindex)
{
+ struct rtmsg *r = NLMSG_DATA(hdr);
struct nlattr *tb[__RTA_MAX];
+ if (r->rtm_protocol == RTPROT_KERNEL &&
+ r->rtm_family == AF_INET6)
+ return false;
+
nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
if (!tb[RTA_OIF])
return false;
}
}
-static void
+void
system_if_apply_settings(struct device *dev, struct device_settings *s)
{
struct ifreq ifr;
if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
s->flags &= ~DEV_OPT_TXQUEUELEN;
}
- if (s->flags & DEV_OPT_MACADDR) {
+ if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
.rtm_family = (alen == 4) ? AF_INET : AF_INET6,
.rtm_dst_len = route->mask,
.rtm_table = RT_TABLE_MAIN,
- .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_BOOT,
+ .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
.rtm_scope = scope,
.rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
};
struct blob_attr *cur;
struct ip_tunnel_parm p;
const char *base, *str;
- int cmd = SIOCADDTUNNEL;
+ bool is_sit;
system_del_ip_tunnel(name);
blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
blob_data(attr), blob_len(attr));
- cur = tb[TUNNEL_ATTR_TYPE];
- if (!cur)
+ if (!(cur = tb[TUNNEL_ATTR_TYPE]))
return -EINVAL;
-
str = blobmsg_data(cur);
- if (!strcmp(str, "sit")) {
+ is_sit = !strcmp(str, "sit");
+
+ if (is_sit) {
p.iph.protocol = IPPROTO_IPV6;
base = "sit0";
} else
}
strncpy(p.name, name, sizeof(p.name));
- return tunnel_ioctl(base, cmd, &p);
+ if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
+ return -1;
+
+#ifdef SIOCADD6RD
+ cur = tb[TUNNEL_ATTR_6RD_PREFIX];
+ if (cur && is_sit) {
+ unsigned int mask;
+ struct ip_tunnel_6rd p6;
+
+ memset(&p6, 0, sizeof(p6));
+
+ if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
+ &p6.prefix, &mask) || mask > 128)
+ return -EINVAL;
+ p6.prefixlen = mask;
+
+ if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
+ if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
+ &p6.relay_prefix, &mask) || mask > 32)
+ return -EINVAL;
+ p6.relay_prefixlen = mask;
+ }
+
+ if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
+ system_del_ip_tunnel(name);
+ return -1;
+ }
+ }
+#endif
+
+ return 0;
}