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