Added support to delete ipv6 route using netlink.
[platform/core/connectivity/net-config.git] / src / utils / util.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 <dlfcn.h>
21 #include <errno.h>
22 #include <vconf.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <net/if.h>
28 #include <net/route.h>
29 #include <arpa/inet.h>
30 #include <sys/wait.h>
31 #include <sys/stat.h>
32 #include <sys/ioctl.h>
33 #include <ctype.h>
34 #include <vconf-keys.h>
35 #include <tzplatform_config.h>
36 #include <system_info.h>
37 #include <stdint.h>
38 #include <linux/netlink.h>
39 #include <linux/rtnetlink.h>
40
41 #include "log.h"
42 #include "util.h"
43 #include "neterror.h"
44 #include "wifi-state.h"
45 #include "netdbus.h"
46
47 #define DBUS_SERVICE_DBUS               "org.freedesktop.DBus"
48 #define DBUS_INTERFACE_DBUS             "org.freedesktop.DBus"
49 #define MAC_INFO_FILEPATH               tzplatform_mkpath(TZ_SYS_ETC, "/.mac.info")
50 #define MAC_ADDRESS_FILEPATH    "/sys/class/net/wlan0/address"
51 #define MAC_ADDRESS_MAX_LEN             18
52 #define HEADED_PLUGIN_FILEPATH          "/usr/lib/net-config-plugin-headed.so"
53 #define TELEPHONY_PLUGIN_FILEPATH       "/usr/lib/net-config-plugin-telephony.so"
54
55 typedef struct {
56         uint8_t family;
57         uint8_t bytelen;
58         int16_t bitlen;
59         uint32_t flags;
60         uint32_t data[8];
61 } netconfig_inet_prefix_s;
62
63 typedef struct {
64         int                     fd;
65         struct sockaddr_nl      local;
66         struct sockaddr_nl      peer;
67         uint32_t                seq;
68         uint32_t                dump;
69 } netconfig_rtnl_s;
70 netconfig_rtnl_s rth = { .fd = -1 };
71
72 static gboolean netconfig_device_picker_test = FALSE;
73 static int mdnsd_ref_count = 0;
74 typedef struct {
75         char *conn_name;
76         int conn_id;
77 } dnssd_conn_destroy_data;
78
79 static gboolean netconfig_plugin_headed_enabled = FALSE;
80 static gboolean netconfig_plugin_telephony_enabled = FALSE;
81 static void *handle_headed;
82 static void *handle_telephony;
83 static struct netconfig_headed_plugin_t *headed_plugin;
84 static struct netconfig_telephony_plugin_t *telephony_plugin;
85
86 static bool is_feature_checked[NETCONFIG_SUPPORTED_FEATURE_MAX] = {0, };
87 static bool feature_supported[NETCONFIG_SUPPORTED_FEATURE_MAX] = {0, };
88
89 gboolean netconfig_check_passphrase(const gchar *service, const char *passphrase)
90 {
91         gsize length;
92
93         if (!passphrase)
94                 return FALSE;
95
96         length = strlen(passphrase);
97
98         if (g_str_has_suffix(service, "psk") == TRUE) {
99                 if (length == 64) {
100                         for (int i = 0; i < 64; i++)
101                                 if (!isxdigit((unsigned char)passphrase[i]))
102                                         return FALSE;
103                 } else if (length < 8 || length > 63)
104                         return FALSE;
105         } else if (g_str_has_suffix(service, "wep") == TRUE) {
106                 if (length == 10 || length == 26) {
107                         for (int i = 0; i < length; i++)
108                                 if (!isxdigit((unsigned char)passphrase[i]))
109                                         return FALSE;
110                 } else if (length != 5 && length != 13)
111                         return FALSE;
112         }
113
114         return TRUE;
115 }
116
117 GKeyFile *netconfig_keyfile_load(const char *pathname)
118 {
119         GKeyFile *keyfile = NULL;
120         GError *error = NULL;
121
122         keyfile = g_key_file_new();
123         if (g_key_file_load_from_file(keyfile, pathname, 0, &error) != TRUE) {
124                 DBG("Unable to open %s, error %s", pathname, error->message);
125                 g_error_free(error);
126
127                 g_key_file_free(keyfile);
128                 keyfile = NULL;
129         }
130
131         DBG("loaded keyfile %s", pathname);
132         return keyfile;
133 }
134
135 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
136 {
137         gsize size = 0;
138         GError *error = NULL;
139         gchar *keydata = NULL;
140         gchar *needle = NULL, *directory = NULL;
141
142         directory = g_strdup(pathname);
143         needle = g_strrstr(directory, "/");
144
145         if (needle != NULL)
146                 *needle = '\0';
147
148         if (directory == NULL || (*directory) == '\0') {
149                 g_free(directory);
150                 ERR("directory is NULL");
151                 return;
152         }
153
154         if (g_file_test(directory, G_FILE_TEST_IS_DIR) != TRUE) {
155                 if (g_mkdir_with_parents(directory,
156                                 S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
157                         g_free(directory);
158                         ERR("failed to make directory");
159                         return;
160                 }
161         }
162         g_free(directory);
163
164         keydata = g_key_file_to_data(keyfile, &size, &error);
165         if (g_file_set_contents(pathname, keydata, size, &error) != TRUE) {
166                 ERR("Unable to save %s, error %s", pathname, error->message);
167                 g_error_free(error);
168         }
169
170         chmod(pathname, S_IRUSR | S_IWUSR);
171         DBG("Successfully saved keyfile %s", pathname);
172
173         g_free(keydata);
174 }
175
176 void netconfig_start_timer_seconds(guint secs,
177                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
178 {
179         guint t_id = 0;
180
181         if (callback == NULL) {
182                 ERR("callback function is NULL");
183                 return;
184         }
185
186         if ((timer_id != NULL && *timer_id != 0)) {
187                 ERR("timer already is registered");
188                 return;
189         }
190
191         t_id = g_timeout_add_seconds(secs, callback, user_data);
192
193         if (t_id == 0) {
194                 ERR("Can't add timer");
195                 return;
196         }
197
198         if (timer_id != NULL)
199                 *timer_id = t_id;
200 }
201
202 void netconfig_start_timer(guint msecs,
203                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
204 {
205         guint t_id = 0;
206
207         INFO("Register timer with callback pointer (%p)", callback);
208
209         if (callback == NULL) {
210                 ERR("callback function is NULL");
211                 return;
212         }
213
214         if ((timer_id != NULL && *timer_id != 0)) {
215                 ERR("timer already is registered");
216                 return;
217         }
218
219         t_id = g_timeout_add(msecs, callback, user_data);
220
221         if (t_id == 0) {
222                 ERR("Can't add timer");
223                 return;
224         }
225
226         if (timer_id != NULL)
227                 *timer_id = t_id;
228 }
229
230 void netconfig_stop_timer(guint *timer_id)
231 {
232         if (timer_id == NULL) {
233                 ERR("timer is NULL");
234                 return;
235         }
236
237         if (*timer_id != 0) {
238                 g_source_remove(*timer_id);
239                 *timer_id = 0;
240         }
241 }
242
243 static gboolean __netconfig_test_device_picker()
244 {
245         char *favorite_wifi_service = NULL;
246
247         favorite_wifi_service = wifi_get_favorite_service();
248         if (favorite_wifi_service != NULL) {
249                 ERR("favorite_wifi_service is existed[%s] : Donot launch device picker", favorite_wifi_service);
250                 g_free(favorite_wifi_service);
251                 return FALSE;
252         }
253
254         return TRUE;
255 }
256
257 static void __netconfig_pop_device_picker(void)
258 {
259         if (!netconfig_plugin_headed_enabled)
260                 return;
261
262         if (!headed_plugin)
263                 return;
264
265         headed_plugin->pop_device_picker();
266 }
267
268 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
269 {
270         if (__netconfig_test_device_picker() == TRUE)
271                 __netconfig_pop_device_picker();
272
273         return FALSE;
274 }
275
276 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method, guint timer_id)
277 {
278         static guint netconfig_wifi_device_picker_service_timer = 0;
279
280         if (is_set_method != TRUE)
281                 return netconfig_wifi_device_picker_service_timer;
282
283         if (netconfig_wifi_device_picker_service_timer != timer_id)
284                 netconfig_wifi_device_picker_service_timer = timer_id;
285
286         return netconfig_wifi_device_picker_service_timer;
287 }
288
289 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
290 {
291         __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
292 }
293
294 static guint __netconfig_wifi_device_picker_get_timer_id(void)
295 {
296         return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
297 }
298
299 void netconfig_wifi_enable_device_picker_test(void)
300 {
301         netconfig_device_picker_test = TRUE;
302 }
303
304 void netconfig_wifi_device_picker_service_start(void)
305 {
306         const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
307         guint timer_id = 0;
308
309         if (netconfig_device_picker_test == TRUE)
310                 netconfig_device_picker_test = FALSE;
311         else
312                 return;
313
314         int wifi_ug_state;
315
316         netconfig_vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
317         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
318                 return;
319
320         DBG("Register device picker timer with %d milliseconds", NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
321         netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL, __netconfig_wifi_try_device_picker, NULL, &timer_id);
322
323         __netconfig_wifi_device_picker_set_timer_id(timer_id);
324 }
325
326 void netconfig_wifi_device_picker_service_stop(void)
327 {
328         guint timer_id = 0;
329
330         timer_id = __netconfig_wifi_device_picker_get_timer_id();
331         if (timer_id == 0)
332                 return;
333
334         DBG("Clear device picker timer with timer_id %d", timer_id);
335
336         netconfig_stop_timer(&timer_id);
337
338         __netconfig_wifi_device_picker_set_timer_id(timer_id);
339 }
340
341 gboolean netconfig_is_wifi_direct_on(void)
342 {
343         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT))
344                 return FALSE;
345
346         int wifi_direct_state = 0;
347
348         netconfig_vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
349
350         DBG("Wi-Fi direct mode %d", wifi_direct_state);
351         return (wifi_direct_state != 0) ? TRUE : FALSE;
352 }
353
354 gboolean netconfig_is_wifi_tethering_on(void)
355 {
356         if (netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_TETHERING)) {
357                 int wifi_tethering_state = 0;
358
359                 netconfig_vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
360                 DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
361                 if ((wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
362                                 || (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI_AP)) {
363                         DBG("Mobile AP is on");
364                         return TRUE;
365                 }
366         }
367
368         DBG("Mobile AP is off");
369         return FALSE;
370 }
371
372 gboolean netconfig_interface_up(const char *ifname)
373 {
374         int fd;
375         struct ifreq ifr;
376
377         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
378         if (fd < 0)
379                 return FALSE;
380
381         memset(&ifr, 0, sizeof(ifr));
382         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
383
384         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
385                 close(fd);
386                 return FALSE;
387         }
388
389         ifr.ifr_flags |= (IFF_UP | IFF_DYNAMIC);
390         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
391                 close(fd);
392                 return FALSE;
393         }
394
395         close(fd);
396
397         DBG("Successfully activated wireless interface %s", ifname);
398         return TRUE;
399 }
400
401 gboolean netconfig_interface_down(const char *ifname)
402 {
403         int fd;
404         struct ifreq ifr;
405
406         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
407         if (fd < 0)
408                 return FALSE;
409
410         memset(&ifr, 0, sizeof(ifr));
411         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
412
413         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
414                 close(fd);
415                 return FALSE;
416         }
417
418         ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
419         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
420                 close(fd);
421                 return FALSE;
422         }
423
424         close(fd);
425
426         DBG("Successfully de-activated wireless interface %s", ifname);
427         return TRUE;
428 }
429
430 int netconfig_execute_file(const char *file_path,
431                 char *const args[], char *const envs[])
432 {
433         pid_t pid = 0;
434         int status = 0;
435         int rv = 0;
436         errno = 0;
437         register unsigned int index = 0;
438         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
439
440         while (args[index] != NULL) {
441                 DBG("%s", args[index]);
442                 index++;
443         }
444
445         if (!(pid = fork())) {
446                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
447                 DBG("Inside child, exec (%s) command", file_path);
448
449                 errno = 0;
450                 if (execve(file_path, args, envs) == -1) {
451                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
452                         DBG("Fail to execute command (%s)", error_buf);
453                         exit(1);
454                 }
455         } else if (pid > 0) {
456                 if (waitpid(pid, &status, 0) == -1)
457                         DBG("wait pid (%u) status (%d)", pid, status);
458
459                 if (WIFEXITED(status)) {
460                         rv = WEXITSTATUS(status);
461                         DBG("exited, status=%d", rv);
462                 } else if (WIFSIGNALED(status)) {
463                         DBG("killed by signal %d", WTERMSIG(status));
464                 } else if (WIFSTOPPED(status)) {
465                         DBG("stopped by signal %d", WSTOPSIG(status));
466                 } else if (WIFCONTINUED(status)) {
467                         DBG("continued");
468                 }
469
470                 return rv;
471         }
472
473         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
474         DBG("failed to fork(%s)", error_buf);
475         return -EIO;
476 }
477
478 int netconfig_execute_cmd(const char *cmd)
479 {
480         if (cmd == NULL)
481                 return -EIO;
482
483         pid_t pid = 0;
484         int status = 0;
485         int rv = 0;
486         errno = 0;
487         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
488         gchar **args = NULL;
489
490         DBG("command: %s", cmd);
491
492         args = g_strsplit_set(cmd, " ", -1);
493
494         if (!(pid = fork())) {
495                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
496
497                 errno = 0;
498                 if (execv(args[0], args) == -1) {
499                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
500                         DBG("Fail to execute command (%s)", error_buf);
501                         g_strfreev(args);
502                         exit(1);
503                 }
504         } else if (pid > 0) {
505                 if (waitpid(pid, &status, 0) == -1)
506                         DBG("wait pid (%u) status (%d)", pid, status);
507
508                 if (WIFEXITED(status)) {
509                         rv = WEXITSTATUS(status);
510                         DBG("exited, status=%d", rv);
511                 } else if (WIFSIGNALED(status)) {
512                         DBG("killed by signal %d", WTERMSIG(status));
513                 } else if (WIFSTOPPED(status)) {
514                         DBG("stopped by signal %d", WSTOPSIG(status));
515                 } else if (WIFCONTINUED(status)) {
516                         DBG("continued");
517                 }
518
519                 g_strfreev(args);
520                 return rv;
521         }
522
523         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
524         DBG("failed to fork(%s)", error_buf);
525         g_strfreev(args);
526
527         return -EIO;
528 }
529
530 static void on_clat_handler()
531 {
532         pid_t clat_pid = 0;
533         int state = 0;
534
535         clat_pid = waitpid(-1, &state, WNOHANG);
536
537         DBG("clat(%d) state(%d)", clat_pid, WEXITSTATUS(state));
538 }
539
540 int netconfig_execute_clatd(const char *file_path, char *const args[])
541 {
542         pid_t pid = 0;
543         int rv = 0;
544         errno = 0;
545         register unsigned int index = 0;
546         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
547
548         struct sigaction act;
549         int state = 0;
550
551         act.sa_handler = on_clat_handler;
552         sigemptyset(&act.sa_mask);
553         act.sa_flags = 0;
554
555         state = sigaction(SIGCHLD, &act, 0);
556         if (state != 0) {
557                 DBG("sigaction() : %d");
558                 return -1;
559         }
560
561         while (args[index] != NULL) {
562                 DBG("%s", args[index]);
563                 index++;
564         }
565
566         if (!(pid = fork())) {
567                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
568                 DBG("Inside child, exec (%s) command", file_path);
569
570                 errno = 0;
571                 if (execvp(file_path, args) == -1) {
572                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
573                         ERR("Fail to execute command (%s)", error_buf);
574                         return -1;
575                 }
576         } else if (pid > 0) {
577                 ERR("Success to launch clatd");
578                 return rv;
579         }
580
581         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
582         DBG("failed to fork(%s)", error_buf);
583         return -EIO;
584 }
585
586 static void no_wait_signal_handler()
587 {
588         pid_t child_pid = 0;
589         int state = 0;
590
591         child_pid = waitpid(-1, &state, WNOHANG);
592
593         DBG("child_id(%d) state(%d)", child_pid, WEXITSTATUS(state));
594 }
595
596 int netconfig_execute_file_no_wait(const char *file_path, char *const args[])
597 {
598         pid_t pid = 0;
599         int rv = 0;
600         errno = 0;
601         register unsigned int index = 0;
602
603         struct sigaction act;
604         int state = 0;
605         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
606
607         act.sa_handler = no_wait_signal_handler;
608         sigemptyset(&act.sa_mask);
609         act.sa_flags = 0;
610
611         state = sigaction(SIGCHLD, &act, 0);
612         if (state != 0) {
613                 DBG("sigaction() : %d");
614                 return -1;
615         }
616
617         while (args[index] != NULL) {
618                 DBG("%s", args[index]);
619                 index++;
620         }
621
622         if (!(pid = fork())) {
623                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
624                 DBG("Inside child, exec (%s) command", file_path);
625
626                 errno = 0;
627                 if (execvp(file_path, args) == -1) {
628                         ERR("Fail to execute command (%s)",
629                                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
630                         return -1;
631                 }
632         } else if (pid > 0) {
633                 ERR("Successfully launched child process");
634                 return rv;
635         }
636
637         DBG("failed to fork(%s)",
638                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
639         return -EIO;
640 }
641
642 int __netconfig_get_interface_index(const char *interface_name)
643 {
644         struct ifreq ifr;
645         int sock = 0;
646         int result = 0;
647         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
648
649         if (interface_name == NULL) {
650                 DBG("Inteface name is NULL");
651                 return -1;
652         }
653
654         errno = 0;
655         sock = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
656         if (sock < 0) {
657                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
658                 DBG("Failed to create socket : %s", error_buf);
659                 return -1;
660         }
661
662         memset(&ifr, 0, sizeof(ifr));
663         strncpy(ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
664         result = ioctl(sock, SIOCGIFINDEX, &ifr);
665         close(sock);
666
667         if (result < 0) {
668                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
669                 DBG("Failed to get ifr index: %s", error_buf);
670                 return -1;
671         }
672
673         return ifr.ifr_ifindex;
674 }
675
676 int netconfig_add_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
677 {
678         struct ifreq ifr;
679         struct rtentry rt;
680         struct sockaddr_in addr_in;
681         int sock;
682         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
683
684         memset(&ifr, 0, sizeof(ifr));
685
686         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
687
688         if (ifr.ifr_ifindex < 0)
689                 return -1;
690
691         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
692
693         memset(&rt, 0, sizeof(rt));
694
695         rt.rt_flags = RTF_UP | RTF_HOST;
696         memset(&addr_in, 0, sizeof(struct sockaddr_in));
697         addr_in.sin_family = address_family;
698         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
699         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
700
701         memset(&addr_in, 0, sizeof(struct sockaddr_in));
702         addr_in.sin_family = address_family;
703         addr_in.sin_addr.s_addr = INADDR_ANY;
704         memcpy(&rt.rt_gateway, &addr_in, sizeof(rt.rt_gateway));
705
706         memset(&addr_in, 0, sizeof(struct sockaddr_in));
707         addr_in.sin_family = AF_INET;
708         addr_in.sin_addr.s_addr = inet_addr(subnet);
709         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
710
711         rt.rt_dev = ifr.ifr_name;
712
713         errno = 0;
714         sock = socket(PF_INET, SOCK_DGRAM, 0);
715
716         if (sock < 0) {
717                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
718                 DBG("Failed to create socket : %s", error_buf);
719                 return -1;
720         }
721
722         if (ioctl(sock, SIOCADDRT, &rt) < 0) {
723                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
724                 DBG("Failed to set route address : %s", error_buf);
725                 close(sock);
726                 return -1;
727         }
728
729         close(sock);
730
731         return 1;
732 }
733
734 int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
735 {
736         struct ifreq ifr;
737         struct rtentry rt;
738         struct sockaddr_in addr_in;
739         int sock;
740         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
741
742         memset(&ifr, 0, sizeof(ifr));
743         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
744
745         if (ifr.ifr_ifindex < 0)
746                 return -1;
747
748         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
749
750         memset(&rt, 0, sizeof(rt));
751
752         rt.rt_flags = RTF_UP;
753         memset(&addr_in, 0, sizeof(struct sockaddr_in));
754         addr_in.sin_family = address_family;
755         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
756         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
757
758         memset(&addr_in, 0, sizeof(struct sockaddr_in));
759         addr_in.sin_family = address_family;
760         addr_in.sin_addr.s_addr = inet_addr(subnet);
761         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
762         rt.rt_dev = ifr.ifr_name;
763
764         errno = 0;
765         sock = socket(PF_INET, SOCK_DGRAM, 0);
766
767         if (sock < 0) {
768                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
769                 DBG("Failed to create socket : %s", error_buf);
770                 return -1;
771         }
772
773         if (ioctl(sock, SIOCDELRT, &rt) < 0) {
774                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
775                 DBG("Failed to set route address : %s", error_buf);
776                 close(sock);
777                 return -1;
778         }
779
780         close(sock);
781
782         return 1;
783 }
784
785 static int __netconfig_rtnl_talk(netconfig_rtnl_s *rtnl, struct nlmsghdr *n, pid_t peer,
786                 unsigned groups, struct nlmsghdr *answer)
787 {
788         struct nlmsghdr *h;
789         struct sockaddr_nl nladdr;
790         struct iovec iov = {
791                 .iov_base = (void*)n,
792                 .iov_len = n->nlmsg_len
793         };
794         struct msghdr msg = {
795                 .msg_name = &nladdr,
796                 .msg_namelen = sizeof(nladdr),
797                 .msg_iov = &iov,
798                 .msg_iovlen = 1,
799         };
800         int status;
801         unsigned seq;
802         char buf[16384];
803         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
804
805         memset(&nladdr, 0, sizeof(nladdr));
806         nladdr.nl_family = AF_NETLINK;
807         nladdr.nl_pid = peer;
808         nladdr.nl_groups = groups;
809
810         n->nlmsg_seq = seq = ++rtnl->seq;
811
812         if (answer == NULL)
813                 n->nlmsg_flags |= NLM_F_ACK;
814
815         status = sendmsg(rtnl->fd, &msg, 0);
816         if (status < 0) {
817                 DBG("failed to send message to kernel, status: %d", status);
818                 return -1;
819         }
820
821         memset(buf, 0, sizeof(buf));
822
823         iov.iov_base = buf;
824
825         while (1) {
826                 iov.iov_len = sizeof(buf);
827                 status = recvmsg(rtnl->fd, &msg, 0);
828                 DBG("status: %d", status);
829
830                 if (status < 0) {
831                         if (errno == EINTR || errno == EAGAIN)
832                                 continue;
833                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
834                         DBG("netlink receive error %s (%d)", error_buf, errno);
835                         return -1;
836                 }
837                 if (status == 0) {
838                         DBG("EOF on netlink");
839                         return -1;
840                 }
841                 if (msg.msg_namelen != sizeof(nladdr)) {
842                         DBG("sender address length == %d", msg.msg_namelen);
843                         return -1;
844                 }
845                 for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
846                         int len = h->nlmsg_len;
847                         int l = len - sizeof(*h);
848
849                         if (l < 0 || len > status) {
850                                 if (msg.msg_flags & MSG_TRUNC) {
851                                         DBG("truncated message");
852                                         return -1;
853                                 }
854                                 DBG("malformed message: len=%d", len);
855                                 return -1;
856                         }
857
858                         if (nladdr.nl_pid != peer ||
859                                         h->nlmsg_pid != rtnl->local.nl_pid ||
860                                         h->nlmsg_seq != seq) {
861                                 /** Don't forget to skip that message. */
862                                 status -= NLMSG_ALIGN(len);
863                                 h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
864                                 continue;
865                         }
866
867                         if (h->nlmsg_type == NLMSG_ERROR) {
868                                 struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
869                                 if (l < sizeof(struct nlmsgerr)) {
870                                         DBG("Error truncated message");
871                                 } else {
872                                         if (!err->error) {
873                                                 if (answer)
874                                                         memcpy(answer, h, h->nlmsg_len);
875                                                 return 0;
876                                         }
877
878                                         errno = -err->error;
879                                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
880                                         DBG("RTNETLINK answers: %s", error_buf);
881                                 }
882                                 return -1;
883                         }
884                         if (answer) {
885                                 memcpy(answer, h, h->nlmsg_len);
886                                 return 0;
887                         }
888
889                         DBG("Unexpected reply");
890
891                         status -= NLMSG_ALIGN(len);
892                         h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
893                 }
894                 if (msg.msg_flags & MSG_TRUNC) {
895                         DBG("Message truncated");
896                         continue;
897                 }
898                 if (status) {
899                         DBG("Remnant of size %d", status);
900                         return -1;
901                 }
902         }
903 }
904
905 static int __netconfig_get_prefix(netconfig_inet_prefix_s *dst, char *arg, int family)
906 {
907         if (family != AF_UNSPEC && family != AF_INET6) {
908                 DBG("Error: invalid address family.");
909                 return -1;
910         }
911
912         memset(dst, 0, sizeof(*dst));
913
914         if (strchr(arg, ':')) {
915                 dst->family = AF_INET6;
916                 if (inet_pton(AF_INET6, arg, dst->data) <= 0) {
917                         DBG("Error: invalid ipv6 address.");
918                         return -1;
919                 }
920                 dst->bytelen = 16;
921                 dst->bitlen = 128;
922         }
923
924         return 0;
925 }
926
927 static int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
928                 int alen)
929 {
930         int len = RTA_LENGTH(alen);
931         struct rtattr *rta;
932
933         if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
934                 DBG("Error message exceeded bound of %d", maxlen);
935                 return -1;
936         }
937         rta = NLMSG_TAIL(n);
938         rta->rta_type = type;
939         rta->rta_len = len;
940         memcpy(RTA_DATA(rta), data, alen);
941         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
942
943         return 0;
944 }
945
946 static int __netconfig_iproute_modify(int cmd, unsigned flags, char *interface, char *ip_addr)
947 {
948         struct {
949                 struct nlmsghdr n;
950                 struct rtmsg    r;
951                 char            buf[1024];
952         } req;
953
954         struct ifreq ifr;
955         int fd, idx, ret;
956         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
957
958         memset(&req, 0, sizeof(req));
959
960         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
961         req.n.nlmsg_flags = NLM_F_REQUEST|flags;
962         req.n.nlmsg_type = cmd;
963         req.r.rtm_family = AF_INET6;
964
965         if (cmd != RTM_DELROUTE) {
966                 req.r.rtm_protocol = RTPROT_BOOT;
967                 req.r.rtm_type = RTN_UNICAST;
968         }
969
970         fd = socket(AF_INET6, SOCK_DGRAM, 0);
971         if (fd < 0) {
972                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
973                 DBG("Failed to create socket : %s", error_buf);
974                 return -1;
975         }
976
977         memset(&ifr, 0, sizeof(ifr));
978         strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
979         ioctl(fd, SIOCGIFINDEX, &ifr);
980         idx = ifr.ifr_ifindex;
981         close(fd);
982
983         if (ifr.ifr_ifindex == 0) {
984                 DBG("Cannot find device %s", interface);
985                 return -1;
986         }
987
988         netconfig_inet_prefix_s dst;
989
990         ret = __netconfig_get_prefix(&dst, ip_addr, req.r.rtm_family);
991         if (ret < 0)
992                 return -1;
993
994         req.r.rtm_dst_len = dst.bitlen;
995         if (dst.bytelen) {
996                 ret = addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen);
997                 if (ret < 0)
998                         return -1;
999         }
1000
1001         ret = addattr_l(&req.n, sizeof(req), RTA_OIF, &idx, sizeof(uint32_t));
1002         if (ret < 0)
1003                 return -1;
1004
1005         if (__netconfig_rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) {
1006                 DBG("__netconfig_rtnl_talk failed");
1007                 return -1;
1008         }
1009
1010         return 0;
1011 }
1012
1013 static void __netconfig_rtnl_close()
1014 {
1015         if (rth.fd >= 0) {
1016                 close(rth.fd);
1017                 rth.fd = -1;
1018         }
1019 }
1020
1021 static int __netconfig_rtnl_open(netconfig_rtnl_s *rth, unsigned subscriptions,
1022                 int protocol)
1023 {
1024         socklen_t addr_len;
1025         int sndbuf = 32768;
1026         int rcvbuf = 1024 * 1024;
1027         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1028
1029         memset(rth, 0, sizeof(*rth));
1030
1031         rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
1032         if (rth->fd < 0) {
1033                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1034                 DBG("Failed to open netlink socket: %s", error_buf);
1035                 return -1;
1036         }
1037
1038         if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) {
1039                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1040                 DBG("Failed to set option(SO_SNDBUF) on socket [Error: %s]", error_buf);
1041                 return -1;
1042         }
1043
1044         if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) {
1045                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1046                 DBG("Failed to set option(SO_RCVBUF) on socket [Error: %s]", error_buf);
1047                 return -1;
1048         }
1049
1050         memset(&rth->local, 0, sizeof(rth->local));
1051         rth->local.nl_family = AF_NETLINK;
1052         rth->local.nl_groups = subscriptions;
1053
1054         if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
1055                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1056                 DBG("Failed to bind netlink socket [Error: %s]", error_buf);
1057                 return -1;
1058         }
1059
1060         addr_len = sizeof(rth->local);
1061         if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
1062                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1063                 DBG("Failed to getsockname [Error: %s]", error_buf);
1064                 return -1;
1065         }
1066         if (addr_len != sizeof(rth->local)) {
1067                 DBG("Wrong address length %d", addr_len);
1068                 return -1;
1069         }
1070         if (rth->local.nl_family != AF_NETLINK) {
1071                 DBG("Wrong address family %d", rth->local.nl_family);
1072                 return -1;
1073         }
1074         rth->seq = time(NULL);
1075
1076         return 0;
1077 }
1078
1079 int netconfig_add_route_ipv6(gchar *interface, gchar *gateway)
1080 {
1081         int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE);
1082         if (ret < 0) {
1083                 DBG("Failed to open rtnl socket");
1084                 return -1;
1085         }
1086
1087         ret = __netconfig_iproute_modify(RTM_NEWROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway);
1088         if (ret < 0) {
1089                 DBG("Failed to modify ipv6 route.");
1090                 __netconfig_rtnl_close();
1091                 return -1;
1092         }
1093
1094         __netconfig_rtnl_close();
1095         return 0;
1096 }
1097
1098 int netconfig_del_route_ipv6(gchar *interface, gchar *gateway)
1099 {
1100         int ret = __netconfig_rtnl_open(&rth, 0, NETLINK_ROUTE);
1101         if (ret < 0) {
1102                 DBG("Failed to open rtnl socket");
1103                 return -1;
1104         }
1105
1106         ret = __netconfig_iproute_modify(RTM_DELROUTE, NLM_F_CREATE|NLM_F_EXCL, interface, gateway);
1107         if (ret < 0) {
1108                 DBG("Failed to delete ipv6 route.");
1109                 __netconfig_rtnl_close();
1110                 return -1;
1111         }
1112
1113         __netconfig_rtnl_close();
1114         return 0;
1115 }
1116
1117 gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context)
1118 {
1119         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT)) {
1120                 wifi_complete_launch_direct(wifi, context);
1121                 return TRUE;
1122         }
1123
1124         int ret = 0;
1125         DBG("Launch Wi-Fi direct daemon");
1126
1127         const char *path = "/usr/bin/wifi-direct-server.sh";
1128         char *const args[] = { "wifi-direct-server.sh", "start", NULL };
1129         char *const envs[] = { NULL };
1130
1131         ret = netconfig_execute_file(path, args, envs);
1132         if (ret < 0) {
1133                 ERR("Failed to launch Wi-Fi direct daemon");
1134                 netconfig_error_wifi_direct_failed(context);
1135                 return TRUE;
1136         }
1137
1138         wifi_complete_launch_direct(wifi, context);
1139         return TRUE;
1140 }
1141
1142 int execute_mdnsd_script(char* op)
1143 {
1144         const char *path = "/usr/bin/mdnsresponder-server.sh";
1145         char *const args[] = { "mdnsresponder-server.sh", op, NULL };
1146         char *const envs[] = { NULL };
1147
1148         return netconfig_execute_file(path, args, envs);
1149 }
1150
1151 static void __dnssd_conn_destroyed_cb(GDBusConnection *conn,
1152                 const gchar *Name, const gchar *path, const gchar *interface,
1153                 const gchar *sig, GVariant *param, gpointer user_data)
1154 {
1155         gchar *name = NULL;
1156         gchar *old = NULL;
1157         gchar *new = NULL;
1158         dnssd_conn_destroy_data *data = user_data;
1159         GDBusConnection *connection = NULL;
1160         connection = netdbus_get_connection();
1161
1162         if (param == NULL)
1163                 return;
1164
1165         g_variant_get(param, "(sss)", &name, &old, &new);
1166
1167         if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') {
1168                 DBG("Connection %s Destroyed: name %s id %d", data->conn_name, name,
1169                         data->conn_id);
1170                 mdnsd_ref_count--;
1171                 g_dbus_connection_signal_unsubscribe(connection, data->conn_id);
1172                 if (mdnsd_ref_count == 0) {
1173                         if (execute_mdnsd_script("stop") < 0)
1174                                 ERR("Failed to stop mdnsresponder daemon");
1175                 }
1176         }
1177         g_free(name);
1178         g_free(old);
1179         g_free(new);
1180         g_free(data->conn_name);
1181         g_free(data);
1182         return;
1183 }
1184
1185 static void register_dnssd_conn_destroy_signal(gchar *name)
1186 {
1187         dnssd_conn_destroy_data *data;
1188         GDBusConnection *connection = NULL;
1189         connection = netdbus_get_connection();
1190
1191         if (connection == NULL) {
1192                 ERR("Failed to get GDbus Connection");
1193                 return;
1194         }
1195
1196         data = g_try_malloc0(sizeof(dnssd_conn_destroy_data));
1197
1198         if (data == NULL) {
1199                 ERR("Out of Memory!");
1200                 return;
1201         }
1202
1203         data->conn_name = g_strdup(name);
1204
1205         data->conn_id = g_dbus_connection_signal_subscribe(connection,
1206                                                         DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS,
1207                                                         "NameOwnerChanged", NULL, name,
1208                                                         G_DBUS_SIGNAL_FLAGS_NONE, __dnssd_conn_destroyed_cb,
1209                                                         data, NULL);
1210         return;
1211 }
1212
1213 gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context,
1214                                                         gchar *name)
1215 {
1216         DBG("Launch mdnsresponder daemon");
1217
1218         if (execute_mdnsd_script("start") < 0) {
1219                 ERR("Failed to launch mdnsresponder daemon");
1220                 netconfig_error_invalid_parameter(context);
1221                 return FALSE;
1222         }
1223
1224         mdnsd_ref_count++;
1225         register_dnssd_conn_destroy_signal(name);
1226         DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count);
1227
1228         network_complete_launch_mdns(object, context);
1229         return TRUE;
1230 }
1231
1232 gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid)
1233 {
1234         if (!netconfig_plugin_headed_enabled)
1235                 return FALSE;
1236
1237         if (!headed_plugin)
1238                 return FALSE;
1239
1240         return headed_plugin->send_notification_to_net_popup(noti, ssid);
1241 }
1242
1243 int netconfig_send_message_to_net_popup(const char *title,
1244                 const char *content, const char *type, const char *ssid)
1245 {
1246         if (!netconfig_plugin_headed_enabled)
1247                 return 0;
1248
1249         if (!headed_plugin)
1250                 return 0;
1251
1252         return headed_plugin->send_message_to_net_popup(title, content, type, ssid);
1253 }
1254
1255 int netconfig_send_restriction_to_net_popup(const char *title,
1256                 const char *type, const char *restriction)
1257 {
1258         if (!netconfig_plugin_headed_enabled)
1259                 return 0;
1260
1261         if (!headed_plugin)
1262                 return 0;
1263
1264         return headed_plugin->send_restriction_to_net_popup(title, type, restriction);
1265 }
1266
1267 void netconfig_set_system_event(int sys_evt, int evt_key, int evt_val)
1268 {
1269         if (!netconfig_plugin_headed_enabled)
1270                 return;
1271
1272         if (!headed_plugin)
1273                 return;
1274
1275         headed_plugin->set_system_event(sys_evt, evt_key, evt_val);
1276 }
1277
1278 void __netconfig_pop_wifi_connected_poppup(const char *ssid)
1279 {
1280         if (!netconfig_plugin_headed_enabled)
1281                 return;
1282
1283         if (!headed_plugin)
1284                 return;
1285
1286         headed_plugin->pop_wifi_connected_poppup(ssid);
1287 }
1288
1289 void netconfig_get_telephony_network_type(int *svctype, int *pstype)
1290 {
1291         if (!netconfig_plugin_telephony_enabled)
1292                 return;
1293
1294         if (!telephony_plugin)
1295                 return;
1296
1297         telephony_plugin->get_telephony_network_type(svctype, pstype);
1298 }
1299
1300 gboolean __netconfig_wifi_get_sim_imsi(Wifi *wifi, GDBusMethodInvocation *context)
1301 {
1302         if (!netconfig_plugin_telephony_enabled)
1303                 return FALSE;
1304
1305         if (!telephony_plugin)
1306                 return FALSE;
1307
1308         return telephony_plugin->wifi_get_sim_imsi(wifi, context);
1309 }
1310
1311 netconfig_error_e __netconfig_wifi_req_aka_auth(GArray *rand_data, GArray *autn_data,
1312                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1313 {
1314         if (!netconfig_plugin_telephony_enabled)
1315                 return NETCONFIG_ERROR_INTERNAL;
1316
1317         if (!telephony_plugin)
1318                 return NETCONFIG_ERROR_INTERNAL;
1319
1320         return telephony_plugin->wifi_req_aka_auth(rand_data, autn_data, context, data);
1321 }
1322
1323 gboolean __netconfig_wifi_req_sim_auth(GArray *rand_data,
1324                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1325 {
1326         if (!netconfig_plugin_telephony_enabled)
1327                 return FALSE;
1328
1329         if (!telephony_plugin)
1330                 return FALSE;
1331
1332         return telephony_plugin->wifi_req_sim_auth(rand_data, context, data);
1333 }
1334
1335 gboolean netconfig_tapi_check_sim_state(void)
1336 {
1337         if (!netconfig_plugin_telephony_enabled)
1338                 return FALSE;
1339
1340         if (!telephony_plugin)
1341                 return FALSE;
1342
1343         return telephony_plugin->tapi_check_sim_state();
1344 }
1345
1346 gboolean __netconfig_wifi_get_aka_authdata(Wifi *wifi,
1347                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1348 {
1349         if (!netconfig_plugin_telephony_enabled)
1350                 return FALSE;
1351
1352         if (!telephony_plugin)
1353                 return FALSE;
1354
1355         return telephony_plugin->wifi_get_aka_authdata(wifi, context, data);
1356 }
1357
1358 gboolean __netconfig_wifi_get_sim_authdata(Wifi *wifi,
1359                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1360 {
1361         if (!netconfig_plugin_telephony_enabled)
1362                 return FALSE;
1363
1364         if (!telephony_plugin)
1365                 return FALSE;
1366
1367         return telephony_plugin->wifi_get_sim_authdata(wifi, context, data);
1368 }
1369
1370 void netconfig_set_vconf_int(const char * key, int value)
1371 {
1372         int ret = 0;
1373
1374         DBG("[%s: %d]", key, value);
1375
1376         ret = vconf_set_int(key, value);
1377         if (ret != VCONF_OK)
1378                 ERR("Failed to set");
1379 }
1380
1381 void netconfig_set_vconf_str(const char * key, const char * value)
1382 {
1383         int ret = 0;
1384
1385         DBG("[%s: %s]", key, value);
1386
1387         ret = vconf_set_str(key, value);
1388         if (ret != VCONF_OK)
1389                 ERR("Failed to set");
1390 }
1391
1392 int netconfig_vconf_get_int(const char * key, int *value)
1393 {
1394         int ret = 0;
1395
1396         ret = vconf_get_int(key, value);
1397         if (ret != VCONF_OK) {
1398                 ERR("Failed to get vconfkey [%s] value", key);
1399                 return -1;
1400         }
1401
1402         return 0;
1403 }
1404
1405 int netconfig_vconf_get_bool(const char * key, int *value)
1406 {
1407         int ret = 0;
1408
1409         ret = vconf_get_bool(key, value);
1410         if (ret != VCONF_OK) {
1411                 ERR("Failed to get vconfkey [%s] value", key);
1412                 return -1;
1413         }
1414
1415         return 0;
1416 }
1417
1418 char* netconfig_get_env(const char *key)
1419 {
1420         FILE *fp;
1421         char buf[256], *entry = NULL, *value = NULL, *last;
1422         int len = 0;
1423
1424         if (!key)
1425                 return NULL;
1426
1427         fp = fopen(NETCONFIG_TIZEN_SYSTEM_ENV, "r");
1428         if (!fp)
1429                 return NULL;
1430
1431         while (fgets(buf, sizeof(buf), fp)) {
1432                 entry = buf;
1433                 entry = strtok_r(entry, "=", &last);
1434                 if (entry) {
1435                         if (strstr(entry, key)) {
1436                                 entry = strtok_r(NULL, "\n", &last);
1437                                 if (entry) {
1438                                         len = strlen(entry);
1439                                         value = (char*)malloc(len+1);
1440                                         g_strlcpy(value, entry, len+1);
1441                                 } else {
1442                                         value = (char*)malloc(sizeof(char));
1443                                         g_strlcpy(value, "\n", sizeof(char));
1444                                 }
1445                                 break;
1446                         }
1447                 }
1448         }
1449
1450         fclose(fp);
1451         return value;
1452 }
1453
1454 void netconfig_set_mac_address_from_file(void)
1455 {
1456         FILE *file = NULL;
1457         char mac_str[MAC_ADDRESS_MAX_LEN];
1458         gchar *mac_lower_str = NULL;
1459         int mac_len = 0;
1460
1461         file = fopen(MAC_INFO_FILEPATH, "r");
1462         if (file == NULL) {
1463                 ERR("Fail to open %s", MAC_INFO_FILEPATH);
1464                 file = fopen(MAC_ADDRESS_FILEPATH, "r");
1465                 if (file == NULL) {
1466                         ERR("Fail to open %s", MAC_ADDRESS_FILEPATH);
1467                         return;
1468                 }
1469         }
1470         if (fgets(mac_str, sizeof(mac_str), file) == NULL) {
1471                 ERR("Fail to read mac address");
1472                 fclose(file);
1473                 return;
1474         }
1475
1476         mac_len = strlen(mac_str);
1477         if (mac_len < 17) {
1478                 ERR("mac.info is empty");
1479                 fclose(file);
1480                 return;
1481         }
1482
1483         mac_lower_str = g_ascii_strup(mac_str, (gssize)mac_len);
1484         netconfig_set_vconf_str(VCONFKEY_WIFI_BSSID_ADDRESS, mac_lower_str);
1485
1486         g_free(mac_lower_str);
1487         fclose(file);
1488 }
1489
1490 tizen_profile_t _get_tizen_profile()
1491 {
1492         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1493         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1494                 return profile;
1495
1496         char *profileName;
1497         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1498         switch (*profileName) {
1499         case 'm':
1500         case 'M':
1501                 profile = TIZEN_PROFILE_MOBILE;
1502                 break;
1503         case 'w':
1504         case 'W':
1505                 profile = TIZEN_PROFILE_WEARABLE;
1506                 break;
1507         case 't':
1508         case 'T':
1509                 profile = TIZEN_PROFILE_TV;
1510                 break;
1511         case 'i':
1512         case 'I':
1513                 profile = TIZEN_PROFILE_IVI;
1514                 break;
1515         default: // common or unknown ==> ALL ARE COMMON.
1516                 profile = TIZEN_PROFILE_COMMON;
1517         }
1518         free(profileName);
1519
1520         return profile;
1521 }
1522
1523 void netconfig_plugin_init()
1524 {
1525         handle_headed = dlopen(HEADED_PLUGIN_FILEPATH, RTLD_NOW);
1526         if (!handle_headed) {
1527                 ERR("Can't load %s: %s", HEADED_PLUGIN_FILEPATH, dlerror());
1528         } else {
1529                 headed_plugin = dlsym(handle_headed, "netconfig_headed_plugin");
1530                 if (!headed_plugin) {
1531                         ERR("Can't load symbol: %s", dlerror());
1532                         dlclose(handle_headed);
1533                 } else {
1534                         netconfig_plugin_headed_enabled = TRUE;
1535                 }
1536         }
1537
1538         handle_telephony = dlopen(TELEPHONY_PLUGIN_FILEPATH, RTLD_NOW);
1539         if (!handle_telephony) {
1540                 ERR("Can't load %s: %s", TELEPHONY_PLUGIN_FILEPATH, dlerror());
1541         } else {
1542                 telephony_plugin = dlsym(handle_telephony, "netconfig_telephony_plugin");
1543                 if (!telephony_plugin) {
1544                         ERR("Can't load symbol: %s", dlerror());
1545                         dlclose(handle_telephony);
1546                 } else {
1547                         netconfig_plugin_telephony_enabled = TRUE;
1548                 }
1549         }
1550 }
1551
1552 void netconfig_plugin_deinit()
1553 {
1554         if (netconfig_plugin_headed_enabled) {
1555                 netconfig_plugin_headed_enabled = FALSE;
1556                 dlclose(handle_headed);
1557         }
1558
1559         if (netconfig_plugin_telephony_enabled) {
1560                 netconfig_plugin_telephony_enabled = FALSE;
1561                 dlclose(handle_telephony);
1562         }
1563 }
1564
1565 gboolean netconfig_get_headed_plugin_flag()
1566 {
1567         return netconfig_plugin_headed_enabled;
1568 }
1569
1570 gboolean netconfig_get_telephony_plugin_flag()
1571 {
1572         return netconfig_plugin_telephony_enabled;
1573 }
1574
1575 bool netconfig_check_feature_supported(netconfig_supported_feature_e feature)
1576 {
1577         const char *key = NULL;
1578
1579         if (!is_feature_checked[feature]) {
1580                 switch (feature) {
1581                 case NETCONFIG_SUPPORTED_FEATURE_ETHERNET:
1582                         key = ETHERNET_FEATURE;
1583                         break;
1584                 case NETCONFIG_SUPPORTED_FEATURE_TETHERING:
1585                         key = TETHERING_FEATURE;
1586                         break;
1587                 case NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT:
1588                         key = WIFI_DIRECT_FEATURE;
1589                         break;
1590                 default:
1591                         ERR("Uknown feature");
1592                         return false;
1593                 }
1594
1595                 if (system_info_get_platform_bool(key, &feature_supported[feature]) < 0) {
1596                         ERR("Get feature is failed");
1597                         return false;
1598                 }
1599                 is_feature_checked[feature] = true;
1600         }
1601         return feature_supported[feature];
1602 }