2 * Network Configuration Module
4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
28 #include <vconf-keys.h>
29 #include <wifi-direct.h>
30 #include <notification.h>
35 #include "wifi-state.h"
37 #define WIFI_MAC_INFO_FILE "/opt/etc/.mac.info"
38 #define WIFI_MAC_INFO_LENGTH 17
39 #define WIFI_DEV_NAME "wlan0"
41 GKeyFile *netconfig_keyfile_load(const char *pathname)
43 GKeyFile *keyfile = NULL;
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);
51 g_key_file_free(keyfile);
58 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
62 gchar *keydata = NULL;
63 gchar *needle = NULL, *directory = NULL;
65 directory = g_strdup(pathname);
66 needle = g_strrstr(directory, "/");
71 if (directory == NULL || (*directory) == '\0') {
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) {
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);
91 if (chmod(pathname, S_IRUSR | S_IWUSR) != 0)
92 DBG("Unable to change permission of %s", pathname);
96 g_key_file_free(keyfile);
99 void netconfig_start_timer_seconds(guint secs,
100 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
104 if (callback == NULL) {
105 ERR("callback function is NULL");
109 if ((timer_id != NULL && *timer_id != 0)) {
110 ERR("timer already is registered");
114 t_id = g_timeout_add_seconds(secs, callback, user_data);
117 ERR("Can't add timer");
121 if (timer_id != NULL)
125 void netconfig_start_timer(guint msecs,
126 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
130 INFO("Register timer with callback pointer (%p)", callback);
132 if (callback == NULL) {
133 ERR("callback function is NULL");
137 if ((timer_id != NULL && *timer_id != 0)) {
138 ERR("timer already is registered");
142 t_id = g_timeout_add(msecs, callback, user_data);
145 ERR("Can't add timer");
149 if (timer_id != NULL)
153 void netconfig_stop_timer(guint *timer_id)
155 if (timer_id == NULL) {
156 ERR("timer is NULL");
160 if (*timer_id != 0) {
161 g_source_remove(*timer_id);
166 static gboolean __netconfig_test_device_picker()
168 char *favorite_wifi_service = NULL;
170 favorite_wifi_service = netconfig_wifi_get_favorite_service();
171 if (favorite_wifi_service != NULL) {
172 g_free(favorite_wifi_service);
179 static void __netconfig_pop_device_picker(void)
182 int wifi_ug_state = 0;
183 notification_error_e err = NOTIFICATION_ERROR_NONE;
185 vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
186 if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
189 DBG("Launch Wi-Fi device picker");
190 // TODO : display a popup
192 notification_h noti = NULL;
194 noti = notification_create(NOTIFICATION_TYPE_NOTI);
196 ERR("Failed to create notification \n");
200 err = notification_set_pkgname(noti, NET_CONFIG_APP_NAME);
201 if (err != NOTIFICATION_ERROR_NONE) {
202 ERR("Unable to set pkgname \n");
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");
212 err = notification_insert(noti, NULL);
213 if (err != NOTIFICATION_ERROR_NONE) {
214 ERR("Unable to insert notification \n");
221 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
223 if (__netconfig_test_device_picker() == TRUE)
224 __netconfig_pop_device_picker();
229 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method,
232 static guint netconfig_wifi_device_picker_service_timer = 0;
234 if (is_set_method != TRUE)
235 return netconfig_wifi_device_picker_service_timer;
237 if (netconfig_wifi_device_picker_service_timer != timer_id)
238 netconfig_wifi_device_picker_service_timer = timer_id;
240 return netconfig_wifi_device_picker_service_timer;
243 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
245 __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
248 static guint __netconfig_wifi_device_picker_get_timer_id(void)
250 return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
253 void netconfig_wifi_device_picker_service_start(void)
256 const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
257 int hotspot_wifi_state = VCONFKEY_MOBILE_HOTSPOT_WIFI_OFF;
260 vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
261 if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
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);
271 DBG("Register device picker timer with %d milliseconds",
272 NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
274 netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL,
275 __netconfig_wifi_try_device_picker, NULL, &timer_id);
277 __netconfig_wifi_device_picker_set_timer_id(timer_id);
280 void netconfig_wifi_device_picker_service_stop(void)
284 timer_id = __netconfig_wifi_device_picker_get_timer_id();
288 DBG("Clear device picker timer with timer_id %d", timer_id);
290 netconfig_stop_timer(&timer_id);
292 __netconfig_wifi_device_picker_set_timer_id(timer_id);
295 gboolean netconfig_is_wifi_direct_on(void)
297 int wifi_direct_state = 0;
299 vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
301 DBG("Wi-Fi direct mode %d", wifi_direct_state);
302 return (wifi_direct_state != 0) ? TRUE : FALSE;
305 gboolean netconfig_is_wifi_tethering_on(void)
307 int wifi_tethering_state = 0;
309 vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
311 DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
312 if (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
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[])
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);
332 while (args[index] != NULL) {
333 INFO(" %s", args[index]);
338 if (execve(file_path, args, env) == -1) {
339 DBG("Fail to execute command...(%s)",
343 } else if (pid > 0) {
344 if (waitpid(pid, &rv, 0) == -1) {
345 DBG("wait pid (%u) rv (%d)", pid, 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)) {
360 DBG("failed to fork()...(%s)", strerror(errno));
364 gboolean netconfig_iface_wifi_launch_direct(NetconfigWifi *wifi, GError **error)
368 DBG("Launch Wi-Fi direct daemon");
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 };
374 ret = netconfig_execute_file(path, args, env);
377 INFO("Failed to launch Wi-Fi direct daemon");
379 netconfig_error_wifi_direct_failed(error);
385 void netconfig_add_wifi_found_notification(void)
387 notification_error_e err = NOTIFICATION_ERROR_NONE;
389 INFO("Add wifi found notification");
391 notification_h noti = NULL;
393 noti = notification_create(NOTIFICATION_TYPE_NOTI);
395 ERR("Failed to create notification \n");
399 err = notification_set_pkgname(noti, NET_CONFIG_APP_NAME);
400 if (err != NOTIFICATION_ERROR_NONE) {
401 ERR("Unable to set pkgname \n");
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");
411 err = notification_insert(noti, NULL);
412 if (err != NOTIFICATION_ERROR_NONE) {
413 ERR("Unable to insert notification \n");
418 void netconfig_del_wifi_found_notification(void)
420 notification_error_e err = NOTIFICATION_ERROR_NONE;
422 INFO("Delete wifi found notification");
424 notification_h noti = NULL;
426 noti = notification_create(NOTIFICATION_TYPE_NOTI);
428 ERR("Failed to create notification \n");
432 err = notification_set_pkgname(noti, NET_CONFIG_APP_NAME);
433 if (err != NOTIFICATION_ERROR_NONE) {
434 ERR("Unable to set pkgname \n");
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");
444 err = notification_insert(noti, NULL);
445 if (err != NOTIFICATION_ERROR_NONE) {
446 ERR("Unable to insert notification \n");
452 void netconfig_set_wifi_mac_address(void)
457 char buf[WIFI_MAC_INFO_LENGTH + 1];
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);
465 INFO("%s : %s", VCONFKEY_WIFI_BSSID_ADDRESS, mac_info);
467 fp = fopen(WIFI_MAC_INFO_FILE, "r");
469 if (fgets(buf, sizeof(buf), fp) == NULL) {
470 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
474 INFO("%s : %s", WIFI_MAC_INFO_FILE, buf);
476 if (strlen(buf) < WIFI_MAC_INFO_LENGTH) {
477 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
481 buf[WIFI_MAC_INFO_LENGTH] = '\0';
483 // not MAC into file use ioctl to get MAC
484 ctl_sk = socket(PF_INET,SOCK_DGRAM,0);
486 ERR("Failed to open socket");
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;
494 if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr) != 0) {
495 ERR("Failed to SIOCGIFHWADDR ioctl");
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]);
508 INFO("%s MAC address: %s", WIFI_DEV_NAME, buf);
511 if (mac_info && (g_str_equal(mac_info, buf) == TRUE))
514 if (vconf_set_str(VCONFKEY_WIFI_BSSID_ADDRESS, buf) != 0)
515 ERR("Failed to set MAC info to %s", VCONFKEY_WIFI_BSSID_ADDRESS);