Apply dpm poilcy for wifi and wifi profile
[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-dpm.h"
44 #include "network-monitor.h"
45 #include "netsupplicant.h"
46 #include "wifi-tel-intf.h"
47 #include "clatd-handler.h"
48
49 #include "generated-code.h"
50 /* Define TCP buffer sizes for various networks */
51 /* ReadMin, ReadInitial, ReadMax */ /* WriteMin, WriteInitial, WriteMax */
52 #define NET_TCP_BUFFERSIZE_DEFAULT_READ         "4096 87380 704512"
53 #define NET_TCP_BUFFERSIZE_DEFAULT_WRITE        "4096 16384 110208"
54 #define NET_TCP_BUFFERSIZE_WIFI_READ            "524288 1048576 2560000"
55 #define NET_TCP_BUFFERSIZE_WIFI_WRITE           "524288 1048576 2560000"
56 #define NET_TCP_BUFFERSIZE_LTE_READ             "524288 1048576 2560000"
57 #define NET_TCP_BUFFERSIZE_LTE_WRITE            "524288 1048576 2560000"
58 #define NET_TCP_BUFFERSIZE_UMTS_READ            "4094 87380 704512"
59 #define NET_TCP_BUFFERSIZE_UMTS_WRITE           "4096 16384 110208"
60 #define NET_TCP_BUFFERSIZE_HSPA_READ            "4092 87380 704512"
61 #define NET_TCP_BUFFERSIZE_HSPA_WRITE           "4096 16384 262144"
62 #define NET_TCP_BUFFERSIZE_HSDPA_READ           "4092 87380 704512"
63 #define NET_TCP_BUFFERSIZE_HSDPA_WRITE          "4096 16384 262144"
64 #define NET_TCP_BUFFERSIZE_HSUPA_READ           "4092 87380 704512"
65 #define NET_TCP_BUFFERSIZE_HSUPA_WRITE          "4096 16384 262144"
66 #define NET_TCP_BUFFERSIZE_HSPAP_READ           "4092 87380 1220608"
67 #define NET_TCP_BUFFERSIZE_HSPAP_WRITE          "4096 16384 1220608"
68 #define NET_TCP_BUFFERSIZE_EDGE_READ            "4093 26280 35040"
69 #define NET_TCP_BUFFERSIZE_EDGE_WRITE           "4096 16384 35040"
70 #define NET_TCP_BUFFERSIZE_GPRS_READ            "4096 30000 30000"
71 #define NET_TCP_BUFFERSIZE_GPRS_WRITE           "4096 8760 11680"
72
73 #define NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX        "1048576"
74 #define NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX        "2097152"
75 #define NET_TCP_BUFFERSIZE_LTE_RMEM_MAX         "5242880"
76
77 #define NET_TCP_BUFFERSIZE_WIFID_WMEM_MAX       "2097152"
78
79 #define NET_PROC_SYS_NET_IPV4_TCP_RMEM          "/proc/sys/net/ipv4/tcp_rmem"
80 #define NET_PROC_SYS_NET_IPv4_TCP_WMEM          "/proc/sys/net/ipv4/tcp_wmem"
81 #define NET_PROC_SYS_NET_CORE_RMEM_MAX          "/proc/sys/net/core/rmem_max"
82 #define NET_PROC_SYS_NET_CORE_WMEM_MAX          "/proc/sys/net/core/wmem_max"
83
84 #define ROUTE_EXEC_PATH                                         "/sbin/route"
85
86 static Network *netconfigstate = NULL;
87
88 struct netconfig_default_connection {
89         char *profile;
90         char *ifname;
91         char *ipaddress;
92         char *ipaddress6;
93         char *proxy;
94         char *essid;
95         unsigned int freq;
96 };
97
98 static struct netconfig_default_connection
99                                 netconfig_default_connection_info = { NULL, };
100
101 gboolean netconfig_iface_network_state_ethernet_cable_state(gint32 *state);
102
103 static gboolean __netconfig_is_connected(GVariantIter *array)
104 {
105         gboolean is_connected = FALSE;
106         GVariant *variant = NULL;
107         gchar *key = NULL;
108         const gchar *value = NULL;
109
110         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
111                 if (g_strcmp0(key, "State") != 0)
112                         continue;
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                 if (netconfig_is_cellular_profile(object_path) && !netconfig_is_cellular_internet_profile(object_path))
150                         continue;
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         } else if (profile != NULL) {
443                 char *old_ip = vconf_get_str(VCONFKEY_NETWORK_IP);
444                 char *old_proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY);
445
446                 if (netconfig_is_wifi_profile(profile) == TRUE) {
447                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_WIFI);
448                         netconfig_set_vconf_int("memory/private/wifi/frequency", freq);
449
450                         netconfig_set_system_event(SYS_EVENT_NETWORK_STATUS,
451                                 EVT_KEY_NETWORK_STATUS, EVT_VAL_NETWORK_WIFI);
452                 } else if (netconfig_is_cellular_profile(profile)) {
453
454                         if (!netconfig_is_cellular_internet_profile(profile)) {
455                                 DBG("connection is not a internet profile - stop to update the cellular state");
456                                 return;
457                         }
458
459                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_CELLULAR);
460
461                         netconfig_set_system_event(SYS_EVENT_NETWORK_STATUS,
462                                 EVT_KEY_NETWORK_STATUS, EVT_VAL_NETWORK_CELLULAR);
463
464                         /* Enable clatd if IPv6 is set and no IPv4 address */
465                         if (!ip_addr && ip_addr6)
466                                 netconfig_clatd_enable();
467                 } else if (netconfig_is_ethernet_profile(profile) == TRUE) {
468                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_ETHERNET);
469                         netconfig_set_system_event(SYS_EVENT_NETWORK_STATUS,
470                                 EVT_KEY_NETWORK_STATUS, EVT_VAL_NETWORK_ETHERNET);
471                 } else if (netconfig_is_bluetooth_profile(profile) == TRUE) {
472                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_BLUETOOTH);
473                         netconfig_set_system_event(SYS_EVENT_NETWORK_STATUS,
474                                 EVT_KEY_NETWORK_STATUS, EVT_VAL_NETWORK_BT);
475                 } else{
476                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_OFF);
477                         netconfig_set_system_event(SYS_EVENT_NETWORK_STATUS,
478                                 EVT_KEY_NETWORK_STATUS, EVT_VAL_NETWORK_DISCONNECTED);
479                 }
480
481                 if (g_strcmp0(old_ip, ip_addr) != 0 || old_ip == NULL) {
482                         if (ip_addr != NULL)
483                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr);
484                         else if (ip_addr6 != NULL)
485                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr6);
486                         else
487                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "");
488                 }
489                 g_free(old_ip);
490
491                 if (g_strcmp0(old_proxy, proxy_addr) != 0) {
492                         if (proxy_addr == NULL)
493                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, "");
494                         else
495                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, proxy_addr);
496                 }
497                 g_free(old_proxy);
498
499                 netconfig_set_vconf_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, 1);
500
501                 DBG("Successfully update default network configuration");
502
503                 /* Disable clatd if it is in running state */
504                 if (netconfig_is_cellular_profile(profile) != TRUE)
505                         netconfig_clatd_disable();
506         }
507
508         __netconfig_adjust_tcp_buffer_size();
509 }
510
511 static gboolean __netconfig_is_tech_state_connected(void)
512 {
513         gboolean ret = FALSE;
514         GVariant *message = NULL, *variant;
515         GVariantIter *iter, *next;
516         gchar *path;
517         gchar *key;
518
519         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
520                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
521                         "GetTechnologies", NULL);
522
523         if (message == NULL) {
524                 DBG("Fail to get technology state");
525                 return FALSE;
526         }
527
528         g_variant_get(message, "(a(oa{sv}))", &iter);
529         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
530                 if (path == NULL)
531                         continue;
532
533                 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
534                         gboolean data;
535                         if (g_strcmp0(key, "Connected") == 0) {
536                                 data = g_variant_get_boolean(variant);
537                                 DBG("%s [%s: %s]", path, key, data ? "True" : "False");
538                                 if (TRUE == data) {
539                                         ret = TRUE;
540                                         g_free(path);
541                                         g_free(key);
542                                         g_variant_unref(variant);
543                                         g_variant_iter_free(next);
544                                         goto done;
545                                 }
546                         }
547                 }
548         }
549
550 done:
551         g_variant_iter_free(iter);
552         g_variant_unref(message);
553
554         return ret;
555 }
556
557 static void __netconfig_update_if_service_connected(void)
558 {
559         GVariant *message = NULL, *var;
560         GVariantIter *iter, *next;
561         gchar *path;
562         gchar *key;
563
564         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
565                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
566                         "GetServices", NULL);
567
568         if (message == NULL) {
569                 ERR("Failed to get services");
570                 return;
571         }
572
573         g_variant_get(message, "(a(oa{sv}))", &iter);
574         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
575                 if (path == NULL)
576                         continue;
577
578                 if (g_str_has_prefix(path,
579                                                 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX) == TRUE) {
580                         if (g_strrstr(path + strlen(CONNMAN_WIFI_SERVICE_PROFILE_PREFIX),
581                                                         "hidden") != NULL) {
582                                 /* skip hidden profiles */
583                                 continue;
584                         }
585                         /* Process this */
586                 } else if (g_str_has_prefix(path,
587                                                 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX) == TRUE) {
588                         /* Process this */
589                 } else {
590                         continue;
591                 }
592
593                 while (g_variant_iter_loop(next, "{sv}", &key, &var)) {
594                         if (g_strcmp0(key, "State") == 0) {
595                                 const gchar *sdata = NULL;
596                                 sdata = g_variant_get_string(var, NULL);
597                                 DBG("%s [%s: %s]", path, key, sdata);
598
599                                 if (g_strcmp0(sdata, "online") == 0 || g_strcmp0(sdata, "ready") == 0) {
600
601                                         /* Found a connected WiFi / 3G service.
602                                          * Lets update the default profile info.
603                                          */
604                                         netconfig_update_default_profile((const gchar*)path);
605                                         g_free(key);
606                                         g_free(path);
607                                         g_variant_unref(var);
608                                         g_variant_iter_free(next);
609                                         goto done;
610                                 }
611                         }
612                 }
613         }
614 done:
615         g_variant_iter_free(iter);
616         g_variant_unref(message);
617
618         return;
619 }
620
621 static void __netconfig_network_notify_result(const char *sig_name, const char *key)
622 {
623         gboolean reply;
624         GVariant *params;
625         GVariantBuilder *builder = NULL;
626         GDBusConnection *connection = NULL;
627         GError *error = NULL;
628         const char *prop_key = "key";
629
630         INFO("[Signal] %s %s", sig_name, key);
631
632         connection = netdbus_get_connection();
633         if (connection == NULL) {
634                 ERR("Failed to get GDBus Connection");
635                 return;
636         }
637
638         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
639         g_variant_builder_add(builder, "{sv}", prop_key, g_variant_new_string(key));
640         params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
641
642         g_variant_builder_unref(builder);
643
644         reply = g_dbus_connection_emit_signal(connection,
645                         NULL,
646                         NETCONFIG_NETWORK_PATH,
647                         NETCONFIG_NETWORK_INTERFACE,
648                         sig_name,
649                         params,
650                         &error);
651
652         if (reply != TRUE) {
653                 if (error != NULL) {
654                         ERR("Failed to send signal [%s]", error->message);
655                         g_error_free(error);
656                 }
657                 return;
658         }
659
660         INFO("Sent signal (%s), key (%s)", sig_name, key);
661         return;
662 }
663
664 const char *netconfig_get_default_profile(void)
665 {
666         return netconfig_default_connection_info.profile;
667 }
668
669 const char *netconfig_get_default_ifname(void)
670 {
671         return netconfig_default_connection_info.ifname;
672 }
673
674 const char *netconfig_get_default_ipaddress(void)
675 {
676         return netconfig_default_connection_info.ipaddress;
677 }
678
679 const char *netconfig_get_default_ipaddress6(void)
680 {
681         return netconfig_default_connection_info.ipaddress6;
682 }
683
684 const char *netconfig_get_default_proxy(void)
685 {
686         return netconfig_default_connection_info.proxy;
687 }
688
689 unsigned int netconfig_get_default_frequency(void)
690 {
691         return netconfig_default_connection_info.freq;
692 }
693
694 const char *netconfig_wifi_get_connected_essid(const char *default_profile)
695 {
696         if (default_profile == NULL)
697                 return NULL;
698
699         if (netconfig_is_wifi_profile(default_profile) != TRUE)
700                 return NULL;
701
702         if (g_strcmp0(default_profile, netconfig_default_connection_info.profile) != 0)
703                 return NULL;
704
705         return netconfig_default_connection_info.essid;
706 }
707
708 static int __netconfig_reset_ipv4_socket(void)
709 {
710         int ret;
711         int fd;
712         struct ifreq ifr;
713         struct sockaddr_in sai;
714         const char *ipaddr = netconfig_get_default_ipaddress();
715         DBG("ipaddr-[%s]", ipaddr);
716
717         if (!ipaddr)
718                 return -1;
719
720         fd = socket(AF_INET, SOCK_DGRAM, 0);
721         if (fd < 0)
722                 return -1;
723
724         memset(&sai, 0, sizeof(struct sockaddr_in));
725         sai.sin_family = AF_INET;
726         sai.sin_port = 0;
727         if (!inet_aton(ipaddr, &sai.sin_addr)) {
728                 DBG("fail to inet_aton()");
729                 close(fd);
730                 return -1;
731         }
732
733         memset(&ifr, 0, sizeof(struct ifreq));
734         memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
735         g_strlcpy((char *)ifr.ifr_name, WIFI_IFNAME, IFNAMSIZ);
736
737 #ifndef SIOCKILLADDR
738 #define SIOCKILLADDR    0x8939
739 #endif
740
741         ret = ioctl(fd, SIOCKILLADDR, &ifr);
742         if (ret < 0) {
743                 DBG("fail to ioctl[SIOCKILLADDR]");
744                 close(fd);
745                 return -1;
746         }
747
748         close(fd);
749         return 0;
750 }
751
752 void netconfig_update_default_profile(const char *profile)
753 {
754         static char *old_profile = NULL;
755
756         /* It's automatically updated by signal-handler
757          * DO NOT update manually
758          *
759          * It is going to update default connection information
760          */
761
762         if (netconfig_default_connection_info.profile != NULL) {
763
764                 if (netconfig_is_wifi_profile(netconfig_default_connection_info.profile))
765                         __netconfig_reset_ipv4_socket();
766
767                 g_free(old_profile);
768                 old_profile = strdup(netconfig_default_connection_info.profile);
769
770                 g_free(netconfig_default_connection_info.profile);
771                 netconfig_default_connection_info.profile = NULL;
772
773                 g_free(netconfig_default_connection_info.ifname);
774                 netconfig_default_connection_info.ifname = NULL;
775
776                 g_free(netconfig_default_connection_info.ipaddress);
777                 netconfig_default_connection_info.ipaddress = NULL;
778
779                 g_free(netconfig_default_connection_info.ipaddress6);
780                 netconfig_default_connection_info.ipaddress6 = NULL;
781
782                 g_free(netconfig_default_connection_info.proxy);
783                 netconfig_default_connection_info.proxy = NULL;
784
785                 netconfig_default_connection_info.freq = 0;
786
787                 if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
788                         g_free(netconfig_default_connection_info.essid);
789                         netconfig_default_connection_info.essid = NULL;
790                 }
791         }
792
793         /* default profile is NULL and new connected profile is NULL */
794         if (!profile) {
795                 profile = __netconfig_get_default_profile();
796
797                 if (profile && netconfig_is_cellular_profile(profile) &&
798                         !netconfig_is_cellular_internet_profile(profile)) {
799                         DBG("not a default cellular profile");
800                         profile = NULL;
801                 }
802
803                 if (!profile) {
804                         __netconfig_update_default_connection_info();
805                         return;
806                 }
807         }
808
809         netconfig_default_connection_info.profile = g_strdup(profile);
810         __netconfig_get_default_connection_info(profile);
811         __netconfig_update_default_connection_info();
812
813 }
814
815 void netconfig_update_default(void)
816 {
817         if (__netconfig_is_tech_state_connected() == TRUE)
818                 __netconfig_update_if_service_connected();
819         else
820                 __netconfig_adjust_tcp_buffer_size();
821 }
822
823 char *netconfig_get_ifname(const char *profile)
824 {
825         GVariant *message = NULL, *variant;
826         GVariantIter *iter, *next;
827         gchar *key;
828         gchar *key1;
829         const gchar *value = NULL;
830         gchar *ifname = NULL;
831
832         if (profile == NULL)
833                 return NULL;
834
835         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, profile,
836                         CONNMAN_SERVICE_INTERFACE, "GetProperties", NULL);
837         if (message == NULL) {
838                 ERR("Failed to get service properties");
839                 return NULL;
840         }
841
842         g_variant_get(message, "(a{sv})", &iter);
843         while (g_variant_iter_loop(iter, "{sv}", &key, &next)) {
844                 if (g_strcmp0(key, "Ethernet") == 0) {
845                         while (g_variant_iter_loop(next, "{sv}", &key1, &variant)) {
846                                 if (g_strcmp0(key1, "Interface") == 0) {
847                                         value = g_variant_get_string(variant, NULL);
848                                         ifname = g_strdup(value);
849                                 }
850                         }
851                 }
852         }
853
854         g_variant_unref(message);
855
856         g_variant_iter_free(iter);
857
858         return ifname;
859 }
860
861 /* Check Ethernet Cable Plug-in /Plug-out Status */
862 void netconfig_network_notify_ethernet_cable_state(const char *key)
863 {
864         __netconfig_network_notify_result("EthernetCableState", key);
865 }
866
867 static gboolean handle_add_route(
868                 Network *object,
869                 GDBusMethodInvocation *context,
870                 gchar *ip_addr,
871                 gchar *netmask,
872                 gchar *interface,  gchar *gateway, gint address_family)
873 {
874         const gchar *path = ROUTE_EXEC_PATH;
875         gchar *const args[] = { "/sbin/route", "add", "-net", ip_addr,
876                 "netmask", netmask, "dev", interface, NULL };
877         gchar *const envs[] = { NULL };
878         const gchar* buf = NULL;
879         gchar* ch = NULL;
880         int prefix_len = 0;
881         int pos = 0;
882
883         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
884
885         switch (address_family) {
886         case AF_INET:
887                 if (ip_addr == NULL || netmask == NULL || interface == NULL) {
888                         ERR("Invalid parameter");
889                         netconfig_error_invalid_parameter(context);
890                         return FALSE;
891                 }
892
893                 if (netconfig_execute_file(path, args, envs) < 0) {
894                         DBG("Failed to add a new route");
895                         netconfig_error_permission_denied(context);
896                         return FALSE;
897                 }
898
899                 break;
900         case AF_INET6:
901                 if (ip_addr == NULL || interface == NULL || gateway == NULL) {
902                         ERR("Invalid parameter");
903                         netconfig_error_invalid_parameter(context);
904                         return FALSE;
905                 }
906
907                 buf = ip_addr;
908                 ch = strchr(buf, '/');
909                 pos = ch - buf + 1;
910                 if (ch) {
911                         prefix_len = atoi(ch + 1);
912                         ip_addr[pos-1] = '\0';
913                 } else {
914                         prefix_len = 128;
915                 }
916
917                 if (netconfig_add_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
918                         DBG("Failed to add a new route");
919                         netconfig_error_permission_denied(context);
920                         return FALSE;
921                 }
922                 break;
923         default:
924                 DBG("Unknown Address Family");
925                 netconfig_error_invalid_parameter(context);
926                 return FALSE;
927         }
928
929         DBG("Successfully added a new route");
930         network_complete_add_route(object, context, TRUE);
931         return TRUE;
932 }
933
934 static gboolean handle_remove_route(
935                 Network *object,
936                 GDBusMethodInvocation *context,
937                 gchar *ip_addr,
938                 gchar *netmask,
939                 gchar *interface, gchar *gateway, gint address_family)
940 {
941         const char *path = ROUTE_EXEC_PATH;
942         gchar *const args[] = { "/sbin/route", "del", "-net", ip_addr,
943                 "netmask", netmask, "dev", interface, NULL };
944         char *const envs[] = { NULL };
945         const char* buf = NULL;
946         char* ch = NULL;
947         int prefix_len = 0;
948         int pos = 0;
949
950         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
951
952         switch (address_family) {
953         case AF_INET:
954                 if (ip_addr == NULL || netmask == NULL || interface == NULL) {
955                         DBG("Invalid parameter!");
956                         netconfig_error_invalid_parameter(context);
957                         return FALSE;
958                 }
959                 if (netconfig_execute_file(path, args, envs) < 0) {
960                         DBG("Failed to remove the route");
961                         netconfig_error_permission_denied(context);
962                         return FALSE;
963                 }
964                 break;
965         case AF_INET6:
966                 if (ip_addr == NULL || interface == NULL || gateway == NULL) {
967                         DBG("Invalid parameter!");
968                         netconfig_error_invalid_parameter(context);
969                         return FALSE;
970                 }
971
972                 buf = ip_addr;
973                 ch = strchr(buf, '/');
974                 pos = ch - buf + 1;
975                 if (ch) {
976                         prefix_len = atoi(ch + 1);
977                         ip_addr[pos-1] = '\0';
978                 } else {
979                         prefix_len = 128;
980                 }
981
982                 if (netconfig_del_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
983                         DBG("Failed to remove the route");
984                         netconfig_error_permission_denied(context);
985                         return FALSE;
986                 }
987                 break;
988         default:
989                 DBG("Unknown Address Family");
990                 netconfig_error_invalid_parameter(context);
991                 return FALSE;
992         }
993
994         DBG("Successfully removed the route");
995         network_complete_remove_route(object, context, TRUE);
996         return TRUE;
997 }
998
999 static gboolean handle_check_get_privilege(Network *object,
1000                 GDBusMethodInvocation *context)
1001 {
1002         network_complete_check_get_privilege(object, context);
1003         return TRUE;
1004 }
1005
1006
1007 static gboolean handle_check_profile_privilege(Network *object,
1008                 GDBusMethodInvocation *context)
1009 {
1010         network_complete_check_profile_privilege(object, context);
1011         return TRUE;
1012 }
1013
1014 gboolean handle_ethernet_cable_state(Network *object,
1015         GDBusMethodInvocation *context)
1016 {
1017         int ret = 0;
1018         int state = 0;
1019
1020         ret = netconfig_get_ethernet_cable_state(&state);
1021         if (ret != 0) {
1022                 DBG("Failed to get ethernet cable state");
1023                 netconfig_error_fail_ethernet_cable_state(context);
1024                 return FALSE;
1025         }
1026
1027         DBG("Successfully get ethernet cable state[%d]", state);
1028         network_complete_ethernet_cable_state(object, context, state);
1029         return TRUE;
1030 }
1031
1032 void state_object_create_and_init(void)
1033 {
1034         DBG("Creating network state object");
1035         GDBusInterfaceSkeleton *interface_network = NULL;
1036         GDBusConnection *connection = NULL;
1037         GDBusObjectManagerServer *server = netdbus_get_state_manager();
1038         if (server == NULL)
1039                 return;
1040
1041         connection = netdbus_get_connection();
1042         g_dbus_object_manager_server_set_connection(server, connection);
1043
1044         /*Interface netconfig.network*/
1045         netconfigstate = network_skeleton_new();
1046
1047         interface_network = G_DBUS_INTERFACE_SKELETON(netconfigstate);
1048         g_signal_connect(netconfigstate, "handle-add-route",
1049                                 G_CALLBACK(handle_add_route), NULL);
1050         g_signal_connect(netconfigstate, "handle-check-get-privilege",
1051                                 G_CALLBACK(handle_check_get_privilege), NULL);
1052         g_signal_connect(netconfigstate, "handle-check-profile-privilege",
1053                                 G_CALLBACK(handle_check_profile_privilege), NULL);
1054         g_signal_connect(netconfigstate, "handle-ethernet-cable-state",
1055                                 G_CALLBACK(handle_ethernet_cable_state), NULL);
1056         g_signal_connect(netconfigstate, "handle-remove-route",
1057                                 G_CALLBACK(handle_remove_route), NULL);
1058         g_signal_connect(netconfigstate, "handle-launch-mdns",
1059                                 G_CALLBACK(handle_launch_mdns), NULL);
1060         g_signal_connect(netconfigstate, "handle-ref-mdns",
1061                                 G_CALLBACK(handle_ref_mdns), NULL);
1062         g_signal_connect(netconfigstate, "handle-unref-mdns",
1063                                 G_CALLBACK(handle_unref_mdns), NULL);
1064         g_signal_connect(netconfigstate, "handle-device-policy-set-wifi",
1065                                 G_CALLBACK(handle_device_policy_set_wifi), NULL);
1066         g_signal_connect(netconfigstate, "handle-device-policy-get-wifi",
1067                                 G_CALLBACK(handle_device_policy_get_wifi), NULL);
1068         g_signal_connect(netconfigstate, "handle-device-policy-set-wifi-profile",
1069                                 G_CALLBACK(handle_device_policy_set_wifi_profile), NULL);
1070         g_signal_connect(netconfigstate, "handle-device-policy-get-wifi-profile",
1071                                 G_CALLBACK(handle_device_policy_get_wifi_profile), NULL);
1072
1073         if (!g_dbus_interface_skeleton_export(interface_network, connection,
1074                         NETCONFIG_NETWORK_STATE_PATH, NULL)) {
1075                 ERR("Export with path failed");
1076         }
1077 }
1078
1079 void state_object_deinit(void)
1080 {
1081         g_object_unref(netconfigstate);
1082 }