update ARP dummy plugin 57/205757/1
authorsaerome.kim <saerome.kim@samsung.com>
Thu, 9 May 2019 04:47:32 +0000 (13:47 +0900)
committersaerome.kim <saerome.kim@samsung.com>
Thu, 9 May 2019 04:58:49 +0000 (13:58 +0900)
- This plugin simply serves to send ARP Request to devices
  that know IP and MAC addresses to unicast.

- If there is an ARP response, the PRESENCE detection is notified.
  If there is no ARP response, the ABSENCE detection is notified.

- Known Issue) In the case of Google Wi-Fi,
  ARP Response is sent to the MAC address of the mobile device
  that has been disconnected for a certain period of time
  even if the mobile device is disconnected.

Change-Id: I8e1ba2520d889c28766a53188717f93ba320538f
Signed-off-by: saerome.kim <saerome.kim@samsung.com>
CMakeLists.txt
include/log.h
include/wifi-networkmanager.h [new file with mode: 0644]
include/wifi-plugin-util.h [new file with mode: 0644]
include/wifi-plugin.h [new file with mode: 0644]
include/wifi-scan.h [new file with mode: 0644]
packaging/ua-plugin-wifi-dummy.spec
src/wifi-networkmanager.c [new file with mode: 0644]
src/wifi-plugin.c
src/wifi-scan.c [new file with mode: 0644]
src/wifi-util.c [new file with mode: 0644]

index 2008510..0ca2946 100644 (file)
@@ -16,6 +16,8 @@ pkg_check_modules(PKGS_WIFI REQUIRED
        gio-unix-2.0
        glib-2.0
        ua-plugins
+       capi-network-connection
+       capi-network-wifi
        )
 
 FOREACH(flag ${PKGS_WIFI_CFLAGS})
@@ -35,6 +37,9 @@ SET(CMAKE_C_FLAGS_RELEASE "-O2")
 MESSAGE (${CMAKE_C_FLAGS})
 SET(SRCS_WIFI
        src/wifi-plugin.c
+       src/wifi-networkmanager.c
+       src/wifi-scan.c
+       src/wifi-util.c
        )
 
 # library build
index 00e4e6d..041db98 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * User Awareness Manager API
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License")
  * you may not use this file except in compliance with the License.
