Sync with Tizen 2.4(v1.1.38)
[platform/core/connectivity/net-config.git] / src / network-state.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 <vconf.h>
21 #include <vconf-keys.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <aul.h>
26 #include <net/if.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
29 #include <sys/ioctl.h>
30 #include <ITapiSim.h>
31 #include <TapiUtility.h>
32
33 #include "log.h"
34 #include "util.h"
35 #include "netdbus.h"
36 #include "neterror.h"
37 #include "emulator.h"
38 #include "wifi-state.h"
39 #include "wifi-power.h"
40 #include "network-state.h"
41 #include "network-monitor.h"
42 #include "netsupplicant.h"
43 #include "wifi-tel-intf.h"
44 #include "clatd-handler.h"
45
46 #include "generated-code.h"
47 /* Define TCP buffer sizes for various networks */
48 /* ReadMin, ReadInitial, ReadMax */ /* WriteMin, WriteInitial, WriteMax */
49 #define NET_TCP_BUFFERSIZE_DEFAULT_READ         "4096 87380 704512"
50 #define NET_TCP_BUFFERSIZE_DEFAULT_WRITE        "4096 16384 110208"
51 #define NET_TCP_BUFFERSIZE_WIFI_READ            "524288 1048576 2560000"
52 #define NET_TCP_BUFFERSIZE_WIFI_WRITE           "524288 1048576 2560000"
53 #define NET_TCP_BUFFERSIZE_LTE_READ             "524288 1048576 2560000"
54 #define NET_TCP_BUFFERSIZE_LTE_WRITE            "524288 1048576 2560000"
55 #define NET_TCP_BUFFERSIZE_UMTS_READ            "4094 87380 704512"
56 #define NET_TCP_BUFFERSIZE_UMTS_WRITE           "4096 16384 110208"
57 #define NET_TCP_BUFFERSIZE_HSPA_READ            "4092 87380 704512"
58 #define NET_TCP_BUFFERSIZE_HSPA_WRITE           "4096 16384 262144"
59 #define NET_TCP_BUFFERSIZE_HSDPA_READ           "4092 87380 704512"
60 #define NET_TCP_BUFFERSIZE_HSDPA_WRITE          "4096 16384 262144"
61 #define NET_TCP_BUFFERSIZE_HSUPA_READ           "4092 87380 704512"
62 #define NET_TCP_BUFFERSIZE_HSUPA_WRITE          "4096 16384 262144"
63 #define NET_TCP_BUFFERSIZE_HSPAP_READ           "4092 87380 1220608"
64 #define NET_TCP_BUFFERSIZE_HSPAP_WRITE          "4096 16384 1220608"
65 #define NET_TCP_BUFFERSIZE_EDGE_READ            "4093 26280 35040"
66 #define NET_TCP_BUFFERSIZE_EDGE_WRITE           "4096 16384 35040"
67 #define NET_TCP_BUFFERSIZE_GPRS_READ            "4096 30000 30000"
68 #define NET_TCP_BUFFERSIZE_GPRS_WRITE           "4096 8760 11680"
69
70 #define NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX        "1048576"
71 #define NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX        "2097152"
72 #define NET_TCP_BUFFERSIZE_LTE_RMEM_MAX         "5242880"
73
74 #define NET_TCP_BUFFERSIZE_WIFID_WMEM_MAX       "2097152"
75
76 #define NET_PROC_SYS_NET_IPV4_TCP_RMEM          "/proc/sys/net/ipv4/tcp_rmem"
77 #define NET_PROC_SYS_NET_IPv4_TCP_WMEM          "/proc/sys/net/ipv4/tcp_wmem"
78 #define NET_PROC_SYS_NET_CORE_RMEM_MAX          "/proc/sys/net/core/rmem_max"
79 #define NET_PROC_SYS_NET_CORE_WMEM_MAX          "/proc/sys/net/core/wmem_max"
80
81 #define ROUTE_EXEC_PATH                                         "/sbin/route"
82
83 static Network *netconfigstate = NULL;
84
85 struct netconfig_default_connection {
86         char *profile;
87         char *ifname;
88         char *ipaddress;
89         char *ipaddress6;
90         char *proxy;
91         char *essid;
92         unsigned int freq;
93 };
94
95 static struct netconfig_default_connection
96                                 netconfig_default_connection_info = { NULL, };
97
98 gboolean netconfig_iface_network_state_ethernet_cable_state(gint32 *state);
99
100 static gboolean __netconfig_is_connected(GVariantIter *array)
101 {
102         gboolean is_connected = FALSE;
103         GVariant *variant = NULL;
104         gchar *key = NULL;
105         const gchar *value = NULL;
106
107         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
108                 if (g_strcmp0(key, "State") != 0) {
109                         continue;
110                 }
111
112                 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
113                         value = g_variant_get_string(variant, NULL);
114                         if (g_strcmp0(value, "ready") == 0 || g_strcmp0(value, "online") == 0)
115                                 is_connected = TRUE;
116                 }
117
118                 g_free(key);
119                 g_variant_unref(variant);
120                 break;
121         }
122
123         return is_connected;
124 }
125
126 static char *__netconfig_get_default_profile(void)
127 {
128         GVariant *message = NULL;
129         GVariantIter *iter;
130         GVariantIter *next;
131         gchar *default_profile = NULL;
132         gchar *object_path;
133
134         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
135                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
136                         "GetServices", NULL);
137         if (message == NULL) {
138                 ERR("Failed to get profiles");
139                 return NULL;
140         }
141
142         g_variant_get(message, "(a(oa{sv}))", &iter);
143         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
144                 if (object_path == NULL) {
145                         continue;
146                 }
147
148                 if(netconfig_is_cellular_profile(object_path) && !netconfig_is_cellular_internet_profile(object_path)){
149                         continue;
150                 }
151
152                 if (__netconfig_is_connected(next) == TRUE) {
153                         default_profile = g_strdup(object_path);
154                         g_free(object_path);
155                         g_variant_iter_free(next);
156                         break;
157                 }
158         }
159         g_variant_iter_free(iter);
160         g_variant_unref(message);
161
162         return default_profile;
163 }
164
165 static void __netconfig_get_default_connection_info(const char *profile)
166 {
167         GVariant *message = NULL, *variant = NULL, *variant2 = NULL;
168         GVariantIter *iter = NULL, *iter1 = NULL;
169         GVariant *next = NULL;
170         gchar *key = NULL;
171         gchar *key1 = NULL;
172         gchar *key2 = NULL;
173
174         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, profile,
175                         CONNMAN_SERVICE_INTERFACE, "GetProperties", NULL);
176         if (message == NULL) {
177                 ERR("Failed to get service properties");
178                 goto done;
179         }
180
181         g_variant_get(message, "(a{sv})", &iter);
182         while (g_variant_iter_loop(iter, "{sv}", &key, &next)) {
183                 const gchar *value = NULL;
184                 guint16 freq = 0;
185                 if (g_strcmp0(key, "Name") == 0 &&
186                                 netconfig_is_wifi_profile(profile) == TRUE) {
187                         if (g_variant_is_of_type(next, G_VARIANT_TYPE_STRING)) {
188                                 value = g_variant_get_string(next, NULL);
189
190                                 netconfig_default_connection_info.essid = g_strdup(value);
191                         }
192                 } else if (g_strcmp0(key, "Ethernet") == 0) {
193                         g_variant_get(next, "a{sv}", &iter1);
194                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
195                                 if (g_strcmp0(key1, "Interface") == 0) {
196                                         value = g_variant_get_string(variant, NULL);
197                                         netconfig_default_connection_info.ifname = g_strdup(value);
198                                 }
199                         }
200                 } else if (g_strcmp0(key, "IPv4") == 0) {
201                         g_variant_get(next, "a{sv}", &iter1);
202                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
203                                 if (g_strcmp0(key1, "Address") == 0) {
204                                         value = g_variant_get_string(variant, NULL);
205                                         netconfig_default_connection_info.ipaddress = g_strdup(value);
206                                 }
207                         }
208                 } else if (g_strcmp0(key, "IPv6") == 0) {
209                         g_variant_get(next, "a{sv}", &iter1);
210                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
211                                 if (g_strcmp0(key1, "Address") == 0) {
212                                         value = g_variant_get_string(variant, NULL);
213                                         netconfig_default_connection_info.ipaddress6 = g_strdup(value);
214                                 }
215                         }
216                 } else if (g_strcmp0(key, "Proxy") == 0) {
217                         g_variant_get(next, "a{sv}", &iter1);
218                         while (g_variant_iter_loop(iter1, "{sv}", &key2, &variant2)) {
219                                 GVariantIter *iter_sub = NULL;
220
221                                 if (g_strcmp0(key2, "Servers") == 0) {
222                                         if (!g_variant_is_of_type(variant2, G_VARIANT_TYPE_STRING_ARRAY)) {
223                                                 g_free(key2);
224                                                 g_variant_unref(variant2);
225                                                 break;
226                                         }
227
228                                         g_variant_get(variant2, "as", &iter_sub);
229                                         g_variant_iter_loop(iter_sub, "s", &value);
230                                         g_variant_iter_free(iter_sub);
231                                         if (value != NULL && (strlen(value) > 0))
232                                                 netconfig_default_connection_info.proxy = g_strdup(value);
233                                 } else if (g_strcmp0(key2, "Method") == 0) {
234                                         if (g_variant_is_of_type(variant2, G_VARIANT_TYPE_STRING)) {
235                                                 g_free(key2);
236                                                 g_variant_unref(variant2);
237                                                 break;
238                                         }
239
240                                         value = g_variant_get_string(variant2, NULL);
241                                         if (g_strcmp0(value, "direct") == 0) {
242                                                 g_free(netconfig_default_connection_info.proxy);
243                                                 netconfig_default_connection_info.proxy = NULL;
244
245                                                 g_free(key2);
246                                                 g_variant_unref(variant2);
247                                                 break;
248                                         }
249                                 }
250                         }
251                 } else if (g_strcmp0(key, "Frequency") == 0) {
252                         if (g_variant_is_of_type(next, G_VARIANT_TYPE_UINT16)) {
253                                 freq = g_variant_get_uint16(next);
254                                 netconfig_default_connection_info.freq = freq;
255                         }
256                 }
257         }
258
259 done:
260         if (message)
261                 g_variant_unref(message);
262
263         if (iter)
264                 g_variant_iter_free (iter);
265
266         if (iter1)
267                 g_variant_iter_free (iter1);
268
269         return;
270 }
271
272 static void __netconfig_adjust_tcp_buffer_size(void)
273 {
274         int fdr = 0, fdw = 0;
275         int fdrmax = 0, fdwmax = 0;
276         const char *rbuf_size = NULL;
277         const char *wbuf_size = NULL;
278         const char *rmax_size = NULL;
279         const char *wmax_size = NULL;
280         const char *profile = netconfig_get_default_profile();
281
282         if (profile == NULL) {
283                 DBG("There is no default connection");
284
285                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
286                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
287         } else if (netconfig_is_wifi_profile(profile) == TRUE) {
288                 DBG("Default connection: Wi-Fi");
289
290                 rbuf_size = NET_TCP_BUFFERSIZE_WIFI_READ;
291                 wbuf_size = NET_TCP_BUFFERSIZE_WIFI_WRITE;
292                 rmax_size = NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX;
293                 wmax_size = NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX;
294         } else if (netconfig_is_cellular_profile(profile) == TRUE) {
295                 TapiHandle *tapi_handle = NULL;
296                 int telephony_svctype = 0, telephony_pstype = 0;
297
298                 tapi_handle = (TapiHandle *)netconfig_tel_init();
299                 if (NULL != tapi_handle) {
300                         tel_get_property_int(tapi_handle,
301                                         TAPI_PROP_NETWORK_SERVICE_TYPE,
302                                         &telephony_svctype);
303                         tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_PS_TYPE,
304                                         &telephony_pstype);
305                         netconfig_tel_deinit();
306                 }
307
308                 DBG("Default cellular %d, %d", telephony_svctype, telephony_pstype);
309
310                 switch (telephony_pstype) {
311                 case VCONFKEY_TELEPHONY_PSTYPE_HSPA:
312                         rbuf_size = NET_TCP_BUFFERSIZE_HSPA_READ;
313                         wbuf_size = NET_TCP_BUFFERSIZE_HSPA_WRITE;
314                         break;
315                 case VCONFKEY_TELEPHONY_PSTYPE_HSUPA:
316                         rbuf_size = NET_TCP_BUFFERSIZE_HSUPA_READ;
317                         wbuf_size = NET_TCP_BUFFERSIZE_HSDPA_WRITE;
318                         break;
319                 case VCONFKEY_TELEPHONY_PSTYPE_HSDPA:
320                         rbuf_size = NET_TCP_BUFFERSIZE_HSDPA_READ;
321                         wbuf_size = NET_TCP_BUFFERSIZE_HSDPA_WRITE;
322                         break;
323 #if !defined TIZEN_WEARABLE
324                 case VCONFKEY_TELEPHONY_PSTYPE_HSPAP:
325                         rbuf_size = NET_TCP_BUFFERSIZE_HSPAP_READ;
326                         wbuf_size = NET_TCP_BUFFERSIZE_HSPAP_WRITE;
327                         break;
328 #endif
329                 default:
330                         switch (telephony_svctype) {
331                         case VCONFKEY_TELEPHONY_SVCTYPE_LTE:
332                                 rbuf_size = NET_TCP_BUFFERSIZE_LTE_READ;
333                                 wbuf_size = NET_TCP_BUFFERSIZE_LTE_WRITE;
334                                 rmax_size = NET_TCP_BUFFERSIZE_LTE_RMEM_MAX;
335                                 break;
336                         case VCONFKEY_TELEPHONY_SVCTYPE_3G:
337                                 rbuf_size = NET_TCP_BUFFERSIZE_UMTS_READ;
338                                 wbuf_size = NET_TCP_BUFFERSIZE_UMTS_WRITE;
339                                 break;
340                         case VCONFKEY_TELEPHONY_SVCTYPE_2_5G_EDGE:
341                                 rbuf_size = NET_TCP_BUFFERSIZE_EDGE_READ;
342                                 wbuf_size = NET_TCP_BUFFERSIZE_EDGE_WRITE;
343                                 break;
344                         case VCONFKEY_TELEPHONY_SVCTYPE_2_5G:
345                                 rbuf_size = NET_TCP_BUFFERSIZE_GPRS_READ;
346                                 wbuf_size = NET_TCP_BUFFERSIZE_GPRS_WRITE;
347                                 break;
348                         default:
349                                 /* TODO: Check LTE support */
350                                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
351                                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
352                                 break;
353                         }
354                         break;
355                 }
356         } else {
357                 DBG("Default TCP buffer configured");
358
359                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
360                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
361         }
362
363         if (rbuf_size != NULL) {
364                 fdr = open(NET_PROC_SYS_NET_IPV4_TCP_RMEM, O_RDWR | O_CLOEXEC);
365
366                 if (fdr < 0 || write(fdr, rbuf_size, strlen(rbuf_size)) < 0)
367                         ERR("Failed to set TCP read buffer size");
368
369                 if (fdr >= 0)
370                         close(fdr);
371         }
372
373         if (wbuf_size != NULL) {
374                 fdw = open(NET_PROC_SYS_NET_IPv4_TCP_WMEM, O_RDWR | O_CLOEXEC);
375
376                 if (fdw < 0 || write(fdw, wbuf_size, strlen(wbuf_size)) < 0)
377                         ERR("Failed to set TCP write buffer size");
378
379                 if (fdw >= 0)
380                         close(fdw);
381         }
382
383         /* As default */
384         if (rmax_size == NULL)
385                 rmax_size = NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX;
386         if (wmax_size == NULL)
387                 wmax_size = NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX;
388
389         if (rmax_size != NULL) {
390                 fdrmax = open(NET_PROC_SYS_NET_CORE_RMEM_MAX, O_RDWR | O_CLOEXEC);
391
392                 if (fdrmax < 0 || write(fdrmax, rmax_size, strlen(rmax_size)) < 0)
393                         ERR("Failed to set TCP rmem_max size");
394
395                 if (fdrmax >= 0)
396                         close(fdrmax);
397         }
398
399         if (wmax_size != NULL) {
400                 fdwmax = open(NET_PROC_SYS_NET_CORE_WMEM_MAX, O_RDWR | O_CLOEXEC);
401
402                 if (fdwmax < 0 || write(fdwmax, wmax_size, strlen(wmax_size)) < 0)
403                         ERR("Failed to set TCP wmem_max size");
404
405                 if (fdwmax >= 0)
406                         close(fdwmax);
407         }
408 }
409
410 static void __netconfig_update_default_connection_info(void)
411 {
412         int old_network_status = 0;
413         const char *profile = netconfig_get_default_profile();
414         const char *ip_addr = netconfig_get_default_ipaddress();
415         const char *ip_addr6 = netconfig_get_default_ipaddress6();
416         const char *proxy_addr = netconfig_get_default_proxy();
417         unsigned int freq = netconfig_get_default_frequency();
418
419         if (emulator_is_emulated() == TRUE)
420                 return;
421
422         if (profile == NULL)
423                 DBG("Reset network state configuration");
424         else
425                 DBG("%s: ip(%s) proxy(%s)", profile, ip_addr, proxy_addr);
426
427         vconf_get_int(VCONFKEY_NETWORK_STATUS, &old_network_status);
428
429         if (profile == NULL && old_network_status != VCONFKEY_NETWORK_OFF) {
430                 netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_OFF);
431
432                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "");
433                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, "");
434
435                 netconfig_set_vconf_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, 0);
436                 netconfig_set_vconf_int("memory/private/wifi/frequency", 0);
437
438                 DBG("Successfully clear IP and PROXY up");
439
440                 /* Disable clatd if it is in running state */
441                 netconfig_clatd_disable();
442         }
443         else if (profile != NULL) {
444                 char *old_ip = vconf_get_str(VCONFKEY_NETWORK_IP);
445                 char *old_proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY);
446
447                 if (netconfig_is_wifi_profile(profile) == TRUE) {
448                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_WIFI);
449                         netconfig_set_vconf_int("memory/private/wifi/frequency", freq);
450                 }
451                 else if (netconfig_is_cellular_profile(profile) ){
452
453                         if( !netconfig_is_cellular_internet_profile(profile)){
454                                 DBG("connection is not a internet profile - stop to update the cellular state");
455                                 return;
456                         }
457
458                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_CELLULAR);
459
460                         /* Enable clatd if IPv6 is set and no IPv4 address */
461                         if (!ip_addr && ip_addr6 )
462                                 netconfig_clatd_enable();
463                 }
464                 else if (netconfig_is_ethernet_profile(profile) == TRUE){
465                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_ETHERNET);
466                 }
467                 else if (netconfig_is_bluetooth_profile(profile) == TRUE){
468                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_BLUETOOTH);
469                 }
470                 else{
471                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_OFF);
472                 }
473
474                 if (g_strcmp0(old_ip, ip_addr) != 0 || old_ip == NULL) {
475                         if (ip_addr != NULL)
476                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr);
477                         else if (ip_addr6 != NULL)
478                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr6);
479                         else
480                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "");
481                 }
482                 g_free(old_ip);
483
484                 if (g_strcmp0(old_proxy, proxy_addr) != 0) {
485                         if (proxy_addr == NULL)
486                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, "");
487                         else
488                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, proxy_addr);
489                 }
490                 g_free(old_proxy);
491
492                 netconfig_set_vconf_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, 1);
493
494                 DBG("Successfully update default network configuration");
495
496                 /* Disable clatd if it is in running state */
497                 if (netconfig_is_cellular_profile(profile) != TRUE)
498                         netconfig_clatd_disable();
499         }
500
501         __netconfig_adjust_tcp_buffer_size();
502 }
503
504 static gboolean __netconfig_is_tech_state_connected(void)
505 {
506         gboolean ret = FALSE;
507         GVariant *message = NULL, *variant;
508         GVariantIter *iter, *next;
509         gchar *path;
510         gchar *key;
511
512         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
513                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
514                         "GetTechnologies", NULL);
515
516         if (message == NULL) {
517                 DBG("Fail to get technology state");
518                 return FALSE;
519         }
520
521         g_variant_get(message, "(a(oa{sv}))", &iter);
522         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
523                 if (path == NULL) {
524                         continue;
525                 }
526
527                 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
528                         gboolean data;
529                         if (g_strcmp0(key, "Connected") == 0) {
530                                 data = g_variant_get_boolean(variant);
531                                 DBG("%s [%s: %s]", path, key, data ? "True" : "False");
532                                 if (TRUE == data) {
533                                         ret = TRUE;
534                                         g_free(path);
535                                         g_free(key);
536                                         g_variant_unref(variant);
537                                         g_variant_iter_free(next);
538                                         goto done;
539                                 }
540                         }
541                 }
542         }
543
544 done:
545         g_variant_iter_free(iter);
546         g_variant_unref(message);
547
548         return ret;
549 }
550
551 static void __netconfig_update_if_service_connected(void)
552 {
553         GVariant *message = NULL, *var;
554         GVariantIter *iter, *next;
555         gchar *path;
556         gchar *key;
557
558         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
559                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
560                         "GetServices", NULL);
561
562         if (message == NULL) {
563                 ERR("Failed to get services");
564                 return;
565         }
566
567         g_variant_get(message, "(a(oa{sv}))", &iter);
568         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
569                 if (path == NULL) {
570                         continue;
571                 }
572
573                 if (g_str_has_prefix(path,
574                                                 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX) == TRUE) {
575                         if (g_strrstr(path + strlen(CONNMAN_WIFI_SERVICE_PROFILE_PREFIX),
576                                                         "hidden") != NULL) {
577                                 /* skip hidden profiles */
578                                 continue;
579                         }
580                         /* Process this */
581                 } else if (g_str_has_prefix(path,
582                                                 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX) == TRUE) {
583                         /* Process this */
584                 } else {
585                         continue;
586                 }
587
588                 while (g_variant_iter_loop(next, "{sv}", &key, &var)) {
589                         if (g_strcmp0(key, "State") == 0) {
590                                 const gchar *sdata = NULL;
591                                 sdata = g_variant_get_string(var, NULL);
592                                 DBG("%s [%s: %s]", path, key, sdata);
593
594                                 if (g_strcmp0(sdata, "online") == 0 || g_strcmp0(sdata, "ready") == 0) {
595
596                                         /* Found a connected WiFi / 3G service.
597                                          * Lets update the default profile info.
598                                          */
599                                         netconfig_update_default_profile((const gchar*)path);
600                                         g_free(key);
601                                         g_free(path);
602                                         g_variant_unref(var);
603                                         g_variant_iter_free(next);
604                                         goto done;
605                                 }
606                         }
607                 }
608         }
609 done:
610         g_variant_iter_free(iter);
611         g_variant_unref(message);
612
613         return;
614 }
615
616 static void __netconfig_network_notify_result(const char *sig_name, const char *key)
617 {
618         gboolean reply;
619         GVariantBuilder *builder = NULL;
620         GDBusConnection *connection = NULL;
621         GError *error = NULL;
622         const char *prop_key = "key";
623
624         INFO("[Signal] %s %s", sig_name, key);
625
626         connection = netdbus_get_connection();
627         if (connection == NULL) {
628                 ERR("Failed to get GDBus Connection");
629                 return;
630         }
631
632         builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
633         g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new("(s)", key));
634
635         reply = g_dbus_connection_emit_signal(connection,
636                         NULL,
637                         NETCONFIG_NETWORK_PATH,
638                         NETCONFIG_NETWORK_INTERFACE,
639                         sig_name,
640                         g_variant_builder_end(builder),
641                         &error);
642
643         if (builder)
644                 g_variant_builder_unref(builder);
645
646         if (reply != TRUE) {
647                 if (error != NULL) {
648                         ERR("Failed to send signal [%s]", error->message);
649                         g_error_free(error);
650                 }
651                 return;
652         }
653
654         INFO("Sent signal (%s), key (%s)", sig_name, key);
655         return;
656 }
657
658 const char *netconfig_get_default_profile(void)
659 {
660         return netconfig_default_connection_info.profile;
661 }
662
663 const char *netconfig_get_default_ifname(void)
664 {
665         return netconfig_default_connection_info.ifname;
666 }
667
668 const char *netconfig_get_default_ipaddress(void)
669 {
670         return netconfig_default_connection_info.ipaddress;
671 }
672
673 const char *netconfig_get_default_ipaddress6(void)
674 {
675         return netconfig_default_connection_info.ipaddress6;
676 }
677
678 const char *netconfig_get_default_proxy(void)
679 {
680         return netconfig_default_connection_info.proxy;
681 }
682
683 unsigned int netconfig_get_default_frequency(void)
684 {
685         return netconfig_default_connection_info.freq;
686 }
687
688 const char *netconfig_wifi_get_connected_essid(const char *default_profile)
689 {
690         if (default_profile == NULL)
691                 return NULL;
692
693         if (netconfig_is_wifi_profile(default_profile) != TRUE)
694                 return NULL;
695
696         if (g_strcmp0(default_profile, netconfig_default_connection_info.profile) != 0)
697                 return NULL;
698
699         return netconfig_default_connection_info.essid;
700 }
701
702 static int __netconfig_reset_ipv4_socket(void)
703 {
704         int ret;
705         int fd;
706         struct ifreq ifr;
707         struct sockaddr_in sai;
708         const char *ipaddr = netconfig_get_default_ipaddress();
709         DBG("ipaddr-[%s]", ipaddr);
710
711         if (!ipaddr)
712                 return -1;
713
714         fd = socket(AF_INET, SOCK_DGRAM, 0);
715         if (fd < 0)
716                 return -1;
717
718         memset(&sai, 0, sizeof(struct sockaddr_in));
719         sai.sin_family = AF_INET;
720         sai.sin_port = 0;
721         if (!inet_aton(ipaddr, &sai.sin_addr)) {
722                 DBG("fail to inet_aton()");
723                 close(fd);
724                 return -1;
725         }
726
727         memset(&ifr, 0, sizeof(struct ifreq));
728         memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
729         g_strlcpy((char *)ifr.ifr_name, WIFI_IFNAME, IFNAMSIZ);
730
731 #ifndef SIOCKILLADDR
732 #define SIOCKILLADDR    0x8939
733 #endif
734
735         ret = ioctl(fd, SIOCKILLADDR, &ifr);
736         if (ret < 0) {
737                 DBG("fail to ioctl[SIOCKILLADDR]");
738                 close(fd);
739                 return -1;
740         }
741
742         close(fd);
743         return 0;
744 }
745
746 void netconfig_update_default_profile(const char *profile)
747 {
748         static char *old_profile = NULL;
749
750         /* It's automatically updated by signal-handler
751          * DO NOT update manually
752          *
753          * It is going to update default connection information
754          */
755
756         if (netconfig_default_connection_info.profile != NULL) {
757
758                 if (netconfig_is_wifi_profile(netconfig_default_connection_info.profile))
759                         __netconfig_reset_ipv4_socket();
760
761                 g_free(old_profile);
762                 old_profile = strdup(netconfig_default_connection_info.profile);
763
764                 g_free(netconfig_default_connection_info.profile);
765                 netconfig_default_connection_info.profile = NULL;
766
767                 g_free(netconfig_default_connection_info.ifname);
768                 netconfig_default_connection_info.ifname = NULL;
769
770                 g_free(netconfig_default_connection_info.ipaddress);
771                 netconfig_default_connection_info.ipaddress = NULL;
772
773                 g_free(netconfig_default_connection_info.ipaddress6);
774                 netconfig_default_connection_info.ipaddress6 = NULL;
775
776                 g_free(netconfig_default_connection_info.proxy);
777                 netconfig_default_connection_info.proxy = NULL;
778
779                 netconfig_default_connection_info.freq = 0;
780
781                 if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
782                         g_free(netconfig_default_connection_info.essid);
783                         netconfig_default_connection_info.essid = NULL;
784                 }
785         }
786
787         //default profile is NULL and new connected profile is NULL
788         if( !profile ){
789                 profile = __netconfig_get_default_profile();
790
791                 if (profile && netconfig_is_cellular_profile(profile) &&
792                         !netconfig_is_cellular_internet_profile(profile)){
793                         DBG("not a default cellular profile");
794                         profile = NULL;
795                 }
796
797                 if(!profile){
798                         __netconfig_update_default_connection_info();
799                         return;
800                 }
801         }
802
803         netconfig_default_connection_info.profile = g_strdup(profile);
804         __netconfig_get_default_connection_info(profile);
805         __netconfig_update_default_connection_info();
806
807 }
808
809 void netconfig_update_default(void)
810 {
811         if (__netconfig_is_tech_state_connected() == TRUE)
812                 __netconfig_update_if_service_connected();
813         else
814                 __netconfig_adjust_tcp_buffer_size();
815 }
816
817 char *netconfig_get_ifname(const char *profile)
818 {
819         GVariant *message = NULL, *variant;
820         GVariantIter *iter, *next;
821         gchar *key;
822         gchar *key1;
823         const gchar *value = NULL;
824         gchar *ifname = NULL;
825
826         if (profile == NULL)
827                 return NULL;
828
829         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, profile,
830                         CONNMAN_SERVICE_INTERFACE, "GetProperties", NULL);
831         if (message == NULL) {
832                 ERR("Failed to get service properties");
833                 return NULL;
834         }
835
836         g_variant_get(message, "(a{sv})", &iter);
837         while (g_variant_iter_loop(iter, "{sv}", &key, &next)) {
838                 if (g_strcmp0(key, "Ethernet") == 0) {
839                         while (g_variant_iter_loop(next, "{sv}", &key1, &variant)) {
840                                 if (g_strcmp0(key1, "Interface") == 0) {
841                                         value = g_variant_get_string(variant, NULL);
842                                         ifname = g_strdup(value);
843                                 }
844                         }
845                 }
846         }
847
848         g_variant_unref(message);
849
850         g_variant_iter_free(iter);
851
852         return ifname;
853 }
854
855 /* Check Ethernet Cable Plug-in /Plug-out Status */
856 void netconfig_network_notify_ethernet_cable_state(const char *key)
857 {
858        __netconfig_network_notify_result("EthernetCableState", key);
859 }
860
861 static gboolean handle_add_route(
862                 Network *object,
863                 GDBusMethodInvocation *context,
864                 gchar *ip_addr,
865                 gchar *netmask,
866                 gchar *interface,  gchar *gateway, gint address_family)
867 {
868         const gchar *path = ROUTE_EXEC_PATH;
869         gchar *const args[] = { "/sbin/route", "add", "-net", ip_addr,
870                 "netmask", netmask, "dev", interface, NULL };
871         gchar *const envs[] = { NULL };
872         const gchar* buf = NULL;
873         gchar* ch = NULL;
874         int prefix_len = 0;
875         int pos = 0;
876
877         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
878
879         switch(address_family) {
880                 case AF_INET:
881                         if (ip_addr == NULL || netmask == NULL || interface == NULL) {
882                                 ERR("Invalid parameter");
883                                 netconfig_error_invalid_parameter(context);
884                                 return FALSE;
885                         }
886
887                         if (netconfig_execute_file(path, args, envs) < 0) {
888                                 DBG("Failed to add a new route");
889                                 netconfig_error_permission_denied(context);
890                                 return FALSE;
891                         }
892
893                         break;
894                 case AF_INET6:
895                         if (ip_addr == NULL || interface == NULL || gateway == NULL) {
896                                 ERR("Invalid parameter");
897                                 netconfig_error_invalid_parameter(context);
898                                 return FALSE;
899                         }
900
901                         buf = ip_addr;
902                         ch = strchr(buf, '/');
903                         pos = ch - buf + 1;
904                         if (ch) {
905                                 prefix_len = atoi(ch + 1);
906                                 ip_addr[pos-1] = '\0';
907                         } else {
908                                 prefix_len = 128;
909                         }
910
911                         if (netconfig_add_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
912                                 DBG("Failed to add a new route");
913                                 netconfig_error_permission_denied(context);
914                                 return FALSE;
915                         }
916                         break;
917                 default:
918                         DBG("Unknown Address Family");
919                         netconfig_error_invalid_parameter(context);
920                         return FALSE;
921         }
922
923         DBG("Successfully added a new route");
924         network_complete_add_route(object, context, TRUE);
925         return TRUE;
926 }
927
928 static gboolean handle_remove_route(
929                 Network *object,
930                 GDBusMethodInvocation *context,
931                 gchar *ip_addr,
932                 gchar *netmask,
933                 gchar *interface, gchar *gateway, gint address_family)
934 {
935         const char *path = ROUTE_EXEC_PATH;
936         gchar *const args[] = { "/sbin/route", "del", "-net", ip_addr,
937                 "netmask", netmask, "dev", interface, NULL };
938         char *const envs[] = { NULL };
939         const char* buf = NULL;
940         char* ch = NULL;
941         int prefix_len = 0;
942         int pos = 0;
943
944         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
945
946         switch(address_family) {
947                 case AF_INET:
948                         if (ip_addr == NULL || netmask == NULL || interface == NULL) {
949                                 DBG("Invalid parameter!");
950                                 netconfig_error_invalid_parameter(context);
951                                 return FALSE;
952                         }
953                         if (netconfig_execute_file(path, args, envs) < 0) {
954                                 DBG("Failed to remove the route");
955                                 netconfig_error_permission_denied(context);
956                                 return FALSE;
957                         }
958                         break;
959                 case AF_INET6:
960                         if (ip_addr == NULL || interface == NULL || gateway == NULL) {
961                                 DBG("Invalid parameter!");
962                                 netconfig_error_invalid_parameter(context);
963                                 return FALSE;
964                         }
965
966                         buf = ip_addr;
967                         ch = strchr(buf, '/');
968                         pos = ch - buf + 1;
969                         if (ch) {
970                                 prefix_len = atoi(ch + 1);
971                                 ip_addr[pos-1] = '\0';
972                         } else {
973                                 prefix_len = 128;
974                         }
975
976                         if (netconfig_del_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
977                                 DBG("Failed to remove the route");
978                                 netconfig_error_permission_denied(context);
979                                 return FALSE;
980                         }
981                         break;
982                 default:
983                         DBG("Unknown Address Family");
984                         netconfig_error_invalid_parameter(context);
985                         return FALSE;
986         }
987
988         DBG("Successfully removed the route");
989         network_complete_remove_route(object, context, TRUE);
990         return TRUE;
991 }
992
993 static gboolean handle_check_get_privilege(Network *object,
994                 GDBusMethodInvocation *context)
995 {
996         network_complete_check_get_privilege(object, context);
997         return TRUE;
998 }
999
1000
1001 static gboolean handle_check_profile_privilege(Network *object,
1002                 GDBusMethodInvocation *context)
1003 {
1004         network_complete_check_profile_privilege(object, context);
1005         return TRUE;
1006 }
1007
1008 gboolean handle_ethernet_cable_state(Network *object,
1009         GDBusMethodInvocation *context)
1010 {
1011         int ret = 0;
1012         int state = 0;
1013
1014         ret = netconfig_get_ethernet_cable_state(&state);
1015         if(ret != 0) {
1016                 DBG("Failed to get ethernet cable state");
1017                 netconfig_error_fail_ethernet_cable_state(context);
1018                 return FALSE;
1019         }
1020
1021         DBG("Successfully get ethernet cable state[%d]", state);
1022         network_complete_ethernet_cable_state(object, context, state);
1023         return TRUE;
1024 }
1025
1026 void state_object_create_and_init(void)
1027 {
1028         DBG("Creating network state object");
1029         GDBusInterfaceSkeleton *interface_network = NULL;
1030         GDBusConnection *connection = NULL;
1031         GDBusObjectManagerServer *server = netdbus_get_state_manager();
1032         if (server == NULL)
1033                 return;
1034
1035         connection = netdbus_get_connection();
1036         g_dbus_object_manager_server_set_connection(server, connection);
1037
1038         /*Interface netconfig.network*/
1039         netconfigstate = network_skeleton_new();
1040
1041         interface_network = G_DBUS_INTERFACE_SKELETON(netconfigstate);
1042         g_signal_connect(netconfigstate, "handle-add-route",
1043                                 G_CALLBACK(handle_add_route), NULL);
1044         g_signal_connect(netconfigstate, "handle-check-get-privilege",
1045                                 G_CALLBACK(handle_check_get_privilege), NULL);
1046         g_signal_connect(netconfigstate, "handle-check-profile-privilege",
1047                                 G_CALLBACK(handle_check_profile_privilege), NULL);
1048         g_signal_connect(netconfigstate, "handle-remove-route",
1049                                 G_CALLBACK(handle_remove_route), NULL);
1050
1051         if (!g_dbus_interface_skeleton_export(interface_network, connection,
1052                         NETCONFIG_NETWORK_STATE_PATH, NULL)) {
1053                 ERR("Export with path failed");
1054         }
1055 }
1056
1057 void state_object_deinit(void)
1058 {
1059         g_object_unref(netconfigstate);
1060 }