Add toolchain and mbtk source

Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/mbtk_lib/src/mbtk_ifc.c b/mbtk/mbtk_lib/src/mbtk_ifc.c
new file mode 100755
index 0000000..51267f5
--- /dev/null
+++ b/mbtk/mbtk_lib/src/mbtk_ifc.c
@@ -0,0 +1,577 @@
+/*
+* MBTK Network Interface control.
+*
+* Author : lb
+* Date   : 2021/8/20 11:44:05
+*
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+//#include <net/if.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/if_ether.h>
+#include <linux/sockios.h>
+//#include <cutils/properties.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <linux/route.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+#include "mbtk_ifc.h"
+
+#define IFNAMSIZ    16
+
+static int ifc_ctl_sock = -1;
+static pthread_mutex_t ifc_sock_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void ifc_init_ifr(const char *name, struct ifreq *ifr)
+{
+    memset(ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr->ifr_name, name, IFNAMSIZ);
+    ifr->ifr_name[IFNAMSIZ - 1] = 0;
+}
+
+static int ifc_set_flags(int sock, const char *name, unsigned set, unsigned clr)
+{
+    struct ifreq ifr;
+    ifc_init_ifr(name, &ifr);
+
+    if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)
+        return -1;
+    ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
+    return ioctl(sock, SIOCSIFFLAGS, &ifr);
+}
+
+static void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr)
+{
+    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+    sin->sin_family = AF_INET;
+    sin->sin_port = 0;
+    sin->sin_addr.s_addr = addr;
+}
+
+#if 1
+static const char *ipaddr_to_string(in_addr_t addr)
+{
+    struct in_addr in_addr;
+
+    in_addr.s_addr = addr;
+    return inet_ntoa(in_addr);
+}
+#endif
+
+static in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
+{
+    in_addr_t mask = 0;
+
+    // C99 (6.5.7): shifts of 32 bits have undefined results
+    if (prefix_length <= 0 || prefix_length > 32)
+    {
+        return 0;
+    }
+
+    mask = ~mask << (32 - prefix_length);
+    mask = htonl(mask);
+
+    return mask;
+}
+
+#if 1
+static int ifc_set_prefixLength(const char *name, int prefixLength)
+{
+    struct ifreq ifr;
+    // TODO - support ipv6
+//    if (prefixLength > 32 || prefixLength < 0) return -1;
+
+    in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength);
+    ifc_init_ifr(name, &ifr);
+    init_sockaddr_in(&ifr.ifr_addr, mask);
+
+    return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
+}
+#endif
+
+int ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length,
+                          struct in_addr gw)
+{
+    struct rtentry rt;
+    int result;
+    in_addr_t netmask;
+
+    memset(&rt, 0, sizeof(rt));
+
+    rt.rt_dst.sa_family = AF_INET;
+    rt.rt_dev = (void*) ifname;
+
+    netmask = prefixLengthToIpv4Netmask(prefix_length);
+    init_sockaddr_in(&rt.rt_genmask, netmask);
+    init_sockaddr_in(&rt.rt_dst, dst.s_addr);
+    rt.rt_flags = RTF_UP;
+
+    if (prefix_length == 32)
+    {
+        rt.rt_flags |= RTF_HOST;
+    }
+
+    if (gw.s_addr != 0)
+    {
+        rt.rt_flags |= RTF_GATEWAY;
+        init_sockaddr_in(&rt.rt_gateway, gw.s_addr);
+    }
+
+    result = ioctl(ifc_ctl_sock, action, &rt);
+    if (result < 0)
+    {
+        if (errno == EEXIST)
+        {
+            result = 0;
+        }
+        else
+        {
+            result = -errno;
+        }
+    }
+    return result;
+}
+
+static int ifc_create_default_route1(const char *name, in_addr_t gw)
+{
+    struct in_addr in_dst, in_gw;
+
+    in_dst.s_addr = 0;
+    in_gw.s_addr = gw;
+
+    int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
+    LOGD("ifc_create_default_route(%s, %d) = %d", name, gw, ret);
+    return ret;
+}
+
+/* deprecated - v4 only */
+static int ifc_create_default_route2(const char *name, const char *gw)
+{
+    struct in_addr in_dst, in_gw;
+
+    in_dst.s_addr = 0;
+    if(gw == NULL)
+    {
+        in_gw.s_addr = 0;
+    }
+    else
+    {
+        if(inet_aton(gw,(struct in_addr *)&(in_gw.s_addr)) < 0)
+        {
+            LOGE("inet_aton error.");
+            return -1;
+        }
+    }
+
+    int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw);
+    LOGD("ifc_create_default_route(%s) = %d", name, ret);
+    return ret;
+}
+
+int mbtk_ifc_open(void)
+{
+    pthread_mutex_lock(&ifc_sock_mutex);
+    if (ifc_ctl_sock == -1)
+    {
+        ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+        if (ifc_ctl_sock < 0)
+        {
+            LOGE("socket() failed: %s\n", strerror(errno));
+        }
+    }
+
+    return ifc_ctl_sock < 0 ? -1 : 0;
+}
+
+int mbtk_ifc_close(void)
+{
+    if (ifc_ctl_sock != -1)
+    {
+        (void)close(ifc_ctl_sock);
+        ifc_ctl_sock = -1;
+    }
+    pthread_mutex_unlock(&ifc_sock_mutex);
+
+    return 0;
+}
+
+int mbtk_ifc_set_addr(const char *name, in_addr_t addr, in_addr_t netmask)
+{
+    struct ifreq ifr, irf_mask;
+    int ret;
+
+    ifc_init_ifr(name, &ifr);
+    init_sockaddr_in(&ifr.ifr_addr, addr);
+
+    ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
+    if(ret)
+    {
+        LOGD("set_addr(%s, %x) = %d fail.", name, addr, ret);
+    }
+
+    if(netmask)
+    {
+        ifc_init_ifr(name, &irf_mask);
+        init_sockaddr_in(&irf_mask.ifr_netmask, netmask);
+        ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &irf_mask);
+        if(ret)
+        {
+            LOGD("set_netmask(%s, %x) = %d fail.", name, netmask, ret);
+        }
+    }
+
+    return ret;
+}
+
+int mbtk_ifc_ip_config(const char *ifname, const char *ipv4, const char *mask, const char *gateway)
+{
+    UNUSED(gateway);
+    struct ifreq ifr;
+
+//    struct rtentry  rt;
+    // Set IPv4
+    struct sockaddr_in *sin;
+    memset(&ifr,0,sizeof(ifr));
+    strcpy(ifr.ifr_name,ifname);
+    sin = (struct sockaddr_in*)&ifr.ifr_addr;
+    sin->sin_family = AF_INET;
+    if(ipv4) {
+        if(inet_aton(ipv4,&(sin->sin_addr)) < 0)
+        {
+            LOGE("inet_aton error.");
+            return -2;
+        }
+    } else {
+        memset(&(sin->sin_addr), 0, sizeof(struct in_addr));
+    }
+
+    if(ioctl(ifc_ctl_sock,SIOCSIFADDR,&ifr) < 0)
+    {
+        LOGE("ioctl SIOCSIFADDR error.");
+        return -3;
+    }
+
+#if 1
+#if 1
+    //netmask
+    if(mask) {
+        if(inet_aton(mask,&(sin->sin_addr)) < 0)
+        {
+            LOGE("inet_pton error.");
+            return -4;
+        }
+
+        if(ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr) < 0)
+        {
+            LOGE("ioctl error.");
+            return -5;
+        }
+    }
+#else
+
+    //struct ifreq ifr;
+    //strcpy(ifr.ifr_name, interface_name);
+    struct sockaddr_in netmask_addr;
+    bzero(&netmask_addr, sizeof(struct sockaddr_in));
+    netmask_addr.sin_family = PF_INET;
+    inet_aton(mask, &netmask_addr.sin_addr);
+    memcpy(&ifr.ifr_ifru.ifru_netmask, &netmask_addr,
+           sizeof(struct sockaddr_in));
+    if (ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr) < 0)
+    {
+        LOGE("ioctl() fail.");
+        return -1;
+    }
+#endif
+#endif
+
+#if 0
+    //gateway
+    memset(&rt, 0, sizeof(struct rtentry));
+    memset(sin, 0, sizeof(struct sockaddr_in));
+    sin->sin_family = AF_INET;
+    sin->sin_port = 0;
+    if(inet_aton(gateway, &sin->sin_addr)<0)
+    {
+        LOGE( "inet_aton error." );
+    }
+    memcpy ( &rt.rt_gateway, sin, sizeof(struct sockaddr_in));
+    ((struct sockaddr_in *)&rt.rt_dst)->sin_family=AF_INET;
+    ((struct sockaddr_in *)&rt.rt_genmask)->sin_family=AF_INET;
+    rt.rt_flags = RTF_GATEWAY;
+    if (ioctl(ifc_ctl_sock, SIOCADDRT, &rt)<0)
+    {
+        LOGE("ioctl(SIOCADDRT) error in set_default_route\n");
+        return -1;
+    }
+#endif
+    return 0;
+}
+
+int mbtk_ifc_set_netmask(const char *ifname, const char *netmask)
+{
+    int s;
+    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+    {
+        LOGE("Socket");
+        return -1;
+    }
+    struct ifreq ifr;
+    strcpy(ifr.ifr_name, ifname);
+    struct sockaddr_in netmask_addr;
+    bzero(&netmask_addr, sizeof(struct sockaddr_in));
+    netmask_addr.sin_family = PF_INET;
+    inet_aton(netmask, &netmask_addr.sin_addr);
+    memcpy(&ifr.ifr_ifru.ifru_netmask, &netmask_addr,
+           sizeof(struct sockaddr_in));
+    if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0)
+    {
+        LOGE("ioctl");
+        close(s);
+        return -1;
+    }
+    close(s);
+    return 0;
+}
+
+
+int mbtk_ifc_get_addr(const char *name, void *addr)
+{
+    int ret;
+    struct ifreq ifr;
+    ifc_init_ifr(name, &ifr);
+
+    ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr);
+    LOGD("ifc_get_addr(%s, %x) = %d", name, ifr.ifr_addr, ret);
+    if(ret < 0) return -1;
+
+    memcpy(addr, &ifr.ifr_addr, sizeof(struct sockaddr));
+    return 0;
+}
+
+
+int mbtk_ifc_up(const char *name)
+{
+    int ret = ifc_set_flags(ifc_ctl_sock, name, IFF_UP, 0);
+//    LOGI("mbtk_ifc_up(%s) = %d", name, ret);
+    return ret;
+}
+
+int mbtk_ifc_down(const char *name)
+{
+    int ret = ifc_set_flags(ifc_ctl_sock, name, 0, IFF_UP);
+//    LOGI("mbtk_ifc_down(%s) = %d", name, ret);
+    return ret;
+}
+
+int mbtk_ifc_get_hwaddr(const char *name, void *ptr)
+{
+    int r;
+    struct ifreq ifr;
+    ifc_init_ifr(name, &ifr);
+
+    r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
+    if(r < 0) return -1;
+
+    memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+    return 0;
+}
+
+int mbtk_ifc_get_ifindex(const char *name, int *if_indexp)
+{
+    int r;
+    struct ifreq ifr;
+    ifc_init_ifr(name, &ifr);
+
+    r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr);
+    if(r < 0) return -1;
+
+    *if_indexp = ifr.ifr_ifindex;
+    return 0;
+}
+
+int mbtk_ifc_configure1(const char *ifname,
+                        in_addr_t address,
+                        uint32_t prefixLength,
+                        in_addr_t gateway,
+                        in_addr_t netmask)
+{
+    if(mbtk_ifc_open())
+    {
+        LOGE("mbtk_ifc_open() fail.", strerror(errno));
+        return -1;
+    }
+
+    if (mbtk_ifc_up(ifname))
+    {
+        LOGE("failed to turn on interface %s: %s", ifname, strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+    if (mbtk_ifc_set_addr(ifname, address, netmask))
+    {
+        LOGE("failed to set ipaddr %s: %s", ipaddr_to_string(address), strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+    if (ifc_set_prefixLength(ifname, prefixLength))
+    {
+        LOGE("failed to set prefixLength %d: %s", prefixLength, strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+    if (ifc_create_default_route1(ifname, gateway))
+    {
+        LOGE("failed to set default route %s: %s", ipaddr_to_string(gateway), strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+
+    mbtk_ifc_close();
+    return 0;
+}
+
+int mbtk_ifc_configure2(const char *ifname,
+                        const char *ipv4,
+                        uint32_t prefixLength,
+                        const char *gateway,
+                        const char *netmask)
+{
+    if(mbtk_ifc_open())
+    {
+        LOGE("mbtk_ifc_open() fail.", strerror(errno));
+        return -1;
+    }
+
+    if(ipv4 == NULL) {
+        if (mbtk_ifc_down(ifname))
+        {
+            LOGE("failed to turn off interface %s: %s", ifname, strerror(errno));
+            mbtk_ifc_close();
+            return -1;
+        }
+    } else {
+        if (mbtk_ifc_up(ifname))
+        {
+            LOGE("failed to turn on interface %s: %s", ifname, strerror(errno));
+            mbtk_ifc_close();
+            return -1;
+        }
+    }
+
+    if (mbtk_ifc_ip_config(ifname, ipv4, netmask, gateway))
+    {
+        LOGE("failed to set ipaddr: %s", strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+
+//    mbtk_ifc_set_netmask(ifname, netmask);
+
+#if 0
+    if (ifc_set_prefixLength(ifname, prefixLength))
+    {
+        LOGE("failed to set prefixLength %d: %s", prefixLength, strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+#endif
+
+#if 0
+    if (ifc_create_default_route2(ifname, gateway))
+    {
+        LOGE("failed to set default route: %s", strerror(errno));
+        mbtk_ifc_close();
+        return -1;
+    }
+#endif
+
+    mbtk_ifc_close();
+
+    return 0;
+}
+
+struct in6_ifreq {
+    struct in6_addr addr;
+    uint32_t        prefixlen;
+    unsigned int    ifindex;
+};
+
+int mbtk_ipv6_config(const char *ifname, const char *ipv6, uint32_t prefixLength)
+{
+    struct ifreq ifr;
+    struct in6_ifreq ifr6;
+    int sockfd;
+    int err = 0;
+
+    // Create IPv6 socket to perform the ioctl operations on
+    sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+    if(sockfd < 0) {
+        LOGE("socket() fail.[%d]", errno);
+        return -1;
+    }
+
+    if(ipv6) {
+        if(ifc_set_flags(sockfd, ifname, IFF_UP, 0) < 0) {
+            LOGE("if up fail[%d].", errno);
+            err = -1;
+            goto exit;
+        }
+
+        // Copy the interface name to the ifreq struct
+        strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+        // Get the ifrindex of the interface
+        if(ioctl(sockfd, SIOGIFINDEX, &ifr) < 0)
+        {
+            LOGE("ioctl SIOGIFINDEX error.");
+            err = -1;
+            goto exit;
+        }
+
+        // Prepare the in6_ifreq struct and set the address to the interface
+        if(inet_pton(AF_INET6, ipv6, &ifr6.addr) < 0) {
+            LOGE("inet_pton() fail[%d].", errno);
+            err = -1;
+            goto exit;
+        }
+    } else {
+        if(ifc_set_flags(sockfd, ifname, 0, IFF_UP) < 0) {
+            LOGE("if down fail[%d].", errno);
+            err = -1;
+            goto exit;
+        }
+
+        // Copy the interface name to the ifreq struct
+        strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+        // Get the ifrindex of the interface
+        if(ioctl(sockfd, SIOGIFINDEX, &ifr) < 0)
+        {
+            LOGE("ioctl SIOGIFINDEX error.");
+            err = -1;
+            goto exit;
+        }
+
+        // Set IPv6 to 0.
+        memset(&(ifr6.addr), 0, sizeof(struct in6_addr));
+    }
+    ifr6.ifindex = ifr.ifr_ifindex;
+    ifr6.prefixlen = prefixLength;
+    if(ioctl(sockfd, SIOCSIFADDR, &ifr6) < 0) {
+        LOGE("ioctl SIOCSIFADDR error.");
+        err = -1;
+        goto exit;
+    }
+
+    LOGD("Set IPv6 : %s success.", ipv6);
+exit:
+    close(socket);
+    return err;
+}