Merge "vpn: Export vpn_ipconfig_foreach as linker symbol" into tizen
[platform/upstream/connman.git] / src / inet.c
index b128e57..e0ef7db 100644 (file)
@@ -189,6 +189,78 @@ done:
        return err;
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+char *connman_inet_ifaddr(const char *name)
+{
+       struct ifreq ifr;
+       struct ether_addr eth;
+       char *str;
+       int sk, err;
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0)
+               return NULL;
+
+       strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
+
+       err = ioctl(sk, SIOCGIFHWADDR, &ifr);
+       close(sk);
+
+       if (err < 0)
+               return NULL;
+
+       str = g_malloc(18);
+       if (!str)
+               return NULL;
+
+       memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
+       snprintf(str, 13, "%02x%02x%02x%02x%02x%02x",
+                                               eth.ether_addr_octet[0],
+                                               eth.ether_addr_octet[1],
+                                               eth.ether_addr_octet[2],
+                                               eth.ether_addr_octet[3],
+                                               eth.ether_addr_octet[4],
+                                               eth.ether_addr_octet[5]);
+
+       return str;
+}
+
+char *connman_inet_ifname2addr(const char *name)
+{
+       struct ifreq ifr;
+       struct ether_addr eth;
+       char *str;
+       int sk, err;
+
+       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+       if (sk < 0)
+               return NULL;
+
+       strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
+
+       err = ioctl(sk, SIOCGIFHWADDR, &ifr);
+       close(sk);
+
+       if (err < 0)
+               return NULL;
+
+       str = g_malloc(18);
+       if (!str)
+               return NULL;
+
+       memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
+       snprintf(str, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                               eth.ether_addr_octet[0],
+                                               eth.ether_addr_octet[1],
+                                               eth.ether_addr_octet[2],
+                                               eth.ether_addr_octet[3],
+                                               eth.ether_addr_octet[4],
+                                               eth.ether_addr_octet[5]);
+
+       return str;
+}
+#endif
+
 bool __connman_inet_is_any_addr(const char *address, int family)
 {
        bool ret = false;
@@ -363,6 +435,46 @@ done:
        return err;
 }
 
+#if defined TIZEN_EXT
+void connman_inet_update_device_ident(struct connman_device *device)
+{
+       int index;
+       enum connman_device_type type;
+       char *ident = NULL, *addr = NULL;
+
+       index = connman_device_get_index(device);
+       type = connman_device_get_type(device);
+
+       switch (type) {
+       case CONNMAN_DEVICE_TYPE_UNKNOWN:
+               return;
+       case CONNMAN_DEVICE_TYPE_ETHERNET:
+       case CONNMAN_DEVICE_TYPE_GADGET:
+       case CONNMAN_DEVICE_TYPE_WIFI:
+               addr = index2addr(index);
+               ident = index2ident(index, NULL);
+               break;
+       case CONNMAN_DEVICE_TYPE_CELLULAR:
+               ident = index2ident(index, NULL);
+               break;
+       case CONNMAN_DEVICE_TYPE_BLUETOOTH:
+       case CONNMAN_DEVICE_TYPE_GPS:
+       case CONNMAN_DEVICE_TYPE_VENDOR:
+               break;
+       }
+
+       if (ident != NULL) {
+               connman_device_set_ident(device, ident);
+               g_free(ident);
+       }
+
+       if (addr != NULL) {
+               connman_device_set_string(device, "Address", addr);
+               g_free(addr);
+       }
+}
+#endif
+
 bool connman_inet_is_ifup(int index)
 {
        int sk;
@@ -1116,6 +1228,67 @@ bool connman_inet_compare_subnet(int index, const char *host)
        return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
 }
 
+static bool mem_mask_equal(const void *a, const void *b,
+                                       const void *mask, size_t n)
+{
+       const unsigned char *addr1 = a;
+       const unsigned char *addr2 = b;
+       const unsigned char *bitmask = mask;
+       size_t i;
+
+       for (i = 0; i < n; i++) {
+               if ((addr1[i] ^ addr2[i]) & bitmask[i])
+                       return false;
+       }
+
+       return true;
+}
+
+bool connman_inet_compare_ipv6_subnet(int index, const char *host)
+{
+       struct ifaddrs *ifaddr, *ifa;
+       bool rv = false;
+       char name[IF_NAMESIZE];
+       struct in6_addr haddr;
+
+       if (inet_pton(AF_INET6, host, &haddr) <= 0)
+               return false;
+
+       if (!if_indextoname(index, name))
+               return false;
+
+       DBG("index %d interface %s", index, name);
+
+       if (getifaddrs(&ifaddr) < 0) {
+               DBG("Cannot get addresses err %d/%s", errno, strerror(errno));
+               return false;
+       }
+
+       for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
+               struct sockaddr_in6 *iaddr;
+               struct sockaddr_in6 *imask;
+
+               if (!ifa->ifa_addr)
+                       continue;
+
+               if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) != 0 ||
+                                       ifa->ifa_addr->sa_family != AF_INET6)
+                       continue;
+
+               iaddr = (struct sockaddr_in6 *)ifa->ifa_addr;
+               imask = (struct sockaddr_in6 *)ifa->ifa_netmask;
+
+               rv = mem_mask_equal(&iaddr->sin6_addr, &haddr,
+                                       &imask->sin6_addr,
+                                       sizeof(haddr));
+               goto out;
+       }
+
+out:
+       freeifaddrs(ifaddr);
+       return rv;
+}
+
 int connman_inet_remove_from_bridge(int index, const char *bridge)
 {
        struct ifreq ifr;
@@ -1366,6 +1539,36 @@ static int icmpv6_recv(int fd, struct xs_cb_data *data)
                return -errno;
        }
 