diff --git a/include/wifi-networkmanager.h b/include/wifi-networkmanager.h
new file mode 100644 (file)
index 0000000..eae88bf
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WIFI_NETWORKMANAGER_PLUGIN_H__
+#define __WIFI_NETWORKMANAGER_PLUGIN_H__
+
+#include <log.h>
+#include <wifi-scan.h>
+#include <net_connection.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool __nm_init();
+
+bool __nm_get_interface_name(char** iface_name);
+
+connection_type_e __nm_get_connection_type();
+
+void __nm_get_connection_profile_handler(connection_profile_h *profile);
+
+void __nm_destroy_profile_iterator();
+
+bool __nm_get_gateway_address(char* gateway);
+
+void __nm_get_linux_arp_table(char* ip_addr, char* mac_addr);
+
+void __nm_get_ips_mac(char* ip_addr, char* mac_addr);
+
+void __nm_update_network_type(bool isConnect);
+
+bool __nm_get_mac_address(char** dest_mac_addr);
+
+char* __nm_get_ip_address(void);
+
+void __nm_get_connected_bssid(char** connect_bssid);
+
+bool __nm_is_network_connected();
+
+void __nm_deinit();
+#ifdef __cplusplus
+}
+#endif
+#endif /* __WIFI_NETWORKMANAGER_PLUGIN_H__*/
diff --git a/include/wifi-plugin-util.h b/include/wifi-plugin-util.h
new file mode 100644 (file)
index 0000000..ba623dc
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WIFI_PLUGIN_UTIL_H__
+#define __WIFI_PLUGIN_UTIL_H__
+
+#include <wifi-plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ret_if(expr) \
+       do { \
+               if (expr) { \
+                       UA_WIFI_ERR("(%s) return", #expr); \
+                       return; \
+               } \
+       } while (0)
+
+#define retv_if(expr, val) \
+       do { \
+               if (expr) { \
+                       UA_WIFI_ERR("(%s) return", #expr); \
+                       return (val); \
+               } \
+       } while (0)
+
+uas_wifi_info_t *_wifi_plugin_util_get_wifi_info_from_dev_info(uas_device_info_t *dev_info);
+
+uas_device_info_t *_wifi_plugin_util_get_dev_info_from_wifi_info(uas_wifi_info_t *wifi_info);
+
+void _wifi_plugin_util_uas_device_info_free(uas_device_info_t *device);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __WIFI_PLUGIN_UTIL_H__*/
diff --git a/include/wifi-plugin.h b/include/wifi-plugin.h
new file mode 100644 (file)
index 0000000..5629911
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WIFI_PLUGIN_H__
+#define __WIFI_PLUGIN_H__
+
+#include <log.h>
+#include <stdbool.h>
+#include <ua-plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UAS_DEVICE_ID_MAX_LEN 50 /** Max device ID length */
+#define MAC_ADDRESS_STRING_SIZE 18 /**< Max MAC address string length */
+#define IP_ADDRESS_STRING_SIZE 16 /* Max IPv4 address string length */
+
+typedef enum {
+       WIFI_PRESENCE_STATUS_ABSENCE, /**< ABSENCE detected */
+       WIFI_PRESENCE_STATUS_PRESENCE, /**< PRESENCE detected */
+} wifi_presence_status_e;
+
+typedef struct {
+       int user_id; /**< User ID which is saved in DB */
+       int os; /**< Operating system type eg) Tizen, Android and iOS */
+       char mobile_id[UAS_DEVICE_ID_MAX_LEN]; /**< MObile ID which is saved in DB */
+       char mac_addr[MAC_ADDRESS_STRING_SIZE]; /**< MAC address which is saved in DB */
+       char ip_addr[IP_ADDRESS_STRING_SIZE]; /**< IP address which is saved in DB */
+       int absence_count; /**< How many detect ABSENCE of the target dev. */
+       int mobile_flag; /**< The order of the target dev. */
+       gboolean new_device; /**< Is newly added device ?*/
+       unsigned int supported_techs; /**< Operating system type of the target dev. */
+       wifi_presence_status_e presence; /**< Detected type (see. wifi_presence_status_e) */
+} uas_wifi_info_t;
+
+void __check_device_found(char* sbuf, char* ip_sbuf);
+
+void __check_mobilelist();
+
+void __check_mobile_list_finish(bool is_check);
+#ifdef __cplusplus
+}
+#endif
+#endif /* __WIFI_PLUGIN_H__*/
diff --git a/include/wifi-scan.h b/include/wifi-scan.h
new file mode 100644 (file)
index 0000000..6c748f5
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WIFI_SCAN_PLUGIN_H__
+#define __WIFI_SCAN_PLUGIN_H__
+
+#include <log.h>
+#include <ua-plugin.h>
+#include <net_connection.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/ethernet.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define MAC_ADD_LENGTH 6 /**< MAC address bytes size */
+#define IP_ADD_LENGTH 4 /**< IPv4 size */
+#define MAX_SIZE_ERROR_BUFFER 256 /**< Error buffer size */
+#define MAX_SIZE_BUFFER 128 /**< Max. buffer size */
+#define SEND_MAC_TIMER 10 /**< Timer value until sending ARP request */
+#define ARP_MAC_TIMER 5 /**< Timer value until receiving ARP response */
+#define BROADCAST_MAC_ADDR     "ff:ff:ff:ff:ff:ff" /**< Broadcast adress */
+#define MAX_MAC_ARP_COUNT 1 /**< Max. count of ARP request */
+#define ARP_PACKET_SIZE 60 /**< MAX ARP payload size */
+
+union uchar_to_uint {
+       unsigned int uint; /**< IP addess for interger */
+       unsigned char uchar[IP_ADD_LENGTH]; /**< IP address for human */
+};
+
+struct arp_message {
+       /* Ethernet header */
+       unsigned char h_dest[MAC_ADD_LENGTH]; /**< destination ether addr */
+       unsigned char h_source[MAC_ADD_LENGTH]; /**< source ether addr */
+       uint16_t h_proto; /**< packet type ID field */
+
+       /* ARP packet */
+       uint16_t hw_type;/**< hardware type(ARPHRD_ETHER) */
+       uint16_t p_type;/**< protocol type(ETH_P_IP) */
+       uint8_t p_len; /**< protocol address length */
+       uint8_t hw_len;/**< hardware address length */
+       uint16_t operation;/* ARP opcode */
+       uint8_t s_hwaddr[MAC_ADD_LENGTH]; /**< sender hardware address */
+       uint8_t s_IPaddr[IP_ADD_LENGTH]; /**< sender IP address */
+       uint8_t t_hwaddr[MAC_ADD_LENGTH]; /**< target hardware address */
+       uint8_t t_IPaddr[IP_ADD_LENGTH]; /**< target IP address */
+       uint8_t pad[18]; /**< pad for min. Ethernet payload (60 bytes) */
+};
+
+struct arping_data {
+       struct arp_message arp; /**< ARP structure */
+       struct sockaddr_ll addr; /**< Socket address structure */
+       GIOChannel *arp_sock_io; /**< GIO channel */
+       int arp_id; /**< Raw socket descriptor ID */
+       int arp_data_id; /**< GIO ID to recieve ARP response */
+       int is_arp_init; /**< Create ARP packet done */
+       char arp_source_ip[MAX_SIZE_BUFFER]; /**< Source IP address */
+       char arp_source_mac[MAX_SIZE_BUFFER]; /**< Source MAC address */
+       char arp_target_mac[MAX_SIZE_BUFFER]; /**< Target MAC address */
+       guint arp_send_packet_timer; /**< Timer ID until sending ARP request */
+       unsigned int arp_send_ip_addr; /**< Sender's IP address (int type) */
+       unsigned int arp_mac_count; /**< How many received ARP response from the target dev. */
+       gboolean mobile_detection; /**< Whether receiving ARP resp. from the target device */
+};
+
+int __initialize_arp_data(void);
+
+int __start_wifi_detection(const char* ip, const char* mac);
+
+int __start_arp(const char* ip, const char* mac);
+
+int __init_ip_mac_count(void);
+
+int __start_wifi_add_device(const char* ip, const char* mac);
+
+bool __is_device_exists(char *device_id);
+
+void __deinit_arp_data(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* __WIFI_SCAN_PLUGIN_H__*/
index 41a6a98..403855e 100644 (file)
@@ -14,7 +14,10 @@ BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(gio-unix-2.0)
+BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(ua-plugins)
+BuildRequires:  pkgconfig(capi-network-connection)
+BuildRequires:  pkgconfig(capi-network-wifi)
 
 %if 0%{?gtests:1}
 BuildRequires:  pkgconfig(gmock)
@@ -38,8 +41,8 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 export LDFLAGS+=" -lgcov"
 %endif
 
-%define NETWORK_FW_DATADIR /opt/usr/data/network
-%define DBDIR /opt/usr/data
+%define NETWORK_FW_DATADIR %{TZ_SYS_GLOBALUSER_DATA}/network
+%define DBDIR %{TZ_SYS_GLOBALUSER_DATA}/
 
 cmake . -DCMAKE_INSTALL_PREFIX=/usr \
                -DCMAKE_LIB_DIR=%{_libdir} \
diff --git a/src/wifi-networkmanager.c b/src/wifi-networkmanager.c
new file mode 100644 (file)
index 0000000..03fc674
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <wifi-networkmanager.h>
+
+typedef enum {
+       NM_NETWORK_TYPE_UNKNOWN, /**< Netwrok type unknown */
+       NM_NETWORK_TYPE_DISCONNECTED, /**< Netwrok type disconnected */
+       NM_NETWORK_TYPE_ETHERNET, /**< Netwrok type ethernet */
+       NM_NETWORK_TYPE_WIFI /**< Netwrok type Wi-Fi */
+} nm_network_type;
+
+typedef struct {
+       char ip_addr[MAX_SIZE_BUFFER]; /**< IP address of the network interface */
+       char hw_type[MAX_SIZE_BUFFER]; /**< HW type for the network interface */
+       char flags[MAX_SIZE_BUFFER]; /**< Network interface flag */
+       char hw_addr[MAX_SIZE_BUFFER]; /**< MAC address of the network interface */
+       char mask[MAX_SIZE_BUFFER]; /**< Submnet mask of the network interface */
+       char device[MAX_SIZE_BUFFER]; /**< Name of the network interface */
+} nm_linux_arp_entry;
+
+#define NETCONN_LOCAL_MAC "00:00:00:00:00:00" /**< So called, link local MAC address */
+#define PROC_ARP_PATH "/proc/net/arp" /**< ARP table in linux */
+
+connection_h h_conn = NULL;
+connection_profile_iterator_h profile_iter = NULL;
+
+nm_network_type network_type = NM_NETWORK_TYPE_UNKNOWN;
+static char connected_bssid[MAX_SIZE_BUFFER];
+
+bool __nm_init()
+{
+       FUNC_ENTER;
+       int ret;
+
+       if (h_conn != NULL) {
+               UA_WIFI_ERR("h_conn was already created!!!");
+               FUNC_EXIT;
+               return false;
+       }
+
+       ret = connection_create(&h_conn);
+
+       if (ret != CONNECTION_ERROR_NONE) {
+               UA_WIFI_ERR("connection_create is fail");
+               h_conn = NULL;
+               FUNC_EXIT;
+               return false;
+       }
+
+       __nm_update_network_type(true);
+
+       FUNC_EXIT;
+       return true;
+}
+
+void __nm_deinit()
+{
+       FUNC_ENTER;
+       if (h_conn == NULL) {
+               UA_WIFI_INFO("h_conn is NULL");
+               return;
+       }
+
+       if (connection_destroy(h_conn) != CONNECTION_ERROR_NONE) {
+               UA_WIFI_INFO("Failed to destroy connection");
+               return;
+       }
+
+       UA_WIFI_INFO("Connection destroyed successfully");
+       h_conn = NULL;
+       FUNC_EXIT;
+       return;
+
+}
+
+bool __nm_get_interface_name(char** iface_name)
+{
+       FUNC_ENTER;
+       bool ret = true;
+
+       if (network_type == NM_NETWORK_TYPE_WIFI) {
+               UA_WIFI_INFO("currently network status WIFI");
+               *iface_name = strdup("wlan0");
+       } else if (network_type == NM_NETWORK_TYPE_ETHERNET) {
+               UA_WIFI_INFO("currently network status Wired");
+               *iface_name = strdup("eth0");
+       } else {
+               UA_WIFI_INFO("No Network or Network status not available");
+               FUNC_EXIT;
+               return false;
+       }
+
+       FUNC_EXIT;
+       return ret;
+}
+
+connection_type_e __nm_get_connection_type()
+{
+       FUNC_ENTER;
+       connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+
+       if (connection_get_type(h_conn, &connection_type) != CONNECTION_ERROR_NONE)
+               UA_WIFI_ERR("connection_get_type error");
+
+       UA_WIFI_INFO("connection get type %d", connection_type);
+       FUNC_EXIT;
+       return connection_type;
+}
+
+void __nm_get_connection_profile_handler(connection_profile_h *profile)
+{
+       FUNC_ENTER;
+
+       /* TODO: Need to check if hconnection can be use instead of connection
+        * So, There should not be need of connection_create if m_hconnection is not NULL.
+        */
+       connection_h connection = NULL;
+       connection_profile_h profile_handlelocal;
+       connection_profile_type_e profile_type;
+
+       int ret = -1;
+
+       ret = connection_create(&connection);
+
+       UA_WIFI_INFO("ret: %d, m_Connection: %p", ret, connection);
+
+       if (!connection) {
+               UA_WIFI_INFO("connection is NULL");
+               return;
+       }
+
+       ret = connection_get_profile_iterator(connection, CONNECTION_ITERATOR_TYPE_REGISTERED,
+               &profile_iter);
+       if (CONNECTION_ERROR_NONE != ret)
+               UA_WIFI_INFO("Failed to get connection profile iterator");
+
+
+       while (connection_profile_iterator_has_next(profile_iter)) {
+
+               ret = connection_profile_iterator_next(profile_iter, &profile_handlelocal);
+               if (CONNECTION_ERROR_NONE != ret) {
+                       UA_WIFI_INFO("failed to get connection profile iterator");
+                       break;
+               }
+
+               if (connection_profile_get_type(profile_handlelocal, &profile_type)) {
+                       UA_WIFI_INFO("failed to get profile get type");
+                       break;
+               }
+
+               UA_WIFI_INFO("Profile Type: [%d]", profile_type);
+
+               if ((profile_type == CONNECTION_PROFILE_TYPE_ETHERNET) ||
+                       (profile_type == CONNECTION_PROFILE_TYPE_WIFI)) {
+                       *profile = profile_handlelocal;
+                       UA_WIFI_INFO("Successfully obtained connection profile handle");
+                       break;
+               }
+       }
+       FUNC_EXIT;
+}
+
+void __nm_destroy_profile_iterator()
+{
+       FUNC_ENTER;
+
+       if (profile_iter) {
+               if (connection_destroy_profile_iterator(profile_iter) == CONNECTION_ERROR_NONE) {
+                       profile_iter = NULL;
+                       UA_WIFI_DBG("Destroyed profile iterator");
+               } else
+                       UA_WIFI_DBG("Failed to Destroy profile iterator");
+       }
+
+       FUNC_EXIT;
+}
+
+bool __nm_get_gateway_address(char* gateway)
+{
+       FUNC_ENTER;
+       int ret = -1;
+       char* gateway_local = NULL;
+       connection_profile_h profile;
+
+       __nm_get_connection_profile_handler(&profile);
+
+       if (profile) {
+               ret = connection_profile_get_gateway_address(profile,
+                       CONNECTION_ADDRESS_FAMILY_IPV4, &gateway_local);
+
+               if (ret == CONNECTION_ERROR_NONE) {
+                       g_strlcpy(gateway, gateway_local, 16);
+                       free(gateway_local);
+               } else {
+                       UA_WIFI_ERR("get gateway failed");
+                       strncpy(gateway, "0.0.0.0", 7);
+               }
+       } else {
+               UA_WIFI_ERR("Failed to get profile handle !!!");
+               strncpy(gateway, "0.0.0.0", 7);
+       }
+
+       UA_WIFI_INFO("gateway is [%s]", gateway);
+       __nm_destroy_profile_iterator();
+       return true;
+}
+
+void __nm_get_linux_arp_table(char* ip_addr, char* mac_addr)
+{
+       FUNC_ENTER;
+
+       FILE *fp = NULL;
+       char data[1024];
+       int matches;
+
+       fp = fopen(PROC_ARP_PATH, "r");
+
+       if (!fp) {
+               UA_WIFI_ERR("fail to read %s", PROC_ARP_PATH);
+               FUNC_EXIT;
+               return;
+       }
+
+       if (!fgets(data, sizeof(data), fp)) {
+               UA_WIFI_ERR("failed to read arp table");
+               fclose(fp);
+               FUNC_EXIT;
+               return;
+       }
+
+       while (fgets(data, sizeof(data) - 1, fp)) {
+               nm_linux_arp_entry entry;
+               matches = sscanf(data, "%128s%128s%128s%128s%128s%128s",
+                               entry.ip_addr, entry.hw_type, entry.flags, entry.hw_addr,
+                               entry.mask, entry.device);
+
+               if ((matches == 6) && !strcmp(ip_addr, entry.ip_addr)) {
+                       UA_WIFI_INFO("IP[%s] found in ARP table", ip_addr);
+                       memcpy(mac_addr, entry.hw_addr, strlen(entry.hw_addr)+1);
+                       fclose(fp);
+                       FUNC_EXIT;
+                       return;
+               }
+       }
+
+       UA_WIFI_ERR("IP[%s] not found in ARP table", ip_addr);
+       fclose(fp);
+       FUNC_EXIT;
+       return;
+}
+
+void __nm_get_ips_mac(char *ip_addr, char *mac_addr)
+{
+       FUNC_ENTER;
+
+       UA_WIFI_INFO("IP address of GetIPsMAC: %s", ip_addr);
+       memcpy(mac_addr, NETCONN_LOCAL_MAC, strlen(NETCONN_LOCAL_MAC)+1);
+
+       /*! local IP has a wildcard MAC address, for now at least */
+       if (!strcmp(ip_addr, "127.0.0.1"))
+               UA_WIFI_INFO("local IP[%s]", ip_addr);
+       else
+               __nm_get_linux_arp_table(ip_addr, mac_addr);
+
+       FUNC_EXIT;
+       return;
+}
+
+void __nm_update_network_type(bool isConnect)
+{
+       FUNC_ENTER;
+
+       if (!isConnect)
+               network_type = NM_NETWORK_TYPE_DISCONNECTED;
+       else {
+               connection_type_e eType = __nm_get_connection_type();
+
+               switch (eType) {
+               case CONNECTION_TYPE_ETHERNET:
+                       network_type = NM_NETWORK_TYPE_ETHERNET;
+                       break;
+               case CONNECTION_TYPE_WIFI:
+                       network_type = NM_NETWORK_TYPE_WIFI;
+                       break;
+               default:
+                       network_type = NM_NETWORK_TYPE_UNKNOWN;
+                       break;
+               }
+       }
+
+       UA_WIFI_INFO("isConnect : %d, network_type : %d", isConnect, network_type);
+
+       if (isConnect) {
+               UA_WIFI_INFO("update network status %s", isConnect ? "CONNECT" : "DISCONNECT");
+               char gateway[16];
+               char macaddr[128];
+
+               memset(gateway, 0, 16);
+
+               if (__nm_get_gateway_address(gateway) == true)
+                       UA_WIFI_INFO("currently gateway address : %s", gateway);
+
+
+               __nm_get_ips_mac(gateway, macaddr);
+
+               UA_WIFI_INFO("IPv4 mac address of the resource: %s", macaddr);
+
+               strncpy(connected_bssid, macaddr, strlen(macaddr));
+               connected_bssid[strlen(macaddr) + 1] = '\0';
+       } else {
+               UA_WIFI_INFO("update network status %s", isConnect ? "CONNECT" : "DISCONNECT");
+               memset(connected_bssid, 0, sizeof(connected_bssid));
+       }
+
+       FUNC_EXIT;
+}
+
+bool __nm_get_mac_address(char** mac_addr)
+{
+       FUNC_ENTER;
+       connection_type_e conn_type;
+
+       if (!h_conn) {
+               UA_WIFI_ERR("Connection is not created");
+               return false;
+       }
+
+       if (network_type == NM_NETWORK_TYPE_WIFI) {
+               UA_WIFI_INFO("Currently Network Status WIFI");
+               conn_type = CONNECTION_TYPE_WIFI;
+       } else if (network_type == NM_NETWORK_TYPE_ETHERNET) {
+               UA_WIFI_INFO("Currently Network Status Wired");
+               conn_type = CONNECTION_TYPE_ETHERNET;
+       } else {
+               UA_WIFI_INFO("No Network or Network status not available");
+               FUNC_EXIT;
+               return false;
+       }
+
+       if (connection_get_mac_address(h_conn, conn_type, mac_addr) != CONNECTION_ERROR_NONE) {
+               UA_WIFI_ERR("Fail to get MAC address");
+               FUNC_EXIT;
+               return false;
+       }
+
+       FUNC_EXIT;
+       return true;
+}
+
+char* __nm_get_ip_address(void)
+{
+       char *ip_addr = NULL;
+       int ret = connection_get_ip_address(h_conn, CONNECTION_ADDRESS_FAMILY_IPV4, &ip_addr);
+       if ( CONNECTION_ERROR_NONE != ret) {
+               UA_WIFI_ERR("Error in getting ip address");
+
+               if (NULL != ip_addr) {
+                       free(ip_addr);
+                       ip_addr = NULL;
+               }
+
+               return NULL;
+       }
+
+       //UA_WIFI_DBG("Connected AP's  IP : %s", ip_addr);
+       return ip_addr;
+}
+
+void __nm_get_connected_bssid(char** connect_bssid)
+{
+       if (connect_bssid == NULL) {
+               *connect_bssid = NULL;
+               return;
+       }
+
+       *connect_bssid = g_strdup(connected_bssid);
+       return;
+}
+
index 5f9362b..6e6ea4b 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * UAFW plugins interface
- *
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <glib.h>
 
 #include <log.h>
-#include <ua-plugin.h>
+#include <wifi-plugin.h>
+#include <wifi-plugin-util.h>
+#include <wifi-scan.h>
+#include <wifi-networkmanager.h>
 
 #define NAME   "wifi-plugin"
 #define AUTHOR "Samsung"
 #define VERSION        "0.1"
 
+#define DETECTION_CYCLE_DEFAULT 900 /* 15 minutes -> 15 * 60 = 900 seconds */
+#define DETECTION_PERIOD_DEFAULT 60 /* 1 minute -> 1 * 60 = 60 seconds */
+#define ABSENCE_THRESHOLD_DEFAULT 1
+
+static int wifi_detection_cycle = DETECTION_CYCLE_DEFAULT;
+static int wifi_detection_period = DETECTION_PERIOD_DEFAULT;
+static int wifi_detection_retries = ABSENCE_THRESHOLD_DEFAULT;
+static guint detection_cycle_timer = 0;
+static bool initial_bursts = true;
+
+static gboolean lpm_enabled = FALSE; /**< Low power mode */
+
 static const uas_callbacks_t *uas_cbs = NULL; /**< Interfaces for ua_manager */
+static uas_state_e curr_state = UAS_STATE_NOT_READY; /**< Plugin state */
+static GSList *dev_list = NULL; /**< Device lists */
+static unsigned int detect_count;
+static int wifi_detection_type = 0;
 
 static int init(const uas_callbacks_t *callbacks)
 {
        FUNC_ENTER;
 
-       uas_cbs = callbacks;
+       retv_if(NULL == callbacks, UAS_STATUS_FAIL);
+
+       if (uas_cbs != NULL) {
+               UA_WIFI_DBG("Wi-Fi plugin is already initialized");
+               FUNC_EXIT;
+               return UAS_STATUS_ALREADY_DONE;
+       } else {
+               uas_cbs = callbacks;
+       }
+
+       detect_count = 0;
+
+       if (__nm_init() != true) {
+               UA_WIFI_ERR("Fail to initialize network manager");
+               FUNC_EXIT;
+               return UAS_STATUS_FAIL;
+       }
+
+       if (__initialize_arp_data() != UAS_STATUS_SUCCESS) {
+               UA_WIFI_ERR("Fail to initialize arp data");
+               FUNC_EXIT;
+               return UAS_STATUS_FAIL;
+       }
 
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
@@ -44,7 +83,13 @@ static int init(const uas_callbacks_t *callbacks)
 static int deinit(void)
 {
        FUNC_ENTER;
+       if (dev_list) {
+               g_slist_free_full(dev_list, g_free);
+               dev_list = NULL;
+       }
 
+       __nm_deinit();
+       __deinit_arp_data();
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -53,6 +98,8 @@ static int get_state(int *state)
 {
        FUNC_ENTER;
 
+       *state = curr_state;
+
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -61,6 +108,8 @@ static int get_capability(uas_capability_e *capability)
 {
        FUNC_ENTER;
 
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+
        *capability = UAS_SUPPORT_USER;
 
        FUNC_EXIT;
@@ -70,16 +119,263 @@ static int get_capability(uas_capability_e *capability)
 static int set_registered_devices(int num_devices, uas_device_info_t *devices)
 {
        FUNC_ENTER;
+       int i, dev_count = 0;
+
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+
+       if (dev_list) {
+               g_slist_free_full(dev_list, g_free);
+               dev_list = NULL;
+       }
+
+       for (i = 0; i < num_devices; i++) {
+               uas_wifi_info_t* wifi_info;
+
+               wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(&(devices[i]));
+
+               if (!wifi_info)
+                       continue;
+               else
+                       dev_count++;
+
+               wifi_info->mobile_flag = dev_count;
+               dev_list = g_slist_prepend(dev_list, wifi_info);
+       }
+
+       detect_count = dev_count;
+
+       if (uas_cbs->state_changed_cb) {
+               switch (curr_state) {
+               case UAS_STATE_NOT_READY:
+                       if (dev_list) {
+                               uas_cbs->state_changed_cb(UAS_STATE_READY);
+                               curr_state = UAS_STATE_READY;
+                       }
+                       break;
+               case UAS_STATE_READY:
+                       if (!dev_list) {
+                               uas_cbs->state_changed_cb(UAS_STATE_NOT_READY);
+                               curr_state = UAS_STATE_NOT_READY;
+                       }
+                       break;
+               }
+       }
 
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
 
+void __check_mobilelist()
+{
+       int ret;
+       GSList *l;
+
+       if (!dev_list) {
+               UA_WIFI_ERR("No devices to scan");
+               return ;
+       }
+
+       for (l = dev_list; NULL != l; l = g_slist_next(l)) {
+               uas_wifi_info_t *wifi_info = l->data;
+
+               if (wifi_info->mobile_flag != detect_count)
+                       continue;
+
+               if (WIFI_PRESENCE_STATUS_ABSENCE == wifi_info->presence) {
+                       UA_WIFI_INFO("Detect this mobild id %s start presence request MAC %s",
+                               wifi_info->mobile_id, wifi_info->mac_addr);
+                       if (initial_bursts == true) {
+                               if (UAS_STATUS_SUCCESS !=__init_ip_mac_count()) {
+                                       UA_WIFI_ERR("ARP Init fail");
+                                       return;
+                               } else
+                                       initial_bursts = false;
+                       }
+
+                       ret = __start_wifi_detection(wifi_info->ip_addr, wifi_info->mac_addr);
+                       if (UAS_STATUS_SUCCESS != ret) {
+                               UA_WIFI_ERR("ARP Init fail");
+                               wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
+                               detect_count--;
+                               continue;
+                       }
+                       break;
+               } else {
+                       UA_WIFI_INFO("Already detected, So skip");
+                       detect_count--;
+               }
+       }
+
+       __check_mobile_list_finish(false);
+}
+
+void __reset_wifi_info()
+{
+       GSList *l;
+       detect_count = g_slist_length(dev_list);
+
+       for (l = dev_list; NULL != l; l = g_slist_next(l)) {
+               uas_wifi_info_t *wifi_info = l->data;
+               wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
+       }
+}
+
+static gboolean __start_wifi_scan(gpointer user_data)
+{
+       FUNC_ENTER;
+
+       initial_bursts = true;
+       __reset_wifi_info();
+       __check_mobilelist();
+
+       /* Send detection started */
+       if (uas_cbs && uas_cbs->detection_state_cb)
+               uas_cbs->detection_state_cb(1);
+
+       FUNC_EXIT;
+       return TRUE;
+}
+
+void __check_device_found(char* sbuf, char* ip_sbuf)
+{
+       FUNC_ENTER;
+       GSList *l;
+
+       for (l = dev_list; NULL != l; l = g_slist_next(l)) {
+               uas_wifi_info_t *wifi_info = l->data;
+               uas_device_info_t *dev_info = NULL;
+
+               if (wifi_info->mobile_flag == detect_count) {
+                       wifi_info->presence = WIFI_PRESENCE_STATUS_PRESENCE;
+
+                       g_strlcpy(wifi_info->mac_addr, sbuf, MAC_ADDRESS_STRING_SIZE);
+                       g_strlcpy(wifi_info->ip_addr, ip_sbuf, IP_ADDRESS_STRING_SIZE);
+
+                       wifi_info->absence_count = 0;
+
+                       if (!(UAS_PRESENCE & wifi_detection_type))
+                               break;
+
+                       if (!uas_cbs && !uas_cbs->device_detected_cb)
+                               break;
+
+                       /* Send PRESENCE callback */
+                       dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
+                       if (!dev_info) {
+                               UA_WIFI_ERR("Unable to get dev_info");
+                               break;
+                       }
+
+                       uas_cbs->device_detected_cb(UAS_PRESENCE, dev_info);
+                       UA_WIFI_INFO("Called uas_cbs->device_detected_cb(UAS_PRESENCE)");
+                       _wifi_plugin_util_uas_device_info_free(dev_info);
+                       break;
+               }
+       }
+       FUNC_EXIT;
+}
+
+void __check_mobile_list_finish(bool is_check)
+{
+       FUNC_ENTER;
+       uas_device_info_t *dev_info = NULL;
+
+       if (is_check == true)
+               detect_count--;
+
+       UA_WIFI_INFO("find next mobile flag %d", detect_count);
+
+       if (!detect_count) {
+
+               GSList *l;
+
+               UA_WIFI_INFO("Already All mobile detected");
+
+               initial_bursts = true;
+
+
+               UA_WIFI_INFO("Detection mode unicast finish");
+
+               for (l = dev_list; NULL != l; l = g_slist_next(l)) {
+                       uas_wifi_info_t *wifi_info = l->data;
+
+                       if (!wifi_info)
+                               continue;
+
+                       if (wifi_info->presence) {
+                               wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
+                               continue;
+                       }
+
+                       wifi_info->absence_count += 1;
+
+                       UA_WIFI_INFO("absence_count = %d", wifi_info->absence_count);
+
+                       if ((UAS_ABSENCE & wifi_detection_type) &&
+                                       (wifi_detection_retries <= wifi_info->absence_count) &&
+                                       (uas_cbs && uas_cbs->device_detected_cb)) {
+                               dev_info = _wifi_plugin_util_get_dev_info_from_wifi_info(wifi_info);
+                               if (!dev_info) {
+                                       UA_WIFI_ERR("Unable to get dev_info");
+                                       break;
+                               }
+
+                               uas_cbs->device_detected_cb(UAS_ABSENCE, dev_info);
+                               UA_WIFI_INFO("Called uas_cbs->device_detected_cb(UAS_ABSENCE)");
+                               _wifi_plugin_util_uas_device_info_free(dev_info);
+                       }
+
+                       wifi_info->presence = WIFI_PRESENCE_STATUS_ABSENCE;
+               }
+
+               /* Send detection stopped */
+               if (uas_cbs && uas_cbs->detection_state_cb)
+                       uas_cbs->detection_state_cb(0);
+
+       } else {
+               if (is_check == true) {
+                       initial_bursts = true;
+                       __check_mobilelist();
+               }
+       }
+
+       FUNC_EXIT;
+}
+
 static int add_device(uas_device_info_t *device)
 {
        FUNC_ENTER;
 
-       uas_cbs->device_added_cb(UAS_STATUS_SUCCESS, device);
+       uas_wifi_info_t *wifi_info;
+       int mac_len;
+       int ip_len;
+
+       retv_if(NULL == device, UAS_STATUS_FAIL);
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+
+       wifi_info = _wifi_plugin_util_get_wifi_info_from_dev_info(device);
+       retv_if(NULL == wifi_info, UAS_STATUS_FAIL);
+
+       mac_len = strlen(wifi_info->mac_addr);
+       ip_len = strlen(wifi_info->ip_addr);
+       if (!mac_len && !ip_len) {
+               free(wifi_info);
+               FUNC_EXIT;
+               return UAS_STATUS_FAIL;
+       }
+
+       /* Add to list */
+       dev_list = g_slist_prepend(dev_list,
+                       g_memdup(wifi_info, sizeof(uas_wifi_info_t)));
+       UA_WIFI_DBG("Added device to list, num devices = %d", g_slist_length(dev_list));
+
+       if (mac_len && ip_len &&
+                       (strcasecmp(wifi_info->mac_addr, BROADCAST_MAC_ADDR) != 0)) {
+               initial_bursts = true;
+               uas_cbs->device_added_cb(UAS_STATUS_SUCCESS, device);
+       }
+
+       free(wifi_info);
 
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
@@ -88,15 +384,57 @@ static int add_device(uas_device_info_t *device)
 static int remove_device(uas_device_info_t *device)
 {
        FUNC_ENTER;
+       GSList *l;
+
+       retv_if(NULL == device, UAS_STATUS_FAIL);
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+
+       for (l = dev_list; NULL != l; l = g_slist_next(l)) {
+               uas_wifi_info_t *wifi_info = l->data;
+
+               if (!strcasecmp(wifi_info->mobile_id, device->device_id)) {
+                       dev_list = g_slist_remove(dev_list, wifi_info);
+                       free(wifi_info);
+                       return UAS_STATUS_SUCCESS;
+               }
+       }
 
        FUNC_EXIT;
-       return UAS_STATUS_SUCCESS;
+       return UAS_STATUS_FAIL;
 }
 
 static int start_detection(unsigned int detection_type)
 {
        FUNC_ENTER;
 
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+       retv_if((wifi_detection_type & detection_type), UAS_STATUS_ALREADY_DONE);
+
+       /* Check if detection already in progress */
+       if (0 != wifi_detection_type) {
+               wifi_detection_type |= detection_type;
+               goto done;
+       }
+
+       wifi_detection_type |= detection_type;
+       /* Check if lpm enabled */
+       if (lpm_enabled) {
+               FUNC_EXIT;
+               return UAS_STATUS_SUCCESS;
+       }
+
+       /* Schedule detection cycle */
+       if (0 < detection_cycle_timer)
+               g_source_remove(detection_cycle_timer);
+
+       detection_cycle_timer = g_timeout_add_seconds(
+                       wifi_detection_cycle, __start_wifi_scan, NULL);
+
+       /* Start detection */
+       __start_wifi_scan(NULL);
+
+done:
+       UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -105,6 +443,22 @@ static int stop_detection(unsigned int detection_type)
 {
        FUNC_ENTER;
 
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+       retv_if(0 == wifi_detection_type, UAS_STATUS_ALREADY_DONE);
+
+       wifi_detection_type &= ~detection_type;
+       UA_WIFI_INFO("wifi_detection_type = 0x%8.8X", wifi_detection_type);
+
+       if (0 != wifi_detection_type)
+               goto done;
+
+       /* Remove detection cycle timer */
+       if (0 < detection_cycle_timer) {
+               g_source_remove(detection_cycle_timer);
+               detection_cycle_timer = 0;
+       }
+
+done:
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -113,6 +467,11 @@ static int set_low_power_mode(int mode)
 {
        FUNC_ENTER;
 
+       if (0 == mode)
+               lpm_enabled = FALSE;
+       else
+               lpm_enabled = TRUE;
+
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -122,6 +481,14 @@ static int set_detection_params(int detection_cycle,
 {
        FUNC_ENTER;
 
+       retv_if(NULL == uas_cbs, UAS_STATUS_NOT_READY);
+       retv_if(detection_period > detection_cycle, UAS_STATUS_FAIL);
+       retv_if(0 >= detection_retries, UAS_STATUS_FAIL);
+
+       wifi_detection_cycle = detection_cycle;
+       wifi_detection_period = detection_period;
+       wifi_detection_retries = detection_retries;
+
        FUNC_EXIT;
        return UAS_STATUS_SUCCESS;
 }
@@ -130,8 +497,11 @@ static int set_detection_threshold(int presence_threshold, int absence_threshold
 {
        FUNC_ENTER;
 
+       UA_WIFI_INFO("presence_threshold = %d, absence_threshold = %d",
+                       presence_threshold, absence_threshold);
+
        FUNC_EXIT;
-       return UAS_STATUS_SUCCESS;
+       return UAS_STATUS_UNSUPPORTED;
 }
 
 static uas_api_t wifi_api = {
diff --git a/src/wifi-scan.c b/src/wifi-scan.c
new file mode 100644 (file)
index 0000000..94bf18c
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <log.h>
+#include <ua-plugin.h>
+#include <wifi-plugin.h>
+#include <wifi-networkmanager.h>
+#include <wifi-scan.h>
+
+struct arping_data *arp_data;
+
+static int __arp_packet_make(const char* mac)
+{
+       FUNC_ENTER;
+       bool ret = false;
+       struct ether_addr* source_mac = NULL;
+       struct ether_addr* dest_mac = NULL;
+       char* source_mac_address = NULL;
+
+       ret = __nm_get_mac_address(&source_mac_address);
+
+       if (ret == false) {
+               UA_WIFI_ERR("Get Mac Fail");
+               return UAS_STATUS_FAIL;
+       }
+
+       memcpy(arp_data->arp_source_mac, source_mac_address, strlen(source_mac_address));
+       source_mac = ether_aton(source_mac_address);
+
+       if (source_mac == NULL) {
+               UA_WIFI_ERR("Wrong Mac address");
+               free(source_mac_address);
+               return UAS_STATUS_FAIL;
+       }
+
+       UA_WIFI_INFO("currently Network mac Address = %s source_mac = %s",
+               source_mac_address, ether_ntoa(source_mac));
+
+       memset(&arp_data->arp, 0, sizeof(arp_data->arp));
+       memcpy(arp_data->arp.h_source, source_mac, MAC_ADD_LENGTH);
+       memcpy(arp_data->arp.s_hwaddr, source_mac, MAC_ADD_LENGTH);
+
+       dest_mac = ether_aton(mac);
+
+       if (dest_mac == NULL) {
+               UA_WIFI_ERR("Destination Mac address is wrong");
+               return UAS_STATUS_FAIL;
+       }
+
+       UA_WIFI_INFO("Scan mac Address = %s dest_mac =%s", mac, ether_ntoa(dest_mac));
+
+       memcpy(arp_data->arp.h_dest, dest_mac, MAC_ADD_LENGTH);
+       memcpy(arp_data->arp.t_hwaddr, dest_mac, MAC_ADD_LENGTH);
+
+       arp_data->arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
+       arp_data->arp.hw_type = htons(ARPHRD_ETHER); /* hardware type */
+       arp_data->arp.p_type = htons(ETH_P_IP); /* protocol type (ARP message) */
+       arp_data->arp.hw_len = MAC_ADD_LENGTH; /* hardware address length */
+       arp_data->arp.p_len = IP_ADD_LENGTH; /* protocol address length */
+       arp_data->arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
+
+       UA_WIFI_INFO("Init arp packet success");
+       free(source_mac_address);
+       FUNC_EXIT;
+       return UAS_STATUS_SUCCESS;
+}
+
+static unsigned int __convert_uchar_to_uint(unsigned char b[IP_ADD_LENGTH])
+{
+       int idx = 0;
+       union uchar_to_uint u;
+       for (; idx < IP_ADD_LENGTH; ++idx)
+               u.uchar[idx] = b[idx];
+
+       return u.uint;
+}
+
+static gboolean clean_socket()
+{
+       GError* error = NULL;
+
+       if (NULL == arp_data->arp_sock_io || arp_data->arp_id == -1) {
+               UA_WIFI_ERR(" Gateway socket or io channel not initilized yet.");
+               return true;
+       }
+
+       UA_WIFI_INFO("arp Closing socket[%d] , and shutdown io channel[%p]",
+               arp_data->arp_id, arp_data->arp_sock_io);
+
+       /* Closing socket descriptor. */
+       if (-1 < arp_data->arp_id) {
+               if (G_IO_STATUS_NORMAL != g_io_channel_shutdown(
+                       arp_data->arp_sock_io, FALSE, &error)) {
+                       UA_WIFI_ERR("Failure received while shutdown io channel[%d]:[%s]",
+                               error->code, error->message);
+                       g_error_free(error);
+                       return false;
+               }
+
+               g_source_remove(arp_data->arp_data_id);
+               arp_data->arp_data_id = -1;
+               arp_data->arp_id = -1;
+               arp_data->arp_sock_io = NULL;
+       }
+
+       arp_data->is_arp_init = 0;
+       return true;
+}
+
+static void __stop_send_arp_packettimer()
+{
+       UA_WIFI_INFO("Stop send arp pcket timer");
+
+       if (arp_data->arp_send_packet_timer) {
+               g_source_remove(arp_data->arp_send_packet_timer);
+               arp_data->arp_send_ip_addr = 0 ;
+               arp_data->arp_send_packet_timer = 0;
+       }
+}
+
+gboolean __arp_packet_receive(GIOChannel *source, GIOCondition condition,
+       gpointer data)
+{
+       gchar buffer[ARP_PACKET_SIZE];
+       gsize bytes_read = 0;
+       struct arp_message arp_recv;
+       char sbuf[MAC_ADDRESS_STRING_SIZE];
+       char tbuf[MAC_ADDRESS_STRING_SIZE];
+       char ip_sbuff[IP_ADDRESS_STRING_SIZE];
+       char ip_tbuff[IP_ADDRESS_STRING_SIZE];
+       int mac_cmp;
+
+       memset(buffer, '\0', ARP_PACKET_SIZE);
+       memset(sbuf, '\0', MAC_ADDRESS_STRING_SIZE);
+       memset(tbuf, '\0', MAC_ADDRESS_STRING_SIZE);
+       memset(ip_sbuff, '\0', IP_ADDRESS_STRING_SIZE);
+       memset(ip_sbuff, '\0', IP_ADDRESS_STRING_SIZE);
+
+       if (!arp_data->is_arp_init)
+               return false;
+
+       switch (condition) {
+       case G_IO_IN:
+               if (g_io_channel_read_chars(
+                       source, buffer, ARP_PACKET_SIZE, &bytes_read, NULL) == G_IO_STATUS_NORMAL) {
+                       uint32_t target_ip = 0;
+
+                       memset(&arp_recv, 0, sizeof(arp_recv));
+                       memcpy(&arp_recv, buffer, sizeof(buffer));
+
+                       target_ip = inet_addr(arp_data->arp_source_ip);
+
+                       if (arp_recv.operation != htons(ARPOP_REPLY))
+                               break;
+
+                       UA_WIFI_INFO("target mac address = %02x:%02x:%02x:%02x:%02x:%02x",
+                               arp_recv.t_hwaddr[0], arp_recv.t_hwaddr[1], arp_recv.t_hwaddr[2],
+                               arp_recv.t_hwaddr[3], arp_recv.t_hwaddr[4], arp_recv.t_hwaddr[5]);
+                       UA_WIFI_INFO("source mac address = %02x:%02x:%02x:%02x:%02x:%02x",
+                               arp_recv.s_hwaddr[0], arp_recv.s_hwaddr[1], arp_recv.s_hwaddr[2],
+                               arp_recv.s_hwaddr[3], arp_recv.s_hwaddr[4], arp_recv.s_hwaddr[5]);
+
+                       snprintf(tbuf, MAC_ADDRESS_STRING_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
+                               arp_recv.t_hwaddr[0], arp_recv.t_hwaddr[1], arp_recv.t_hwaddr[2],
+                               arp_recv.t_hwaddr[3], arp_recv.t_hwaddr[4], arp_recv.t_hwaddr[5]);
+                       snprintf(sbuf, MAC_ADDRESS_STRING_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
+                               arp_recv.s_hwaddr[0], arp_recv.s_hwaddr[1], arp_recv.s_hwaddr[2],
+                               arp_recv.s_hwaddr[3], arp_recv.s_hwaddr[4], arp_recv.s_hwaddr[5]);
+
+                       if (strcasecmp(tbuf, arp_data->arp_source_mac)) {
+                               UA_WIFI_INFO("Packet not intended to us.");
+                               break;
+                       }
+
+                       if (!strcasecmp(tbuf , "00:00:00:00:00:00"))
+                               UA_WIFI_INFO("Broadcast packet.");
+
+                       snprintf(ip_sbuff, IP_ADDRESS_STRING_SIZE, "%d.%d.%d.%d",
+                               arp_recv.s_IPaddr[0], arp_recv.s_IPaddr[1],
+                               arp_recv.s_IPaddr[2], arp_recv.s_IPaddr[3]);
+                       UA_WIFI_INFO("source ip_sbuff = %s target ip = %d source ip = %d",
+                               ip_sbuff, target_ip, __convert_uchar_to_uint(arp_recv.s_IPaddr));
+
+                       snprintf(ip_tbuff, IP_ADDRESS_STRING_SIZE, "%d.%d.%d.%d",
+                               arp_recv.t_IPaddr[0], arp_recv.t_IPaddr[1],
+                               arp_recv.t_IPaddr[2], arp_recv.t_IPaddr[3]);
+                       UA_WIFI_INFO("target ip_tbuff = %s target ip = %d source ip = %d",
+                               ip_tbuff, target_ip, __convert_uchar_to_uint(arp_recv.s_IPaddr));
+
+                       mac_cmp = strcasecmp(sbuf, arp_data->arp_target_mac);//same target mac ip is valid
+
+                       if (!mac_cmp) {
+                               UA_WIFI_INFO("%d ARP packet - received info and init arp_mac_count",
+                                       arp_data->arp_mac_count);
+                               arp_data->arp_mac_count = MAX_MAC_ARP_COUNT;
+                       } else {
+                               UA_WIFI_INFO("received arp source mac and our made target mac is " \
+                                       "different, wrong arp packet");
+                               break;
+                       }
+
+                       UA_WIFI_INFO("device found");
+
+                       if (arp_data->mobile_detection == true)
+                               __check_device_found(sbuf, ip_sbuff);
+
+                       UA_WIFI_INFO("find device set ARP Count MAX");
+                       clean_socket();
+                       __stop_send_arp_packettimer();
+               }
+               break;
+       case G_IO_HUP:
+               UA_WIFI_INFO("G_IO_HUP event received.");
+               break;
+       case G_IO_ERR:
+               UA_WIFI_INFO("G_IO_ERR event received.");
+               break;
+       case G_IO_NVAL:
+               UA_WIFI_INFO("G_IO_NVAL event received.");
+               break;
+       default:
+               UA_WIFI_INFO("Unknown event received.");
+               break;
+       }
+
+       return true;
+}
+
+gboolean __arp_packet_callback()
+{
+       if (arp_data && arp_data->is_arp_init)
+               clean_socket();
+
+       if (arp_data->arp_mac_count <= 0)
+               return false;
+
+       arp_data->arp_mac_count++;
+       UA_WIFI_INFO("Next Send ARP count %d", arp_data->arp_mac_count);
+
+       if (arp_data->arp_mac_count <= MAX_MAC_ARP_COUNT) {
+               UA_WIFI_INFO("Next Send %d ARP Packet number", arp_data->arp_mac_count);
+               if (arp_data->mobile_detection == true)
+                       __check_mobilelist();
+       } else {
+               UA_WIFI_INFO("Finish ARP because already send count %d init arp_mac_count",
+                       arp_data->arp_mac_count);
+               arp_data->arp_mac_count = 0;
+               if (arp_data->mobile_detection == true)
+                       __check_mobile_list_finish(true);
+       }
+
+       return false;
+}
+
+static int __init_arp(const char* mac)
+{
+       struct ifreq net_ifr;
+       char error_buf[MAX_SIZE_ERROR_BUFFER];
+       char *iface_name = NULL;
+       int val = 1;
+       int if_name_len ;
+       struct ether_addr *dest_mac = NULL;
+
+       dest_mac = ether_aton(mac);
+
+       if (dest_mac == NULL) {
+               UA_WIFI_ERR("Destination Mac address is wrong");
+               return UAS_STATUS_FAIL;
+       }
+
+       UA_WIFI_INFO("Scan mac Address = %s uni_dest_mac =%s", mac, ether_ntoa(dest_mac));
+
+       memset(&(arp_data->addr), 0, sizeof(arp_data->addr));
+       memset(&net_ifr, 0, sizeof(net_ifr));
+       memset(error_buf, 0, MAX_SIZE_ERROR_BUFFER);
+
+       arp_data->arp_id = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
+
+       if (arp_data->arp_id == -1) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               UA_WIFI_ERR("Socket failed. Error: %s", error_buf);
+               return UAS_STATUS_FAIL;
+       }
+
+       if (setsockopt(arp_data->arp_id, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)) == -1) {
+               UA_WIFI_ERR("setsocketopt on socket failed");
+               close(arp_data->arp_id);
+               arp_data->arp_id = -1;
+               return UAS_STATUS_FAIL;
+       }
+
+       /* ifreq structure creation */
+       if (__nm_get_interface_name(&iface_name) == false) {
+               UA_WIFI_ERR("interface is wrong");
+               return UAS_STATUS_FAIL;
+       }
+
+       UA_WIFI_INFO("Network interface %s", iface_name);
+       if_name_len = strlen(iface_name);
+
+       if (if_name_len < sizeof(net_ifr.ifr_name)) {
+               memcpy(net_ifr.ifr_name, iface_name, if_name_len);
+               net_ifr.ifr_name[if_name_len] = 0;
+       } else {
+               UA_WIFI_ERR("Error : Interface name is too long");
+               free(iface_name);
+               return UAS_STATUS_FAIL;
+       }
+
+       free(iface_name);
+
+       if (ioctl(arp_data->arp_id, SIOCGIFINDEX, &net_ifr) == -1) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               UA_WIFI_ERR("ioctl failed. Error: %s", error_buf);
+               return UAS_STATUS_FAIL;
+       }
+
+       /* Construct the destination address */
+       arp_data->addr.sll_family = AF_PACKET;
+       arp_data->addr.sll_ifindex = net_ifr.ifr_ifindex;
+       arp_data->addr.sll_halen = ETHER_ADDR_LEN;
+       arp_data->addr.sll_protocol = htons(ETH_P_ARP);
+       memcpy(arp_data->addr.sll_addr, dest_mac, ETHER_ADDR_LEN);
+
+       arp_data->arp_sock_io = g_io_channel_unix_new(arp_data->arp_id);
+
+       if (arp_data->arp_sock_io == NULL) {
+               UA_WIFI_ERR("Failed to create channel");
+               close(arp_data->arp_id);
+               arp_data->arp_id = -1;
+               return UAS_STATUS_FAIL;
+       }
+
+       if (G_IO_STATUS_NORMAL != g_io_channel_set_encoding(
+               arp_data->arp_sock_io, NULL, NULL)) {
+               UA_WIFI_ERR("Failed to set encoding NULL on io channel");
+               close(arp_data->arp_id);
+               arp_data->arp_id = -1;
+               return UAS_STATUS_FAIL;
+       }
+
+       if (G_IO_STATUS_NORMAL != g_io_channel_set_flags(
+               arp_data->arp_sock_io, G_IO_FLAG_NONBLOCK, NULL)) {
+               UA_WIFI_ERR("Failed to set flags on io channel");
+               close(arp_data->arp_id);
+               arp_data->arp_id = -1;
+               return UAS_STATUS_FAIL;
+       }
+
+       arp_data->arp_data_id = g_io_add_watch(
+               arp_data->arp_sock_io, G_IO_IN, __arp_packet_receive, NULL);
+       g_io_channel_unref(arp_data->arp_sock_io);
+
+       UA_WIFI_INFO("Init arp socket success");
+       return UAS_STATUS_SUCCESS;
+}
+
+gboolean __send_arp_ip_packet_timeout(gpointer user_data)
+{
+       uint32_t source_ip = 0;
+       uint32_t target_ip = 0;
+
+       char arp_target_ip[MAX_SIZE_BUFFER];
+       char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+
+       memset(arp_target_ip, '\0', MAX_SIZE_BUFFER);
+
+       source_ip = inet_addr(__nm_get_ip_address());
+       memcpy(arp_data->arp.s_IPaddr, &source_ip, IP_ADD_LENGTH); // source IP address
+       //snprintf(ip_buff, 16, "%d.%d.%d.%d",
+       //      arp.s_IPaddr[0],arp.s_IPaddr[1],arp.s_IPaddr[2],pArping->arp_send_ip_addr);
+
+       target_ip = inet_addr(arp_data->arp_source_ip);
+       memcpy(arp_data->arp.t_IPaddr, &target_ip, IP_ADD_LENGTH); // target IP address
+       memcpy(arp_target_ip, arp_data->arp_source_ip , strlen(arp_data->arp_source_ip));
+
+       UA_WIFI_INFO("arp_target_ip = %s ", arp_target_ip);
+
+       if (sendto(arp_data->arp_id, &arp_data->arp, sizeof(arp_data->arp), 0,
+               (struct sockaddr*)&arp_data->addr, sizeof(arp_data->addr)) < 0) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               UA_WIFI_ERR("Sending ARP Packet Failed. Error: %s", error_buf);
+       }
+
+       arp_data->arp_send_packet_timer = 0;
+       return G_SOURCE_REMOVE;
+}
+
+gboolean __send_arp_unimul_packet_timeout(gpointer user_data)
+{
+       uint32_t source_ip = 0;
+       uint32_t target_ip = 0;
+       char arp_target_ip[MAX_SIZE_BUFFER];
+       char error_buf[MAX_SIZE_ERROR_BUFFER];
+       char ip_buff[IP_ADDRESS_STRING_SIZE];
+
+       memset(arp_target_ip, '\0', MAX_SIZE_BUFFER);
+       memset(error_buf, '\0', MAX_SIZE_ERROR_BUFFER);
+       memset(ip_buff, '\0', IP_ADDRESS_STRING_SIZE);
+       source_ip = inet_addr(__nm_get_ip_address());
+       memcpy(arp_data->arp.s_IPaddr, &source_ip, IP_ADD_LENGTH); // source IP address
+       snprintf(ip_buff, IP_ADDRESS_STRING_SIZE, "%d.%d.%d.%d",
+               arp_data->arp.s_IPaddr[0], arp_data->arp.s_IPaddr[1],
+               arp_data->arp.s_IPaddr[2], arp_data->arp_send_ip_addr);
+
+       if (arp_target_ip[0])
+               UA_WIFI_INFO("Arp source ip: %s", arp_target_ip);
+
+       target_ip = inet_addr(ip_buff);
+       memcpy(arp_target_ip, ip_buff, strlen(ip_buff));
+       memcpy(arp_data->arp.t_IPaddr, &target_ip, IP_ADD_LENGTH); // target IP address
+
+       if (arp_data->arp_send_ip_addr == 1 || arp_data->arp_send_ip_addr == 255)
+               UA_WIFI_INFO("Arp target ip: %s", arp_target_ip);
+
+       if (sendto(arp_data->arp_id, &arp_data->arp, sizeof(arp_data->arp), 0,
+               (struct sockaddr*)&arp_data->addr, sizeof(arp_data->addr)) < 0) {
+               strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+               UA_WIFI_ERR("Sending ARP Packet Failed. Error: %s", error_buf);
+       }
+
+       if (arp_data->arp_send_ip_addr == 255) {
+               arp_data->arp_send_ip_addr = 0;
+               arp_data->arp_send_packet_timer = 0;
+               return G_SOURCE_REMOVE;
+       }
+
+       arp_data->arp_send_ip_addr++;
+       return G_SOURCE_CONTINUE;
+}
+
+static void __send_arp_uni_mode(const char* ip)
+{
+       guint Time;
+
+       if (arp_data->arp_send_packet_timer == 0) {
+               arp_data->arp_send_ip_addr = 1;
+               arp_data->arp_send_packet_timer =  g_timeout_add(SEND_MAC_TIMER,
+                       __send_arp_unimul_packet_timeout, NULL);
+               UA_WIFI_INFO("SendArpPacket Timer Id is %d Starting Timer ",
+                       arp_data->arp_send_packet_timer);
+       }
+
+       Time = ARP_MAC_TIMER * 1000;//1sec
+       arp_data->is_arp_init = 1;
+       g_timeout_add(Time, __arp_packet_callback, NULL);
+       UA_WIFI_INFO("Send %d UNICAST ARP Packet", arp_data->arp_mac_count);
+}
+
+static int __arp_make_send(const char* ip, const char* mac)
+{
+       FUNC_ENTER;
+       int ret;
+
+       ret = __arp_packet_make(mac);
+
+       if (ret != UAS_STATUS_SUCCESS) {
+               UA_WIFI_ERR("Fail to make arp packet");
+               FUNC_EXIT;
+               return ret;
+       }
+
+       ret = __init_arp(mac);
+
+       if (ret != UAS_STATUS_SUCCESS) {
+               UA_WIFI_ERR("Fail to init arp");
+               FUNC_EXIT;
+               return ret;
+       }
+
+       memcpy(arp_data->arp_target_mac, mac, strlen(mac));
+       UA_WIFI_INFO("Request mac address %s IP address %s", mac, ip);
+       __send_arp_uni_mode(ip);
+
+       FUNC_EXIT;
+       return UAS_STATUS_SUCCESS;
+}
+
+int __start_arp(const char* ip, const char* mac)
+{
+       int ret;
+
+       if (arp_data && arp_data->is_arp_init == 1) {
+               UA_WIFI_ERR("Already initialized");
+               return UAS_STATUS_FAIL;
+       }
+
+       arp_data->arp_data_id = -1;
+       arp_data->arp_id = -1;
+       arp_data->arp_sock_io = NULL;
+       memset(arp_data->arp_source_mac, '\0', MAX_SIZE_BUFFER);
+       memset(arp_data->arp_source_ip, '\0', MAX_SIZE_BUFFER);
+       memset(arp_data->arp_target_mac, '\0', MAX_SIZE_BUFFER);
+
+       ret = __arp_make_send(ip, mac);
+
+       return ret;
+}
+
+int __init_ip_mac_count(void)
+{
+       if (!arp_data) {
+               UA_WIFI_ERR("ARP data is not initialized");
+               return UAS_STATUS_FAIL;
+       }
+       arp_data->arp_mac_count = 1;
+
+       return UAS_STATUS_SUCCESS;
+}
+
+int __start_wifi_detection(const char* ip, const char* mac)
+{
+       int ret;
+
+       if (!arp_data) {
+               UA_WIFI_ERR("ARP data is not initialized");
+               return UAS_STATUS_FAIL;
+       }
+
+       arp_data->mobile_detection = true;
+
+       ret = __start_arp(ip, mac);
+
+       return ret;
+}
+
+int __start_wifi_add_device(const char* ip, const char* mac)
+{
+       int ret;
+
+       if (!arp_data) {
+               UA_WIFI_ERR("ARP data is not initialized");
+               return UAS_STATUS_FAIL;
+       }
+
+       arp_data->mobile_detection = false;
+
+       ret = __start_arp(ip, mac);
+
+       return ret;
+}
+
+int __initialize_arp_data(void)
+{
+       if (!arp_data)
+               arp_data = g_try_malloc0(sizeof(struct arping_data));
+
+       if (arp_data == NULL) {
+               UA_WIFI_ERR("Failed to malloc arping_data");
+               return UAS_STATUS_FAIL;
+       }
+
+       return UAS_STATUS_SUCCESS;
+}
+
+void __deinit_arp_data(void)
+{
+       if (arp_data)
+               g_free(arp_data);
+
+       arp_data = NULL;
+}
diff --git a/src/wifi-util.c b/src/wifi-util.c
new file mode 100644 (file)
index 0000000..8d9c0f5
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#include <wifi-plugin.h>
+#include <wifi-plugin-util.h>
+
+uas_wifi_info_t *_wifi_plugin_util_get_wifi_info_from_dev_info(
+       uas_device_info_t *dev_info)
+{
+       FUNC_ENTER;
+       uas_wifi_info_t* wifi_info;
+       int i;
+       int found = 0;
+
+       retv_if(NULL == dev_info, NULL);
+       retv_if(NULL == dev_info->device_id, NULL);
+
+       wifi_info = g_new0(uas_wifi_info_t, 1);
+       wifi_info->user_id = dev_info->user_id;
+       wifi_info->os = dev_info->os;
+       wifi_info->absence_count = 0;
+       wifi_info->supported_techs = dev_info->supported_techs;
+
+       g_strlcpy(wifi_info->mobile_id, dev_info->device_id, UAS_DEVICE_ID_MAX_LEN);
+
+       for (i = 0; i < dev_info->num_addr; i++) {
+               if (UAS_ADDR_TYPE_WIFI == dev_info->addr_list[i].type) {
+                       g_strlcpy(wifi_info->mac_addr,
+                                       dev_info->addr_list[i].address,
+                                       MAC_ADDRESS_STRING_SIZE);
+                       found = 1;
+               } else if (UAS_ADDR_TYPE_IPv4 == dev_info->addr_list[i].type) {
+                       g_strlcpy(wifi_info->ip_addr,
+                                       dev_info->addr_list[i].address,
+                                       IP_ADDRESS_STRING_SIZE);
+                       found = 1;
+               }
+       }
+
+       if (!found) {
+               UA_WIFI_ERR("Wi-Fi info not present in dev_info structure");
+               g_free(wifi_info);
+               return NULL;
+       }
+
+       UA_WIFI_DBG("User Id: [0x%X], OS: [0x%X], Device Id: [%s], \
+                                       MAC Addr: [%s], IP Addr: [%s]",
+                       wifi_info->user_id, wifi_info->os, wifi_info->mobile_id,
+                       wifi_info->mac_addr, wifi_info->ip_addr);
+
+       FUNC_EXIT;
+       return wifi_info;
+}
+
+uas_device_info_t *_wifi_plugin_util_get_dev_info_from_wifi_info(
+       uas_wifi_info_t *wifi_info)
+{
+       FUNC_ENTER;
+       uas_device_info_t *dev_info;
+       int count = 0, i;
+       int is_mac = 0, is_ip = 0;
+
+       retv_if(NULL == wifi_info, NULL);
+
+       dev_info = g_new0(uas_device_info_t, 1);
+       dev_info->user_id = wifi_info->user_id;
+       dev_info->os = wifi_info->os;
+       dev_info->supported_techs = wifi_info->supported_techs;
+       dev_info->device_id = g_strdup(wifi_info->mobile_id);
+
+       if (strlen(wifi_info->mac_addr) != 0) {
+               count++;
+               is_mac = 1;
+       }
+
+       if (strlen(wifi_info->ip_addr) != 0) {
+               count++;
+               is_ip = 1;
+       }
+
+       if (count) {
+               dev_info->addr_list = g_new0(uas_address_info_t, count);
+
+               for (i = 0; i < count; i++) {
+                       if (is_mac) {
+                               dev_info->addr_list[i].type = UAS_ADDR_TYPE_WIFI;
+                               dev_info->addr_list[i].address = g_strdup(wifi_info->mac_addr);
+                               is_mac = 0;
+                       } else if (is_ip) {
+                               dev_info->addr_list[i].type = UAS_ADDR_TYPE_IPv4;
+                               dev_info->addr_list[i].address = g_strdup(wifi_info->ip_addr);
+                               is_ip = 0;
+                       }
+               }
+       }
+
+       dev_info->num_addr = count;
+
+       for (int i = 0; i < count; i++) {
+               UA_WIFI_DBG("User Id: [0x%X], OS: [0x%X], Device Id: [%s], MAC/IP Addr: [%s]",
+                               dev_info->user_id, dev_info->os, dev_info->device_id,
+                               dev_info->addr_list[i].address);
+       }
+
+       FUNC_EXIT;
+       return dev_info;
+}
+
+void _wifi_plugin_util_uas_device_info_free(uas_device_info_t *device)
+{
+       FUNC_ENTER;
+       int i;
+
+       ret_if(NULL == device);
+
+       g_free(device->device_id);
+
+       for (i = 0; i < device->num_addr; i++)
+               g_free(device->addr_list[i].address);
+
+       g_free(device->addr_list);
+
+       g_free(device);
+
+       FUNC_EXIT;
+}
+