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