27c2238441ba2292c0a5a077cc0605938cc02d57
[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         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
586
587         act.sa_handler = no_wait_signal_handler;
588         sigemptyset(&act.sa_mask);
589         act.sa_flags = 0;
590
591         state = sigaction(SIGCHLD, &act, 0);
592         if (state != 0) {
593                 DBG("sigaction() : %d");
594                 return -1;
595         }
596
597         while (args[index] != NULL) {
598                 DBG("%s", args[index]);
599                 index++;
600         }
601
602         if (!(pid = fork())) {
603                 DBG("pid(%d), ppid (%d)", getpid(), getppid());
604                 DBG("Inside child, exec (%s) command", file_path);
605
606                 errno = 0;
607                 if (execvp(file_path, args) == -1) {
608                         ERR("Fail to execute command (%s)",
609                                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
610                         return -1;
611                 }
612         } else if (pid > 0) {
613                 ERR("Successfully launched child process");
614                 return rv;
615         }
616
617         DBG("failed to fork(%s)",
618                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
619         return -EIO;
620 }
621
622 int __netconfig_get_interface_index(const char *interface_name)
623 {
624         struct ifreq ifr;
625         int sock = 0;
626         int result = 0;
627         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
628
629         if (interface_name == NULL) {
630                 DBG("Inteface name is NULL");
631                 return -1;
632         }
633
634         errno = 0;
635         sock = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
636         if (sock < 0) {
637                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
638                 DBG("Failed to create socket : %s", error_buf);
639                 return -1;
640         }
641
642         memset(&ifr, 0, sizeof(ifr));
643         strncpy(ifr.ifr_name, interface_name, sizeof(ifr.ifr_name) - 1);
644         result = ioctl(sock, SIOCGIFINDEX, &ifr);
645         close(sock);
646
647         if (result < 0) {
648                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
649                 DBG("Failed to get ifr index: %s", error_buf);
650                 return -1;
651         }
652
653         return ifr.ifr_ifindex;
654 }
655
656 int netconfig_add_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
657 {
658         struct ifreq ifr;
659         struct rtentry rt;
660         struct sockaddr_in addr_in;
661         int sock;
662         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
663
664         memset(&ifr, 0, sizeof(ifr));
665
666         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
667
668         if (ifr.ifr_ifindex < 0)
669                 return -1;
670
671         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
672
673         memset(&rt, 0, sizeof(rt));
674
675         rt.rt_flags = RTF_UP | RTF_HOST;
676         memset(&addr_in, 0, sizeof(struct sockaddr_in));
677         addr_in.sin_family = address_family;
678         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
679         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
680
681         memset(&addr_in, 0, sizeof(struct sockaddr_in));
682         addr_in.sin_family = address_family;
683         addr_in.sin_addr.s_addr = INADDR_ANY;
684         memcpy(&rt.rt_gateway, &addr_in, sizeof(rt.rt_gateway));
685
686         memset(&addr_in, 0, sizeof(struct sockaddr_in));
687         addr_in.sin_family = AF_INET;
688         addr_in.sin_addr.s_addr = inet_addr(subnet);
689         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
690
691         rt.rt_dev = ifr.ifr_name;
692
693         errno = 0;
694         sock = socket(PF_INET, SOCK_DGRAM, 0);
695
696         if (sock < 0) {
697                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
698                 DBG("Failed to create socket : %s", error_buf);
699                 return -1;
700         }
701
702         if (ioctl(sock, SIOCADDRT, &rt) < 0) {
703                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
704                 DBG("Failed to set route address : %s", error_buf);
705                 close(sock);
706                 return -1;
707         }
708
709         close(sock);
710
711         return 1;
712 }
713
714 int netconfig_del_route_ipv4(gchar *ip_addr, gchar *subnet, gchar *interface, gint address_family)
715 {
716         struct ifreq ifr;
717         struct rtentry rt;
718         struct sockaddr_in addr_in;
719         int sock;
720         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
721
722         memset(&ifr, 0, sizeof(ifr));
723         ifr.ifr_ifindex = __netconfig_get_interface_index(interface);
724
725         if (ifr.ifr_ifindex < 0)
726                 return -1;
727
728         strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
729
730         memset(&rt, 0, sizeof(rt));
731
732         rt.rt_flags = RTF_UP;
733         memset(&addr_in, 0, sizeof(struct sockaddr_in));
734         addr_in.sin_family = address_family;
735         addr_in.sin_addr.s_addr = inet_addr(ip_addr);
736         memcpy(&rt.rt_dst, &addr_in, sizeof(rt.rt_dst));
737
738         memset(&addr_in, 0, sizeof(struct sockaddr_in));
739         addr_in.sin_family = address_family;
740         addr_in.sin_addr.s_addr = inet_addr(subnet);
741         memcpy(&rt.rt_genmask, &addr_in, sizeof(rt.rt_genmask));
742         rt.rt_dev = ifr.ifr_name;
743
744         errno = 0;
745         sock = socket(PF_INET, SOCK_DGRAM, 0);
746
747         if (sock < 0) {
748                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
749                 DBG("Failed to create socket : %s", error_buf);
750                 return -1;
751         }
752
753         if (ioctl(sock, SIOCDELRT, &rt) < 0) {
754                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
755                 DBG("Failed to set route address : %s", error_buf);
756                 close(sock);
757                 return -1;
758         }
759
760         close(sock);
761
762         return 1;
763 }
764
765 int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
766 {
767         struct in6_rtmsg rt;
768         int fd = 0;
769         int err = 0;
770         char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
771
772         memset(&rt, 0, sizeof(rt));
773
774         rt.rtmsg_dst_len = prefix_len;
775
776         rt.rtmsg_flags = RTF_UP | RTF_HOST;
777
778         errno = 0;
779         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
780                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
781                 DBG("inet_pton failed : %s", error_buf);
782                 return -1;
783         }
784
785         if (gateway != NULL) {
786                 rt.rtmsg_flags |= RTF_GATEWAY;
787                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
788                         strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
789                         DBG("inet_pton failed : %s", error_buf);
790                         return -1;
791                 }
792         }
793
794         rt.rtmsg_metric = 1;
795
796         fd = socket(AF_INET6, SOCK_DGRAM, 0);
797         if (fd < 0) {
798                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
799                 DBG("Failed to create socket : %s", error_buf);
800                 return -1;
801         }
802
803         rt.rtmsg_ifindex = 0;
804
805         if (interface) {
806                 struct ifreq ifr;
807                 memset(&ifr, 0, sizeof(ifr));
808                 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
809                 ioctl(fd, SIOCGIFINDEX, &ifr);
810                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
811         }
812
813         if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
814                 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
815                 DBG("Failed to add route: %s", error_buf);
816                 close(fd);
817                 return -1;
818         }
819
820         close(fd);
821
822         return 1;
823 }
824
825 int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
826 {
827         struct in6_rtmsg rt;
828         int fd = 0;
829         int err = 0;
830
831         memset(&rt, 0, sizeof(rt));
832
833         rt.rtmsg_dst_len = prefix_len;
834
835         rt.rtmsg_flags = RTF_UP | RTF_HOST;
836
837         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
838                 err = -errno;
839                 return err;
840         }
841
842         if (gateway != NULL) {
843                 rt.rtmsg_flags |= RTF_GATEWAY;
844                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
845                         err = -errno;
846                         return err;
847                 }
848         }
849
850         rt.rtmsg_metric = 1;
851
852         fd = socket(AF_INET6, SOCK_DGRAM, 0);
853         if (fd < 0)
854                 return -1;
855
856         rt.rtmsg_ifindex = 0;
857
858         if (interface) {
859                 struct ifreq ifr;
860                 memset(&ifr, 0, sizeof(ifr));
861                 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1);
862                 ioctl(fd, SIOCGIFINDEX, &ifr);
863                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
864         }
865
866         if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
867                 DBG("Failed to del route: %d\n", err);
868                 close(fd);
869                 return -1;
870         }
871
872         close(fd);
873
874         return 1;
875 }
876
877 gboolean handle_launch_direct(Wifi *wifi, GDBusMethodInvocation *context)
878 {
879         if (!netconfig_check_feature_supported(NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT)) {
880                 wifi_complete_launch_direct(wifi, context);
881                 return TRUE;
882         }
883
884         int ret = 0;
885         DBG("Launch Wi-Fi direct daemon");
886
887         const char *path = "/usr/bin/wifi-direct-server.sh";
888         char *const args[] = { "wifi-direct-server.sh", "start", NULL };
889         char *const envs[] = { NULL };
890
891         ret = netconfig_execute_file(path, args, envs);
892         if (ret < 0) {
893                 ERR("Failed to launch Wi-Fi direct daemon");
894                 netconfig_error_wifi_direct_failed(context);
895                 return TRUE;
896         }
897
898         wifi_complete_launch_direct(wifi, context);
899         return TRUE;
900 }
901
902 int execute_mdnsd_script(char* op)
903 {
904         const char *path = "/usr/bin/mdnsresponder-server.sh";
905         char *const args[] = { "mdnsresponder-server.sh", op, NULL };
906         char *const envs[] = { NULL };
907
908         return netconfig_execute_file(path, args, envs);
909 }
910
911 static void __dnssd_conn_destroyed_cb(GDBusConnection *conn,
912                 const gchar *Name, const gchar *path, const gchar *interface,
913                 const gchar *sig, GVariant *param, gpointer user_data)
914 {
915         gchar *name = NULL;
916         gchar *old = NULL;
917         gchar *new = NULL;
918         dnssd_conn_destroy_data *data = user_data;
919         GDBusConnection *connection = NULL;
920         connection = netdbus_get_connection();
921
922         if (param == NULL)
923                 return;
924
925         g_variant_get(param, "(sss)", &name, &old, &new);
926
927         if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') {
928                 DBG("Connection %s Destroyed: name %s id %d", data->conn_name, name,
929                         data->conn_id);
930                 mdnsd_ref_count--;
931                 g_dbus_connection_signal_unsubscribe(connection, data->conn_id);
932                 if (mdnsd_ref_count == 0) {
933                         if (execute_mdnsd_script("stop") < 0)
934                                 ERR("Failed to stop mdnsresponder daemon");
935                 }
936         }
937         g_free(name);
938         g_free(old);
939         g_free(new);
940         g_free(data->conn_name);
941         g_free(data);
942         return;
943 }
944
945 static void register_dnssd_conn_destroy_signal(gchar *name)
946 {
947         dnssd_conn_destroy_data *data;
948         GDBusConnection *connection = NULL;
949         connection = netdbus_get_connection();
950
951         if (connection == NULL) {
952                 ERR("Failed to get GDbus Connection");
953                 return;
954         }
955
956         data = g_try_malloc0(sizeof(dnssd_conn_destroy_data));
957
958         if (data == NULL) {
959                 ERR("Out of Memory!");
960                 return;
961         }
962
963         data->conn_name = g_strdup(name);
964
965         data->conn_id = g_dbus_connection_signal_subscribe(connection,
966                                                         DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS,
967                                                         "NameOwnerChanged", NULL, name,
968                                                         G_DBUS_SIGNAL_FLAGS_NONE, __dnssd_conn_destroyed_cb,
969                                                         data, NULL);
970         return;
971 }
972
973 gboolean handle_launch_mdns(Network *object, GDBusMethodInvocation *context,
974                                                         gchar *name)
975 {
976         DBG("Launch mdnsresponder daemon");
977
978         if (execute_mdnsd_script("start") < 0) {
979                 ERR("Failed to launch mdnsresponder daemon");
980                 netconfig_error_invalid_parameter(context);
981                 return TRUE;
982         }
983
984         mdnsd_ref_count++;
985         register_dnssd_conn_destroy_signal(name);
986         DBG("Ref mdnsresponder daemon. ref count: %d", mdnsd_ref_count);
987
988         network_complete_launch_mdns(object, context);
989         return TRUE;
990 }
991
992 gboolean netconfig_send_notification_to_net_popup(const char * noti, const char * ssid)
993 {
994         if (!netconfig_plugin_headed_enabled)
995                 return FALSE;
996
997         if (!headed_plugin)
998                 return FALSE;
999
1000         return headed_plugin->send_notification_to_net_popup(noti, ssid);
1001 }
1002
1003 int netconfig_send_message_to_net_popup(const char *title,
1004                 const char *content, const char *type, const char *ssid)
1005 {
1006         if (!netconfig_plugin_headed_enabled)
1007                 return 0;
1008
1009         if (!headed_plugin)
1010                 return 0;
1011
1012         return headed_plugin->send_message_to_net_popup(title, content, type, ssid);
1013 }
1014
1015 int netconfig_send_restriction_to_net_popup(const char *title,
1016                 const char *type, const char *restriction)
1017 {
1018         if (!netconfig_plugin_headed_enabled)
1019                 return 0;
1020
1021         if (!headed_plugin)
1022                 return 0;
1023
1024         return headed_plugin->send_restriction_to_net_popup(title, type, restriction);
1025 }
1026
1027 void netconfig_set_system_event(int sys_evt, int evt_key, int evt_val)
1028 {
1029         if (!netconfig_plugin_headed_enabled)
1030                 return;
1031
1032         if (!headed_plugin)
1033                 return;
1034
1035         headed_plugin->set_system_event(sys_evt, evt_key, evt_val);
1036 }
1037
1038 void __netconfig_pop_wifi_connected_poppup(const char *ssid)
1039 {
1040         if (!netconfig_plugin_headed_enabled)
1041                 return;
1042
1043         if (!headed_plugin)
1044                 return;
1045
1046         headed_plugin->pop_wifi_connected_poppup(ssid);
1047 }
1048
1049 void netconfig_get_telephony_network_type(int *svctype, int *pstype)
1050 {
1051         if (!netconfig_plugin_telephony_enabled)
1052                 return;
1053
1054         if (!telephony_plugin)
1055                 return;
1056
1057         telephony_plugin->get_telephony_network_type(svctype, pstype);
1058 }
1059
1060 gboolean __netconfig_wifi_get_sim_imsi(Wifi *wifi, GDBusMethodInvocation *context)
1061 {
1062         if (!netconfig_plugin_telephony_enabled)
1063                 return FALSE;
1064
1065         if (!telephony_plugin)
1066                 return FALSE;
1067
1068         return telephony_plugin->wifi_get_sim_imsi(wifi, context);
1069 }
1070
1071 netconfig_error_e __netconfig_wifi_req_aka_auth(GArray *rand_data, GArray *autn_data,
1072                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1073 {
1074         if (!netconfig_plugin_telephony_enabled)
1075                 return NETCONFIG_ERROR_INTERNAL;
1076
1077         if (!telephony_plugin)
1078                 return NETCONFIG_ERROR_INTERNAL;
1079
1080         return telephony_plugin->wifi_req_aka_auth(rand_data, autn_data, context, data);
1081 }
1082
1083 gboolean __netconfig_wifi_req_sim_auth(GArray *rand_data,
1084                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1085 {
1086         if (!netconfig_plugin_telephony_enabled)
1087                 return FALSE;
1088
1089         if (!telephony_plugin)
1090                 return FALSE;
1091
1092         return telephony_plugin->wifi_req_sim_auth(rand_data, context, data);
1093 }
1094
1095 gboolean netconfig_tapi_check_sim_state(void)
1096 {
1097         if (!netconfig_plugin_telephony_enabled)
1098                 return FALSE;
1099
1100         if (!telephony_plugin)
1101                 return FALSE;
1102
1103         return telephony_plugin->tapi_check_sim_state();
1104 }
1105
1106 gboolean __netconfig_wifi_get_aka_authdata(Wifi *wifi,
1107                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1108 {
1109         if (!netconfig_plugin_telephony_enabled)
1110                 return FALSE;
1111
1112         if (!telephony_plugin)
1113                 return FALSE;
1114
1115         return telephony_plugin->wifi_get_aka_authdata(wifi, context, data);
1116 }
1117
1118 gboolean __netconfig_wifi_get_sim_authdata(Wifi *wifi,
1119                 GDBusMethodInvocation *context, struct wifi_authentication_data **data)
1120 {
1121         if (!netconfig_plugin_telephony_enabled)
1122                 return FALSE;
1123
1124         if (!telephony_plugin)
1125                 return FALSE;
1126
1127         return telephony_plugin->wifi_get_sim_authdata(wifi, context, data);
1128 }
1129
1130 void netconfig_set_vconf_int(const char * key, int value)
1131 {
1132         int ret = 0;
1133
1134         DBG("[%s: %d]", key, value);
1135
1136         ret = vconf_set_int(key, value);
1137         if (ret != VCONF_OK)
1138                 ERR("Failed to set");
1139 }
1140
1141 void netconfig_set_vconf_str(const char * key, const char * value)
1142 {
1143         int ret = 0;
1144
1145         DBG("[%s: %s]", key, value);
1146
1147         ret = vconf_set_str(key, value);
1148         if (ret != VCONF_OK)
1149                 ERR("Failed to set");
1150 }
1151
1152 int netconfig_vconf_get_int(const char * key, int *value)
1153 {
1154         int ret = 0;
1155
1156         ret = vconf_get_int(key, value);
1157         if (ret != VCONF_OK) {
1158                 ERR("Failed to get vconfkey [%s] value", key);
1159                 return -1;
1160         }
1161
1162         return 0;
1163 }
1164
1165 int netconfig_vconf_get_bool(const char * key, int *value)
1166 {
1167         int ret = 0;
1168
1169         ret = vconf_get_bool(key, value);
1170         if (ret != VCONF_OK) {
1171                 ERR("Failed to get vconfkey [%s] value", key);
1172                 return -1;
1173         }
1174
1175         return 0;
1176 }
1177
1178 char* netconfig_get_env(const char *key)
1179 {
1180         FILE *fp;
1181         char buf[256], *entry = NULL, *value = NULL, *last;
1182         int len = 0;
1183
1184         if (!key)
1185                 return NULL;
1186
1187         fp = fopen(NETCONFIG_TIZEN_SYSTEM_ENV, "r");
1188         if (!fp)
1189                 return NULL;
1190
1191         while (fgets(buf, sizeof(buf), fp)) {
1192                 entry = buf;
1193                 entry = strtok_r(entry, "=", &last);
1194                 if (entry) {
1195                         if (strstr(entry, key)) {
1196                                 entry = strtok_r(NULL, "\n", &last);
1197                                 if (entry) {
1198                                         len = strlen(entry);
1199                                         value = (char*)malloc(len+1);
1200                                         g_strlcpy(value, entry, len+1);
1201                                 } else {
1202                                         value = (char*)malloc(sizeof(char));
1203                                         g_strlcpy(value, "\n", sizeof(char));
1204                                 }
1205                                 break;
1206                         }
1207                 }
1208         }
1209
1210         fclose(fp);
1211         return value;
1212 }
1213
1214 void netconfig_set_mac_address_from_file(void)
1215 {
1216         FILE *file = NULL;
1217         char mac_str[MAC_ADDRESS_MAX_LEN];
1218         gchar *mac_lower_str = NULL;
1219         int mac_len = 0;
1220
1221         file = fopen(MAC_INFO_FILEPATH, "r");
1222         if (file == NULL) {
1223                 ERR("Fail to open %s", MAC_INFO_FILEPATH);
1224                 file = fopen(MAC_ADDRESS_FILEPATH, "r");
1225                 if (file == NULL) {
1226                         ERR("Fail to open %s", MAC_ADDRESS_FILEPATH);
1227                         return;
1228                 }
1229         }
1230         if (fgets(mac_str, sizeof(mac_str), file) == NULL) {
1231                 ERR("Fail to read mac address");
1232                 fclose(file);
1233                 return;
1234         }
1235
1236         mac_len = strlen(mac_str);
1237         if (mac_len < 17) {
1238                 ERR("mac.info is empty");
1239                 fclose(file);
1240                 return;
1241         }
1242
1243         mac_lower_str = g_ascii_strup(mac_str, (gssize)mac_len);
1244         netconfig_set_vconf_str(VCONFKEY_WIFI_BSSID_ADDRESS, mac_lower_str);
1245
1246         g_free(mac_lower_str);
1247         fclose(file);
1248 }
1249
1250 tizen_profile_t _get_tizen_profile()
1251 {
1252         static tizen_profile_t profile = TIZEN_PROFILE_UNKNOWN;
1253         if (__builtin_expect(profile != TIZEN_PROFILE_UNKNOWN, 1))
1254                 return profile;
1255
1256         char *profileName;
1257         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
1258         switch (*profileName) {
1259         case 'm':
1260         case 'M':
1261                 profile = TIZEN_PROFILE_MOBILE;
1262                 break;
1263         case 'w':
1264         case 'W':
1265                 profile = TIZEN_PROFILE_WEARABLE;
1266                 break;
1267         case 't':
1268         case 'T':
1269                 profile = TIZEN_PROFILE_TV;
1270                 break;
1271         case 'i':
1272         case 'I':
1273                 profile = TIZEN_PROFILE_IVI;
1274                 break;
1275         default: // common or unknown ==> ALL ARE COMMON.
1276                 profile = TIZEN_PROFILE_COMMON;
1277         }
1278         free(profileName);
1279
1280         return profile;
1281 }
1282
1283 void netconfig_plugin_init()
1284 {
1285         handle_headed = dlopen(HEADED_PLUGIN_FILEPATH, RTLD_NOW);
1286         if (!handle_headed) {
1287                 ERR("Can't load %s: %s", HEADED_PLUGIN_FILEPATH, dlerror());
1288         } else {
1289                 headed_plugin = dlsym(handle_headed, "netconfig_headed_plugin");
1290                 if (!headed_plugin) {
1291                         ERR("Can't load symbol: %s", dlerror());
1292                         dlclose(handle_headed);
1293                 } else {
1294                         netconfig_plugin_headed_enabled = TRUE;
1295                 }
1296         }
1297
1298         handle_telephony = dlopen(TELEPHONY_PLUGIN_FILEPATH, RTLD_NOW);
1299         if (!handle_telephony) {
1300                 ERR("Can't load %s: %s", TELEPHONY_PLUGIN_FILEPATH, dlerror());
1301         } else {
1302                 telephony_plugin = dlsym(handle_telephony, "netconfig_telephony_plugin");
1303                 if (!telephony_plugin) {
1304                         ERR("Can't load symbol: %s", dlerror());
1305                         dlclose(handle_telephony);
1306                 } else {
1307                         netconfig_plugin_telephony_enabled = TRUE;
1308                 }
1309         }
1310 }
1311
1312 void netconfig_plugin_deinit()
1313 {
1314         if (netconfig_plugin_headed_enabled) {
1315                 netconfig_plugin_headed_enabled = FALSE;
1316                 dlclose(handle_headed);
1317         }
1318
1319         if (netconfig_plugin_telephony_enabled) {
1320                 netconfig_plugin_telephony_enabled = FALSE;
1321                 dlclose(handle_telephony);
1322         }
1323 }
1324
1325 gboolean netconfig_get_headed_plugin_flag()
1326 {
1327         return netconfig_plugin_headed_enabled;
1328 }
1329
1330 gboolean netconfig_get_telephony_plugin_flag()
1331 {
1332         return netconfig_plugin_telephony_enabled;
1333 }
1334
1335 bool netconfig_check_feature_supported(netconfig_supported_feature_e feature)
1336 {
1337         const char *key = NULL;
1338
1339         if (!is_feature_checked[feature]) {
1340                 switch (feature) {
1341                 case NETCONFIG_SUPPORTED_FEATURE_ETHERNET:
1342                         key = ETHERNET_FEATURE;
1343                         break;
1344                 case NETCONFIG_SUPPORTED_FEATURE_TETHERING:
1345                         key = TETHERING_FEATURE;
1346                         break;
1347                 case NETCONFIG_SUPPORTED_FEATURE_WIFI_DIRECT:
1348                         key = WIFI_DIRECT_FEATURE;
1349                         break;
1350                 case NETCONFIG_SUPPORTED_FEATURE_WIFI_SOFTAP:
1351                         key = WIFI_SOFTAP_FEATURE;
1352                         break;
1353                 default:
1354                         ERR("Uknown feature");
1355                         return false;
1356                 }
1357
1358                 if (system_info_get_platform_bool(key, &feature_supported[feature]) < 0) {
1359                         ERR("Get feature is failed");
1360                         return false;
1361                 }
1362                 is_feature_checked[feature] = true;
1363         }
1364         return feature_supported[feature];
1365 }