2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <linux/if_packet.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <arpa/inet.h>
26 #include <netinet/ether.h>
27 #include <net/ethernet.h>
28 #include <netinet/in.h>
37 #include "ip-conflict-detect.h"
38 #include "network-state.h"
43 #define ARP_PACKET_SIZE 60
44 #define MAX_SIZE_ERROR_BUFFER 256
45 #define IP_ADDRESS_LENGTH 4
46 #define MAC_ADDRESS_LENGTH 6
47 #define WLAN_MAC_ADDR_MAX 20
48 #define ARP_SOURCE_IP "0.0.0.0"
49 #define INITIAL_BURST_ARP_COUNT 5
51 #define CONFLICT_REMOVE_ITERATION_LIMIT 4
52 #define MIN_ARP_SEND_TIME 20000
53 #define BURST_ARP_SEND_TIME 3000
54 #define MAX_ARP_SEND_TIME 32000
55 #define GRATUITOUS_ARP_MAC_ADDR "00:00:00:00:00:00"
56 #define UCHAR_TO_ADDRESS(hwaddr, buf) do {\
57 snprintf(buf, WLAN_MAC_ADDR_MAX,\
58 "%02X:%02X:%02X:%02X:%02X:%02X", hwaddr[0], hwaddr[1],\
59 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);\
64 unsigned short arp_hrd;
65 unsigned short arp_pro;
66 unsigned char arp_hln;
67 unsigned char arp_pln;
68 unsigned short arp_op;
69 unsigned char arp_sha[MAC_ADDRESS_LENGTH];
70 unsigned char arp_sip[IP_ADDRESS_LENGTH];
71 unsigned char arp_tha[MAC_ADDRESS_LENGTH];
72 unsigned char arp_tip[IP_ADDRESS_LENGTH];
76 NETCONFIG_IP_CONFLICT_STATE_UNKNOWN,
77 NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED,
78 NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED,
79 } ip_conflict_state_e;
85 static struct timer_data td = {
86 MIN_ARP_SEND_TIME, MIN_ARP_SEND_TIME
90 static bool initial_bursts = true;
91 bool is_ip_conflict_detect_enabled = false;
92 static gboolean send_arp(gpointer data);
93 static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac);
94 ip_conflict_state_e conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
98 typedef unsigned int in_addr_t;
100 union uchar_to_uint {
102 unsigned char uchar[IP_ADDRESS_LENGTH];
105 static unsigned int __convert_uchar_to_uint(unsigned char b[IP_ADDRESS_LENGTH])
108 union uchar_to_uint u;
109 for (; idx < IP_ADDRESS_LENGTH; ++idx)
110 u.uchar[idx] = b[idx];
115 static gboolean __arp_reply_timeout_cb(gpointer data)
118 INFO("Ignore timeout cb");
119 return G_SOURCE_REMOVE;
123 sd->arp_reply_timer = -1;
125 if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED &&
126 sd->iteration == CONFLICT_REMOVE_ITERATION_LIMIT) {
128 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
129 __netconfig_wifi_notify_ip_conflict("resolved", GRATUITOUS_ARP_MAC_ADDR);
130 initial_bursts = true;
133 if (sd->timer_id > 0)
134 g_source_remove(sd->timer_id);
135 sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
136 return G_SOURCE_REMOVE;
139 static gboolean __netconfig_check_arp_receive(GIOChannel *source,
140 GIOCondition condition, gpointer data)
142 struct sock_data *sd = data;
143 gchar buffer[ARP_PACKET_SIZE] = {0, };
144 gsize bytes_read = 0;
145 arp_message_s *arp_recv = NULL;
146 char sbuf[WLAN_MAC_ADDR_MAX];
147 char tbuf[WLAN_MAC_ADDR_MAX];
148 const char *default_ip = NULL;
151 if (g_io_channel_read_chars(source, buffer, ARP_PACKET_SIZE,
152 &bytes_read, NULL) == G_IO_STATUS_NORMAL) {
153 unsigned int target_ip = 0;
155 ptr = buffer + ETH_HLEN;
156 arp_recv = (arp_message_s *)ptr;
158 default_ip = netconfig_get_default_ipaddress();
159 if (default_ip == NULL) {
160 INFO("ip address is not set yet");
163 target_ip = inet_addr(default_ip);
166 /* Only handle ARP replies */
167 if (arp_recv->arp_op != htons(ARPOP_REPLY))
170 UCHAR_TO_ADDRESS(arp_recv->arp_tha, tbuf);
171 UCHAR_TO_ADDRESS(arp_recv->arp_sha, sbuf);
173 int zero_mac = strcmp(tbuf , GRATUITOUS_ARP_MAC_ADDR);
175 DBG("Broadcast packet.\n");
178 DBG("our mac= %s source mac= %s target mac= %s", netconfig_get_default_mac_address(), sbuf, tbuf);
179 int mac_cmp = strcmp(tbuf , netconfig_get_default_mac_address());
181 INFO("Packet not intended to us.\n");
185 mac_cmp = strcmp(sbuf, netconfig_get_default_mac_address());
186 DBG("target ip = %d source ip = %d", target_ip, __convert_uchar_to_uint(arp_recv->arp_sip));
187 if ((mac_cmp != 0) && (__convert_uchar_to_uint(arp_recv->arp_sip) == target_ip)) {
189 if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED) {
190 INFO("ip conflict is detected !\n");
191 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED;
192 __netconfig_wifi_notify_ip_conflict("conflict", sbuf);
193 sd->timeout = BURST_ARP_SEND_TIME;
196 if (sd->arp_reply_timer != -1) {
197 g_source_remove(sd->arp_reply_timer);
198 sd->arp_reply_timer = -1;
202 g_source_remove(sd->timer_id);
203 sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
211 static void __close_channel_and_sock(struct sock_data *sd)
216 g_io_channel_unref(sd->chk_conflict_sock_io);
217 g_source_remove(sd->chk_conflict_data_id);
218 sd->chk_conflict_data_id = -1;
220 close(sd->chk_conflict_sd);
221 sd->chk_conflict_sd = -1;
224 static int __open_channel_and_sock(struct sock_data *sd)
229 if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) {
230 INFO("socket Failed.\n");
234 sd->chk_conflict_sock_io = g_io_channel_unix_new(sd->chk_conflict_sd);
235 if (sd->chk_conflict_sock_io == NULL) {
236 INFO("Failed to create channel");
237 close(sd->chk_conflict_sd);
238 sd->chk_conflict_sd = -1;
242 if (G_IO_STATUS_NORMAL != g_io_channel_set_encoding(sd->chk_conflict_sock_io, NULL, NULL))
243 INFO("Failed to set encoding NULL on io channel");
245 if (G_IO_STATUS_NORMAL != g_io_channel_set_flags(sd->chk_conflict_sock_io,
246 G_IO_FLAG_NONBLOCK, NULL))
247 INFO("Failed to set flags on io channel");
249 sd->chk_conflict_data_id = g_io_add_watch(sd->chk_conflict_sock_io, G_IO_IN,
250 __netconfig_check_arp_receive, sd);
251 DBG("socket %d", sd->chk_conflict_sd);
255 static int __get_iface_info(int *ifindex, unsigned char *mac, unsigned char *ip)
257 struct ifreq net_ifr;
260 const char *default_mac = netconfig_get_default_mac_address();
261 if (default_mac == NULL) {
266 memcpy(mac, ether_aton(default_mac), MAC_ADDRESS_LENGTH);
268 ERR("ether_aton fail");
272 ip = netconfig_get_default_ipaddress();
274 ERR("ip address is not set yet");
278 memset(&net_ifr, 0, sizeof(net_ifr));
279 if_name = netconfig_get_default_ifname();
280 size_t if_name_len = strlen(if_name);
282 if (if_name_len == 0) {
283 ERR("Error : Unable to get interface name ");
287 if (if_name_len < sizeof(net_ifr.ifr_name)) {
288 memcpy(net_ifr.ifr_name, if_name, if_name_len);
289 net_ifr.ifr_name[if_name_len] = 0;
291 ERR("Error : Interface name is too long");
295 if (ioctl(sock, SIOCGIFINDEX, &net_ifr) == -1) {
296 INFO("ioctl Failed. Error..... = %s\n",
297 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
304 static void __init_ll_addr(struct sockaddr_ll *ll_addr, int ifindex, unsigned char *mac)
306 ll_addr->sll_family = AF_PACKET;
307 ll_addr->sll_protocol = htons(ETH_P_ARP);
308 ll_addr->sll_hatype = htons(ARPHRD_ETHER);
309 ll_addr->sll_pkttype = (PACKET_BROADCAST);
310 ll_addr->sll_halen = MAC_ADDRESS_LENGTH;
311 ll_addr->sll_addr[6] = 0x00;
312 ll_addr->sll_addr[7] = 0x00;
313 ll_addr->sll_ifindex = ifindex;
314 memcpy(ll_addr->sll_addr, mac, MAC_ADDRESS_LENGTH);
317 static void __set_defend_arp_ethhdr(unsigned char *hw_addr, struct ethhdr *eh)
319 memset(eh->h_dest, 0xff, MAC_ADDRESS_LENGTH);
320 memcpy(eh->h_source, hw_addr, MAC_ADDRESS_LENGTH);
321 eh->h_proto = htons(ETH_P_ARP);
325 static void __set_defend_arp(unsigned char *hw_addr, unsigned char *ip_addr, arp_message_s *ah)
327 ah->arp_hrd = htons(ARPHRD_ETHER);
328 ah->arp_pro = htons(ETH_P_IP);
329 ah->arp_hln = ETH_ALEN;
331 ah->arp_op = htons(ARPOP_REQUEST);
333 memcpy(ah->arp_sha, hw_addr, ETH_ALEN);
334 /* by RFC 5227 2.1.1. Probe Details,
335 'sender IP address' field MUST be set to all zeroes;
336 this is to avoid polluting ARP caches in other hosts
337 on the same link in the case where the address turns
338 out to be already in use by another host. */
340 memset(ah->arp_sip, 0x00, 4);
341 //memcpy(ah->arp_sip, ip_conflict_mons.ipaddr, 4);
343 memset(ah->arp_tha, 0x00, ETH_ALEN);
345 memcpy(ah->arp_tip, ip_addr, 4);
349 static gboolean send_arp(gpointer data)
351 struct sock_data *sd = data;
352 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
353 unsigned int source_ip = 0;
354 unsigned int target_ip = 0;
355 struct sockaddr_ll addr = {0};
358 const char *default_ip = NULL;
359 static int initial_send_arp_count = 0;
360 unsigned char buf[60] = {0, };
361 unsigned char *pos = NULL;
363 if (initial_bursts && initial_send_arp_count >= INITIAL_BURST_ARP_COUNT) {
364 initial_bursts = false;
365 initial_send_arp_count = 0;
369 initial_send_arp_count++;
371 if (__get_iface_info(&ifindex, mac, ip) == -1) {
372 ERR("__get_iface_info fail");
377 __set_defend_arp_ethhdr(source_mac, (struct ethhdr *)pos);
380 __set_defend_arp(source_mac, default_ip, (arp_message_s *)pos);
382 __init_ll_addr(&addr, ifindex, mac);
384 if (sendto(sd->chk_conflict_sd, buf, 42, 0,
385 (struct sockaddr*)&addr, sizeof(struct sockaddr_ll)) < 0) {
386 ERR("Sending ARP Packet Failed. Error. = %s\n",
387 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
388 __close_channel_and_sock(sd);
389 if (__open_channel_and_sock(sd) == -1)
390 INFO("__open_channel_and_sock failed");
393 DBG("Sent ARP Packet \n");
396 g_source_remove(sd->timer_id);
399 if (conflict_state == NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED || initial_bursts)
400 sd->timeout = BURST_ARP_SEND_TIME;
402 sd->timeout = td.initial_time;
404 /* Adding timeout callback for arp request */
405 sd->arp_reply_timer = g_timeout_add(1000, __arp_reply_timeout_cb,
406 (gpointer) &sd->arp_reply_timer);
410 g_source_remove(sd->timer_id);
411 sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
415 struct sock_data * start_ip_conflict_mon(void)
417 if (is_ip_conflict_detect_enabled == true) {
418 INFO("detection mode is set to true");
422 initial_bursts = true;
424 sd = g_try_malloc0(sizeof(struct sock_data));
426 INFO("Failed to malloc sock_data");
429 sd->chk_conflict_data_id = -1;
430 sd->chk_conflict_sd = -1;
434 if (__open_channel_and_sock(sd) == -1) {
435 INFO("__open_channel_and_sock failed");
440 sd->timeout = td.initial_time;
442 is_ip_conflict_detect_enabled = true;
443 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
448 void stop_ip_conflict_mon()
456 if (-1 < sd->chk_conflict_sd)
457 __close_channel_and_sock(sd);
459 if (sd->timer_id > 0) {
460 g_source_remove(sd->timer_id);
465 is_ip_conflict_detect_enabled = false;
466 conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN;
467 INFO("Monitoring stopped");
470 static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac)
472 GVariantBuilder *builder = NULL;
474 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
475 g_variant_builder_add(builder, "{sv}", "state", g_variant_new_string(state));
476 g_variant_builder_add(builder, "{sv}", "mac", g_variant_new_string(mac));
478 wifi_emit_ip_conflict_event((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
479 g_variant_builder_unref(builder);
481 /* send notification using net-popup */
482 if (!strcmp(state, "conflict"))
483 netconfig_send_notification_to_net_popup(NETCONFIG_ADD_IP_CONFLICT_NOTI, mac);
485 netconfig_send_notification_to_net_popup(NETCONFIG_DEL_IP_CONFLICT_NOTI, mac);
490 gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context,
493 g_return_val_if_fail(wifi != NULL, TRUE);
495 if (detect == false) {
497 stop_ip_conflict_mon();
499 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
500 wifi_complete_ip_conflict_set_enable(wifi, context);
505 if (start_ip_conflict_mon() == NULL) {
506 INFO("Failed to start IP conflict monitoring");
507 netconfig_error_dbus_method_return(context,
508 NETCONFIG_ERROR_INTERNAL, "Failed");
509 wifi_complete_ip_conflict_set_enable(wifi, context);
513 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
514 wifi_complete_ip_conflict_set_enable(wifi, context);
519 wifi_complete_ip_conflict_set_enable(wifi, context);
523 gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context)
525 g_return_val_if_fail(wifi != NULL, TRUE);
526 GVariant *param = NULL;
527 param = g_variant_new("(b)", is_ip_conflict_detect_enabled);
528 g_dbus_method_invocation_return_value(context, param);
532 gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context, guint initial_time)
534 g_return_val_if_fail(wifi != NULL, TRUE);
535 INFO("%d", initial_time);
536 if (initial_time > MAX_ARP_SEND_TIME || initial_time < MIN_ARP_SEND_TIME) {
537 netconfig_error_dbus_method_return(context,
538 NETCONFIG_ERROR_INTERNAL, "Failed");
542 td.initial_time = 1000 * initial_time;
544 stop_ip_conflict_mon();
545 start_ip_conflict_mon();
546 wifi_complete_set_ip_conflict_period(wifi, context);
550 gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context)
552 g_return_val_if_fail(wifi != NULL, TRUE);
553 GVariant *param = NULL;
554 param = g_variant_new("(u)", conflict_state);
555 g_dbus_method_invocation_return_value(context, param);
559 gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context)
561 g_return_val_if_fail(wifi != NULL, TRUE);
562 GVariant *param = NULL;
563 param = g_variant_new("(u)", td.initial_time/1000);
564 g_dbus_method_invocation_return_value(context, param);