Change default period of ARP probe to 20 seconds
[platform/core/connectivity/net-config.git] / src / ip-conflict-detect.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <stdio.h>
21 #include <net/if.h>
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>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <errno.h>
32 #include <glib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <stdbool.h>
36
37 #include "ip-conflict-detect.h"
38 #include "network-state.h"
39 #include "log.h"
40 #include "neterror.h"
41
42 #define ARP_PACKET_SIZE 60
43 #define MAX_SIZE_ERROR_BUFFER 256
44 #define IP_ADDRESS_LENGTH 4
45 #define MAC_ADDRESS_LENGTH 6
46 #define WLAN_MAC_ADDR_MAX 20
47 #define ARP_SOURCE_IP "0.0.0.0"
48 #define INITIAL_BURST_ARP_COUNT 5
49
50 #define CONFLICT_REMOVE_ITERATION_LIMIT 4
51 #define MIN_ARP_SEND_TIME 20000
52 #define BURST_ARP_SEND_TIME 3000
53 #define MAX_ARP_SEND_TIME 32000
54 #define GRATUITOUS_ARP_MAC_ADDR "00:00:00:00:00:00"
55 #define UCHAR_TO_ADDRESS(hwaddr, buf) do {\
56                 snprintf(buf, WLAN_MAC_ADDR_MAX,\
57                 "%02X:%02X:%02X:%02X:%02X:%02X", hwaddr[0], hwaddr[1],\
58                 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);\
59                 } while (0)
60
61 struct arp_message {
62         /* Ethernet header */
63         unsigned char   h_dest[MAC_ADDRESS_LENGTH];     /* destination ether addr */
64         unsigned char   h_source[MAC_ADDRESS_LENGTH];   /* source ether addr */
65         unsigned short  h_proto;                                /* packet type ID field */
66
67         /* ARP packet */
68         unsigned short hw_type;                         /* hardware type(ARPHRD_ETHER) */
69         unsigned short p_type;                          /* protocol type(ETH_P_IP) */
70         unsigned char  hw_len;                          /* hardware address length */
71         unsigned char  p_len;                                   /* protocol address length */
72         unsigned short operation;                               /* ARP opcode */
73         unsigned char  s_hwaddr[MAC_ADDRESS_LENGTH];            /* sender hardware address */
74         unsigned char  s_IPaddr[IP_ADDRESS_LENGTH];             /* sender IP address */
75         unsigned char  t_hwaddr[MAC_ADDRESS_LENGTH];            /* target hardware address */
76         unsigned char  t_IPaddr[IP_ADDRESS_LENGTH];             /* target IP address */
77         unsigned char  pad[18];                         /* pad for min. Ethernet payload (60 bytes) */
78 };
79
80 typedef enum {
81         NETCONFIG_IP_CONFLICT_STATE_UNKNOWN,
82         NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED,
83         NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED
84 } ip_conflict_state_e;
85
86 struct timer_data {
87         guint initial_time;
88         guint timeout;
89 };
90 static struct timer_data td = {
91         MIN_ARP_SEND_TIME, MIN_ARP_SEND_TIME
92 };
93
94 int ioctl_sock;
95 static bool initial_bursts = true;
96 bool is_ip_conflict_detect_enabled = true;
97 static gboolean send_arp(gpointer data);
98 static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac);
99 ip_conflict_state_e conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
100
101 struct sock_data *sd;
102
103 typedef unsigned int in_addr_t;
104
105 union uchar_to_uint {
106         unsigned int uint;
107         unsigned char uchar[IP_ADDRESS_LENGTH];
108 };
109
110 static unsigned int __convert_uchar_to_uint(unsigned char b[IP_ADDRESS_LENGTH])
111 {
112         int idx = 0;
113         union uchar_to_uint u;
114         for (; idx < IP_ADDRESS_LENGTH; ++idx)
115                 u.uchar[idx] = b[idx];
116
117         return u.uint;
118 }
119
120 static gboolean __arp_reply_timeout_cb(gpointer data)
121 {
122         if (sd == NULL) {
123                 INFO("Ignore timeout cb");
124                 return G_SOURCE_REMOVE;
125         }
126
127         sd->iteration++;
128         sd->arp_reply_timer = -1;
129         if (sd->timer_id != -1)
130                 g_source_remove(sd->timer_id);
131
132         if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED &&
133                         sd->iteration == CONFLICT_REMOVE_ITERATION_LIMIT) {
134                 sd->iteration = 0;
135                 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
136                 __netconfig_wifi_notify_ip_conflict("resolved", GRATUITOUS_ARP_MAC_ADDR);
137                 initial_bursts = true;
138         }
139
140         sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
141         return G_SOURCE_REMOVE;
142 }
143
144 static gboolean __netconfig_check_arp_receive(GIOChannel *source,
145                                                   GIOCondition condition, gpointer data)
146 {
147         struct sock_data *sd = data;
148         gchar buffer[ARP_PACKET_SIZE] = {0, };
149         gsize bytes_read = 0;
150         struct arp_message arp_recv;
151         char sbuf[WLAN_MAC_ADDR_MAX];
152         char tbuf[WLAN_MAC_ADDR_MAX];
153         const char *default_ip = NULL;
154
155         if (g_io_channel_read_chars(source, buffer, ARP_PACKET_SIZE,
156                                 &bytes_read, NULL) == G_IO_STATUS_NORMAL) {
157                 unsigned int target_ip = 0;
158
159                 memset(&arp_recv, 0, sizeof(arp_recv));
160                 memcpy(&arp_recv, buffer, sizeof(buffer));
161
162                 default_ip = netconfig_get_default_ipaddress();
163                 if (default_ip == NULL) {
164                         INFO("ip address is not set yet");
165                         goto out;
166                 }
167                 target_ip = inet_addr(default_ip);
168
169
170                 /* Only handle ARP replies */
171                 if (arp_recv.operation != htons(ARPOP_REPLY))
172                         goto out;
173
174                 UCHAR_TO_ADDRESS(arp_recv.t_hwaddr, tbuf);
175                 UCHAR_TO_ADDRESS(arp_recv.s_hwaddr, sbuf);
176
177                 int zero_mac = strcmp(tbuf , GRATUITOUS_ARP_MAC_ADDR);
178                 if (zero_mac == 0) {
179                         DBG("Broadcast packet.\n");
180                         goto skip;
181                 }
182                 DBG("our mac= %s source mac= %s target mac= %s", netconfig_get_default_mac_address(), sbuf, tbuf);
183                 int mac_cmp = strcmp(tbuf , netconfig_get_default_mac_address());
184                 if (mac_cmp != 0) {
185                         INFO("Packet not intended to us.\n");
186                         goto out;
187                 }
188 skip:
189                 mac_cmp = strcmp(sbuf, netconfig_get_default_mac_address());
190                 DBG("target ip = %d source ip = %d", target_ip, __convert_uchar_to_uint(arp_recv.s_IPaddr));
191                 if ((mac_cmp != 0) && (__convert_uchar_to_uint(arp_recv.s_IPaddr) == target_ip)) {
192                         sd->iteration = 0;
193                         if (conflict_state != NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED) {
194                                 INFO("ip conflict is detected !\n");
195                                 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED;
196                                 __netconfig_wifi_notify_ip_conflict("conflict", sbuf);
197                                 sd->timeout = BURST_ARP_SEND_TIME;
198                         }
199
200                         if (sd->arp_reply_timer != -1) {
201                                 g_source_remove(sd->arp_reply_timer);
202                                 sd->arp_reply_timer = -1;
203                         }
204
205                         if (sd->timer_id)
206                                 g_source_remove(sd->timer_id);
207                         sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
208
209                 }
210         }
211
212 out:
213         return TRUE;
214 }
215
216 static gboolean send_arp(gpointer data)
217 {
218         struct sock_data *sd = data;
219         struct ether_addr *source_mac = NULL;
220         struct arp_message arp;
221         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
222         unsigned int source_ip = 0;
223         unsigned int target_ip = 0;
224         const unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
225         struct sockaddr_ll addr = {0};
226         struct ifreq net_ifr;
227         int ifindex = 0;
228         errno = 0;
229         const char *default_ip = NULL;
230         static int initial_send_arp_count = 0;
231
232         if (initial_bursts && initial_send_arp_count >= INITIAL_BURST_ARP_COUNT) {
233                 initial_bursts = false;
234                 initial_send_arp_count = 0;
235         }
236
237         if (initial_bursts)
238                 initial_send_arp_count++;
239
240         const char *mac = netconfig_get_default_mac_address();
241         if (mac == NULL)
242                 goto err;
243         source_mac = ether_aton(mac);
244         if (source_mac == NULL) {
245                 INFO("Mac address is NULL");
246                 goto err;
247         }
248
249         memset(&arp, 0, sizeof(arp));
250
251         unsigned char  broadcast_mac_addr[MAC_ADDRESS_LENGTH];
252         memset(broadcast_mac_addr, 0xff, sizeof(broadcast_mac_addr));
253         memcpy(arp.h_dest, broadcast_mac_addr, MAC_ADDRESS_LENGTH);             /* MAC dest */
254         memcpy(arp.h_source, source_mac, MAC_ADDRESS_LENGTH);                   /* MAC source */
255
256         arp.h_proto = htons(ETH_P_ARP);                                         /* protocol type (Ethernet) */
257         arp.hw_type = htons(ARPHRD_ETHER);                                      /* hardware type */
258         arp.p_type = htons(ETH_P_IP);                                           /* protocol type (ARP message) */
259         arp.hw_len = MAC_ADDRESS_LENGTH;                                        /* hardware address length */
260         arp.p_len = IP_ADDRESS_LENGTH;                                          /* protocol address length */
261         arp.operation = htons(ARPOP_REQUEST);                                   /* ARP op code */
262         default_ip = netconfig_get_default_ipaddress();
263         if (default_ip == NULL) {
264                 INFO("ip address is not set yet");
265                 goto err;
266         }
267
268         source_ip = inet_addr(ARP_SOURCE_IP);
269         target_ip = inet_addr(default_ip);
270         memcpy(arp.s_IPaddr, &source_ip, IP_ADDRESS_LENGTH);                    /* source IP address */
271         memcpy(arp.s_hwaddr, source_mac, MAC_ADDRESS_LENGTH);                   /* source hardware address */
272         memcpy(arp.t_IPaddr, &target_ip, IP_ADDRESS_LENGTH);                    /* target IP addressshek" */
273
274         memset(&net_ifr, 0, sizeof(net_ifr));
275         /* ifreq structure creation */
276         size_t if_name_len = strlen(netconfig_get_default_ifname());
277         if (if_name_len < sizeof(net_ifr.ifr_name)) {
278                 memcpy(net_ifr.ifr_name, netconfig_get_default_ifname(), if_name_len);
279                 net_ifr.ifr_name[if_name_len] = 0;
280         } else {
281                 INFO("Error : Interface name is too long");
282                 goto err;
283         }
284
285         if (ioctl(sd->chk_conflict_sd, SIOCGIFINDEX, &net_ifr) == -1) {
286                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
287                 INFO("ioctl Failed. Error..... = %s\n", error_buf);
288                 goto err;
289         }
290
291         ifindex = net_ifr.ifr_ifindex;
292         /* Construct the destination address */
293         addr.sll_family = AF_PACKET;
294         addr.sll_ifindex = ifindex;
295         addr.sll_halen = ETHER_ADDR_LEN;
296         addr.sll_protocol = htons(ETH_P_ARP);
297         memcpy(addr.sll_addr, broadcast_addr, ETHER_ADDR_LEN);
298
299         if (sendto(sd->chk_conflict_sd, &arp, sizeof(arp), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
300                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
301                 INFO("Sending ARP Packet Failed. Error. = %s\n", error_buf);
302                 /* close socket */
303                 if (-1 < sd->chk_conflict_sd) {
304                         close(sd->chk_conflict_sd);
305                         sd->chk_conflict_sd = -1;
306                 }
307
308                 /* reopen socket */
309                 if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) {
310                         INFO("socket %d", sd->chk_conflict_sd);
311                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
312                         INFO("socket Failed. Error = %s\n", error_buf);
313                 }
314                 goto err;
315         } else {
316                 DBG("Sent ARP Packet \n");
317         }
318
319         g_source_remove(sd->timer_id);
320
321         if (conflict_state == NETCONFIG_IP_CONFLICT_STATE_CONFLICT_DETECTED || initial_bursts)
322                 sd->timeout = BURST_ARP_SEND_TIME;
323         else
324                 sd->timeout = td.initial_time;
325
326         /* Adding timeout callback for arp request */
327         sd->arp_reply_timer = g_timeout_add(1000, __arp_reply_timeout_cb,
328                                         (gpointer) &sd->arp_reply_timer);
329         return FALSE;
330 err:
331         if (sd->timer_id)
332                 g_source_remove(sd->timer_id);
333         sd->timer_id = g_timeout_add(sd->timeout, send_arp, sd);
334         return FALSE;
335 }
336
337 struct sock_data * start_ip_conflict_mon(void)
338 {
339         if (is_ip_conflict_detect_enabled == false) {
340                 INFO("detection mode is set to false");
341                 return NULL;
342         }
343
344         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
345         initial_bursts = true;
346
347         sd = g_try_malloc0(sizeof(struct sock_data));
348         if (sd == NULL) {
349                 INFO("Failed to malloc sock_data");
350                 return NULL;
351         }
352         sd->chk_conflict_data_id = -1;
353         sd->chk_conflict_sd = -1;
354         sd->timer_id = 0;
355         sd->iteration = 0;
356
357         if ((sd->chk_conflict_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1) {
358                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
359                 INFO("socket Failed. Error = %s\n", error_buf);
360                 g_free(sd);
361                 return NULL;
362         } else {
363                 sd->chk_conflict_sock_io = g_io_channel_unix_new(sd->chk_conflict_sd);
364                 if (sd->chk_conflict_sock_io == NULL) {
365                         INFO("Failed to create channel");
366                         INFO("Exit");
367                         g_free(sd);
368                         return NULL;
369                 }
370
371                 g_io_channel_set_close_on_unref(sd->chk_conflict_sock_io, TRUE);
372
373                 if (G_IO_STATUS_NORMAL != g_io_channel_set_encoding(sd->chk_conflict_sock_io,
374                                                                    NULL, NULL))
375                         INFO("Failed to set encoding NULL on io channel");
376                 if (G_IO_STATUS_NORMAL != g_io_channel_set_flags(sd->chk_conflict_sock_io,
377                                                                 G_IO_FLAG_NONBLOCK, NULL))
378                         INFO("Failed to set flags on io channel");
379                 sd->chk_conflict_data_id = g_io_add_watch(sd->chk_conflict_sock_io, G_IO_IN,
380                                                           __netconfig_check_arp_receive, sd);
381                 DBG("socket %d", sd->chk_conflict_sd);
382
383                 sd->timeout = td.initial_time;
384                 send_arp(sd);
385                 return sd;
386         }
387 }
388
389 void stop_ip_conflict_mon()
390 {
391         INFO("+");
392         GError* error = NULL;
393         if (sd == NULL) {
394                 INFO("sd is NULL");
395                 return;
396         }
397         if (-1 < sd->chk_conflict_sd) {
398                 if (G_IO_STATUS_NORMAL !=
399                     g_io_channel_shutdown(sd->chk_conflict_sock_io, FALSE,
400                                           &error)) {
401                         INFO("Failure received while shutdown io channel[%d]:[%s]", error->code, error->message);
402                         g_error_free(error);
403                 }
404                 g_io_channel_unref(sd->chk_conflict_sock_io);
405                 g_source_remove(sd->chk_conflict_data_id);
406                 sd->chk_conflict_data_id = -1;
407                 close(sd->chk_conflict_sd);
408                 sd->chk_conflict_sd = -1;
409         }
410         if (sd->timer_id > 0) {
411                 g_source_remove(sd->timer_id);
412                 sd->timer_id = 0;
413         }
414         g_free(sd);
415         sd = NULL;
416         INFO("Monitoring stopped");
417 }
418
419 static void __netconfig_wifi_notify_ip_conflict(char *state, char *mac)
420 {
421         GVariantBuilder *builder = NULL;
422
423         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
424         g_variant_builder_add(builder, "{sv}", "state", g_variant_new_string(state));
425         g_variant_builder_add(builder, "{sv}", "mac", g_variant_new_string(mac));
426
427         wifi_emit_ip_conflict_event((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
428         g_variant_builder_unref(builder);
429
430         return;
431 }
432
433 gboolean handle_ip_conflict_set_enable(Wifi *wifi, GDBusMethodInvocation *context,
434                                        bool detect)
435 {
436         g_return_val_if_fail(wifi != NULL, FALSE);
437
438
439         if (detect == false) {
440                 is_ip_conflict_detect_enabled = false;
441                 conflict_state = NETCONFIG_IP_CONFLICT_STATE_UNKNOWN;
442                 if (sd != NULL)
443                         stop_ip_conflict_mon();
444                 else {
445                         netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
446                         wifi_complete_ip_conflict_set_enable(wifi, context);
447                         return FALSE;
448                 }
449         } else {
450                 is_ip_conflict_detect_enabled = true;
451                 conflict_state = NETCONFIG_IP_CONFLICT_STATE_CONFLICT_NOT_DETECTED;
452                 if (sd == NULL) {
453                         if (start_ip_conflict_mon() == NULL) {
454                                 INFO("Failed to start IP conflict monitoring");
455                                 netconfig_error_dbus_method_return(context,
456                                                 NETCONFIG_ERROR_INTERNAL, "Failed");
457                                 wifi_complete_ip_conflict_set_enable(wifi, context);
458                                 return FALSE;
459                         }
460                 } else {
461                         netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AlreadyExists");
462                         wifi_complete_ip_conflict_set_enable(wifi, context);
463                         return FALSE;
464                 }
465         }
466
467         wifi_complete_ip_conflict_set_enable(wifi, context);
468         return TRUE;
469 }
470
471 gboolean handle_is_ip_conflict_detect_enabled(Wifi *wifi, GDBusMethodInvocation *context)
472 {
473         g_return_val_if_fail(wifi != NULL, FALSE);
474         GVariant *param = NULL;
475         param = g_variant_new("(b)", is_ip_conflict_detect_enabled);
476         g_dbus_method_invocation_return_value(context, param);
477         return TRUE;
478 }
479
480 gboolean handle_set_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context, guint initial_time)
481 {
482         g_return_val_if_fail(wifi != NULL, FALSE);
483         if (initial_time < MAX_ARP_SEND_TIME && initial_time > MIN_ARP_SEND_TIME)
484                 return FALSE;
485
486         td.initial_time = 1000 * initial_time;
487         // remove timer
488         stop_ip_conflict_mon();
489         start_ip_conflict_mon();
490         wifi_complete_set_ip_conflict_period(wifi, context);
491         return TRUE;
492 }
493
494 gboolean handle_get_ip_conflict_state(Wifi *wifi, GDBusMethodInvocation *context)
495 {
496         g_return_val_if_fail(wifi != NULL, FALSE);
497         GVariant *param = NULL;
498         param = g_variant_new("(u)", conflict_state);
499         g_dbus_method_invocation_return_value(context, param);
500         return TRUE;
501 }
502
503 gboolean handle_get_ip_conflict_period(Wifi *wifi, GDBusMethodInvocation *context)
504 {
505         g_return_val_if_fail(wifi != NULL, FALSE);
506         GVariant *param = NULL;
507         param = g_variant_new("(u)", td.initial_time/1000);
508         g_dbus_method_invocation_return_value(context, param);
509         return TRUE;
510 }