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