Revert "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 *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
1099 {
1100         struct in6_rtmsg rt;
1101         int fd = 0;
1102         int err = 0;
1103
1104         memset(&rt, 0, sizeof(rt));
1105
1106         rt.rtmsg_dst_len = prefix_len;
1107
1108         rt.rtmsg_flags = RTF_UP | RTF_HOST;
1109
1110         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
1111                 err = -errno;
1112                 return err;
1113         }
1114
1115         if (gateway != NULL) {
1116                 rt.rtmsg_flags |= RTF_GATEWAY;
1117                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
1118                         err = -errno;
1119                         return err;
1120                 }
1121         }
1122
1123         rt.rtmsg_metric = 1;
1124
1125         fd = socket(AF_INET6, SOCK_DGRAM, 0);
1126         if (fd < 0)
1127                 return -1;
1128
1129         rt.rtmsg_ifindex = 0;
1130
1131         if (interface) {
1132                 struct ifreq ifr;
1133                 memset(&ifr, 0, sizeof(ifr));
1134                 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
1135                 ioctl(fd, SIOCGIFINDEX, &ifr);
1136                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
1137         }
1138
1139         if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
1140                 DBG("Failed to del route: %d\n", err);
1141                 close(fd);
1142                 return -1;
1143         }
1144
1145         close(fd);
1146
1147         return 1;
1148 }
1149
1150 gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context)
1151 {
1152         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT)) {
1153                 wifi_complete_launch_direct(wifi, context);
1154                 return TRUE;
1155         }
1156
1157         int ret = 0;
1158         DBG("Launch Wi-Fi direct daemon");
1159
1160         const char *path = "/usr/bin/wifi-direct-server.sh";
1161         char *const args[] = { "wifi-direct-server.sh", "start", NULL };
1162         char *const envs[] = { NULL };
1163
1164         ret = netconfig_execute_file(path, args, envs);
1165         if (ret < 0) {
1166                 ERR("Failed to launch Wi-Fi direct daemon");
1167                 netconfig_error_wifi_direct_failed(context);
1168                 return TRUE;
1169         }
1170
1171         wifi_complete_launch_direct(wifi, context);
1172         return TRUE;
1173 }
1174
1175 int execute_mdnsd_script(char* op)
1176 {
1177         const char *path = "/usr/bin/mdnsresponder-server.sh";
1178         char *const args[] = { "mdnsresponder-server.sh", op, NULL };
1179         char *const envs[] = { NULL };
1180
1181         return netconfig_execute_file(path, args, envs);
1182 }
1183
1184 static void __dnssd_conn_destroyed_cb(GDBusConnection *conn,
1185                 const gchar *Name, const gchar *path, const gchar *interface,
1186                 const gchar *sig, GVariant *param, gpointer user_data)
1187 {
1188         gchar *name = NULL;
1189         gchar *old = NULL;
1190         gchar *new = NULL;
1191         dnssd_conn_destroy_data *data = user_data;
1192         GDBusConnection *connection = NULL;
1193         connection = netdbus_get_connection();
1194
1195         if (param == NULL)
1196                 return;
1197
1198         g_variant_get(param, "(sss)", &name, &old, &new);
1199
1200         if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') {
1201                 DBG("Connection %s Destroyed: name %s id %d", data->conn_name, name,
1202                         data->conn_id);
1203                 mdnsd_ref_count--;
1204                 g_dbus_connection_signal_unsubscribe(connection, data->conn_id);
1205                 if (mdnsd_ref_count == 0) {
1206                         if (execute_mdnsd_script("stop") < 0)
1207                                 ERR("Failed to stop mdnsresponder daemon");
1208                 }
1209         }
1210         g_free(name);
1211         g_free(old);
1212         g_free(new);
1213         g_free(data->conn_name);
1214         g_free(data);
1215         return;
1216 }
1217
1218 static void register_dnssd_conn_destroy_signal(gchar *name)
1219 {
1220         dnssd_conn_destroy_data *data;
1221         GDBusConnection *connection = NULL;
1222         connection = netdbus_get_connection();
1223
1224         if (connection == NULL) {
1225                 ERR("Failed to get GDbus Connection");
1226                 return;
1227         }
1228
1229         data = g_try_malloc0(sizeof(dnssd_conn_destroy_data));
1230
1231         if (data == NULL) {
1232                 ERR("Out of Memory!");
1233                 return;
1234         }
1235
1236         data->conn_name = g_strdup(name);
1237
1238         data->conn_id = g_dbus_connection_signal_subscribe(connection,
1239                                                         DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS,
1240                                                         "NameOwnerChanged", NULL, name,
1241                                                         G_DBUS_SIGNAL_FLAGS_NONE, __dnssd_conn_destroyed_cb,
1242                                                         data, NULL);
1243         return;
1244 }
1245
1246 gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context,
1247                                                         gchar *name)
1248 {
1249         DBG("Launch mdnsresponder daemon");
1250
1251         if (execute_mdnsd_script("start") < 0) {
1252                 ERR("Failed to launch mdnsresponder daemon");
1253                 netconfig_error_invalid_parameter(context);
1254                 return TRUE;
1255         }
1256
1257         mdnsd_ref_count++;
1258         register_dnssd_conn_destroy_signal(name);
1259         DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count);
1260
1261         network_complete_launch_mdns(object, context);
1262         return TRUE;
1263 }
1264
1265 gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid)
1266 {
1267         if (!netconfig_plugin_headed_enabled)
1268                 return FALSE;
1269
1270         if (!headed_plugin)
1271                 return FALSE;
1272
1273         return headed_plugin->send_notification_to_net_popup(noti, ssid);
1274 }
1275
1276 int netconfig_send_message_to_net_popup(const char *title,
1277                 const char *content, const char *type, const char *ssid)
1278 {
1279         if (!netconfig_plugin_headed_enabled)
1280                 return 0;
1281
1282         if (!headed_plugin)
1283                 return 0;
1284
1285         return headed_plugin->send_message_to_net_popup(title, content, type, ssid);
1286 }
1287
1288 int netconfig_send_restriction_to_net_popup(const char *title,
1289                 const char *type, const char *restriction)
1290 {
1291         if (!netconfig_plugin_headed_enabled)
1292                 return 0;
1293
1294         if (!headed_plugin)
1295                 return 0;
1296
1297         return headed_plugin->send_restriction_to_net_popup(title, type, restriction);
1298 }
1299
1300 void netconfig_set_system_event(int sys_evt, int evt_key, int evt_val)
1301 {
1302         if (!netconfig_plugin_headed_enabled)
1303                 return;
1304
1305         if (!headed_plugin)
1306                 return;
1307
1308         headed_plugin->set_system_event(sys_evt, evt_key, evt_val);
1309 }
1310
1311 void __netconfig_pop_wifi_connected_poppup(const char *ssid)
1312 {
1313         if (!netconfig_plugin_headed_enabled)
1314                 return;
1315
1316         if (!headed_plugin)
1317                 return;
1318
1319         headed_plugin->pop_wifi_connected_poppup(ssid);
1320 }
1321
1322 void netconfig_get_telephony_network_type(int *svctype, int *pstype)
1323 {
1324         if (!netconfig_plugin_telephony_enabled)
1325                 return;
1326
1327         if (!telephony_plugin)
1328                 return;
1329
1330         telephony_plugin->get_telephony_network_type(svctype, pstype);
1331 }
1332
1333 gboolean __netconfig_wifi_get_sim_imsi(Wifi *wifi, GDBusMethodInvocation *context)
1334 {
1335         if (!netconfig_plugin_telephony_enabled)
1336                 return FALSE;
1337
1338         if (!telephony_plugin)
1339                 return FALSE;
1340
1341         return telephony_plugin->wifi_get_sim_imsi(wifi, context);
1342 }
1343
1344 netconfig_error_e __netconfig_wifi_req_aka_auth(GArray *rand_data, GArray *autn_data,
1345                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1346 {
1347         if (!netconfig_plugin_telephony_enabled)
1348                 return NETCONFIG_ERROR_INTERNAL;
1349
1350         if (!telephony_plugin)
1351                 return NETCONFIG_ERROR_INTERNAL;
1352
1353         return telephony_plugin->wifi_req_aka_auth(rand_data, autn_data, context, data);
1354 }
1355
1356 gboolean __netconfig_wifi_req_sim_auth(GArray *rand_data,
1357                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1358 {
1359         if (!netconfig_plugin_telephony_enabled)
1360                 return FALSE;
1361
1362         if (!telephony_plugin)
1363                 return FALSE;
1364
1365         return telephony_plugin->wifi_req_sim_auth(rand_data, context, data);
1366 }
1367
1368 gboolean netconfig_tapi_check_sim_state(void)
1369 {
1370         if (!netconfig_plugin_telephony_enabled)
1371                 return FALSE;
1372
1373         if (!telephony_plugin)
1374                 return FALSE;
1375
1376         return telephony_plugin->tapi_check_sim_state();
1377 }
1378
1379 gboolean __netconfig_wifi_get_aka_authdata(Wifi *wifi,
1380                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1381 {
1382         if (!netconfig_plugin_telephony_enabled)
1383                 return FALSE;
1384
1385         if (!telephony_plugin)
1386                 return FALSE;
1387
1388         return telephony_plugin->wifi_get_aka_authdata(wifi, context, data);
1389 }
1390
1391 gboolean __netconfig_wifi_get_sim_authdata(Wifi *wifi,
1392                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1393 {
1394         if (!netconfig_plugin_telephony_enabled)
1395                 return FALSE;
1396
1397         if (!telephony_plugin)
1398                 return FALSE;
1399
1400         return telephony_plugin->wifi_get_sim_authdata(wifi, context, data);
1401 }
1402
1403 void netconfig_set_vconf_int(const char * key, int value)
1404 {
1405         int ret = 0;
1406
1407         DBG("[%s: %d]", key, value);
1408
1409         ret = vconf_set_int(key, value);
1410         if (ret != VCONF_OK)
1411                 ERR("Failed to set");
1412 }
1413
1414 void netconfig_set_vconf_str(const char * key, const char * value)
1415 {
1416         int ret = 0;
1417
1418         DBG("[%s: %s]", key, value);
1419
1420         ret = vconf_set_str(key, value);
1421         if (ret != VCONF_OK)
1422                 ERR("Failed to set");
1423 }
1424
1425 int netconfig_vconf_get_int(const char * key, int *value)
1426 {
1427         int ret = 0;
1428
1429         ret = vconf_get_int(key, value);
1430         if (ret != VCONF_OK) {
1431                 ERR("Failed to get vconfkey [%s] value", key);
1432                 return -1;
1433         }
1434
1435         return 0;
1436 }
1437
1438 int netconfig_vconf_get_bool(const char * key, int *value)
1439 {
1440         int ret = 0;
1441
1442         ret = vconf_get_bool(key, value);
1443         if (ret != VCONF_OK) {
1444                 ERR("Failed to get vconfkey [%s] value", key);
1445                 return -1;
1446         }
1447
1448         return 0;
1449 }
1450
1451 char* netconfig_get_env(const char *key)
1452 {
1453         FILE *fp;
1454         char buf[256], *entry = NULL, *value = NULL, *last;
1455         int len = 0;
1456
1457         if (!key)
1458                 return NULL;
1459
1460         fp = fopen(NETCONFIG_TIZEN_SYSTEM_ENV, "r");
1461         if (!fp)
1462                 return NULL;
1463
1464         while (fgets(buf, sizeof(buf), fp)) {
1465                 entry = buf;
1466                 entry = strtok_r(entry, "=", &last);
1467                 if (entry) {
1468                         if (strstr(entry, key)) {
1469                                 entry = strtok_r(NULL, "\n", &last);
1470                                 if (entry) {
1471                                         len = strlen(entry);
1472                                         value = (char*)malloc(len+1);
1473                                         g_strlcpy(value, entry, len+1);
1474                                 } else {
1475                                         value = (char*)malloc(sizeof(char));
1476                                         g_strlcpy(value, "\n", sizeof(char));
1477                                 }
1478                                 break;
1479                         }
1480                 }
1481         }
1482
1483         fclose(fp);
1484         return value;
1485 }
1486
1487 void netconfig_set_mac_address_from_file(void)
1488 {
1489         FILE *file = NULL;
1490         char mac_str[MAC_ADDRESS_MAX_LEN];
1491         gchar *mac_lower_str = NULL;
1492         int mac_len = 0;
1493
1494         file = fopen(MAC_INFO_FILEPATH, "r");
1495         if (file == NULL) {
1496                 ERR("Fail to open %s", MAC_INFO_FILEPATH);
1497                 file = fopen(MAC_ADDRESS_FILEPATH, "r");
1498                 if (file == NULL) {
1499                         ERR("Fail to open %s", MAC_ADDRESS_FILEPATH);
1500                         return;
1501                 }
1502         }
1503         if (fgets(mac_str, sizeof(mac_str), file) == NULL) {
1504                 ERR("Fail to read mac address");
1505                 fclose(file);
1506                 return;
1507         }
1508
1509         mac_len = strlen(mac_str);
1510         if (mac_len < 17) {
1511                 ERR("mac.info is empty");
1512                 fclose(file);
1513                 return;
1514         }
1515
1516         mac_lower_str = g_ascii_strup(mac_str, (gssize)mac_len);
1517         netconfig_set_vconf_str(VCONFKEY_WIFI_BSSID_ADDRESS, mac_lower_str);
1518
1519         g_free(mac_lower_str);
1520         fclose(file);
1521 }
1522
1523 tizen_profile_t _get_tizen_profile()
1524 {
1525         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1526         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1527                 return profile;
1528
1529         char *profileName;
1530         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1531         switch (*profileName) {
1532         case 'm':
1533         case 'M':
1534                 profile = TIZEN_PROFILE_MOBILE;
1535                 break;
1536         case 'w':
1537         case 'W':
1538                 profile = TIZEN_PROFILE_WEARABLE;
1539                 break;
1540         case 't':
1541         case 'T':
1542                 profile = TIZEN_PROFILE_TV;
1543                 break;
1544         case 'i':
1545         case 'I':
1546                 profile = TIZEN_PROFILE_IVI;
1547                 break;
1548         default: // common or unknown ==> ALL ARE COMMON.
1549                 profile = TIZEN_PROFILE_COMMON;
1550         }
1551         free(profileName);
1552
1553         return profile;
1554 }
1555
1556 void netconfig_plugin_init()
1557 {
1558         handle_headed = dlopen(HEADED_PLUGIN_FILEPATH, RTLD_NOW);
1559         if (!handle_headed) {
1560                 ERR("Can't load %s: %s", HEADED_PLUGIN_FILEPATH, dlerror());
1561         } else {
1562                 headed_plugin = dlsym(handle_headed, "netconfig_headed_plugin");
1563                 if (!headed_plugin) {
1564                         ERR("Can't load symbol: %s", dlerror());
1565                         dlclose(handle_headed);
1566                 } else {
1567                         netconfig_plugin_headed_enabled = TRUE;
1568                 }
1569         }
1570
1571         handle_telephony = dlopen(TELEPHONY_PLUGIN_FILEPATH, RTLD_NOW);
1572         if (!handle_telephony) {
1573                 ERR("Can't load %s: %s", TELEPHONY_PLUGIN_FILEPATH, dlerror());
1574         } else {
1575                 telephony_plugin = dlsym(handle_telephony, "netconfig_telephony_plugin");
1576                 if (!telephony_plugin) {
1577                         ERR("Can't load symbol: %s", dlerror());
1578                         dlclose(handle_telephony);
1579                 } else {
1580                         netconfig_plugin_telephony_enabled = TRUE;
1581                 }
1582         }
1583 }
1584
1585 void netconfig_plugin_deinit()
1586 {
1587         if (netconfig_plugin_headed_enabled) {
1588                 netconfig_plugin_headed_enabled = FALSE;
1589                 dlclose(handle_headed);
1590         }
1591
1592         if (netconfig_plugin_telephony_enabled) {
1593                 netconfig_plugin_telephony_enabled = FALSE;
1594                 dlclose(handle_telephony);
1595         }
1596 }
1597
1598 gboolean netconfig_get_headed_plugin_flag()
1599 {
1600         return netconfig_plugin_headed_enabled;
1601 }
1602
1603 gboolean netconfig_get_telephony_plugin_flag()
1604 {
1605         return netconfig_plugin_telephony_enabled;
1606 }
1607
1608 bool netconfig_check_feature_supported(netconfig_supported_feature_e feature)
1609 {
1610         const char *key = NULL;
1611
1612         if (!is_feature_checked[feature]) {
1613                 switch (feature) {
1614                 case NETCONFIG_SUPPORTED_FEATURE_ETHERNET:
1615                         key = ETHERNET_FEATURE;
1616                         break;
1617                 case NETCONFIG_SUPPORTED_FEATURE_TETHERING:
1618                         key = TETHERING_FEATURE;
1619                         break;
1620                 case NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT:
1621                         key = WIFI_DIRECT_FEATURE;
1622                         break;
1623                 case NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP:
1624                         key = WIFI_SOFTAP_FEATURE;
1625                         break;
1626                 default:
1627                         ERR("Uknown feature");
1628                         return false;
1629                 }
1630
1631                 if (system_info_get_platform_bool(key, &feature_supported[feature]) < 0) {
1632                         ERR("Get feature is failed");
1633                         return false;
1634                 }
1635                 is_feature_checked[feature] = true;
1636         }
1637         return feature_supported[feature];
1638 }