From: taesub kim Date: Wed, 8 Nov 2017 07:02:47 +0000 (+0000) Subject: Merge "Fixed memory leak in SetField method" into tizen X-Git-Tag: submit/tizen/20171108.071810~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=01b24ff1630dc85a823278a8f70e6247b1cd35fb;hp=629b0b5d274adf7c1c1a98d8b9025935e64e1417;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git Merge "Fixed memory leak in SetField method" into tizen --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 8546f90..1069cdd 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ SET(SRCS src/wifi-background-scan.c src/wifi-config.c src/wifi-extension.c + src/ip-conflict-detect.c ) IF("${CMAKE_BUILD_TYPE}" STREQUAL "") diff --git a/include/ip-conflict-detect.h b/include/ip-conflict-detect.h new file mode 100644 index 0000000..f830a4f --- /dev/null +++ b/include/ip-conflict-detect.h @@ -0,0 +1,56 @@ +/* + * Network Configuration Module + * + * Copyright (c) 2000 - 2012 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 __NETCONFIG_IP_CONFLICT_DETECT_H__ +#define __NETCONFIG_IP_CONFLICT_DETECT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "wifi.h" + +struct sock_data { + guint timer_id; + int chk_conflict_data_id; + GIOChannel *chk_conflict_sock_io; + int chk_conflict_sd; + guint timeout; + guint arp_reply_timer; + int iteration; +}; + +struct sock_data * start_ip_conflict_mon(void); +void stop_ip_conflict_mon(); +gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context, + bool detect); +gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context); +gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context, + guint initial_time); +gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation + *context); +gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context); + + +#ifdef __cplusplus +} +#endif + +#endif /* __NETCONFIG_IP_CONFLICT_DETECT_H__ */ diff --git a/include/network-state.h b/include/network-state.h index a1bdd0d..a38b1af 100755 --- a/include/network-state.h +++ b/include/network-state.h @@ -26,18 +26,19 @@ extern "C" { void netconfig_network_notify_ethernet_cable_state(const char *key); -const char *netconfig_get_default_profile(void); -const char *netconfig_get_default_ifname(void); -const char *netconfig_get_default_ipaddress(void); -const char *netconfig_get_default_ipaddress6(void); -const char *netconfig_get_default_proxy(void); -unsigned int netconfig_get_default_frequency(void); -const char *netconfig_wifi_get_connected_essid(const char *default_profile); -gboolean netconfig_get_default_is_metered(void); - -void netconfig_update_default(void); -void netconfig_update_default_profile(const char *profile); -char *netconfig_get_ifname(const char *profile); +const char *netconfig_get_default_profile(void); +const char *netconfig_get_default_ifname(void); +const char *netconfig_get_default_ipaddress(void); +const char *netconfig_get_default_ipaddress6(void); +const char *netconfig_get_default_proxy(void); +const char *netconfig_get_default_mac_address(void); +unsigned int netconfig_get_default_frequency(void); +const char *netconfig_wifi_get_connected_essid(const char *default_profile); +gboolean netconfig_get_default_is_metered(void); + +void netconfig_update_default(void); +void netconfig_update_default_profile(const char *profile); +char *netconfig_get_ifname(const char *profile); void state_object_create_and_init(void); void state_object_deinit(void); diff --git a/interfaces/netconfig-iface-wifi.xml b/interfaces/netconfig-iface-wifi.xml index c1d46e6..54c665a 100755 --- a/interfaces/netconfig-iface-wifi.xml +++ b/interfaces/netconfig-iface-wifi.xml @@ -17,6 +17,9 @@ + + + @@ -31,6 +34,12 @@ + + + + + + @@ -58,6 +67,9 @@ + + + @@ -85,6 +97,9 @@ + + + @@ -160,6 +175,9 @@ + + + diff --git a/resources/etc/dbus-1/system.d/net-config.conf b/resources/etc/dbus-1/system.d/net-config.conf index ef94c1d..04677f7 100755 --- a/resources/etc/dbus-1/system.d/net-config.conf +++ b/resources/etc/dbus-1/system.d/net-config.conf @@ -20,6 +20,8 @@ + + @@ -43,6 +45,10 @@ + + + + @@ -69,6 +75,7 @@ + diff --git a/src/ip-conflict-detect.c b/src/ip-conflict-detect.c new file mode 100644 index 0000000..53c1dd1 --- /dev/null +++ b/src/ip-conflict-detect.c @@ -0,0 +1,490 @@ +/* + * Network Configuration Module + * + * Copyright (c) 2000 - 2012 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ip-conflict-detect.h" +#include "network-state.h" +#include "log.h" +#include "neterror.h" + +#define ARP_PACKET_SIZE 60 +#define MAX_SIZE_ERROR_BUFFER 256 +#define IP_ADDRESS_LENGTH 4 +#define MAC_ADDRESS_LENGTH 6 +#define WLAN_MAC_ADDR_MAX 20 +#define ARP_SOURCE_IP "0.0.0.0" + +#define MIN_ARP_SEND_TIME 2000 +#define MAX_ARP_SEND_TIME 32000 +#define GRATUITOUS_ARP_MAC_ADDR "00:00:00:00:00:00" +#define UCHAR_TO_ADDRESS(hwaddr, buf) do {\ + snprintf(buf, WLAN_MAC_ADDR_MAX,\ + "%02X:%02X:%02X:%02X:%02X:%02X", hwaddr[0], hwaddr[1],\ + hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);\ + } while (0) + +struct arp_message { + /* Ethernet header */ + unsigned char h_dest[MAC_ADDRESS_LENGTH]; /* destination ether addr */ + unsigned char h_source[MAC_ADDRESS_LENGTH]; /* source ether addr */ + unsigned short h_proto; /* packet type ID field */ + + /* ARP packet */ + unsigned short hw_type; /* hardware type(ARPHRD_ETHER) */ + unsigned short p_type; /* protocol type(ETH_P_IP) */ + unsigned char hw_len; /* hardware address length */ + unsigned char p_len; /* protocol address length */ + unsigned short operation; /* ARP opcode */ + unsigned char s_hwaddr[MAC_ADDRESS_LENGTH]; /* sender hardware address */ + unsigned char s_IPaddr[IP_ADDRESS_LENGTH]; /* sender IP address */ + unsigned char t_hwaddr[MAC_ADDRESS_LENGTH]; /* target hardware address */ + unsigned char t_IPaddr[IP_ADDRESS_LENGTH]; /* target IP address */ + unsigned char pad[18]; /* pad for min. Ethernet payload (60 bytes) */ +}; + +typedef enum { + NETCONFIG_IP_CONFLICT_STATE_UNKNOWN, + NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED, + NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED +} ip_conflict_state_e; + +struct timer_data { + guint initial_time; + guint timeout; +}; +static struct timer_data td = { + MIN_ARP_SEND_TIME, MIN_ARP_SEND_TIME +}; + +int ioctl_sock; +bool is_ip_conflict_detect_enabled = true; +static gboolean send_arp(gpointer data); +static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac); +ip_conflict_state_e conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED; + +struct sock_data *sd; + +typedef unsigned int in_addr_t; + +union uchar_to_uint { + unsigned int uint; + unsigned char uchar[IP_ADDRESS_LENGTH]; +}; + +static unsigned int __convert_uchar_to_uint(unsigned char b[IP_ADDRESS_LENGTH]) +{ + int idx = 0; + union uchar_to_uint u; + for (; idx < IP_ADDRESS_LENGTH; ++idx) + u.uchar[idx] = b[idx]; + + return u.uint; +} + +static gboolean __arp_reply_timeout_cb(gpointer data) +{ + if (sd == NULL) { + INFO("Ignore timeout cb"); + return G_SOURCE_REMOVE; + } + + sd->iteration++; + sd->arp_reply_timer = -1; + if (sd->timer_id != -1) + g_source_remove(sd->timer_id); + + if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED && sd->iteration == 5) { + sd->iteration = 0; + conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED; + __netconfig_wifi_notify_ip_conflict("resolved", GRATUITOUS_ARP_MAC_ADDR); + } + + sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd); + return G_SOURCE_REMOVE; +} + +static gboolean __netconfig_check_arp_receive(GIOChannel *source, + GIOCondition condition, gpointer data) +{ + struct sock_data *sd = data; + gchar buffer[ARP_PACKET_SIZE] = {0, }; + gsize bytes_read = 0; + struct arp_message arp_recv; + char sbuf[WLAN_MAC_ADDR_MAX]; + char tbuf[WLAN_MAC_ADDR_MAX]; + const char *default_ip = NULL; + + if (g_io_channel_read_chars(source, buffer, ARP_PACKET_SIZE, + &bytes_read, NULL) == G_IO_STATUS_NORMAL) { + unsigned int target_ip = 0; + + memset(&arp_recv, 0, sizeof(arp_recv)); + memcpy(&arp_recv, buffer, sizeof(buffer)); + + default_ip = netconfig_get_default_ipaddress(); + if (default_ip == NULL) { + INFO("ip address is not set yet"); + goto out; + } + target_ip = inet_addr(default_ip); + + + /* Only handle ARP replies */ + if (arp_recv.operation != htons(ARPOP_REPLY)) + goto out; + + UCHAR_TO_ADDRESS(arp_recv.t_hwaddr, tbuf); + UCHAR_TO_ADDRESS(arp_recv.s_hwaddr, sbuf); + + int zero_mac = strcmp(tbuf , GRATUITOUS_ARP_MAC_ADDR); + if (zero_mac == 0) { + DBG("Broadcast packet.\n"); + goto skip; + } + DBG("our mac= %s source mac= %s target mac= %s", netconfig_get_default_mac_address(), sbuf, tbuf); + int mac_cmp = strcmp(tbuf , netconfig_get_default_mac_address()); + if (mac_cmp != 0) { + INFO("Packet not intended to us.\n"); + goto out; + } +skip: + mac_cmp = strcmp(sbuf, netconfig_get_default_mac_address()); + DBG("target ip = %d source ip = %d", target_ip, __convert_uchar_to_uint(arp_recv.s_IPaddr)); + if ((mac_cmp != 0) && (__convert_uchar_to_uint(arp_recv.s_IPaddr) == target_ip)) { + sd->iteration = 0; + if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED) { + INFO("ip conflict is detected !\n"); + conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED; + __netconfig_wifi_notify_ip_conflict("conflict", sbuf); + } + + if (sd->arp_reply_timer != -1) { + g_source_remove(sd->arp_reply_timer); + sd->arp_reply_timer = -1; + } + + if (sd->timer_id) + g_source_remove(sd->timer_id); + sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd); + + } + } + +out: + return TRUE; +} + +static gboolean send_arp(gpointer data) +{ + struct sock_data *sd = data; + struct ether_addr *source_mac = NULL; + struct arp_message arp; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + unsigned int source_ip = 0; + unsigned int target_ip = 0; + const unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct sockaddr_ll addr = {0}; + struct ifreq net_ifr; + int ifindex = 0; + errno = 0; + const char *default_ip = NULL; + + const char *mac = netconfig_get_default_mac_address(); + if (mac == NULL) + goto err; + source_mac = ether_aton(mac); + if (source_mac == NULL) { + INFO("Mac address is NULL"); + goto err; + } + + memset(&arp, 0, sizeof(arp)); + + unsigned char broadcast_mac_addr[MAC_ADDRESS_LENGTH]; + memset(broadcast_mac_addr, 0xff, sizeof(broadcast_mac_addr)); + memcpy(arp.h_dest, broadcast_mac_addr, MAC_ADDRESS_LENGTH); /* MAC dest */ + memcpy(arp.h_source, source_mac, MAC_ADDRESS_LENGTH); /* MAC source */ + + arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ + arp.hw_type = htons(ARPHRD_ETHER); /* hardware type */ + arp.p_type = htons(ETH_P_IP); /* protocol type (ARP message) */ + arp.hw_len = MAC_ADDRESS_LENGTH; /* hardware address length */ + arp.p_len = IP_ADDRESS_LENGTH; /* protocol address length */ + arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ + default_ip = netconfig_get_default_ipaddress(); + if (default_ip == NULL) { + INFO("ip address is not set yet"); + goto err; + } + + source_ip = inet_addr(ARP_SOURCE_IP); + target_ip = inet_addr(default_ip); + memcpy(arp.s_IPaddr, &source_ip, IP_ADDRESS_LENGTH); /* source IP address */ + memcpy(arp.s_hwaddr, source_mac, MAC_ADDRESS_LENGTH); /* source hardware address */ + memcpy(arp.t_IPaddr, &target_ip, IP_ADDRESS_LENGTH); /* target IP addressshek" */ + + memset(&net_ifr, 0, sizeof(net_ifr)); + /* ifreq structure creation */ + size_t if_name_len = strlen(netconfig_get_default_ifname()); + if (if_name_len < sizeof(net_ifr.ifr_name)) { + memcpy(net_ifr.ifr_name, netconfig_get_default_ifname(), if_name_len); + net_ifr.ifr_name[if_name_len] = 0; + } else { + INFO("Error : Interface name is too long"); + goto err; + } + + if (ioctl(sd->chk_conflict_sd, SIOCGIFINDEX, &net_ifr) == -1) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + INFO("ioctl Failed. Error..... = %s\n", error_buf); + goto err; + } + + ifindex = net_ifr.ifr_ifindex; + /* Construct the destination address */ + addr.sll_family = AF_PACKET; + addr.sll_ifindex = ifindex; + addr.sll_halen = ETHER_ADDR_LEN; + addr.sll_protocol = htons(ETH_P_ARP); + memcpy(addr.sll_addr, broadcast_addr, ETHER_ADDR_LEN); + + if (sendto(sd->chk_conflict_sd, &arp, sizeof(arp), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + INFO("Sending ARP Packet Failed. Error. = %s\n", error_buf); + /* close socket */ + if (-1 < sd->chk_conflict_sd) { + close(sd->chk_conflict_sd); + sd->chk_conflict_sd = -1; + } + + /* reopen socket */ + if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) { + INFO("socket %d", sd->chk_conflict_sd); + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + INFO("socket Failed. Error = %s\n", error_buf); + } + goto err; + } else { + DBG("Sent ARP Packet \n"); + } + + g_source_remove(sd->timer_id); + + sd->timeout = td.initial_time; + + /* Adding timeout callback for arp request */ + sd->arp_reply_timer = g_timeout_add(1000, __arp_reply_timeout_cb, + (gpointer) &sd->arp_reply_timer); + return FALSE; +err: + if (sd->timer_id) + g_source_remove(sd->timer_id); + sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd); + return FALSE; +} + +struct sock_data * start_ip_conflict_mon(void) +{ + if (is_ip_conflict_detect_enabled == false) { + INFO("detection mode is set to false"); + return NULL; + } + + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + + sd = g_try_malloc0(sizeof(struct sock_data)); + if (sd == NULL) { + INFO("Failed to malloc sock_data"); + return NULL; + } + sd->chk_conflict_data_id = -1; + sd->chk_conflict_sd = -1; + sd->timer_id = 0; + sd->iteration = 0; + + if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) { + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER); + INFO("socket Failed. Error = %s\n", error_buf); + g_free(sd); + return NULL; + } else { + sd->chk_conflict_sock_io = g_io_channel_unix_new(sd->chk_conflict_sd); + if (sd->chk_conflict_sock_io == NULL) { + INFO("Failed to create channel"); + INFO("Exit"); + g_free(sd); + return NULL; + } + + g_io_channel_set_close_on_unref(sd->chk_conflict_sock_io, TRUE); + + if (G_IO_STATUS_NORMAL != g_io_channel_set_encoding(sd->chk_conflict_sock_io, + NULL, NULL)) + INFO("Failed to set encoding NULL on io channel"); + if (G_IO_STATUS_NORMAL != g_io_channel_set_flags(sd->chk_conflict_sock_io, + G_IO_FLAG_NONBLOCK, NULL)) + INFO("Failed to set flags on io channel"); + sd->chk_conflict_data_id = g_io_add_watch(sd->chk_conflict_sock_io, G_IO_IN, + __netconfig_check_arp_receive, sd); + DBG("socket %d", sd->chk_conflict_sd); + + sd->timeout = td.initial_time; + send_arp(sd); + return sd; + } +} + +void stop_ip_conflict_mon() +{ + INFO("+"); + GError* error = NULL; + if (sd == NULL) { + INFO("sd is NULL"); + return; + } + if (-1 < sd->chk_conflict_sd) { + if (G_IO_STATUS_NORMAL != + g_io_channel_shutdown(sd->chk_conflict_sock_io, FALSE, + &error)) { + INFO("Failure received while shutdown io channel[%d]:[%s]", error->code, error->message); + g_error_free(error); + } + g_io_channel_unref(sd->chk_conflict_sock_io); + g_source_remove(sd->chk_conflict_data_id); + sd->chk_conflict_data_id = -1; + close(sd->chk_conflict_sd); + sd->chk_conflict_sd = -1; + } + if (sd->timer_id > 0) { + g_source_remove(sd->timer_id); + sd->timer_id = 0; + } + g_free(sd); + sd = NULL; + INFO("Monitoring stopped"); +} + +static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac) +{ + GVariantBuilder *builder = NULL; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(builder, "{sv}", "state", g_variant_new_string(state)); + g_variant_builder_add(builder, "{sv}", "mac", g_variant_new_string(mac)); + + wifi_emit_ip_conflict_event((Wifi *)get_wifi_object(), g_variant_builder_end(builder)); + g_variant_builder_unref(builder); + + return; +} + +gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context, + bool detect) +{ + g_return_val_if_fail(wifi != NULL, FALSE); + + + if (detect == false) { + is_ip_conflict_detect_enabled = false; + conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN; + if (sd != NULL) + stop_ip_conflict_mon(); + else { + netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists"); + wifi_complete_ip_conflict_set_enable(wifi, context); + return FALSE; + } + } else { + is_ip_conflict_detect_enabled = true; + conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED; + if (sd == NULL) { + if (start_ip_conflict_mon() == NULL) { + INFO("Failed to start IP conflict monitoring"); + netconfig_error_dbus_method_return(context, + NETCONFIG_ERROR_INTERNAL, "Failed"); + wifi_complete_ip_conflict_set_enable(wifi, context); + return FALSE; + } + } else { + netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists"); + wifi_complete_ip_conflict_set_enable(wifi, context); + return FALSE; + } + } + + wifi_complete_ip_conflict_set_enable(wifi, context); + return TRUE; +} + +gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context) +{ + g_return_val_if_fail(wifi != NULL, FALSE); + GVariant *param = NULL; + param = g_variant_new("(b)", is_ip_conflict_detect_enabled); + g_dbus_method_invocation_return_value(context, param); + return TRUE; +} + +gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context, guint initial_time) +{ + g_return_val_if_fail(wifi != NULL, FALSE); + if (initial_time < MAX_ARP_SEND_TIME && initial_time > MIN_ARP_SEND_TIME) + return FALSE; + + td.initial_time = 1000 * initial_time; + // remove timer + stop_ip_conflict_mon(); + start_ip_conflict_mon(); + wifi_complete_set_ip_conflict_period(wifi, context); + return TRUE; +} + +gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context) +{ + g_return_val_if_fail(wifi != NULL, FALSE); + GVariant *param = NULL; + param = g_variant_new("(u)", conflict_state); + g_dbus_method_invocation_return_value(context, param); + return TRUE; +} + +gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context) +{ + g_return_val_if_fail(wifi != NULL, FALSE); + GVariant *param = NULL; + param = g_variant_new("(u)", td.initial_time/1000); + g_dbus_method_invocation_return_value(context, param); + return TRUE; +} diff --git a/src/network-state.c b/src/network-state.c index 0fb0280..c2f5e92 100755 --- a/src/network-state.c +++ b/src/network-state.c @@ -92,6 +92,7 @@ static Network *netconfigstate = NULL; struct netconfig_default_connection { char *profile; char *ifname; + char *mac_address; char *ipaddress; char *ipaddress6; char *proxy; @@ -409,6 +410,9 @@ static void __netconfig_get_default_connection_info(const char *profile) if (g_strcmp0(key1, "Interface") == 0) { value = g_variant_get_string(variant, NULL); netconfig_default_connection_info.ifname = g_strdup(value); + } else if (g_strcmp0(key1, "Address") == 0) { + value = g_variant_get_string(variant, NULL); + netconfig_default_connection_info.mac_address = g_strdup(value); } } g_variant_iter_free(iter1); @@ -913,6 +917,11 @@ unsigned int netconfig_get_default_frequency(void) return netconfig_default_connection_info.freq; } +const char *netconfig_get_default_mac_address(void) +{ + return netconfig_default_connection_info.mac_address; +} + const char *netconfig_wifi_get_connected_essid(const char *default_profile) { if (default_profile == NULL) @@ -1009,6 +1018,9 @@ void netconfig_update_default_profile(const char *profile) g_free(netconfig_default_connection_info.proxy); netconfig_default_connection_info.proxy = NULL; + g_free(netconfig_default_connection_info.mac_address); + netconfig_default_connection_info.mac_address = NULL; + netconfig_default_connection_info.freq = 0; netconfig_default_connection_info.is_metered = FALSE; diff --git a/src/signal-handler.c b/src/signal-handler.c index e3ee51f..0bd5689 100755 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -38,6 +38,7 @@ #include "signal-handler.h" #include "wifi-background-scan.h" #include "wifi-tdls.h" +#include "ip-conflict-detect.h" #define DBUS_SERVICE_DBUS "org.freedesktop.DBus" #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" @@ -61,6 +62,7 @@ #define MAX_SIG_LEN 64 #define TOTAL_CONN_SIGNALS 5 +#define MAX_SOCKET_OPEN_RETRY 5 typedef enum { SIG_INTERFACE_REMOVED = 0, @@ -194,6 +196,8 @@ static void _service_signal_cb(GDBusConnection *conn, GVariant *variant = NULL, *var; GVariantIter *iter; const gchar *value = NULL; + struct sock_data *sd = NULL; + int idx = 0; if (path == NULL || param == NULL) goto done; @@ -208,6 +212,18 @@ static void _service_signal_cb(GDBusConnection *conn, if (g_strcmp0(sigvalue, "State") == 0) { g_variant_get(variant, "s", &property); + if (g_strcmp0(property, "ready") == 0) { + for (idx = 0; idx < MAX_SOCKET_OPEN_RETRY; idx++) { + sd = start_ip_conflict_mon(); + if (sd != NULL) + break; + } + } else if (g_strcmp0(property, "online") == 0) { + // do nothing + } else { + stop_ip_conflict_mon(); + } + DBG("[%s] %s", property, path); if (netconfig_is_wifi_profile(path) == TRUE) { int wifi_state = 0; diff --git a/src/wifi-indicator.c b/src/wifi-indicator.c index 1c99a18..86fd4d8 100755 --- a/src/wifi-indicator.c +++ b/src/wifi-indicator.c @@ -82,22 +82,16 @@ static int __netconfig_wifi_update_and_get_rssi(void) } message = netconfig_invoke_dbus_method(SUPPLICANT_SERVICE, if_path, - SUPPLICANT_INTERFACE ".Interface", "SignalPoll", NULL); - - g_free(if_path); + SUPPLICANT_INTERFACE ".Interface", "SignalPoll", NULL); if (message == NULL) { ERR("Fail to get SignalPoll from wpa_supplicant"); + g_free(if_path); return 0; } g_variant_get(message, "(v)", &value); g_variant_get(value, "a{sv}", &iter); - if (iter == NULL) { - ERR("Fail to get list from SignalPoll"); - return 0; - } - while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) { key_value = g_variant_get_int32(variant); @@ -115,6 +109,10 @@ static int __netconfig_wifi_update_and_get_rssi(void) if (value) g_variant_unref(value); + g_variant_unref(message); + + g_free(if_path); + netconfig_wifi_rssi = rssi_dbm; return rssi_dbm; diff --git a/src/wifi.c b/src/wifi.c index ef8db47..3ec8d94 100755 --- a/src/wifi.c +++ b/src/wifi.c @@ -38,6 +38,7 @@ #include "wifi-passpoint.h" #include "wifi-eap-config.h" #include "wifi-background-scan.h" +#include "ip-conflict-detect.h" #include "wifi-config.h" #include "wifi-tdls.h" #include "wifi-extension.h" @@ -190,6 +191,18 @@ void wifi_object_create_and_init(void) g_signal_connect(wifi_object, "handle-remove-vsie", G_CALLBACK(handle_remove_vsie), NULL); + /* IP conflict methods */ + g_signal_connect(wifi_object, "handle-ip-conflict-set-enable", + G_CALLBACK(handle_ip_conflict_set_enable), NULL); + g_signal_connect(wifi_object, "handle-is-ip-conflict-detect-enabled", + G_CALLBACK(handle_is_ip_conflict_detect_enabled), NULL); + g_signal_connect(wifi_object, "handle-set-ip-conflict-period", + G_CALLBACK(handle_set_ip_conflict_period), NULL); + g_signal_connect(wifi_object, "handle-get-ip-conflict-state", + G_CALLBACK(handle_get_ip_conflict_state), NULL); + g_signal_connect(wifi_object, "handle-get-ip-conflict-period", + G_CALLBACK(handle_get_ip_conflict_period), NULL); + /* WIFI configuration */ g_signal_connect(wifi_object, "handle-save-configuration", G_CALLBACK(handle_save_configuration), NULL);