Use rand_r() instead of rand()
[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 <stdio.h>
25 #include <stdlib.h>
26 #include <net/if.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
29 #include <sys/ioctl.h>
30
31 #include "log.h"
32 #include "util.h"
33 #include "setting.h"
34 #include "netdbus.h"
35 #include "neterror.h"
36 #include "emulator.h"
37 #include "wifi-state.h"
38 #include "wifi-power.h"
39 #include "network-state.h"
40 #include "network-dpm.h"
41 #include "network-monitor.h"
42 #include "netsupplicant.h"
43 #include "clatd-handler.h"
44 #if defined TIZEN_DEBUG_ENABLE
45 #include "network-dump.h"
46 #endif
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_IPV4_UDP_MEM                   "/proc/sys/net/ipv4/udp_mem"
81 #define NET_PROC_SYS_NET_CORE_RMEM_DEFAULT              "/proc/sys/net/core/rmem_default"
82 #define NET_PROC_SYS_NET_CORE_RMEM_MAX                  "/proc/sys/net/core/rmem_max"
83 #define NET_PROC_SYS_NET_CORE_WMEM_DEFAULT              "/proc/sys/net/core/wmem_default"
84 #define NET_PROC_SYS_NET_CORE_WMEM_MAX                  "/proc/sys/net/core/wmem_max"
85
86 #define ROUTE_EXEC_PATH                                         "/sbin/route"
87
88 #define TELEPHONY_SERVICE                       "com.tcore.ps"
89 #define TELEPHONY_MASTER_INTERFACE              TELEPHONY_SERVICE ".master"
90 #define TELEPHONY_MODEM_INTERFACE               TELEPHONY_SERVICE ".modem"
91 #define TELEPHONY_PROFILE_INTERFACE             TELEPHONY_SERVICE ".context"
92 #define TELEPHONY_MASTER_PATH                   "/"
93 #define NET_PROFILE_NAME_LEN_MAX 512
94
95 typedef struct {
96         char                    profile_name[NET_PROFILE_NAME_LEN_MAX];
97 } net_profile_name_t;
98
99 static Network *netconfigstate = NULL;
100 #if defined TIZEN_DEBUG_ENABLE
101 static Tcpdump *tcpdump_object = NULL;
102 #endif
103 static Battery *battery_object = NULL;
104
105 struct netconfig_default_connection {
106         char *profile;
107         char *ifname;
108         char *mac_address;
109         char *ipaddress;
110         char *ipaddress6;
111         char *proxy;
112         char *essid;
113         unsigned int freq;
114         gboolean is_metered;
115         gboolean is_internet;
116 };
117
118 static struct netconfig_default_connection
119                                 netconfig_default_connection_info = { NULL, };
120
121 gboolean netconfig_iface_network_state_ethernet_cable_state(gint32 *state);
122
123 static gboolean __netconfig_is_connected(GVariantIter *array)
124 {
125         gboolean is_connected = FALSE;
126         GVariant *variant = NULL;
127         gchar *key = NULL;
128         const gchar *value = NULL;
129
130         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
131                 if (g_strcmp0(key, "State") != 0)
132                         continue;
133
134                 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
135                         value = g_variant_get_string(variant, NULL);
136                         if (g_strcmp0(value, "ready") == 0 || g_strcmp0(value, "online") == 0)
137                                 is_connected = TRUE;
138                 }
139
140                 g_free(key);
141                 g_variant_unref(variant);
142                 break;
143         }
144
145         return is_connected;
146 }
147
148 static int __netconfig_telephony_get_modem_object_path(GSList **modem_path_list)
149 {
150         GVariant *result;
151         GVariantIter *iter_modem = NULL;
152         GVariantIter *modem_properties = NULL;
153         const char *modem_path;
154
155         result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, TELEPHONY_MASTER_PATH,
156                         TELEPHONY_MASTER_INTERFACE, "GetModems", NULL);
157         if (result == NULL) {
158                 ERR("Failed to get modem path list");
159                 return -1;
160         }
161
162         g_variant_get(result, "(a{sa{ss}})", &iter_modem);
163         while (g_variant_iter_loop(iter_modem, "{sa{ss}}", &modem_path, &modem_properties)) {
164                 *modem_path_list = g_slist_append(*modem_path_list, g_strdup(modem_path));
165                 DBG("modem object path: %s",    modem_path);
166         }
167
168         g_variant_iter_free(iter_modem);
169         g_variant_unref(result);
170
171         return 0;
172 }
173
174 static int __netconfig_telephony_get_profile_list(net_profile_name_t **profile_list,
175                 int *profile_count)
176 {
177         int ret = 0;
178         int count = 0, i = 0;
179         const char *str = NULL;
180         GVariant *result;
181         GVariantIter *iter = NULL;
182         GSList *profiles = NULL, *list = NULL;
183         net_profile_name_t *plist = NULL;
184
185         GSList *modem_path_list = NULL;
186         const char *path = NULL;
187
188         ret = __netconfig_telephony_get_modem_object_path(&modem_path_list);
189         if (ret < 0) {
190                 ERR("Failed to get modems path list");
191
192                 g_slist_free_full(modem_path_list, g_free);
193                 return ret;
194         }
195
196         for (list = modem_path_list; list != NULL; list = list->next) {
197                 path = (const char *)list->data;
198
199                 DBG("path: %s", path);
200                 result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, path,
201                                 TELEPHONY_MODEM_INTERFACE, "GetProfileList", NULL);
202                 if (result == NULL) {
203                         DBG("Failed to get profiles: %s", path);
204                         continue;
205                 }
206
207                 g_variant_get(result, "(as)", &iter);
208                 while (g_variant_iter_loop(iter, "s", &str))
209                         profiles = g_slist_append(profiles, g_strdup(str));
210
211                 g_variant_iter_free(iter);
212                 g_variant_unref(result);
213         }
214
215         g_slist_free_full(modem_path_list, g_free);
216
217         count = g_slist_length(profiles);
218         if (count > 0) {
219                 plist = (net_profile_name_t*)malloc(sizeof(net_profile_name_t) * count);
220         } else {
221                 *profile_count = 0;
222                 goto out;
223         }
224
225         if (plist == NULL) {
226                 ERR("Failed to allocate memory");
227                 *profile_count = 0;
228                 ret = -1;
229                 goto out;
230         }
231
232         for (list = profiles, i = 0; list != NULL; list = list->next, i++)
233                 g_strlcpy(plist[i].profile_name,
234                                 (const char *)list->data, NET_PROFILE_NAME_LEN_MAX);
235
236         *profile_list = plist;
237         *profile_count = count;
238
239 out:
240         g_slist_free_full(profiles, g_free);
241
242         return ret;
243 }
244
245 static int __netconfig_telephony_search_pdp_profile(const char* profile_name, net_profile_name_t* pdp_name)
246 {
247         int ret;
248         net_profile_name_t* profile_list = NULL;
249         char* prof_name = NULL;
250         char* tel_prof_name = NULL;
251         char* found_ptr = NULL;
252         int profile_count = 0;
253         int i;
254
255         /* Get pdp profile list from telephony service */
256         ret = __netconfig_telephony_get_profile_list(&profile_list, &profile_count);
257         if (ret < 0) {
258                 ERR("Failed to get profile list from telephony service");
259                 g_free(profile_list);
260                 return ret;
261         }
262
263         if (profile_list == NULL || profile_count <= 0) {
264                 ERR("There is no PDP profiles");
265                 g_free(profile_list);
266                 return -1;
267         }
268
269         /* Find matching profile */
270         prof_name = strrchr(profile_name, '/') + 1;
271         for (i = 0; i < profile_count; i++) {
272                 tel_prof_name = strrchr(profile_list[i].profile_name, '/') + 1;
273                 found_ptr = strstr(prof_name, tel_prof_name);
274
275                 if (found_ptr != NULL && g_strcmp0(found_ptr, tel_prof_name) == 0) {
276                         g_strlcpy(pdp_name->profile_name,
277                                         profile_list[i].profile_name, NET_PROFILE_NAME_LEN_MAX);
278
279                         DBG("PDP profile name found in cellular profile: %s", pdp_name->profile_name);
280                         break;
281                 }
282         }
283
284         if (i >= profile_count) {
285                 ERR("There is no matching PDP profiles");
286                 g_free(profile_list);
287                 return -1;
288         }
289
290         g_free(profile_list);
291
292         return ret;
293 }
294
295 static gboolean __netconfig_telephony_get_metered_info(net_profile_name_t* pdp_name)
296 {
297         GVariant *result;
298         GVariantIter *iter;
299         const gchar *key = NULL;
300         const gchar *value = NULL;
301         gboolean ret = FALSE;
302
303         if (pdp_name == NULL) {
304                 ERR("Invalid parameter!");
305                 return ret;
306         }
307
308         result = netconfig_invoke_dbus_method(TELEPHONY_SERVICE, pdp_name->profile_name,
309                         TELEPHONY_PROFILE_INTERFACE, "GetProfile", NULL);
310         if (result == NULL) {
311                 ERR("_net_invoke_dbus_method failed");
312                 return ret;
313         }
314
315         g_variant_get(result, "(a{ss})", &iter);
316         while (g_variant_iter_next(iter, "{ss}", &key, &value)) {
317                 if (g_strcmp0(key, "is_metered") == 0) {
318                         if (value == NULL)
319                                 continue;
320
321                         if (g_strcmp0(value, "TRUE") == 0)
322                                 ret = TRUE;
323                 }
324         }
325
326         g_variant_iter_free(iter);
327         g_variant_unref(result);
328
329         DBG("is_metered = %s", ret ? "TRUE" : "FALSE");
330
331         return ret;
332 }
333
334 static int __netconfig_reset_ipv4_socket(const char *interface_name)
335 {
336         int ret;
337         int fd;
338         struct ifreq ifr;
339         struct sockaddr_in sai;
340         const char *ipaddr = netconfig_get_default_ipaddress();
341         DBG("ipaddr-[%s]", ipaddr);
342
343         if (!ipaddr)
344                 return -1;
345
346         fd = socket(AF_INET, SOCK_DGRAM, 0);
347         if (fd < 0)
348                 return -1;
349
350         memset(&sai, 0, sizeof(struct sockaddr_in));
351         sai.sin_family = AF_INET;
352         sai.sin_port = 0;
353         if (!inet_aton(ipaddr, &sai.sin_addr)) {
354                 DBG("fail to inet_aton()");
355                 close(fd);
356                 return -1;
357         }
358
359         memset(&ifr, 0, sizeof(struct ifreq));
360         memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
361         g_strlcpy((char *)ifr.ifr_name, interface_name, IFNAMSIZ);
362
363 #ifndef SIOCKILLADDR
364 #define SIOCKILLADDR    0x8939
365 #endif
366
367         ret = ioctl(fd, SIOCKILLADDR, &ifr);
368         if (ret < 0) {
369                 DBG("fail to ioctl[SIOCKILLADDR]");
370                 close(fd);
371                 return -1;
372         }
373
374         close(fd);
375         return 0;
376 }
377
378 static void __netconfig_clear_default_connection_info(void)
379 {
380         static char *old_profile = NULL;
381
382         if (netconfig_default_connection_info.profile != NULL) {
383
384                 netconfig_notify_online_state(netconfig_default_connection_info.ifname, FALSE);
385
386                 if (netconfig_is_wifi_profile(netconfig_default_connection_info.profile))
387                         __netconfig_reset_ipv4_socket(netconfig_default_connection_info.ifname);
388
389                 g_free(old_profile);
390                 old_profile = strdup(netconfig_default_connection_info.profile);
391
392                 g_free(netconfig_default_connection_info.profile);
393                 netconfig_default_connection_info.profile = NULL;
394
395                 g_free(netconfig_default_connection_info.ifname);
396                 netconfig_default_connection_info.ifname = NULL;
397
398                 g_free(netconfig_default_connection_info.ipaddress);
399                 netconfig_default_connection_info.ipaddress = NULL;
400
401                 g_free(netconfig_default_connection_info.ipaddress6);
402                 netconfig_default_connection_info.ipaddress6 = NULL;
403
404                 g_free(netconfig_default_connection_info.proxy);
405                 netconfig_default_connection_info.proxy = NULL;
406
407                 g_free(netconfig_default_connection_info.mac_address);
408                 netconfig_default_connection_info.mac_address = NULL;
409
410                 netconfig_default_connection_info.freq = 0;
411                 netconfig_default_connection_info.is_metered = FALSE;
412                 netconfig_default_connection_info.is_internet = FALSE;
413
414                 g_free(netconfig_default_connection_info.essid);
415                 netconfig_default_connection_info.essid = NULL;
416         }
417 }
418
419 static gboolean __netconfig_get_default_connection_info(void)
420 {
421         GVariant *message = NULL, *variant = NULL, *variant2 = NULL;
422         GVariantIter *iter = NULL, *iter1 = NULL;
423         GVariant *var = NULL;
424         gchar *obj_path;
425         gchar *key = NULL;
426         gchar *key1 = NULL;
427         gchar *key2 = NULL;
428
429         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
430                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
431                         "GetDefaultService", NULL);
432         if (message == NULL) {
433                 ERR("Failed to get services informations");
434                 return FALSE;
435         }
436
437         if (!g_variant_is_of_type(message, G_VARIANT_TYPE("(oa{sv})"))) {
438                 DBG("There is no default service");
439                 __netconfig_clear_default_connection_info();
440                 g_variant_unref(message);
441                 return TRUE;
442         }
443
444         g_variant_get(message, "(oa{sv})", &obj_path, &iter);
445
446         if (g_strcmp0(obj_path, netconfig_default_connection_info.profile) == 0) {
447                 g_variant_unref(message);
448                 g_variant_iter_free(iter);
449                 return FALSE;
450         }
451
452         __netconfig_clear_default_connection_info();
453
454         netconfig_default_connection_info.profile = g_strdup(obj_path);
455
456         while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
457                 const gchar *value = NULL;
458                 guint16 freq = 0;
459                 if (g_strcmp0(key, "Name") == 0 &&
460                                 netconfig_is_wifi_profile(obj_path) == TRUE) {
461                         if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
462                                 value = g_variant_get_string(var, NULL);
463
464                                 netconfig_default_connection_info.essid = g_strdup(value);
465                         }
466                 } else if (g_strcmp0(key, "State") == 0) {
467                         if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
468                                 value = g_variant_get_string(var, NULL);
469
470                                 if (g_strcmp0(value, "online") == 0) {
471                                         netconfig_default_connection_info.is_internet = TRUE;
472                                         netconfig_notify_online_state(netconfig_default_connection_info.ifname, TRUE);
473                                 }
474                         }
475                 } else if (g_strcmp0(key, "Ethernet") == 0) {
476                         g_variant_get(var, "a{sv}", &iter1);
477                         if (iter1 == NULL)
478                                 continue;
479                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
480                                 if (g_strcmp0(key1, "Interface") == 0) {
481                                         value = g_variant_get_string(variant, NULL);
482                                         netconfig_default_connection_info.ifname = g_strdup(value);
483                                 } else if (g_strcmp0(key1, "Address") == 0) {
484                                         value = g_variant_get_string(variant, NULL);
485                                         netconfig_default_connection_info.mac_address = g_strdup(value);
486                                 }
487                         }
488                         g_variant_iter_free(iter1);
489                 } else if (g_strcmp0(key, "IPv4") == 0) {
490                         g_variant_get(var, "a{sv}", &iter1);
491                         if (iter1 == NULL)
492                                 continue;
493                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
494                                 if (g_strcmp0(key1, "Address") == 0) {
495                                         value = g_variant_get_string(variant, NULL);
496                                         netconfig_default_connection_info.ipaddress = g_strdup(value);
497                                 }
498                         }
499                         g_variant_iter_free(iter1);
500                 } else if (g_strcmp0(key, "IPv6") == 0) {
501                         g_variant_get(var, "a{sv}", &iter1);
502                         if (iter1 == NULL)
503                                 continue;
504                         while (g_variant_iter_loop(iter1, "{sv}", &key1, &variant)) {
505                                 if (g_strcmp0(key1, "Address") == 0) {
506                                         value = g_variant_get_string(variant, NULL);
507                                         netconfig_default_connection_info.ipaddress6 = g_strdup(value);
508                                 }
509                         }
510                         g_variant_iter_free(iter1);
511
512                 } else if (g_strcmp0(key, "Proxy") == 0) {
513                         g_variant_get(var, "a{sv}", &iter1);
514                         if (iter1 == NULL)
515                                 continue;
516                         while (g_variant_iter_loop(iter1, "{sv}", &key2, &variant2)) {
517                                 GVariantIter *iter_sub = NULL;
518
519                                 if (g_strcmp0(key2, "Servers") == 0) {
520                                         if (!g_variant_is_of_type(variant2, G_VARIANT_TYPE_STRING_ARRAY)) {
521                                                 g_free(key2);
522                                                 g_variant_unref(variant2);
523                                                 break;
524                                         }
525
526                                         g_variant_get(variant2, "as", &iter_sub);
527                                         g_variant_iter_loop(iter_sub, "s", &value);
528                                         g_variant_iter_free(iter_sub);
529                                         if (value != NULL && (strlen(value) > 0))
530                                                 netconfig_default_connection_info.proxy = g_strdup(value);
531                                 } else if (g_strcmp0(key2, "Method") == 0) {
532                                         if (g_variant_is_of_type(variant2, G_VARIANT_TYPE_STRING)) {
533                                                 g_free(key2);
534                                                 g_variant_unref(variant2);
535                                                 break;
536                                         }
537
538                                         value = g_variant_get_string(variant2, NULL);
539                                         if (g_strcmp0(value, "direct") == 0) {
540                                                 g_free(netconfig_default_connection_info.proxy);
541                                                 netconfig_default_connection_info.proxy = NULL;
542
543                                                 g_free(key2);
544                                                 g_variant_unref(variant2);
545                                                 break;
546                                         }
547                                 }
548                         }
549                         g_variant_iter_free(iter1);
550                 } else if (g_strcmp0(key, "Frequency") == 0) {
551                         if (g_variant_is_of_type(var, G_VARIANT_TYPE_UINT16)) {
552                                 freq = g_variant_get_uint16(var);
553                                 netconfig_default_connection_info.freq = freq;
554                         }
555                 }
556         }
557
558         if (netconfig_is_cellular_profile(obj_path) == TRUE) {
559                 net_profile_name_t pdp_name;
560                 int ret;
561
562                 ret = __netconfig_telephony_search_pdp_profile(obj_path, &pdp_name);
563                 if (ret >= 0 && strlen(pdp_name.profile_name) > 0)
564                         if (__netconfig_telephony_get_metered_info(&pdp_name))
565                                 netconfig_default_connection_info.is_metered = TRUE;
566         }
567
568         g_variant_unref(message);
569         g_variant_iter_free(iter);
570
571         return TRUE;
572 }
573
574 static char *__netconfig_get_preferred_ipv6_address(char *profile)
575 {
576         GVariant *message = NULL, *variant = NULL, *next = NULL;
577         GVariantIter *iter = NULL, *sub_iter = NULL, *service = NULL;
578         gchar *obj_path;
579         gchar *key = NULL;
580         gchar *sub_key = NULL;
581         gchar *preferred_address6 = NULL;
582         gboolean found_profile = 0;
583
584         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
585                                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
586                                         "GetServices", NULL);
587         if (message == NULL) {
588                 ERR("Failed to get service informations");
589                 goto done;
590         }
591
592         g_variant_get(message, "(a(oa{sv}))", &service);
593         if (service == NULL) {
594                 ERR("Failed to get services iter");
595                 goto done;
596         }
597
598         while (g_variant_iter_loop(service, "(oa{sv})", &obj_path, &iter)) {
599                 if (g_strcmp0(obj_path, profile) == 0) {
600                         g_free(obj_path);
601                         found_profile = 1;
602                         break;
603                 }
604         }
605
606         if (iter == NULL || found_profile == 0) {
607                 ERR("Profile %s doesn't exist", profile);
608                         goto done;
609         }
610
611         while (g_variant_iter_loop(iter, "{sv}", &key, &next)) {
612                 const gchar *value = NULL;
613                 if (g_strcmp0(key, "IPv6") == 0) {
614                         g_variant_get(next, "a{sv}", &sub_iter);
615                         if (sub_iter == NULL)
616                                 continue;
617                         while (g_variant_iter_loop(sub_iter, "{sv}", &sub_key, &variant)) {
618                                 if (g_strcmp0(sub_key, "Address") == 0) {
619                                         value = g_variant_get_string(variant, NULL);
620                                         if (!preferred_address6)
621                                                 preferred_address6 = g_strdup(value);
622                                 }
623                         }
624                         g_variant_iter_free(sub_iter);
625                 }
626         }
627
628 done:
629         if (message)
630                 g_variant_unref(message);
631
632         if (iter)
633                 g_variant_iter_free(iter);
634
635         if (service)
636                 g_variant_iter_free(service);
637
638         return preferred_address6;
639 }
640
641 static void __netconfig_adjust_tcp_buffer_size(void)
642 {
643         int fdr = 0, fdw = 0;
644         int fdrmax = 0, fdwmax = 0;
645         const char *rbuf_size = NULL;
646         const char *wbuf_size = NULL;
647         const char *rmax_size = NULL;
648         const char *wmax_size = NULL;
649         const char *profile = netconfig_get_default_profile();
650
651         if (profile == NULL) {
652                 DBG("There is no default connection");
653
654                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
655                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
656         } else if (netconfig_is_wifi_profile(profile) == TRUE) {
657                 DBG("Default connection: Wi-Fi");
658
659                 rbuf_size = NET_TCP_BUFFERSIZE_WIFI_READ;
660                 wbuf_size = NET_TCP_BUFFERSIZE_WIFI_WRITE;
661                 rmax_size = NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX;
662                 wmax_size = NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX;
663         } else if (netconfig_is_cellular_profile(profile) == TRUE) {
664                 int telephony_svctype = 0, telephony_pstype = 0;
665
666                 netconfig_get_telephony_network_type(&telephony_svctype, &telephony_pstype);
667                 DBG("Default cellular %d, %d", telephony_svctype, telephony_pstype);
668
669                 switch (telephony_pstype) {
670                 case VCONFKEY_TELEPHONY_PSTYPE_HSPA:
671                         rbuf_size = NET_TCP_BUFFERSIZE_HSPA_READ;
672                         wbuf_size = NET_TCP_BUFFERSIZE_HSPA_WRITE;
673                         break;
674                 case VCONFKEY_TELEPHONY_PSTYPE_HSUPA:
675                         rbuf_size = NET_TCP_BUFFERSIZE_HSUPA_READ;
676                         wbuf_size = NET_TCP_BUFFERSIZE_HSDPA_WRITE;
677                         break;
678                 case VCONFKEY_TELEPHONY_PSTYPE_HSDPA:
679                         rbuf_size = NET_TCP_BUFFERSIZE_HSDPA_READ;
680                         wbuf_size = NET_TCP_BUFFERSIZE_HSDPA_WRITE;
681                         break;
682 #if !defined TIZEN_WEARABLE
683                 case VCONFKEY_TELEPHONY_PSTYPE_HSPAP:
684                         rbuf_size = NET_TCP_BUFFERSIZE_HSPAP_READ;
685                         wbuf_size = NET_TCP_BUFFERSIZE_HSPAP_WRITE;
686                         break;
687 #endif
688                 default:
689                         switch (telephony_svctype) {
690                         case VCONFKEY_TELEPHONY_SVCTYPE_LTE:
691                                 rbuf_size = NET_TCP_BUFFERSIZE_LTE_READ;
692                                 wbuf_size = NET_TCP_BUFFERSIZE_LTE_WRITE;
693                                 rmax_size = NET_TCP_BUFFERSIZE_LTE_RMEM_MAX;
694                                 break;
695                         case VCONFKEY_TELEPHONY_SVCTYPE_3G:
696                                 rbuf_size = NET_TCP_BUFFERSIZE_UMTS_READ;
697                                 wbuf_size = NET_TCP_BUFFERSIZE_UMTS_WRITE;
698                                 break;
699                         case VCONFKEY_TELEPHONY_SVCTYPE_2_5G_EDGE:
700                                 rbuf_size = NET_TCP_BUFFERSIZE_EDGE_READ;
701                                 wbuf_size = NET_TCP_BUFFERSIZE_EDGE_WRITE;
702                                 break;
703                         case VCONFKEY_TELEPHONY_SVCTYPE_2_5G:
704                                 rbuf_size = NET_TCP_BUFFERSIZE_GPRS_READ;
705                                 wbuf_size = NET_TCP_BUFFERSIZE_GPRS_WRITE;
706                                 break;
707                         default:
708                                 /* TODO: Check LTE support */
709                                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
710                                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
711                                 break;
712                         }
713                         break;
714                 }
715         } else {
716                 DBG("Default TCP buffer configured");
717
718                 rbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_READ;
719                 wbuf_size = NET_TCP_BUFFERSIZE_DEFAULT_WRITE;
720         }
721
722         if (rbuf_size != NULL) {
723                 fdr = open(NET_PROC_SYS_NET_IPV4_TCP_RMEM, O_RDWR | O_CLOEXEC);
724
725                 if (fdr < 0 || write(fdr, rbuf_size, strlen(rbuf_size)) < 0)
726                         ERR("Failed to set TCP read buffer size");
727
728                 if (fdr >= 0)
729                         close(fdr);
730         }
731
732         if (wbuf_size != NULL) {
733                 fdw = open(NET_PROC_SYS_NET_IPv4_TCP_WMEM, O_RDWR | O_CLOEXEC);
734
735                 if (fdw < 0 || write(fdw, wbuf_size, strlen(wbuf_size)) < 0)
736                         ERR("Failed to set TCP write buffer size");
737
738                 if (fdw >= 0)
739                         close(fdw);
740         }
741
742         /* As default */
743         if (rmax_size == NULL)
744                 rmax_size = NET_TCP_BUFFERSIZE_WIFI_RMEM_MAX;
745         if (wmax_size == NULL)
746                 wmax_size = NET_TCP_BUFFERSIZE_WIFI_WMEM_MAX;
747
748         if (rmax_size != NULL) {
749                 fdrmax = open(NET_PROC_SYS_NET_CORE_RMEM_MAX, O_RDWR | O_CLOEXEC);
750
751                 if (fdrmax < 0 || write(fdrmax, rmax_size, strlen(rmax_size)) < 0)
752                         ERR("Failed to set TCP rmem_max size");
753
754                 if (fdrmax >= 0)
755                         close(fdrmax);
756         }
757
758         if (wmax_size != NULL) {
759                 fdwmax = open(NET_PROC_SYS_NET_CORE_WMEM_MAX, O_RDWR | O_CLOEXEC);
760
761                 if (fdwmax < 0 || write(fdwmax, wmax_size, strlen(wmax_size)) < 0)
762                         ERR("Failed to set TCP wmem_max size");
763
764                 if (fdwmax >= 0)
765                         close(fdwmax);
766         }
767 }
768
769 static void __netconfig_write_socket_buffer_size(const char *path, int size)
770 {
771         int fd = 0;
772         char buf[11] = {0, };
773
774         snprintf(buf, sizeof(buf) - 1, "%d", size);
775         fd = open(path, O_RDWR | O_CLOEXEC);
776         if (fd < 0) {
777                 ERR("Failed to open %s", path);
778                 return;
779         }
780
781         if (write(fd, buf, strlen(buf)) < 0)
782                 ERR("Failed to set %s", path);
783         close(fd);
784 }
785
786 static void __netconfig_write_socket_buffer_size_list(const char *path, int *size)
787 {
788         int fd = 0;
789         char buf[33] = {0, };
790
791         snprintf(buf, sizeof(buf) - 1, "%d %d %d", size[0], size[1], size[2]);
792         fd = open(path, O_RDWR | O_CLOEXEC);
793         if (fd < 0) {
794                 ERR("Failed to open %s", path);
795                 return;
796         }
797
798         if (write(fd, buf, strlen(buf)) < 0)
799                 ERR("Failed to set %s", path);
800         close(fd);
801 }
802
803 static void __netconfig_adjust_udp_buffer_size(void)
804 {
805         int rmem_default = netconfig_setting_get_read_buffer_size_default();
806         int rmem_max = netconfig_setting_get_read_buffer_size_max();
807         int wmem_default = netconfig_setting_get_write_buffer_size_default();
808         int wmem_max = netconfig_setting_get_write_buffer_size_max();
809         int *udp_mem = netconfig_setting_get_ipv4_udp_buffer_size();
810
811         if (rmem_default == 0 || rmem_max == 0 ||
812                         wmem_default == 0 || wmem_max == 0 || udp_mem == NULL) {
813                 ERR("Failed to get udp buffer size information. Do nothing.");
814                 return;
815         }
816
817         __netconfig_write_socket_buffer_size(NET_PROC_SYS_NET_CORE_RMEM_DEFAULT, rmem_default);
818         __netconfig_write_socket_buffer_size(NET_PROC_SYS_NET_CORE_RMEM_MAX, rmem_max);
819         __netconfig_write_socket_buffer_size(NET_PROC_SYS_NET_CORE_WMEM_DEFAULT, wmem_default);
820         __netconfig_write_socket_buffer_size(NET_PROC_SYS_NET_CORE_WMEM_MAX, wmem_max);
821         __netconfig_write_socket_buffer_size_list(NET_PROC_SYS_NET_IPV4_UDP_MEM, udp_mem);
822 }
823
824 static void __netconfig_update_default_connection_info(void)
825 {
826         int old_network_status = 0;
827         const char *profile = netconfig_get_default_profile();
828         const char *ip_addr = netconfig_get_default_ipaddress();
829         const char *ip_addr6 = netconfig_get_default_ipaddress6();
830         const char *proxy_addr = netconfig_get_default_proxy();
831         unsigned int freq = netconfig_get_default_frequency();
832         GVariantBuilder *builder;
833         GVariant *params;
834
835         if (emulator_is_emulated() == TRUE) {
836                 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
837
838                 if (ip_addr != NULL) {
839                         netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr, TRUE);
840                         g_variant_builder_add(builder, "{sv}", "IPv4Address",
841                                                                   g_variant_new_string(ip_addr));
842                 } else {
843                         netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "", TRUE);
844                         g_variant_builder_add(builder, "{sv}", "IPv4Address",
845                                                                   g_variant_new_string(""));
846                 }
847
848                 if (ip_addr6 != NULL) {
849                         netconfig_set_vconf_str(VCONFKEY_NETWORK_IP6, ip_addr6, TRUE);
850                         g_variant_builder_add(builder, "{sv}", "IPv6Address",
851                                                                   g_variant_new_string(ip_addr6));
852                 } else {
853                         netconfig_set_vconf_str(VCONFKEY_NETWORK_IP6, "", TRUE);
854                         g_variant_builder_add(builder, "{sv}", "IPv6Address",
855                                                                   g_variant_new_string(""));
856                 }
857
858                 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
859                 g_variant_builder_unref(builder);
860
861                 netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
862                                                    NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
863                                                    params);
864
865                 return;
866         }
867
868         if (profile == NULL)
869                 DBG("Reset network state configuration");
870         else
871                 DBG("profile[%s] ipv4(%s) ipv6(%s) proxy(%s)", profile, ip_addr,
872                         ip_addr6, proxy_addr);
873
874         netconfig_vconf_get_int(VCONFKEY_NETWORK_STATUS, &old_network_status);
875
876         if (profile == NULL && old_network_status != VCONFKEY_NETWORK_OFF) {
877                 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
878
879                 netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_OFF, TRUE);
880                 g_variant_builder_add(builder, "{sv}", "NetworkStatus",
881                                                           g_variant_new_int32(VCONFKEY_NETWORK_OFF));
882
883                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "", TRUE);
884                 g_variant_builder_add(builder, "{sv}", "IPv4Address",
885                                                           g_variant_new_string(""));
886
887                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP6, "", TRUE);
888                 g_variant_builder_add(builder, "{sv}", "IPv6Address",
889                                                           g_variant_new_string(""));
890
891                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, "", TRUE);
892                 g_variant_builder_add(builder, "{sv}", "ProxyAddress",
893                                                           g_variant_new_string(""));
894
895                 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
896
897                 netconfig_set_vconf_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, 0, TRUE);
898                 netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
899                                                    NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
900                                                    params);
901                 netconfig_set_vconf_int("memory/private/wifi/frequency", 0, TRUE);
902
903                 g_variant_builder_unref(builder);
904
905                 DBG("Successfully clear IP and PROXY up");
906
907                 /* Try to disable CLATD if it was enabled */
908                 DBG("Disable clatd");
909                 netconfig_clatd_disable();
910         } else if (profile != NULL) {
911                 char *old_ip = vconf_get_str(VCONFKEY_NETWORK_IP);
912                 char *old_ip6 = vconf_get_str(VCONFKEY_NETWORK_IP6);
913                 char *old_proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY);
914
915                 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
916
917                 if (netconfig_is_wifi_profile(profile) == TRUE) {
918                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_WIFI, TRUE);
919                         g_variant_builder_add(builder, "{sv}", "NetworkStatus",
920                                                           g_variant_new_int32(VCONFKEY_NETWORK_WIFI));
921                         netconfig_set_vconf_int("memory/private/wifi/frequency", freq, TRUE);
922
923                         netconfig_set_system_event(SYS_EVT_NETWORK_STATUS,
924                                 EKEY_NETWORK_STATUS, EVAL_NETWORK_WIFI);
925                 } else if (netconfig_is_cellular_profile(profile)) {
926
927                         if (!netconfig_is_cellular_internet_profile(profile)) {
928                                 DBG("connection is not a internet profile - stop to update the cellular state");
929                                 if (old_ip)
930                                         free(old_ip);
931                                 if (old_ip6)
932                                         free(old_ip6);
933                                 if (old_proxy)
934                                         free(old_proxy);
935                                 return;
936                         }
937
938                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_CELLULAR, TRUE);
939                         g_variant_builder_add(builder, "{sv}", "NetworkStatus",
940                                                           g_variant_new_int32(VCONFKEY_NETWORK_CELLULAR));
941
942                         netconfig_set_system_event(SYS_EVT_NETWORK_STATUS,
943                                 EKEY_NETWORK_STATUS, EVAL_NETWORK_CELLULAR);
944                         /* Enable clatd if IPv6 is set and no IPv4 address */
945                         if (!ip_addr && ip_addr6) {
946                                 DBG("Enable clatd");
947                                 netconfig_clatd_enable();
948                         }
949                 } else if (netconfig_is_ethernet_profile(profile) == TRUE) {
950                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_ETHERNET, TRUE);
951                         g_variant_builder_add(builder, "{sv}", "NetworkStatus",
952                                                           g_variant_new_int32(VCONFKEY_NETWORK_ETHERNET));
953                         netconfig_set_system_event(SYS_EVT_NETWORK_STATUS,
954                                 EKEY_NETWORK_STATUS, EVAL_NETWORK_ETHERNET);
955                 } else if (netconfig_is_bluetooth_profile(profile) == TRUE) {
956                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_BLUETOOTH, TRUE);
957                         g_variant_builder_add(builder, "{sv}", "NetworkStatus",
958                                                           g_variant_new_int32(VCONFKEY_NETWORK_BLUETOOTH));
959                         netconfig_set_system_event(SYS_EVT_NETWORK_STATUS,
960                                 EKEY_NETWORK_STATUS, EVAL_NETWORK_BT);
961                 } else{
962                         netconfig_set_vconf_int(VCONFKEY_NETWORK_STATUS, VCONFKEY_NETWORK_OFF, TRUE);
963                         g_variant_builder_add(builder, "{sv}", "NetworkStatus",
964                                                           g_variant_new_int32(VCONFKEY_NETWORK_OFF));
965                         netconfig_set_system_event(SYS_EVT_NETWORK_STATUS,
966                                 EKEY_NETWORK_STATUS, EVAL_NETWORK_DISCONNECTED);
967                 }
968
969                 if (g_strcmp0(old_ip, ip_addr) != 0 || old_ip == NULL) {
970                         if (ip_addr != NULL) {
971                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, ip_addr, TRUE);
972                                 g_variant_builder_add(builder, "{sv}", "IPv4Address",
973                                                                   g_variant_new_string(ip_addr));
974                         } else if (old_ip != NULL && strlen(old_ip) > 0) {
975                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP, "", TRUE);
976                                 g_variant_builder_add(builder, "{sv}", "IPv4Address",
977                                                                   g_variant_new_string(""));
978                         }
979                 }
980                 if (old_ip)
981                         free(old_ip);
982
983                 if (g_strcmp0(old_ip6, ip_addr6) != 0 || old_ip6 == NULL) {
984                         if (ip_addr6 != NULL) {
985                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP6, ip_addr6, TRUE);
986                                 g_variant_builder_add(builder, "{sv}", "IPv6Address",
987                                                                   g_variant_new_string(ip_addr6));
988                         } else if (old_ip6 != NULL && strlen(old_ip6) > 0) {
989                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_IP6, "", TRUE);
990                                 g_variant_builder_add(builder, "{sv}", "IPv6Address",
991                                                                   g_variant_new_string(""));
992                         }
993                 }
994                 if (old_ip6)
995                         free(old_ip6);
996
997                 if (g_strcmp0(old_proxy, proxy_addr) != 0) {
998                         if (proxy_addr == NULL) {
999                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, "", TRUE);
1000                                 g_variant_builder_add(builder, "{sv}", "ProxyAddress",
1001                                                                   g_variant_new_string(""));
1002                         } else {
1003                                 netconfig_set_vconf_str(VCONFKEY_NETWORK_PROXY, proxy_addr, TRUE);
1004                                 g_variant_builder_add(builder, "{sv}", "ProxyAddress",
1005                                                                   g_variant_new_string(proxy_addr));
1006                         }
1007                 }
1008                 if (old_proxy)
1009                         free(old_proxy);
1010
1011                 params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
1012
1013                 netconfig_set_vconf_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, 1, TRUE);
1014                 netconfig_dbus_emit_signal(NULL, NETCONFIG_NETWORK_PATH,
1015                                                    NETCONFIG_NETWORK_INTERFACE, "NetworkConfigChanged",
1016                                                    params);
1017
1018                 g_variant_builder_unref(builder);
1019
1020                 DBG("Successfully update default network configuration");
1021         }
1022
1023         __netconfig_adjust_tcp_buffer_size();
1024         __netconfig_adjust_udp_buffer_size();
1025 }
1026
1027 static gboolean __netconfig_is_tech_state_connected(void)
1028 {
1029         gboolean ret = FALSE;
1030         GVariant *message = NULL, *variant;
1031         GVariantIter *iter, *next;
1032         gchar *path;
1033         gchar *key;
1034
1035         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
1036                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
1037                         "GetTechnologies", NULL);
1038
1039         if (message == NULL) {
1040                 DBG("Fail to get technology state");
1041                 return FALSE;
1042         }
1043
1044         g_variant_get(message, "(a(oa{sv}))", &iter);
1045         while (g_variant_iter_loop(iter, "(oa{sv})", &path, &next)) {
1046                 if (path == NULL)
1047                         continue;
1048
1049                 while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
1050                         gboolean data;
1051                         if (g_strcmp0(key, "Connected") == 0) {
1052                                 data = g_variant_get_boolean(variant);
1053                                 DBG("%s [%s: %s]", path, key, data ? "True" : "False");
1054                                 if (TRUE == data) {
1055                                         ret = TRUE;
1056                                         g_free(path);
1057                                         g_free(key);
1058                                         g_variant_unref(variant);
1059                                         g_variant_iter_free(next);
1060                                         goto done;
1061                                 }
1062                         }
1063                 }
1064         }
1065
1066 done:
1067         g_variant_iter_free(iter);
1068         g_variant_unref(message);
1069
1070         return ret;
1071 }
1072
1073 static void __netconfig_network_notify_result(const char *sig_name, const char *key)
1074 {
1075         GVariantBuilder *builder;
1076         GVariant *params;
1077
1078         INFO("[Signal] %s %s", sig_name, key);
1079
1080         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1081         g_variant_builder_add(builder, "{sv}", "key", g_variant_new_string(key));
1082
1083         params = g_variant_new("(@a{sv})", g_variant_builder_end(builder));
1084         g_variant_builder_unref(builder);
1085
1086         netconfig_dbus_emit_signal(NULL,
1087                                 NETCONFIG_NETWORK_PATH,
1088                                 NETCONFIG_NETWORK_INTERFACE,
1089                                 sig_name,
1090                                 params);
1091
1092         return;
1093 }
1094
1095 static char *__netconfig_get_mac_address(const char *profile)
1096 {
1097         char mac_str[MAC_ADDRESS_MAX_LEN] = { 0, };
1098         const char *orgin = NULL;
1099         int org_index, dst_index;
1100         int i;
1101
1102         org_index = strlen(CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
1103         dst_index = 0;
1104
1105         for (i = 0; i < 6; i++) {
1106                 orgin = &profile[org_index];
1107
1108                 memcpy(&mac_str[dst_index], orgin, 2);
1109                 if (i < 5)
1110                         mac_str[dst_index + 2] = ':';
1111                 else
1112                         mac_str[dst_index + 2] = '\0';
1113
1114                 org_index += 2;
1115                 dst_index += 3;
1116         }
1117
1118         return g_strdup(mac_str);
1119 }
1120
1121 const char *netconfig_get_default_profile(void)
1122 {
1123         return netconfig_default_connection_info.profile;
1124 }
1125
1126 const char *netconfig_get_default_ifname(void)
1127 {
1128         return netconfig_default_connection_info.ifname;
1129 }
1130
1131 const char *netconfig_get_default_ipaddress(void)
1132 {
1133         return netconfig_default_connection_info.ipaddress;
1134 }
1135
1136
1137 const char *netconfig_get_default_ipaddress6(void)
1138 {
1139         return netconfig_default_connection_info.ipaddress6;
1140 }
1141
1142 const char *netconfig_get_default_proxy(void)
1143 {
1144         return netconfig_default_connection_info.proxy;
1145 }
1146
1147 unsigned int netconfig_get_default_frequency(void)
1148 {
1149         return netconfig_default_connection_info.freq;
1150 }
1151
1152 const char *netconfig_get_default_mac_address(void)
1153 {
1154         return netconfig_default_connection_info.mac_address;
1155 }
1156
1157 const char *netconfig_wifi_get_connected_essid(const char *default_profile)
1158 {
1159         if (default_profile == NULL)
1160                 return NULL;
1161
1162         if (netconfig_is_wifi_profile(default_profile) != TRUE)
1163                 return NULL;
1164
1165         if (g_strcmp0(default_profile, netconfig_default_connection_info.profile) != 0)
1166                 return NULL;
1167
1168         return netconfig_default_connection_info.essid;
1169 }
1170
1171 gboolean netconfig_get_default_is_metered(void)
1172 {
1173         return netconfig_default_connection_info.is_metered;
1174 }
1175
1176 gboolean netconfig_get_default_is_internet(void)
1177 {
1178         return netconfig_default_connection_info.is_internet;
1179 }
1180
1181 void netconfig_set_default_ipaddress(const char *ipaddr)
1182 {
1183         netconfig_default_connection_info.ipaddress = g_strdup(ipaddr);
1184 }
1185
1186 void netconfig_set_default_ipaddress6(const char *ipaddr)
1187 {
1188         netconfig_default_connection_info.ipaddress6 = g_strdup(ipaddr);
1189 }
1190
1191 void netconfig_set_default_proxy(const char *proxy)
1192 {
1193         netconfig_default_connection_info.proxy = g_strdup(proxy);
1194 }
1195
1196 void netconfig_set_default_is_internet(gboolean state)
1197 {
1198         netconfig_default_connection_info.is_internet = state;
1199         netconfig_notify_online_state(netconfig_default_connection_info.ifname, state);
1200 }
1201
1202 void netconfig_update_default_profile(void)
1203 {
1204         if (__netconfig_get_default_connection_info())
1205                 __netconfig_update_default_connection_info();
1206 }
1207
1208 void netconfig_update_default(void)
1209 {
1210         if (__netconfig_is_tech_state_connected() == TRUE) {
1211                 netconfig_update_default_profile();
1212         } else {
1213                 __netconfig_adjust_tcp_buffer_size();
1214                 __netconfig_adjust_udp_buffer_size();
1215         }
1216 }
1217
1218 const char *netconfig_get_ifname(const char *profile)
1219 {
1220         const char *ifname = NULL;
1221         char *mac_addr = NULL;
1222
1223         mac_addr = __netconfig_get_mac_address(profile);
1224         ifname = wifi_state_get_interface_name(mac_addr);
1225
1226         g_free(mac_addr);
1227         return ifname;
1228 }
1229
1230 /* Check Ethernet Cable Plug-in /Plug-out Status */
1231 void netconfig_network_notify_ethernet_cable_state(const char *key)
1232 {
1233         __netconfig_network_notify_result("EthernetCableState", key);
1234 }
1235
1236 static gboolean handle_add_route(
1237                 Network *object,
1238                 GDBusMethodInvocation *context,
1239                 gchar *ip_addr,
1240                 gchar *netmask,
1241                 gchar *interface,  gchar *gateway, gint address_family)
1242 {
1243         const gchar *path = ROUTE_EXEC_PATH;
1244         gchar gw_str[64] = {0,};
1245         if (gateway != NULL && strlen(gateway) > 1)
1246                 g_snprintf(gw_str, 64, "gw %s", gateway);
1247         gchar *const args[] = { "/sbin/route", "add", "-net", ip_addr, gw_str,
1248                 "netmask", netmask, "dev", interface, NULL };
1249         gchar *const envs[] = { NULL };
1250         const gchar* buf = NULL;
1251         gchar* ch = NULL;
1252         int prefix_len = 0;
1253         int pos = 0;
1254
1255         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
1256
1257         switch (address_family) {
1258         case AF_INET:
1259                 if (ip_addr == NULL || netmask == NULL || interface == NULL) {
1260                         ERR("Invalid parameter");
1261                         netconfig_error_invalid_parameter(context);
1262                         return TRUE;
1263                 }
1264
1265                 if (netconfig_execute_file(path, args, envs) < 0) {
1266                         DBG("Failed to add a new route");
1267                         netconfig_error_permission_denied(context);
1268                         return TRUE;
1269                 }
1270
1271                 break;
1272         case AF_INET6:
1273                 if (ip_addr == NULL || interface == NULL || gateway == NULL) {
1274                         ERR("Invalid parameter");
1275                         netconfig_error_invalid_parameter(context);
1276                         return TRUE;
1277                 }
1278
1279                 buf = ip_addr;
1280                 ch = strchr(buf, '/');
1281                 pos = ch - buf + 1;
1282                 if (ch) {
1283                         prefix_len = atoi(ch + 1);
1284                         ip_addr[pos-1] = '\0';
1285                 } else {
1286                         prefix_len = 128;
1287                 }
1288
1289                 if (netconfig_add_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
1290                         DBG("Failed to add a new route");
1291                         netconfig_error_permission_denied(context);
1292                         return TRUE;
1293                 }
1294                 break;
1295         default:
1296                 DBG("Unknown Address Family");
1297                 netconfig_error_invalid_parameter(context);
1298                 return TRUE;
1299         }
1300
1301         DBG("Successfully added a new route");
1302         network_complete_add_route(object, context, TRUE);
1303         return TRUE;
1304 }
1305
1306 static gboolean handle_remove_route(
1307                 Network *object,
1308                 GDBusMethodInvocation *context,
1309                 gchar *ip_addr,
1310                 gchar *netmask,
1311                 gchar *interface, gchar *gateway, gint address_family)
1312 {
1313         const char *path = ROUTE_EXEC_PATH;
1314         gchar gw_str[64] = {0,};
1315         if (gateway != NULL && strlen(gateway) > 1)
1316                 g_snprintf(gw_str, 64, "gw %s", gateway);
1317         gchar *const args[] = { "/sbin/route", "del", "-net", ip_addr, gw_str,
1318                 "netmask", netmask, "dev", interface, NULL };
1319         char *const envs[] = { NULL };
1320         const char* buf = NULL;
1321         char* ch = NULL;
1322         int prefix_len = 0;
1323         int pos = 0;
1324
1325         DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
1326
1327         switch (address_family) {
1328         case AF_INET:
1329                 if (ip_addr == NULL || netmask == NULL || interface == NULL) {
1330                         DBG("Invalid parameter!");
1331                         netconfig_error_invalid_parameter(context);
1332                         return TRUE;
1333                 }
1334                 if (netconfig_execute_file(path, args, envs) < 0) {
1335                         DBG("Failed to remove the route");
1336                         netconfig_error_permission_denied(context);
1337                         return TRUE;
1338                 }
1339                 break;
1340         case AF_INET6:
1341                 if (ip_addr == NULL || interface == NULL || gateway == NULL) {
1342                         DBG("Invalid parameter!");
1343                         netconfig_error_invalid_parameter(context);
1344                         return TRUE;
1345                 }
1346
1347                 buf = ip_addr;
1348                 ch = strchr(buf, '/');
1349                 pos = ch - buf + 1;
1350                 if (ch) {
1351                         prefix_len = atoi(ch + 1);
1352                         ip_addr[pos-1] = '\0';
1353                 } else {
1354                         prefix_len = 128;
1355                 }
1356
1357                 if (netconfig_del_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
1358                         DBG("Failed to remove the route");
1359                         netconfig_error_permission_denied(context);
1360                         return TRUE;
1361                 }
1362                 break;
1363         default:
1364                 DBG("Unknown Address Family");
1365                 netconfig_error_invalid_parameter(context);
1366                 return TRUE;
1367         }
1368
1369         DBG("Successfully removed the route");
1370         network_complete_remove_route(object, context, TRUE);
1371         return TRUE;
1372 }
1373
1374 static gboolean handle_check_get_privilege(Network *object,
1375                 GDBusMethodInvocation *context)
1376 {
1377         network_complete_check_get_privilege(object, context);
1378         return TRUE;
1379 }
1380
1381
1382 static gboolean handle_check_profile_privilege(Network *object,
1383                 GDBusMethodInvocation *context)
1384 {
1385         network_complete_check_profile_privilege(object, context);
1386         return TRUE;
1387 }
1388
1389 static gboolean handle_check_internet_privilege(Network *object,
1390                 GDBusMethodInvocation *context)
1391 {
1392         network_complete_check_internet_privilege(object, context);
1393         return TRUE;
1394 }
1395
1396 gboolean handle_ethernet_cable_state(Network *object,
1397         GDBusMethodInvocation *context)
1398 {
1399         int ret = 0;
1400         int state = 0;
1401
1402         ret = netconfig_get_ethernet_cable_state(&state);
1403         if (ret != 0) {
1404                 DBG("Failed to get ethernet cable state");
1405                 netconfig_error_fail_ethernet_cable_state(context);
1406                 return TRUE;
1407         }
1408
1409         DBG("Successfully get ethernet cable state[%d]", state);
1410         network_complete_ethernet_cable_state(object, context, state);
1411         return TRUE;
1412 }
1413
1414 gboolean handle_get_metered_info(Network *object,
1415         GDBusMethodInvocation *context)
1416 {
1417         gboolean state = 0;
1418
1419         state = netconfig_get_default_is_metered();
1420
1421         DBG("Default metered state [%s]", state ? "TRUE" : "FALSE");
1422         network_complete_get_metered_info(object, context, state);
1423         return TRUE;
1424 }
1425
1426 gboolean handle_preferred_ipv6_address(Network *object,
1427         GDBusMethodInvocation *context, gchar *profile)
1428 {
1429         char *address = NULL;
1430
1431         address = __netconfig_get_preferred_ipv6_address(profile);
1432         if (address == NULL) {
1433                 DBG("Failed to get preferred IPv6 address");
1434                 netconfig_error_fail_preferred_ipv6_address(context);
1435                 return TRUE;
1436         }
1437
1438         DBG("Successfully get preferred IPv6 address[%s]", address);
1439         network_complete_preferred_ipv6_address(object, context, address);
1440         return TRUE;
1441 }
1442
1443 gboolean handle_get_battery_dn_list(Battery *object,
1444         GDBusMethodInvocation *context)
1445 {
1446         GVariantBuilder *builder = NULL;
1447         GVariant *ret_params = NULL;
1448         gchar *params_str = NULL;
1449
1450         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1451
1452         netconfig_battery_get_dn_list(builder);
1453
1454         ret_params = g_variant_builder_end(builder);
1455         if (ret_params) {
1456                 params_str = g_variant_print(ret_params, TRUE);
1457                 DBG("DN list [%s]", params_str);
1458                 g_free(params_str);
1459         }
1460
1461         battery_complete_get_battery_dn_list(object, context, ret_params);
1462         g_variant_builder_unref(builder);
1463         return TRUE;
1464 }
1465
1466 gboolean handle_get_battery_wifi_list(Battery *object,
1467         GDBusMethodInvocation *context)
1468 {
1469         GVariantBuilder *builder = NULL;
1470         GVariant *ret_params = NULL;
1471         gchar *params_str = NULL;
1472
1473         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1474
1475         netconfig_battery_get_wifi_list(builder);
1476
1477         ret_params = g_variant_builder_end(builder);
1478         if (ret_params) {
1479                 params_str = g_variant_print(ret_params, TRUE);
1480                 DBG("Wi-Fi list [%s]", params_str);
1481                 g_free(params_str);
1482         }
1483
1484         battery_complete_get_battery_wifi_list(object, context, ret_params);
1485         g_variant_builder_unref(builder);
1486         return TRUE;
1487 }
1488
1489 void state_object_create_and_init(void)
1490 {
1491         DBG("Creating network state object");
1492         GDBusInterfaceSkeleton *interface_network = NULL;
1493 #if defined TIZEN_DEBUG_ENABLE
1494         GDBusInterfaceSkeleton *interface_tcpdump = NULL;
1495 #endif
1496         GDBusInterfaceSkeleton *interface_battery = NULL;
1497         GDBusConnection *connection = NULL;
1498         GDBusObjectManagerServer *server = netdbus_get_state_manager();
1499         if (server == NULL)
1500                 return;
1501
1502         connection = netdbus_get_connection();
1503         g_dbus_object_manager_server_set_connection(server, connection);
1504
1505         /*Interface netconfig.network*/
1506         netconfigstate = network_skeleton_new();
1507
1508         interface_network = G_DBUS_INTERFACE_SKELETON(netconfigstate);
1509         g_signal_connect(netconfigstate, "handle-add-route",
1510                                 G_CALLBACK(handle_add_route), NULL);
1511         g_signal_connect(netconfigstate, "handle-check-get-privilege",
1512                                 G_CALLBACK(handle_check_get_privilege), NULL);
1513         g_signal_connect(netconfigstate, "handle-check-profile-privilege",
1514                                 G_CALLBACK(handle_check_profile_privilege), NULL);
1515         g_signal_connect(netconfigstate, "handle-check-internet-privilege",
1516                                 G_CALLBACK(handle_check_internet_privilege), NULL);
1517         g_signal_connect(netconfigstate, "handle-ethernet-cable-state",
1518                                 G_CALLBACK(handle_ethernet_cable_state), NULL);
1519         g_signal_connect(netconfigstate, "handle-preferred-ipv6-address",
1520                                 G_CALLBACK(handle_preferred_ipv6_address), NULL);
1521         g_signal_connect(netconfigstate, "handle-remove-route",
1522                                 G_CALLBACK(handle_remove_route), NULL);
1523         g_signal_connect(netconfigstate, "handle-device-policy-set-wifi",
1524                                 G_CALLBACK(handle_device_policy_set_wifi), NULL);
1525         g_signal_connect(netconfigstate, "handle-device-policy-get-wifi",
1526                                 G_CALLBACK(handle_device_policy_get_wifi), NULL);
1527         g_signal_connect(netconfigstate, "handle-device-policy-set-wifi-profile",
1528                                 G_CALLBACK(handle_device_policy_set_wifi_profile), NULL);
1529         g_signal_connect(netconfigstate, "handle-device-policy-get-wifi-profile",
1530                                 G_CALLBACK(handle_device_policy_get_wifi_profile), NULL);
1531         g_signal_connect(netconfigstate, "handle-get-metered-info",
1532                                 G_CALLBACK(handle_get_metered_info), NULL);
1533
1534         if (!g_dbus_interface_skeleton_export(interface_network, connection,
1535                         NETCONFIG_NETWORK_STATE_PATH, NULL)) {
1536                 ERR("Export with path failed");
1537         }
1538
1539 #if defined TIZEN_DEBUG_ENABLE
1540         /*Interface netconfig.tcpdump*/
1541         tcpdump_object = tcpdump_skeleton_new();
1542
1543         interface_tcpdump = G_DBUS_INTERFACE_SKELETON(tcpdump_object);
1544         g_signal_connect(tcpdump_object, "handle-start-tcpdump",
1545                                 G_CALLBACK(handle_start_tcpdump), NULL);
1546         g_signal_connect(tcpdump_object, "handle-stop-tcpdump",
1547                                 G_CALLBACK(handle_stop_tcpdump), NULL);
1548         g_signal_connect(tcpdump_object, "handle-get-tcpdump-state",
1549                                 G_CALLBACK(handle_get_tcpdump_state), NULL);
1550
1551         if (!g_dbus_interface_skeleton_export(interface_tcpdump, connection,
1552                         NETCONFIG_NETWORK_STATE_PATH, NULL)) {
1553                 ERR("Export with path failed");
1554         }
1555 #endif
1556
1557         battery_object = battery_skeleton_new();
1558
1559         interface_battery = G_DBUS_INTERFACE_SKELETON(battery_object);
1560         g_signal_connect(battery_object, "handle-get-battery-dn-list",
1561                                 G_CALLBACK(handle_get_battery_dn_list), NULL);
1562         g_signal_connect(battery_object, "handle-get-battery-wifi-list",
1563                                 G_CALLBACK(handle_get_battery_wifi_list), NULL);
1564
1565         if (!g_dbus_interface_skeleton_export(interface_battery, connection,
1566                         NETCONFIG_NETWORK_STATE_PATH, NULL)) {
1567                 ERR("Export with path failed");
1568         }
1569 }
1570
1571 void state_object_deinit(void)
1572 {
1573         g_object_unref(netconfigstate);
1574 #if defined TIZEN_DEBUG_ENABLE
1575         g_object_unref(tcpdump_object);
1576 #endif
1577 }
1578
1579 static gboolean __netconfig_check_ipv6_address(const char *address)
1580 {
1581         unsigned char buf[sizeof(struct in6_addr)];
1582         int err;
1583
1584         if (!address)
1585                 return FALSE;
1586
1587         err = inet_pton(AF_INET6, address, buf);
1588         if (err > 0)
1589                 return TRUE;
1590
1591         return FALSE;
1592 }
1593
1594 char *netconfig_get_connected_cellular_internet_ipv6only_profile(struct clatd_ctrl_hint *hint)
1595 {
1596         GVariant *message = NULL;
1597         GVariantIter *iter = NULL;
1598         GVariantIter *next = NULL;
1599         gchar *cellular_internet_profile = NULL;
1600         gchar *object_path = NULL;
1601
1602         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE,
1603                         CONNMAN_MANAGER_PATH, CONNMAN_MANAGER_INTERFACE,
1604                         "GetServices", NULL);
1605         if (message == NULL) {
1606                 ERR("Failed to get profiles");
1607                 return NULL;
1608         }
1609
1610         g_variant_get(message, "(a(oa{sv}))", &iter);
1611         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
1612                 if (object_path == NULL)
1613                         continue;
1614
1615                 if (netconfig_is_cellular_profile(object_path) == FALSE)
1616                         continue;
1617
1618                 if (netconfig_is_cellular_internet_profile(object_path) == FALSE)
1619                         continue;
1620
1621                 if (__netconfig_is_connected(next) == TRUE) {
1622                         DBG("found connected profiles");
1623                         gchar *key = NULL;
1624                         gboolean has_v4 = FALSE, has_v6 = FALSE;
1625
1626                         GVariant *variant = NULL;
1627                         while (g_variant_iter_loop(next, "{sv}", &key, &variant)) {
1628                                 if (g_strcmp0(key, "IPv4") == 0) {
1629                                         GVariantIter *ipv4_iter = NULL;
1630                                         GVariant *ipv4_variant = NULL;
1631                                         gchar *ipv4_key = NULL;
1632                                         const gchar *ipv4_value = NULL;
1633                                         g_variant_get(variant, "a{sv}", &ipv4_iter);
1634                                         while (g_variant_iter_loop(ipv4_iter, "{sv}",
1635                                                 &ipv4_key, &ipv4_variant)) {
1636                                                 if (g_strcmp0(ipv4_key, "Address") == 0) {
1637                                                         ipv4_value = g_variant_get_string(ipv4_variant, NULL);
1638                                                         DBG("ipv4: %s", ipv4_value);
1639                                                         has_v4 = TRUE;
1640                                                 }
1641                                         }
1642                                         g_variant_iter_free (ipv4_iter);
1643                                 } else if (g_strcmp0(key, "IPv6") == 0) {
1644                                         GVariantIter *ipv6_iter = NULL;
1645                                         GVariant *ipv6_variant = NULL;
1646                                         gchar *ipv6_key = NULL;
1647                                         const gchar *ipv6_value = NULL;
1648                                         g_variant_get(variant, "a{sv}", &ipv6_iter);
1649                                         while (g_variant_iter_loop(ipv6_iter, "{sv}",
1650                                                 &ipv6_key, &ipv6_variant)) {
1651                                                 if (g_strcmp0(ipv6_key, "Address") == 0) {
1652                                                         ipv6_value = g_variant_get_string(ipv6_variant, NULL);
1653                                                         DBG("ipv6: %s", ipv6_value);
1654                                                         has_v6 = TRUE;
1655                                                 }
1656                                         }
1657                                         g_variant_iter_free (ipv6_iter);
1658                                 } else if (hint && g_strcmp0(key, "Nameservers") == 0) {
1659                                         int idx = 0;
1660                                         GVariantIter *ns_iter = NULL;
1661                                         gchar *nameserver = NULL;
1662                                         g_variant_get(variant, "as", &ns_iter);
1663                                         while(g_variant_iter_loop(ns_iter, "s", &nameserver)) {
1664                                                 INFO("nameserver[%d]: %s", idx, nameserver);
1665                                                 if (idx >= MAX_DNS) {
1666                                                         INFO("index exceeded %d -- skip", idx);
1667                                                         continue;
1668                                                 }
1669                                                 if (__netconfig_check_ipv6_address(nameserver) == TRUE) {
1670                                                         hint->nameserver[idx] = g_strdup(nameserver);
1671                                                         idx++;
1672                                                 } else {
1673                                                         INFO("malformed address %s -- skip", nameserver);
1674                                                 }
1675                                         }
1676                                 }
1677                         }
1678
1679                         if (!has_v4 && has_v6) {
1680                                 DBG("found 'ipv6-only/connected/internet cellular profile'");
1681                                 cellular_internet_profile = g_strdup(object_path);
1682                                 g_free(object_path);
1683                                 g_variant_iter_free(next);
1684                                 break;
1685                         }
1686                 }
1687         }
1688         g_variant_iter_free(iter);
1689         g_variant_unref(message);
1690
1691         return cellular_internet_profile;
1692 }