+#if defined TIZEN_EXT
+       /* Set Received Source Address from router as IPv6 Gateway Address */
+       char src_addr[INET6_ADDRSTRLEN];
+       if(inet_ntop(AF_INET6, &(saddr.sin6_addr), src_addr, INET6_ADDRSTRLEN)
+                       == NULL)
+               return -errno;
+
+       DBG("Received Source Address %s from router", src_addr);
+
+       /* icmpv6_recv() function can be called in two scenarios :
+        * 1. When __connman_inet_ipv6_send_rs() is called from check_dhcpv6()
+        * 2. When __connman_inet_ipv6_send_rs() is called from
+        * __connman_6to4_probe()
+        * In the second case it is not  required to set DHCPv6 Gateway  Address
+        * as DHCPv6 was not started and  network structure was not passed as
+        * user_data. If it is tried  to add Source Address as  Gateway Address
+        * then it will lead to  crash because of  user_data being ip_address
+        * instead of network structure. So Adding Gateway Address in case 1st
+        * case only.
+        */
+       char *address = data->user_data;
+       int err = 0;
+       unsigned char buffer[sizeof(struct in6_addr)] = {0, };
+       /* Checking if user_data is an ip_address */
+       err = inet_pton(AF_INET, address, buffer);
+       /* Setting Received Source Address from
+        * router as Gateway Address */
+       if(err <= 0)
+               __connman_network_set_auto_ipv6_gateway(src_addr, data->user_data);
+#endif
        hdr = (struct nd_router_advert *)buf;
        DBG("code %d len %zd hdr %zd", hdr->nd_ra_code, len,
                                sizeof(struct nd_router_advert));
@@ -1465,6 +1668,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest,
        char cbuf[CMSG_SPACE(sizeof(*pinfo))];
        struct iovec iov[2];
        int fd, datalen, ret, iovlen = 1;
+#if defined TIZEN_EXT
+       char ebuf[256];
+#endif
 
        DBG("");
 
@@ -1543,6 +1749,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest,
        msgh.msg_controllen = cmsg->cmsg_len;
 
        ret = sendmsg(fd, &msgh, 0);
+#if defined TIZEN_EXT
+       DBG("sendmsg errno: %d/%s", errno, strerror_r(errno, ebuf, sizeof(ebuf)));
+#endif
 
        close(fd);
        return ret;
@@ -2563,11 +2772,21 @@ int __connman_inet_get_route(const char *dest_address,
        rth->req.u.r.rt.rtm_scope = 0;
        rth->req.u.r.rt.rtm_type = 0;
        rth->req.u.r.rt.rtm_src_len = 0;
-       rth->req.u.r.rt.rtm_dst_len = rp->ai_addrlen << 3;
        rth->req.u.r.rt.rtm_tos = 0;
 
-       __connman_inet_rtnl_addattr_l(&rth->req.n, sizeof(rth->req), RTA_DST,
-                               &rp->ai_addr, rp->ai_addrlen);
+       if (rp->ai_family == AF_INET) {
+               struct sockaddr_in *sin = (struct sockaddr_in *)rp->ai_addr;
+
+               rth->req.u.r.rt.rtm_dst_len = 32;
+               __connman_inet_rtnl_addattr_l(&rth->req.n, sizeof(rth->req),
+                       RTA_DST, &sin->sin_addr, sizeof(sin->sin_addr));
+       } else if (rp->ai_family == AF_INET6) {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rp->ai_addr;
+
+               rth->req.u.r.rt.rtm_dst_len = 128;
+               __connman_inet_rtnl_addattr_l(&rth->req.n, sizeof(rth->req),
+                       RTA_DST, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
+       }
 
        freeaddrinfo(rp);
 
@@ -3165,7 +3384,7 @@ static int get_nfs_server_ip(const char *cmdline_file, const char *pnp_file,
        if (cmdline[len - 1] == '\n')
                cmdline[--len] = '\0';
 
-       /* split in arguments (seperated by space) */
+       /* split in arguments (separated by space) */
        args = g_strsplit(cmdline, " ", 0);
        if (!args) {
                connman_error("%s: Cannot split cmdline \"%s\"\n", __func__,
@@ -3368,7 +3587,7 @@ char **__connman_inet_get_pnp_nameservers(const char *pnp_file)
        }
 
        /*
-        * Perform two passes to retreive a char ** array of
+        * Perform two passes to retrieve a char ** array of
         * nameservers that are not 0.0.0.0
         *
         * The first pass counts them, the second fills in the