[net-config]: Fix build warning error
[platform/core/connectivity/net-config.git] / src / utils / util.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 <unistd.h>
21 #include <string.h>
22 #include <sys/wait.h>
23 #include <sys/stat.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <net/if.h>
27 #include <net/route.h>
28 #include <arpa/inet.h>
29 #include <vconf.h>
30 #include <vconf-keys.h>
31 #include <wifi-direct.h>
32
33 #include "log.h"
34 #include "util.h"
35 #include "neterror.h"
36 #include "wifi-state.h"
37
38 #define WIFI_MAC_INFO_FILE      "/opt/etc/.mac.info"
39 #define WIFI_MAC_INFO_LENGTH    17
40 #define WIFI_DEV_NAME           "wlan0"
41
42 GKeyFile *netconfig_keyfile_load(const char *pathname)
43 {
44         GKeyFile *keyfile = NULL;
45         GError *error = NULL;
46
47         keyfile = g_key_file_new();
48         if (g_key_file_load_from_file(keyfile, pathname, 0, &error) != TRUE) {
49                 DBG("Unable to open %s, error %s", pathname, error->message);
50                 g_error_free(error);
51
52                 g_key_file_free(keyfile);
53                 keyfile = NULL;
54         }
55
56         return keyfile;
57 }
58
59 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
60 {
61         gsize size = 0;
62         GError *error = NULL;
63         gchar *keydata = NULL;
64         gchar *needle = NULL, *directory = NULL;
65
66         directory = g_strdup(pathname);
67         needle = g_strrstr(directory, "/");
68
69         if (needle != NULL)
70                 *needle = '\0';
71
72         if (directory == NULL || (*directory) == '\0') {
73                 g_free(directory);
74                 return;
75         }
76
77         if (g_file_test(directory, G_FILE_TEST_IS_DIR) != TRUE) {
78                 if (g_mkdir_with_parents(directory,
79                                 S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
80                         g_free(directory);
81                         return;
82                 }
83         }
84         g_free(directory);
85
86         keydata = g_key_file_to_data(keyfile, &size, &error);
87         if (g_file_set_contents(pathname, keydata, size, &error) != TRUE) {
88                 DBG("Unable to save %s, error %s", pathname, error->message);
89                 g_error_free(error);
90         }
91
92         if (chmod(pathname, S_IRUSR | S_IWUSR) != 0)
93                 DBG("Unable to change permission of %s", pathname);
94
95         g_free(keydata);
96
97         g_key_file_free(keyfile);
98 }
99
100 void netconfig_start_timer_seconds(guint secs,
101                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
102 {
103         guint t_id = 0;
104
105         if (callback == NULL) {
106                 ERR("callback function is NULL");
107                 return;
108         }
109
110         if ((timer_id != NULL && *timer_id != 0)) {
111                 ERR("timer already is registered");
112                 return;
113         }
114
115         t_id = g_timeout_add_seconds(secs, callback, user_data);
116
117         if (t_id == 0) {
118                 ERR("Can't add timer");
119                 return;
120         }
121
122         if (timer_id != NULL)
123                 *timer_id = t_id;
124 }
125
126 void netconfig_start_timer(guint msecs,
127                 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
128 {
129         guint t_id = 0;
130
131         INFO("Register timer with callback pointer (%p)", callback);
132
133         if (callback == NULL) {
134                 ERR("callback function is NULL");
135                 return;
136         }
137
138         if ((timer_id != NULL && *timer_id != 0)) {
139                 ERR("timer already is registered");
140                 return;
141         }
142
143         t_id = g_timeout_add(msecs, callback, user_data);
144
145         if (t_id == 0) {
146                 ERR("Can't add timer");
147                 return;
148         }
149
150         if (timer_id != NULL)
151                 *timer_id = t_id;
152 }
153
154 void netconfig_stop_timer(guint *timer_id)
155 {
156         if (timer_id == NULL) {
157                 ERR("timer is NULL");
158                 return;
159         }
160
161         if (*timer_id != 0) {
162                 g_source_remove(*timer_id);
163                 *timer_id = 0;
164         }
165 }
166
167 static gboolean __netconfig_test_device_picker()
168 {
169         char *favorite_wifi_service = NULL;
170
171         favorite_wifi_service = netconfig_wifi_get_favorite_service();
172         if (favorite_wifi_service != NULL) {
173                 g_free(favorite_wifi_service);
174                 return FALSE;
175         }
176
177         return TRUE;
178 }
179
180 static void __netconfig_pop_device_picker(void)
181 {
182         int wifi_ug_state = 0;
183
184         vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
185         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
186                 return;
187
188         DBG("Launch Wi-Fi device picker");
189         // TODO : display a popup
190
191 }
192
193 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
194 {
195         if (__netconfig_test_device_picker() == TRUE)
196                 __netconfig_pop_device_picker();
197
198         return FALSE;
199 }
200
201 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method,
202                 guint timer_id)
203 {
204         static guint netconfig_wifi_device_picker_service_timer = 0;
205
206         if (is_set_method != TRUE)
207                 return netconfig_wifi_device_picker_service_timer;
208
209         if (netconfig_wifi_device_picker_service_timer != timer_id)
210                 netconfig_wifi_device_picker_service_timer = timer_id;
211
212         return netconfig_wifi_device_picker_service_timer;
213 }
214
215 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
216 {
217         __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
218 }
219
220 static guint __netconfig_wifi_device_picker_get_timer_id(void)
221 {
222         return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
223 }
224
225 void netconfig_wifi_device_picker_service_start(void)
226 {
227         int wifi_ug_state;
228         const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
229         int hotspot_wifi_state = VCONFKEY_MOBILE_HOTSPOT_WIFI_OFF;
230         guint timer_id = 0;
231
232         vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
233         if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
234                 return;
235
236         /* If Wi-Fi tethering is pending on, don't show device picker UI*/
237         vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_WIFI_STATE, &hotspot_wifi_state);
238         if (hotspot_wifi_state == VCONFKEY_MOBILE_HOTSPOT_WIFI_PENDING_ON) {
239                 DBG("hotspot_wifi_state %d", hotspot_wifi_state);
240                 return;
241         }
242
243         DBG("Register device picker timer with %d milliseconds",
244                         NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
245
246         netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL,
247                         __netconfig_wifi_try_device_picker, NULL, &timer_id);
248
249         __netconfig_wifi_device_picker_set_timer_id(timer_id);
250 }
251
252 void netconfig_wifi_device_picker_service_stop(void)
253 {
254         guint timer_id = 0;
255
256         timer_id = __netconfig_wifi_device_picker_get_timer_id();
257         if (timer_id == 0)
258                 return;
259
260         DBG("Clear device picker timer with timer_id %d", timer_id);
261
262         netconfig_stop_timer(&timer_id);
263
264         __netconfig_wifi_device_picker_set_timer_id(timer_id);
265 }
266
267 gboolean netconfig_is_wifi_direct_on(void)
268 {
269         int wifi_direct_state = 0;
270
271         vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
272
273         DBG("Wi-Fi direct mode %d", wifi_direct_state);
274         return (wifi_direct_state != 0) ? TRUE : FALSE;
275 }
276
277 gboolean netconfig_is_wifi_tethering_on(void)
278 {
279         int wifi_tethering_state = 0;
280
281         vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
282
283         DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
284         if (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
285                 return TRUE;
286
287         return FALSE;
288 }
289
290 /* args[] and env[] should be terminated with NULL pointer */
291 gboolean netconfig_execute_file(const char *file_path,
292                 char *const args[], char *const env[])
293 {
294         pid_t pid = 0;
295         int rv = 0;
296         errno = 0;
297
298         if (!(pid = fork())) {
299                 register unsigned int index = 0;
300                 INFO("pid(%d), ppid (%d)", getpid(), getppid());
301                 INFO("Inside child, exec (%s) command", file_path);
302
303                 index = 0;
304                 while (args[index] != NULL) {
305                         INFO(" %s", args[index]);
306                         index++;
307                 }
308
309                 errno = 0;
310                 if (execve(file_path, args, env) == -1) {
311                         DBG("Fail to execute command...(%s)",
312                                         strerror(errno));
313                         return FALSE;
314                 }
315         } else if (pid > 0) {
316                 if (waitpid(pid, &rv, 0) == -1) {
317                         DBG("wait pid (%u) rv (%d)", pid, rv);
318
319                         if (WIFEXITED(rv)) {
320                                 DBG("exited, rv=%d", WEXITSTATUS(rv));
321                         } else if (WIFSIGNALED(rv)) {
322                                 DBG("killed by signal %d", WTERMSIG(rv));
323                         } else if (WIFSTOPPED(rv)) {
324                                 DBG("stopped by signal %d", WSTOPSIG(rv));
325                         } else if (WIFCONTINUED(rv)) {
326                                 DBG("continued");
327                         }
328                 }
329                 return TRUE;
330         }
331
332         DBG("failed to fork()...(%s)", strerror(errno));
333         return FALSE;
334 }
335
336 int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
337 {
338         struct in6_rtmsg rt;
339         int fd = 0;
340         int err = 0;
341
342         memset(&rt, 0, sizeof(rt));
343
344         rt.rtmsg_dst_len = prefix_len;
345
346         rt.rtmsg_flags = RTF_UP | RTF_HOST;
347
348         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
349                 err = -errno;
350                 return err;
351         }
352
353         if (gateway != NULL) {
354                 rt.rtmsg_flags |= RTF_GATEWAY;
355                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
356                         err = -errno;
357                         return err;
358                 }
359         }
360
361         rt.rtmsg_metric = 1;
362
363         fd = socket(AF_INET6, SOCK_DGRAM, 0);
364         if (fd < 0)
365                 return -1;
366
367         rt.rtmsg_ifindex = 0;
368
369         if (interface) {
370                 struct ifreq ifr;
371                 memset(&ifr, 0, sizeof(ifr));
372                 strcpy(ifr.ifr_name, interface);
373                 ioctl(fd, SIOCGIFINDEX, &ifr);
374                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
375         }
376
377         if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
378                 DBG("Failed to add route: %d\n", err);
379                 close(fd);
380                 return -1;
381         }
382
383         close(fd);
384
385         return 1;
386 }
387
388 int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
389 {
390         struct in6_rtmsg rt;
391         int fd = 0;
392         int err = 0;
393
394         memset(&rt, 0, sizeof(rt));
395
396         rt.rtmsg_dst_len = prefix_len;
397
398         rt.rtmsg_flags = RTF_UP | RTF_HOST;
399
400         if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
401                 err = -errno;
402                 return err;
403         }
404
405         if (gateway != NULL) {
406                 rt.rtmsg_flags |= RTF_GATEWAY;
407                 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
408                         err = -errno;
409                         return err;
410                 }
411         }
412
413         rt.rtmsg_metric = 1;
414
415         fd = socket(AF_INET6, SOCK_DGRAM, 0);
416         if (fd < 0)
417                 return -1;
418
419         rt.rtmsg_ifindex = 0;
420
421         if (interface) {
422                 struct ifreq ifr;
423                 memset(&ifr, 0, sizeof(ifr));
424                 strcpy(ifr.ifr_name, interface);
425                 ioctl(fd, SIOCGIFINDEX, &ifr);
426                 rt.rtmsg_ifindex = ifr.ifr_ifindex;
427         }
428
429         if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
430                 DBG("Failed to add route: %d\n", err);
431                 close(fd);
432                 return -1;
433         }
434
435         close(fd);
436
437         return 1;
438 }
439
440 gboolean netconfig_iface_wifi_launch_direct(NetconfigWifi *wifi, GError **error)
441 {
442         gboolean ret = TRUE;
443
444         DBG("Launch Wi-Fi direct daemon");
445
446         const char *path = "/usr/bin/wifi-direct-server.sh";
447         char *const args[] = { "wifi-direct-server.sh", "start", NULL};
448         char *const env[] = { NULL };
449
450         ret = netconfig_execute_file(path, args, env);
451
452         if (ret != TRUE) {
453                 INFO("Failed to launch Wi-Fi direct daemon");
454
455                 netconfig_error_wifi_direct_failed(error);
456         }
457
458         return ret;
459 }
460
461 void netconfig_add_wifi_found_notification(void)
462 {
463         INFO("Add wifi found notification");
464 }
465
466 void netconfig_del_wifi_found_notification(void)
467 {
468         INFO("Delete wifi found notification");
469 }
470
471
472 void netconfig_set_wifi_mac_address(void)
473 {
474         FILE *fp = NULL;
475         struct ifreq ifr;
476         int ctl_sk = -1;
477         char buf[WIFI_MAC_INFO_LENGTH + 1];
478         char *mac_info;
479
480         mac_info = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS);
481         if (mac_info == NULL) {
482                 ERR("Failed to open vconf key %s", VCONFKEY_WIFI_BSSID_ADDRESS);
483         }
484
485         INFO("%s : %s", VCONFKEY_WIFI_BSSID_ADDRESS, mac_info);
486
487         fp = fopen(WIFI_MAC_INFO_FILE, "r");
488         if (fp != NULL) {
489                 if (fgets(buf, sizeof(buf), fp) == NULL) {
490                         ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
491                         goto done;
492                 }
493
494                 INFO("%s : %s", WIFI_MAC_INFO_FILE, buf);
495
496                 if (strlen(buf) < WIFI_MAC_INFO_LENGTH) {
497                         ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
498                         goto done;
499                 }
500
501                 buf[WIFI_MAC_INFO_LENGTH] = '\0';
502         } else {
503                 // not MAC into file use ioctl to get MAC
504                 ctl_sk = socket(PF_INET,SOCK_DGRAM,0);
505                 if (ctl_sk < 0 ) {
506                         ERR("Failed to open socket");
507                         goto done;
508                 }
509
510                 memset(&ifr, 0, sizeof(struct ifreq));
511                 strncpy(ifr.ifr_name, WIFI_DEV_NAME, sizeof(ifr.ifr_name) - 1);
512                 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = 0;
513
514                 if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr) != 0) {
515                         ERR("Failed to SIOCGIFHWADDR ioctl");
516                         goto done;
517                 }
518
519                 snprintf(buf, WIFI_MAC_INFO_LENGTH + 1,
520                          "%02x:%02x:%02x:%02x:%02x:%02x",
521                          (unsigned char)ifr.ifr_hwaddr.sa_data[0],
522                          (unsigned char)ifr.ifr_hwaddr.sa_data[1],
523                          (unsigned char)ifr.ifr_hwaddr.sa_data[2],
524                          (unsigned char)ifr.ifr_hwaddr.sa_data[3],
525                          (unsigned char)ifr.ifr_hwaddr.sa_data[4],
526                          (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
527
528                 INFO("%s MAC address: %s", WIFI_DEV_NAME, buf);
529         }
530
531         if (mac_info && (g_str_equal(mac_info, buf) == TRUE))
532                 goto done;
533
534         if (vconf_set_str(VCONFKEY_WIFI_BSSID_ADDRESS, buf) != 0)
535                 ERR("Failed to set MAC info to %s", VCONFKEY_WIFI_BSSID_ADDRESS);
536
537 done:
538         g_free(mac_info);
539
540         if (fp != NULL) {
541                 fclose(fp);
542         }
543
544         if (ctl_sk >= 0) {
545                 close(ctl_sk);
546         }
547 }
548
549 gboolean netconfig_interface_up(const char *ifname)
550 {
551         int fd;
552         struct ifreq ifr;
553
554         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
555         if (fd < 0)
556                 return FALSE;
557
558         memset(&ifr, 0, sizeof(ifr));
559         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
560
561         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
562                 close(fd);
563                 return FALSE;
564         }
565
566         ifr.ifr_flags |= (IFF_UP | IFF_DYNAMIC);
567         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
568                 close(fd);
569                 return FALSE;
570         }
571
572         close(fd);
573
574         INFO("Successfully activated wireless interface");
575         return TRUE;
576 }
577
578 gboolean netconfig_interface_down(const char *ifname)
579 {
580         int fd;
581         struct ifreq ifr;
582
583         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
584         if (fd < 0)
585                 return FALSE;
586
587         memset(&ifr, 0, sizeof(ifr));
588         g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
589
590         if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
591                 close(fd);
592                 return FALSE;
593         }
594
595         ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
596         if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
597                 close(fd);
598                 return FALSE;
599         }
600
601         close(fd);
602
603         DBG("Successfully de-activated wireless interface");
604         return TRUE;
605 }
606