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