495567d09242d7a6e717cbdc1a2586c121763736
[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 <vconf-keys.h>
34 #include <tzplatform_config.h>
35 #include <system_info.h>
36
37 #include "log.h"
38 #include "util.h"
39 #include "neterror.h"
40 #include "wifi-state.h"
41 #include "netdbus.h"
42
43 #define DBUS_SERVICE_DBUS               "org.freedesktop.DBus"
44 #define DBUS_INTERFACE_DBUS             "org.freedesktop.DBus"
45 #define MAC_INFO_FILEPATH               tzplatform_mkpath(TZ_SYS_ETC, "/.mac.info")
46 #define MAC_ADDRESS_FILEPATH    "/sys/class/net/wlan0/address"
47 #define MAC_ADDRESS_MAX_LEN             18
48 #define HEADED_PLUGIN_FILEPATH          "/usr/lib/net-config-plugin-headed.so"
49
50 static gboolean netconfig_device_picker_test = FALSE;
51 static int mdnsd_ref_count = 0;
52 typedef struct {
53         char *conn_name;
54         int conn_id;
55 } dnssd_conn_destroy_data;
56
57 static gboolean netconfig_plugin_headed_enabled = FALSE;
58 static void *handle_headed;
59 static struct netconfig_headed_plugin_t *headed_plugin;
60
61 GKeyFile *netconfig_keyfile_load(const char *pathname)
62 {
63         GKeyFile *keyfile = NULL;
64         GError *error = NULL;
65
66         keyfile = g_key_file_new();
67         if (g_key_file_load_from_file(keyfile, pathname, 0, &error) != TRUE) {
68                 DBG("Unable to open %s, error %s", pathname, error->message);
69                 g_error_free(error);
70
71                 g_key_file_free(keyfile);
72                 keyfile = NULL;
73         }
74
75         DBG("loaded keyfile %s", pathname);
76         return keyfile;
77 }
78
79 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
80 {
81         gsize size = 0;
82         GError *error = NULL;
83         gchar *keydata = NULL;
84         gchar *needle = NULL, *directory = NULL;
85
86         directory = g_strdup(pathname);
87         needle = g_strrstr(directory, "/");
88
89         if (needle != NULL)
90                 *needle = '\0';
91
92         if (directory == NULL || (*directory) == '\0') {
93                 g_free(directory);
94                 ERR("directory is NULL");
95                 return;
96         }
97
98         if (g_file_test(directory, G_FILE_TEST_IS_DIR) != TRUE) {
99                 if (g_mkdir_with_parents(directory,
100                                 S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
101                         g_free(directory);
102                         ERR("failed to make directory");
103                         return;
104                 }
105         }
106         g_free(directory);
107
108         keydata = g_key_file_to_data(keyfile, &size, &error);
109         if (g_file_set_contents(pathname, keydata, size, &error) != TRUE) {
110                 ERR("Unable to save %s, error %s", pathname, error->message);
111                 g_error_free(error);
112         }
113
114         chmod(pathname, S_IRUSR | S_IWUSR);
115         DBG("Successfully saved keyfile %s", pathname);
116
117         g_free(keydata);
118 }
119
120 void netconfig_start_timer_seconds(guint secs,
121                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
122 {
123         guint t_id = 0;
124
125         if (callback == NULL) {
126                 ERR("callback function is NULL");
127                 return;
128         }
129
130         if ((timer_id != NULL && *timer_id != 0)) {
131                 ERR("timer already is registered");
132                 return;
133         }
134
135         t_id = g_timeout_add_seconds(secs, callback, user_data);
136
137         if (t_id == 0) {
138                 ERR("Can't add timer");
139                 return;
140         }
141
142         if (timer_id != NULL)
143                 *timer_id = t_id;
144 }
145
146 void netconfig_start_timer(guint msecs,
147                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
148 {
149         guint t_id = 0;
150
151         INFO("Register timer with callback pointer (%p)", callback);
152
153         if (callback == NULL) {
154                 ERR("callback function is NULL");
155                 return;
156         }
157
158         if ((timer_id != NULL && *timer_id != 0)) {
159                 ERR("timer already is registered");
160                 return;
161         }
162
163         t_id = g_timeout_add(msecs, callback, user_data);
164
165         if (t_id == 0) {
166                 ERR("Can't add timer");
167                 return;
168         }
169
170         if (timer_id != NULL)
171                 *timer_id = t_id;
172 }
173
174 void netconfig_stop_timer(guint *timer_id)
175 {
176         if (timer_id == NULL) {
177                 ERR("timer is NULL");
178                 return;
179         }
180
181         if (*timer_id != 0) {
182                 g_source_remove(*timer_id);
183                 *timer_id = 0;
184         }
185 }
186
187 static gboolean __netconfig_test_device_picker()
188 {
189         char *favorite_wifi_service = NULL;
190
191         favorite_wifi_service = wifi_get_favorite_service();
192         if (favorite_wifi_service != NULL) {
193                 ERR("favorite_wifi_service is existed[%s] : Donot launch device picker", favorite_wifi_service);
194                 g_free(favorite_wifi_service);
195                 return FALSE;
196         }
197
198         return TRUE;
199 }
200
201 static void __netconfig_pop_device_picker(void)
202 {
203         if (!netconfig_plugin_headed_enabled)
204                 return;
205
206         if (!headed_plugin)
207                 return;
208
209         headed_plugin->pop_device_picker();
210 }
211
212 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
213 {
214         if (__netconfig_test_device_picker() == TRUE)
215                 __netconfig_pop_device_picker();
216
217         return FALSE;
218 }
219
220 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method, guint timer_id)
221 {
222         static guint netconfig_wifi_device_picker_service_timer = 0;
223
224         if (is_set_method != TRUE)
225                 return netconfig_wifi_device_picker_service_timer;
226
227         if (netconfig_wifi_device_picker_service_timer != timer_id)
228                 netconfig_wifi_device_picker_service_timer = timer_id;
229
230         return netconfig_wifi_device_picker_service_timer;
231 }
232
233 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
234 {
235         __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
236 }
237
238 static guint __netconfig_wifi_device_picker_get_timer_id(void)
239 {
240         return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
241 }
242
243 void netconfig_wifi_enable_device_picker_test(void)
244 {
245         netconfig_device_picker_test = TRUE;
246 }
247
248 void netconfig_wifi_device_picker_service_start(void)
249 {
250         const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
251         guint timer_id = 0;
252
253         if (netconfig_device_picker_test == TRUE)
254                 netconfig_device_picker_test = FALSE;
255         else
256                 return;
257
258         int wifi_ug_state;
259
260         netconfig_vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
261         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
262                 return;
263
264         DBG("Register device picker timer with %d milliseconds", NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
265         netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL, __netconfig_wifi_try_device_picker, NULL, &timer_id);
266
267         __netconfig_wifi_device_picker_set_timer_id(timer_id);
268 }
269
270 void netconfig_wifi_device_picker_service_stop(void)
271 {
272         guint timer_id = 0;
273
274         timer_id = __netconfig_wifi_device_picker_get_timer_id();
275         if (timer_id == 0)
276                 return;
277
278         DBG("Clear device picker timer with timer_id %d", timer_id);
279
280         netconfig_stop_timer(&timer_id);
281
282         __netconfig_wifi_device_picker_set_timer_id(timer_id);
283 }
284
285 gboolean netconfig_is_wifi_direct_on(void)
286 {
287 #if defined TIZEN_P2P_ENABLE
288         int wifi_direct_state = 0;
289
290         netconfig_vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
291
292         DBG("Wi-Fi direct mode %d", wifi_direct_state);
293         return (wifi_direct_state != 0) ? TRUE : FALSE;
294 #else
295         return FALSE;
296 #endif
297 }
298
299 gboolean netconfig_is_wifi_tethering_on(void)
300 {
301 #if defined TIZEN_TETHERING_ENABLE
302         int wifi_tethering_state = 0;
303
304         netconfig_vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
305         DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
306         if ((wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
307                 || (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI_AP)) {
308                 DBG("Mobile AP is on");
309                 return TRUE;
310         }
311 #endif
312         DBG("Mobile AP is off");
313         return FALSE;
314 }
315
316 gboolean netconfig_interface_up(const char *ifname)
317 {
318         int fd;
319         struct ifreq ifr;
320
321         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
322         if (fd < 0)
323                 return FALSE;
324
325         memset(&ifr, 0, sizeof(ifr));
326         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
327
328         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
329                 close(fd);
330                 return FALSE;
331         }
332
333         ifr.ifr_flags |= (IFF_UP | IFF_DYNAMIC);
334         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
335                 close(fd);
336                 return FALSE;
337         }
338
339         close(fd);
340
341         DBG("Successfully activated wireless interface %s", ifname);
342         return TRUE;
343 }
344
345 gboolean netconfig_interface_down(const char *ifname)
346 {
347         int fd;
348         struct ifreq ifr;
349
350         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
351         if (fd < 0)
352                 return FALSE;
353
354         memset(&ifr, 0, sizeof(ifr));
355         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
356
357         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
358                 close(fd);
359                 return FALSE;
360         }
361
362         ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
363         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
364                 close(fd);
365                 return FALSE;
366         }
367
368         close(fd);
369
370         DBG("Successfully de-activated wireless interface %s", ifname);
371         return TRUE;
372 }
373
374 int netconfig_execute_file(const char *file_path,
375                 char *const args[], char *const envs[])
376 {
377         pid_t pid = 0;
378         int status = 0;
379         int rv = 0;
380         errno = 0;
381         register unsigned int index = 0;
382         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
383
384         while (args[index] != NULL) {
385                 DBG("%s", args[index]);
386                 index++;
387         }
388
389         if (!(pid = fork())) {
390                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
391                 DBG("Inside child, exec (%s) command", file_path);
392
393                 errno = 0;
394                 if (execve(file_path, args, envs) == -1) {
395                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
396                         DBG("Fail to execute command (%s)", error_buf);
397                         exit(1);
398                 }
399         } else if (pid > 0) {
400                 if (waitpid(pid, &status, 0) == -1)
401                         DBG("wait pid (%u) status (%d)", pid, status);
402
403                 if (WIFEXITED(status)) {
404                         rv = WEXITSTATUS(status);
405                         DBG("exited, status=%d", rv);
406                 } else if (WIFSIGNALED(status)) {
407                         DBG("killed by signal %d", WTERMSIG(status));
408                 } else if (WIFSTOPPED(status)) {
409                         DBG("stopped by signal %d", WSTOPSIG(status));
410                 } else if (WIFCONTINUED(status)) {
411                         DBG("continued");
412                 }
413
414                 return rv;
415         }
416
417         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
418         DBG("failed to fork(%s)", error_buf);
419         return -EIO;
420 }
421
422 int netconfig_execute_cmd(const char *cmd)
423 {
424         if (cmd == NULL)
425                 return -EIO;
426
427         pid_t pid = 0;
428         int status = 0;
429         int rv = 0;
430         errno = 0;
431         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
432         gchar **args = NULL;
433
434         DBG("command: %s", cmd);
435
436         args = g_strsplit_set(cmd, " ", -1);
437
438         if (!(pid = fork())) {
439                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
440
441                 errno = 0;
442                 if (execv(args[0], args) == -1) {
443                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
444                         DBG("Fail to execute command (%s)", error_buf);
445                         g_strfreev(args);
446                         exit(1);
447                 }
448         } else if (pid > 0) {
449                 if (waitpid(pid, &status, 0) == -1)
450                         DBG("wait pid (%u) status (%d)", pid, status);
451
452                 if (WIFEXITED(status)) {
453                         rv = WEXITSTATUS(status);
454                         DBG("exited, status=%d", rv);
455                 } else if (WIFSIGNALED(status)) {
456                         DBG("killed by signal %d", WTERMSIG(status));
457                 } else if (WIFSTOPPED(status)) {
458                         DBG("stopped by signal %d", WSTOPSIG(status));
459                 } else if (WIFCONTINUED(status)) {
460                         DBG("continued");
461                 }
462
463                 g_strfreev(args);
464                 return rv;
465         }
466
467         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
468         DBG("failed to fork(%s)", error_buf);
469         g_strfreev(args);
470
471         return -EIO;
472 }
473
474 static void on_clat_handler()
475 {
476         pid_t clat_pid = 0;
477         int state = 0;
478
479         clat_pid = waitpid(-1, &state, WNOHANG);
480
481         DBG("clat(%d) state(%d)", clat_pid, WEXITSTATUS(state));
482 }
483
484 int netconfig_execute_clatd(const char *file_path, char *const args[])
485 {
486         pid_t pid = 0;
487         int rv = 0;
488         errno = 0;
489         register unsigned int index = 0;
490         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
491
492         struct sigaction act;
493         int state = 0;
494
495         act.sa_handler = on_clat_handler;
496         sigemptyset(&act.sa_mask);
497         act.sa_flags = 0;
498
499         state = sigaction(SIGCHLD, &act, 0);
500         if (state != 0) {
501                 DBG("sigaction() : %d");
502                 return -1;
503         }
504
505         while (args[index] != NULL) {
506                 DBG("%s", args[index]);
507                 index++;
508         }
509
510         if (!(pid = fork())) {
511                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
512                 DBG("Inside child, exec (%s) command", file_path);
513
514                 errno = 0;
515                 if (execvp(file_path, args) == -1) {
516                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
517                         ERR("Fail to execute command (%s)", error_buf);
518                         return -1;
519                 }
520         } else if (pid > 0) {
521                 ERR("Success to launch clatd");
522                 return rv;
523         }
524
525         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
526         DBG("failed to fork(%s)", error_buf);
527         return -EIO;
528 }
529
530 int __netconfig_get_interface_index(const char *interface_name)
531 {
532         struct ifreq ifr;
533         int sock = 0;
534         int result = 0;
535         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
536
537         if (interface_name == NULL) {
538                 DBG("Inteface name is NULL");
539                 return -1;
540         }
541
542         errno = 0;
543         sock = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
544         if (sock < 0) {
545                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
546                 DBG("Failed to create socket : %s", error_buf);
547                 return -1;
548         }
549
550         memset(&ifr, 0, sizeof(ifr));
551         strncpy(ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
552         result = ioctl(sock, SIOCGIFINDEX, &ifr);
553         close(sock);
554
555         if (result < 0) {
556                 DBG("Failed to get ifr index: %s", error_buf);
557                 return -1;
558         }
559
560         return ifr.ifr_ifindex;
561 }
562
563 int netconfig_add_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
564 {
565         struct ifreq ifr;
566         struct rtentry rt;
567         struct sockaddr_in addr_in;
568         int sock;
569         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
570
571         memset(&ifr, 0, sizeof(ifr));
572
573         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
574
575         if (ifr.ifr_ifindex < 0)
576                 return -1;
577
578         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
579
580         memset(&rt, 0, sizeof(rt));
581
582         rt.rt_flags = RTF_UP | RTF_HOST;
583         memset(&addr_in, 0, sizeof(struct sockaddr_in));
584         addr_in.sin_family = address_family;
585         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
586         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
587
588         memset(&addr_in, 0, sizeof(struct sockaddr_in));
589         addr_in.sin_family = address_family;
590         addr_in.sin_addr.s_addr = INADDR_ANY;
591         memcpy(&rt.rt_gateway, &addr_in, sizeof(rt.rt_gateway));
592
593         memset(&addr_in, 0, sizeof(struct sockaddr_in));
594         addr_in.sin_family = AF_INET;
595         addr_in.sin_addr.s_addr = inet_addr(subnet);
596         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
597
598         rt.rt_dev = ifr.ifr_name;
599
600         errno = 0;
601         sock = socket(PF_INET, SOCK_DGRAM, 0);
602
603         if (sock < 0) {
604                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
605                 DBG("Failed to create socket : %s", error_buf);
606                 return -1;
607         }
608
609         if (ioctl(sock, SIOCADDRT, &rt) < 0) {
610                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
611                 DBG("Failed to set route address : %s", error_buf);
612                 close(sock);
613                 return -1;
614         }
615
616         close(sock);
617
618         return 1;
619 }
620
621 int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
622 {
623         struct ifreq ifr;
624         struct rtentry rt;
625         struct sockaddr_in addr_in;
626         int sock;
627         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
628
629         memset(&ifr, 0, sizeof(ifr));
630         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
631
632         if (ifr.ifr_ifindex < 0)
633                 return -1;
634
635         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
636
637         memset(&rt, 0, sizeof(rt));
638
639         rt.rt_flags = RTF_UP;
640         memset(&addr_in, 0, sizeof(struct sockaddr_in));
641         addr_in.sin_family = address_family;
642         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
643         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
644
645         memset(&addr_in, 0, sizeof(struct sockaddr_in));
646         addr_in.sin_family = address_family;
647         addr_in.sin_addr.s_addr = inet_addr(subnet);
648         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
649         rt.rt_dev = ifr.ifr_name;
650
651         errno = 0;
652         sock = socket(PF_INET, SOCK_DGRAM, 0);
653
654         if (sock < 0) {
655                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
656                 DBG("Failed to create socket : %s", error_buf);
657                 return -1;
658         }
659
660         if (ioctl(sock, SIOCDELRT, &rt) < 0) {
661                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
662                 DBG("Failed to set route address : %s", error_buf);
663                 close(sock);
664                 return -1;
665         }
666
667         close(sock);
668
669         return 1;
670 }
671
672 int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
673 {
674         struct in6_rtmsg rt;
675         int fd = 0;
676         int err = 0;
677         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
678
679         memset(&rt, 0, sizeof(rt));
680
681         rt.rtmsg_dst_len = prefix_len;
682
683         rt.rtmsg_flags = RTF_UP | RTF_HOST;
684
685         errno = 0;
686         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
687                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
688                 DBG("inet_pton failed : %s", error_buf);
689                 return -1;
690         }
691
692         if (gateway != NULL) {
693                 rt.rtmsg_flags |= RTF_GATEWAY;
694                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
695                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
696                         DBG("inet_pton failed : %s", error_buf);
697                         return -1;
698                 }
699         }
700
701         rt.rtmsg_metric = 1;
702
703         fd = socket(AF_INET6, SOCK_DGRAM, 0);
704         if (fd < 0) {
705                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
706                 DBG("Failed to create socket : %s", error_buf);
707                 return -1;
708         }
709
710         rt.rtmsg_ifindex = 0;
711
712         if (interface) {
713                 struct ifreq ifr;
714                 memset(&ifr, 0, sizeof(ifr));
715                 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
716                 ioctl(fd, SIOCGIFINDEX, &ifr);
717                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
718         }
719
720         if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
721                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
722                 DBG("Failed to add route: %s", error_buf);
723                 close(fd);
724                 return -1;
725         }
726
727         close(fd);
728
729         return 1;
730 }
731
732 int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
733 {
734         struct in6_rtmsg rt;
735         int fd = 0;
736         int err = 0;
737
738         memset(&rt, 0, sizeof(rt));
739
740         rt.rtmsg_dst_len = prefix_len;
741
742         rt.rtmsg_flags = RTF_UP | RTF_HOST;
743
744         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
745                 err = -errno;
746                 return err;
747         }
748
749         if (gateway != NULL) {
750                 rt.rtmsg_flags |= RTF_GATEWAY;
751                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
752                         err = -errno;
753                         return err;
754                 }
755         }
756
757         rt.rtmsg_metric = 1;
758
759         fd = socket(AF_INET6, SOCK_DGRAM, 0);
760         if (fd < 0)
761                 return -1;
762
763         rt.rtmsg_ifindex = 0;
764
765         if (interface) {
766                 struct ifreq ifr;
767                 memset(&ifr, 0, sizeof(ifr));
768                 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
769                 ioctl(fd, SIOCGIFINDEX, &ifr);
770                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
771         }
772
773         if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
774                 DBG("Failed to del route: %d\n", err);
775                 close(fd);
776                 return -1;
777         }
778
779         close(fd);
780
781         return 1;
782 }
783
784 gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context)
785 {
786 #if defined TIZEN_P2P_ENABLE
787         int ret = 0;
788         DBG("Launch Wi-Fi direct daemon");
789
790         const char *path = "/usr/bin/wifi-direct-server.sh";
791         char *const args[] = { "wifi-direct-server.sh", "start", NULL };
792         char *const envs[] = { NULL };
793
794         ret = netconfig_execute_file(path, args, envs);
795         if (ret < 0) {
796                 ERR("Failed to launch Wi-Fi direct daemon");
797                 netconfig_error_wifi_direct_failed(context);
798                 return FALSE;
799         }
800
801         wifi_complete_launch_direct(wifi, context);
802         return TRUE;
803 #else
804         wifi_complete_launch_direct(wifi, context);
805         return FALSE;
806 #endif
807 }
808
809 int execute_mdnsd_script(char* op)
810 {
811         const char *path = "/usr/bin/mdnsresponder-server.sh";
812         char *const args[] = { "mdnsresponder-server.sh", op, NULL };
813         char *const envs[] = { NULL };
814
815         return netconfig_execute_file(path, args, envs);
816 }
817
818 static void __dnssd_conn_destroyed_cb(GDBusConnection *conn,
819                 const gchar *Name, const gchar *path, const gchar *interface,
820                 const gchar *sig, GVariant *param, gpointer user_data)
821 {
822         gchar *name = NULL;
823         gchar *old = NULL;
824         gchar *new = NULL;
825         dnssd_conn_destroy_data *data = user_data;
826         GDBusConnection *connection = NULL;
827         connection = netdbus_get_connection();
828
829         if (param == NULL)
830                 return;
831
832         g_variant_get(param, "(sss)", &name, &old, &new);
833
834         if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') {
835                 DBG("Connection %s Destroyed: name %s id %d", data->conn_name, name,
836                         data->conn_id);
837                 mdnsd_ref_count--;
838                 g_dbus_connection_signal_unsubscribe(connection, data->conn_id);
839                 if (mdnsd_ref_count == 0) {
840                         if (execute_mdnsd_script("stop") < 0)
841                                 ERR("Failed to stop mdnsresponder daemon");
842                 }
843         }
844         g_free(name);
845         g_free(old);
846         g_free(new);
847         g_free(data->conn_name);
848         g_free(data);
849         return;
850 }
851
852 static void register_dnssd_conn_destroy_signal(gchar *name)
853 {
854         dnssd_conn_destroy_data *data;
855         GDBusConnection *connection = NULL;
856         connection = netdbus_get_connection();
857
858         if (connection == NULL) {
859                 ERR("Failed to get GDbus Connection");
860                 return;
861         }
862
863         data = g_try_malloc0(sizeof(dnssd_conn_destroy_data));
864         data->conn_name = g_strdup(name);
865
866         data->conn_id = g_dbus_connection_signal_subscribe(connection,
867                                                         DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS,
868                                                         "NameOwnerChanged", NULL, name,
869                                                         G_DBUS_SIGNAL_FLAGS_NONE, __dnssd_conn_destroyed_cb,
870                                                         data, NULL);
871         return;
872 }
873
874 gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context,
875                                                         gchar *name)
876 {
877         DBG("Launch mdnsresponder daemon");
878
879         if (execute_mdnsd_script("start") < 0) {
880                 ERR("Failed to launch mdnsresponder daemon");
881                 netconfig_error_invalid_parameter(context);
882                 return FALSE;
883         }
884
885         mdnsd_ref_count++;
886         register_dnssd_conn_destroy_signal(name);
887         DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count);
888
889         network_complete_launch_mdns(object, context);
890         return TRUE;
891 }
892
893 gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid)
894 {
895         if (!netconfig_plugin_headed_enabled)
896                 return FALSE;
897
898         if (!headed_plugin)
899                 return FALSE;
900
901         return headed_plugin->send_notification_to_net_popup(noti, ssid);
902 }
903
904 int netconfig_send_message_to_net_popup(const char *title,
905                 const char *content, const char *type, const char *ssid)
906 {
907         if (!netconfig_plugin_headed_enabled)
908                 return 0;
909
910         if (!headed_plugin)
911                 return 0;
912
913         return headed_plugin->send_message_to_net_popup(title, content, type, ssid);
914 }
915
916 int netconfig_send_restriction_to_net_popup(const char *title,
917                 const char *type, const char *restriction)
918 {
919         if (!netconfig_plugin_headed_enabled)
920                 return 0;
921
922         if (!headed_plugin)
923                 return 0;
924
925         return headed_plugin->send_restriction_to_net_popup(title, type, restriction);
926 }
927
928 void netconfig_set_system_event(int sys_evt, int evt_key, int evt_val)
929 {
930         if (!netconfig_plugin_headed_enabled)
931                 return;
932
933         if (!headed_plugin)
934                 return;
935
936         headed_plugin->set_system_event(sys_evt, evt_key, evt_val);
937 }
938
939 void __netconfig_pop_wifi_connected_poppup(const char *ssid)
940 {
941         if (!netconfig_plugin_headed_enabled)
942                 return;
943
944         if (!headed_plugin)
945                 return;
946
947         headed_plugin->pop_wifi_connected_poppup(ssid);
948 }
949
950 void netconfig_set_vconf_int(const char * key, int value)
951 {
952         int ret = 0;
953
954         DBG("[%s: %d]", key, value);
955
956         ret = vconf_set_int(key, value);
957         if (ret != VCONF_OK)
958                 ERR("Failed to set");
959 }
960
961 void netconfig_set_vconf_str(const char * key, const char * value)
962 {
963         int ret = 0;
964
965         DBG("[%s: %s]", key, value);
966
967         ret = vconf_set_str(key, value);
968         if (ret != VCONF_OK)
969                 ERR("Failed to set");
970 }
971
972 int netconfig_vconf_get_int(const char * key, int *value)
973 {
974         int ret = 0;
975
976         ret = vconf_get_int(key, value);
977         if (ret != VCONF_OK) {
978                 ERR("Failed to get vconfkey [%s] value", key);
979                 return -1;
980         }
981
982         return 0;
983 }
984
985 int netconfig_vconf_get_bool(const char * key, int *value)
986 {
987         int ret = 0;
988
989         ret = vconf_get_bool(key, value);
990         if (ret != VCONF_OK) {
991                 ERR("Failed to get vconfkey [%s] value", key);
992                 return -1;
993         }
994
995         return 0;
996 }
997
998 char* netconfig_get_env(const char *key)
999 {
1000         FILE *fp;
1001         char buf[256], *entry = NULL, *value = NULL, *last;
1002         int len = 0;
1003
1004         if (!key)
1005                 return NULL;
1006
1007         fp = fopen(NETCONFIG_TIZEN_SYSTEM_ENV, "r");
1008         if (!fp)
1009                 return NULL;
1010
1011         while (fgets(buf, sizeof(buf), fp)) {
1012                 entry = buf;
1013                 entry = strtok_r(entry, "=", &last);
1014                 if (entry) {
1015                         if (strstr(entry, key)) {
1016                                 entry = strtok_r(NULL, "\n", &last);
1017                                 if (entry) {
1018                                         len = strlen(entry);
1019                                         value = (char*)malloc(len+1);
1020                                         g_strlcpy(value, entry, len+1);
1021                                 } else {
1022                                         value = (char*)malloc(sizeof(char));
1023                                         g_strlcpy(value, "\n", sizeof(char));
1024                                 }
1025                                 break;
1026                         }
1027                 }
1028         }
1029
1030         fclose(fp);
1031         return value;
1032 }
1033
1034 void netconfig_set_mac_address_from_file(void)
1035 {
1036         FILE *file = NULL;
1037         char mac_str[MAC_ADDRESS_MAX_LEN];
1038         gchar *mac_lower_str = NULL;
1039         int mac_len = 0;
1040
1041         file = fopen(MAC_INFO_FILEPATH, "r");
1042         if (file == NULL) {
1043                 ERR("Fail to open %s", MAC_INFO_FILEPATH);
1044                 file = fopen(MAC_ADDRESS_FILEPATH, "r");
1045                 if (file == NULL) {
1046                         ERR("Fail to open %s", MAC_ADDRESS_FILEPATH);
1047                         return;
1048                 }
1049         }
1050         if (fgets(mac_str, sizeof(mac_str), file) == NULL) {
1051                 ERR("Fail to read mac address");
1052                 fclose(file);
1053                 return;
1054         }
1055
1056         mac_len = strlen(mac_str);
1057         if (mac_len < 17) {
1058                 ERR("mac.info is empty");
1059                 fclose(file);
1060                 return;
1061         }
1062
1063         mac_lower_str = g_ascii_strup(mac_str, (gssize)mac_len);
1064         netconfig_set_vconf_str(VCONFKEY_WIFI_BSSID_ADDRESS, mac_lower_str);
1065
1066         g_free(mac_lower_str);
1067         fclose(file);
1068 }
1069
1070 tizen_profile_t _get_tizen_profile()
1071 {
1072         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1073         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1074                 return profile;
1075
1076         char *profileName;
1077         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1078         switch (*profileName) {
1079         case 'm':
1080         case 'M':
1081                 profile = TIZEN_PROFILE_MOBILE;
1082                 break;
1083         case 'w':
1084         case 'W':
1085                 profile = TIZEN_PROFILE_WEARABLE;
1086                 break;
1087         case 't':
1088         case 'T':
1089                 profile = TIZEN_PROFILE_TV;
1090                 break;
1091         case 'i':
1092         case 'I':
1093                 profile = TIZEN_PROFILE_IVI;
1094                 break;
1095         default: // common or unknown ==> ALL ARE COMMON.
1096                 profile = TIZEN_PROFILE_COMMON;
1097         }
1098         free(profileName);
1099
1100         return profile;
1101 }
1102
1103 void netconfig_plugin_init()
1104 {
1105         handle_headed = dlopen(HEADED_PLUGIN_FILEPATH, RTLD_NOW);
1106         if (!handle_headed) {
1107                 ERR("Can't load %s: %s", HEADED_PLUGIN_FILEPATH, dlerror());
1108                 return;
1109         }
1110
1111         headed_plugin = dlsym(handle_headed, "netconfig_headed_plugin");
1112         if (!headed_plugin) {
1113                 ERR("Can't load symbol: %s", dlerror());
1114                 dlclose(handle_headed);
1115                 return;
1116         }
1117
1118         netconfig_plugin_headed_enabled = TRUE;
1119 }
1120
1121 void netconfig_plugin_deinit()
1122 {
1123         if (!netconfig_plugin_headed_enabled)
1124                 return;
1125
1126         netconfig_plugin_headed_enabled = FALSE;
1127         dlclose(handle_headed);
1128 }
1129
1130 gboolean netconfig_get_headed_plugin_flag()
1131 {
1132         return netconfig_plugin_headed_enabled;
1133 }
1134