#include <unistd.h>
#include <stdbool.h>
+#include "netdbus.h"
#include "ip-conflict-detect.h"
#include "network-state.h"
#include "log.h"
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) */
+ unsigned char pad[22]; /* pad for min. Ethernet payload (64 bytes) */
};
typedef enum {
int ioctl_sock;
static bool initial_bursts = true;
bool is_ip_conflict_detect_enabled = false;
+bool is_ip_conflict_detect_running = false;
static gboolean send_arp(gpointer data);
-static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac);
+static void __netconfig_wifi_notify_ip_conflict(const char *interface_name,
+ char *state, char *mac);
ip_conflict_state_e conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
struct sock_data *sd;
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);
+ __netconfig_wifi_notify_ip_conflict(netconfig_get_default_ifname(),
+ "resolved", GRATUITOUS_ARP_MAC_ADDR);
initial_bursts = true;
}
+ if (sd->timer_id)
+ g_source_remove(sd->timer_id);
sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
return G_SOURCE_REMOVE;
}
char sbuf[WLAN_MAC_ADDR_MAX];
char tbuf[WLAN_MAC_ADDR_MAX];
const char *default_ip = NULL;
+ int mac_cmp = 0;
if (g_io_channel_read_chars(source, buffer, ARP_PACKET_SIZE,
&bytes_read, NULL) == G_IO_STATUS_NORMAL) {
int zero_mac = strcmp(tbuf , GRATUITOUS_ARP_MAC_ADDR);
if (zero_mac == 0) {
- DBG("Broadcast packet.\n");
+ DBG("Broadcast packet.");
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());
+ mac_cmp = strcmp(tbuf , netconfig_get_default_mac_address());
if (mac_cmp != 0) {
- INFO("Packet not intended to us.\n");
+ INFO("Packet not intended to us.");
goto out;
}
skip:
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");
+ INFO("ip conflict is detected !");
conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED;
- __netconfig_wifi_notify_ip_conflict("conflict", sbuf);
+ __netconfig_wifi_notify_ip_conflict(
+ netconfig_get_default_ifname(),
+ "conflict", sbuf);
sd->timeout = BURST_ARP_SEND_TIME;
}
if (sd->timer_id)
g_source_remove(sd->timer_id);
sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
-
}
}
return TRUE;
}
+static void __close_channel_and_sock(struct sock_data *sd)
+{
+ if (sd == NULL)
+ return;
+
+ 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;
+}
+
+static int __open_channel_and_sock(struct sock_data *sd)
+{
+ if (sd == NULL)
+ return -1;
+
+ if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) {
+ INFO("socket Failed.");
+ return -1;
+ }
+
+ 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");
+ close(sd->chk_conflict_sd);
+ sd->chk_conflict_sd = -1;
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
static gboolean send_arp(gpointer data)
{
struct sock_data *sd = data;
int ifindex = 0;
errno = 0;
const char *default_ip = NULL;
+ const char *if_name = NULL;
static int initial_send_arp_count = 0;
if (initial_bursts && initial_send_arp_count >= INITIAL_BURST_ARP_COUNT) {
memset(&net_ifr, 0, sizeof(net_ifr));
/* ifreq structure creation */
- size_t if_name_len = strlen(netconfig_get_default_ifname());
+ if_name = netconfig_get_default_ifname();
+ size_t if_name_len = strlen(if_name);
+
+ if (if_name_len == 0) {
+ INFO("Error : Unable to get interface name ");
+ goto err;
+ }
+
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;
}
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);
+ INFO("ioctl Failed. Error..... = %s",
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
goto err;
}
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);
- }
+ if (sendto(sd->chk_conflict_sd, &arp, sizeof(arp), 0,
+ (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ INFO("Sending ARP Packet Failed. Error. = %s",
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
+ __close_channel_and_sock(sd);
+ if (__open_channel_and_sock(sd) == -1)
+ INFO("__open_channel_and_sock failed");
goto err;
} else {
- DBG("Sent ARP Packet \n");
+ /* DBG("Sent ARP Packet"); */
}
- g_source_remove(sd->timer_id);
+ if (sd->timer_id) {
+ g_source_remove(sd->timer_id);
+ sd->timer_id = 0;
+ }
if (conflict_state == NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED || initial_bursts)
sd->timeout = BURST_ARP_SEND_TIME;
struct sock_data * start_ip_conflict_mon(void)
{
- if (is_ip_conflict_detect_enabled == true) {
+ if (is_ip_conflict_detect_enabled == false) {
+ INFO("ip_conflict_detect is disabled");
+ return NULL;
+ }
+
+ if (is_ip_conflict_detect_running == 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));
}
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);
+ if (__open_channel_and_sock(sd) == -1) {
+ INFO("__open_channel_and_sock failed");
g_free(sd);
+ sd = NULL;
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);
+ is_ip_conflict_detect_running = true;
+ conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
- 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;
- }
+ 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) {
+
+ if (-1 < sd->chk_conflict_sd)
+ __close_channel_and_sock(sd);
+
+ if (sd->timer_id) {
g_source_remove(sd->timer_id);
- sd->timer_id = 0;
}
g_free(sd);
sd = NULL;
- is_ip_conflict_detect_enabled = false;
+ is_ip_conflict_detect_running = false;
conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN;
INFO("Monitoring stopped");
}
-static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac)
+static void __netconfig_wifi_notify_ip_conflict(const char *interface_name,
+ char *state, char *mac)
{
GVariantBuilder *builder = NULL;
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));
+ wifi_emit_ip_conflict_event((Wifi *)get_wifi_object(),
+ interface_name, g_variant_builder_end(builder));
g_variant_builder_unref(builder);
/* send notification using net-popup */
}
gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context,
- bool detect)
+ const gchar *ifname, bool detect)
{
g_return_val_if_fail(wifi != NULL, TRUE);
-
if (detect == false) {
- if (sd != NULL)
+ if (is_ip_conflict_detect_enabled == true) {
stop_ip_conflict_mon();
- else {
+ is_ip_conflict_detect_enabled = false;
+ } else {
netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
- wifi_complete_ip_conflict_set_enable(wifi, context);
return TRUE;
}
} else {
- 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 TRUE;
+ if (is_ip_conflict_detect_enabled == false) {
+ is_ip_conflict_detect_enabled = true;
+ const char *def_profile = netconfig_get_default_profile();
+ if (netconfig_is_wifi_profile(def_profile) ||
+ netconfig_is_ethernet_profile(def_profile)) {
+ if (start_ip_conflict_mon() == NULL) {
+ INFO("Failed to start IP conflict monitoring");
+ netconfig_error_dbus_method_return(context,
+ NETCONFIG_ERROR_INTERNAL, "Failed");
+ return TRUE;
+ }
}
} else {
netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
- wifi_complete_ip_conflict_set_enable(wifi, context);
return TRUE;
}
}
return TRUE;
}
-gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context)
+gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context,
+ const gchar *ifname)
{
g_return_val_if_fail(wifi != NULL, TRUE);
GVariant *param = NULL;
return TRUE;
}
-gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context, guint initial_time)
+gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context,
+ const gchar *ifname, guint initial_time)
{
g_return_val_if_fail(wifi != NULL, TRUE);
- if (initial_time < MAX_ARP_SEND_TIME && initial_time > MIN_ARP_SEND_TIME) {
+ INFO("%d", initial_time);
+ 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;
return TRUE;
}
-gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context)
+gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context,
+ const gchar *ifname)
{
g_return_val_if_fail(wifi != NULL, TRUE);
GVariant *param = NULL;
return TRUE;
}
-gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context)
+gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context,
+ const gchar *ifname)
{
g_return_val_if_fail(wifi != NULL, TRUE);
GVariant *param = NULL;