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