X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=0e6ce5ac686570dc15de99b6f6b46c43225d6d4c;hp=4a8c03df4bb5de55dcae9d2412ebeac04457ff7e;hb=87648299f8944a3268210e0315f6b5244d42fa4f;hpb=73cb255e78e88637a620108bd34ac917ac6e7c41 diff --git a/system-linux.c b/system-linux.c index 4a8c03d..0e6ce5a 100644 --- a/system-linux.c +++ b/system-linux.c @@ -5,12 +5,19 @@ #include #include +#include +#include + +#include +#include + #include #include +#include #include #include +#include #include -#include #include #include @@ -942,3 +949,87 @@ time_t system_get_rtime(void) return 0; } + +#ifndef IP_DF +#define IP_DF 0x4000 +#endif + +static void tunnel_parm_init(struct ip_tunnel_parm *p) +{ + memset(p, 0, sizeof(*p)); + p->iph.version = 4; + p->iph.ihl = 5; + p->iph.frag_off = htons(IP_DF); +} + +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)); + ifr.ifr_ifru.ifru_data = p; + return ioctl(sock_ioctl, cmd, &ifr); +} + +int system_del_ip_tunnel(const char *name) +{ + struct ip_tunnel_parm p; + + tunnel_parm_init(&p); + return tunnel_ioctl(name, SIOCDELTUNNEL, &p); +} + +static int parse_ipaddr(struct blob_attr *attr, __be32 *addr) +{ + if (!attr) + return 1; + + return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr); +} + + +int system_add_ip_tunnel(const char *name, struct blob_attr *attr) +{ + struct blob_attr *tb[__TUNNEL_ATTR_MAX]; + struct blob_attr *cur; + struct ip_tunnel_parm p; + const char *base, *str; + int cmd = SIOCADDTUNNEL; + + system_del_ip_tunnel(name); + + tunnel_parm_init(&p); + + blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb, + blob_data(attr), blob_len(attr)); + + cur = tb[TUNNEL_ATTR_TYPE]; + if (!cur) + return -EINVAL; + + str = blobmsg_data(cur); + if (!strcmp(str, "sit")) { + p.iph.protocol = IPPROTO_IPV6; + base = "sit0"; + } else + return -EINVAL; + + if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr)) + return -EINVAL; + + if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr)) + return -EINVAL; + + if ((cur = tb[TUNNEL_ATTR_TTL])) { + unsigned int val = blobmsg_get_u32(cur); + + if (val > 255) + return -EINVAL; + + p.iph.ttl = val; + } + + strncpy(p.name, name, sizeof(p.name)); + return tunnel_ioctl(base, cmd, &p); +}