#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 IP_ADDRESS_LENGTH 4
#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 {\
};
typedef enum {
- IP_CONFLICT_MODE_EXPONENTIAL = 0x00,
- IP_CONFLICT_MODE_PERIODIC,
- IP_CONFLICT_MODE_MAX
-} ip_conflict_mode_e;
-
-typedef enum {
NETCONFIG_IP_CONFLICT_STATE_UNKNOWN,
NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED,
NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED
struct timer_data {
guint initial_time;
guint timeout;
- ip_conflict_mode_e mode;
};
static struct timer_data td = {
- MIN_ARP_SEND_TIME, MIN_ARP_SEND_TIME, IP_CONFLICT_MODE_PERIODIC
+ MIN_ARP_SEND_TIME, MIN_ARP_SEND_TIME
};
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;
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) {
+ 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);
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) {
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)
goto err;
}
- source_ip = inet_addr(default_ip);
+ 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 */
}
g_source_remove(sd->timer_id);
- if (td.mode == IP_CONFLICT_MODE_PERIODIC)
+
+ if (conflict_state == NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED || initial_bursts)
+ sd->timeout = BURST_ARP_SEND_TIME;
+ else
sd->timeout = td.initial_time;
- else if (td.mode == IP_CONFLICT_MODE_EXPONENTIAL && 2*sd->timeout < MAX_ARP_SEND_TIME)
- sd->timeout *= 2;
/* Adding timeout callback for arp request */
sd->arp_reply_timer = g_timeout_add(1000, __arp_reply_timeout_cb,
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) {
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;
}
}
}
g_free(sd);
sd = NULL;
+ is_ip_conflict_detect_enabled = false;
+ conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN;
INFO("Monitoring stopped");
}
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;
}
}
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);
return TRUE;
}
-gboolean handle_set_ip_conflict_mode(Wifi *wifi, GDBusMethodInvocation *context,
- guint mode, guint initial_time)
+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;
- td.mode = mode;
// remove timer
stop_ip_conflict_mon();
start_ip_conflict_mon();
- wifi_complete_set_ip_conflict_mode(wifi, context);
+ 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);
+ 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);
return TRUE;
}
+
+gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context)
+{
+ 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);
+ return TRUE;
+}