Fix bug in Ip conflict set/get enabled API's
[platform/core/connectivity/net-config.git] / src / ip-conflict-detect.c
old mode 100644 (file)
new mode 100755 (executable)
index 53c1dd1..65805e3
@@ -38,6 +38,7 @@
 #include "network-state.h"
 #include "log.h"
 #include "neterror.h"
+#include "util.h"
 
 #define ARP_PACKET_SIZE 60
 #define MAX_SIZE_ERROR_BUFFER 256
 #define MAC_ADDRESS_LENGTH 6
 #define WLAN_MAC_ADDR_MAX 20
 #define ARP_SOURCE_IP "0.0.0.0"
+#define INITIAL_BURST_ARP_COUNT 5
 
-#define MIN_ARP_SEND_TIME 2000
+#define CONFLICT_REMOVE_ITERATION_LIMIT 4
+#define MIN_ARP_SEND_TIME 20000
+#define BURST_ARP_SEND_TIME 3000
 #define MAX_ARP_SEND_TIME 32000
 #define GRATUITOUS_ARP_MAC_ADDR "00:00:00:00:00:00"
 #define UCHAR_TO_ADDRESS(hwaddr, buf) do {\
@@ -89,7 +93,8 @@ static struct timer_data td = {
 };
 
 int ioctl_sock;
-bool is_ip_conflict_detect_enabled = true;
+static bool initial_bursts = true;
+bool is_ip_conflict_detect_enabled = false;
 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;
@@ -122,13 +127,13 @@ static gboolean __arp_reply_timeout_cb(gpointer data)
 
        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) {
+       if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED &&
+                       sd->iteration == CONFLICT_REMOVE_ITERATION_LIMIT) {
                sd->iteration = 0;
                conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
                __netconfig_wifi_notify_ip_conflict("resolved", GRATUITOUS_ARP_MAC_ADDR);
+               initial_bursts = true;
        }
 
        sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
@@ -188,6 +193,7 @@ skip:
                                INFO("ip conflict is detected !\n");
                                conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED;
                                __netconfig_wifi_notify_ip_conflict("conflict", sbuf);
+                               sd->timeout = BURST_ARP_SEND_TIME;
                        }
 
                        if (sd->arp_reply_timer != -1) {
@@ -220,6 +226,15 @@ static gboolean send_arp(gpointer data)
        int ifindex = 0;
        errno = 0;
        const char *default_ip = NULL;
+       static int initial_send_arp_count = 0;
+
+       if (initial_bursts && initial_send_arp_count >= INITIAL_BURST_ARP_COUNT) {
+               initial_bursts = false;
+               initial_send_arp_count = 0;
+       }
+
+       if (initial_bursts)
+               initial_send_arp_count++;
 
        const char *mac = netconfig_get_default_mac_address();
        if (mac == NULL)
@@ -302,7 +317,10 @@ static gboolean send_arp(gpointer data)
 
        g_source_remove(sd->timer_id);
 
-       sd->timeout = td.initial_time;
+       if (conflict_state == NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED || initial_bursts)
+               sd->timeout = BURST_ARP_SEND_TIME;
+       else
+               sd->timeout = td.initial_time;
 
        /* Adding timeout callback for arp request */
        sd->arp_reply_timer = g_timeout_add(1000, __arp_reply_timeout_cb,
@@ -317,12 +335,13 @@ err:
 
 struct sock_data * start_ip_conflict_mon(void)
 {
-       if (is_ip_conflict_detect_enabled == false) {
-               INFO("detection mode is set to false");
+       if (is_ip_conflict_detect_enabled == true) {
+               INFO("detection mode is set to true");
                return NULL;
        }
 
        char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+       initial_bursts = true;
 
        sd = g_try_malloc0(sizeof(struct sock_data));
        if (sd == NULL) {
@@ -362,6 +381,8 @@ struct sock_data * start_ip_conflict_mon(void)
 
                sd->timeout = td.initial_time;
                send_arp(sd);
+               is_ip_conflict_detect_enabled = true;
+               conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
                return sd;
        }
 }
@@ -393,6 +414,8 @@ void stop_ip_conflict_mon()
        }
        g_free(sd);
        sd = NULL;
+       is_ip_conflict_detect_enabled = false;
+       conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN;
        INFO("Monitoring stopped");
 }
 
@@ -407,40 +430,42 @@ static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac)
        wifi_emit_ip_conflict_event((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
        g_variant_builder_unref(builder);
 
+       /* send notification using net-popup */
+       if (!strcmp(state, "conflict"))
+               netconfig_send_notification_to_net_popup(NETCONFIG_ADD_IP_CONFLICT_NOTI, mac);
+       else
+               netconfig_send_notification_to_net_popup(NETCONFIG_DEL_IP_CONFLICT_NOTI, mac);
+
        return;
 }
 
 gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context,
                                       bool detect)
 {
-       g_return_val_if_fail(wifi != NULL, FALSE);
+       g_return_val_if_fail(wifi != NULL, TRUE);
 
 
        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;
+                       return TRUE;
                }
        } 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;
+                               return TRUE;
                        }
                } else {
                        netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
                        wifi_complete_ip_conflict_set_enable(wifi, context);
-                       return FALSE;
+                       return TRUE;
                }
        }
 
@@ -450,7 +475,7 @@ gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *contex
 
 gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context)
 {
-       g_return_val_if_fail(wifi != NULL, FALSE);
+       g_return_val_if_fail(wifi != NULL, TRUE);
        GVariant *param = NULL;
        param = g_variant_new("(b)", is_ip_conflict_detect_enabled);
        g_dbus_method_invocation_return_value(context, param);
@@ -459,9 +484,12 @@ gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation
 
 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;
+       g_return_val_if_fail(wifi != NULL, TRUE);
+       if (initial_time < MAX_ARP_SEND_TIME && initial_time > MIN_ARP_SEND_TIME) {
+               netconfig_error_dbus_method_return(context,
+                                               NETCONFIG_ERROR_INTERNAL, "Failed");
+               return TRUE;
+       }
 
        td.initial_time = 1000 * initial_time;
        // remove timer
@@ -473,7 +501,7 @@ gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *contex
 
 gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context)
 {
-       g_return_val_if_fail(wifi != NULL, FALSE);
+       g_return_val_if_fail(wifi != NULL, TRUE);
        GVariant *param = NULL;
        param = g_variant_new("(u)", conflict_state);
        g_dbus_method_invocation_return_value(context, param);
@@ -482,7 +510,7 @@ gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context
 
 gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context)
 {
-       g_return_val_if_fail(wifi != NULL, FALSE);
+       g_return_val_if_fail(wifi != NULL, TRUE);
        GVariant *param = NULL;
        param = g_variant_new("(u)", td.initial_time/1000);
        g_dbus_method_invocation_return_value(context, param);