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