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>
27 #include <net/route.h>
28 #include <arpa/inet.h>
30 #include <vconf-keys.h>
31 #include <wifi-direct.h>
36 #include "wifi-state.h"
38 #define WIFI_MAC_INFO_FILE "/opt/etc/.mac.info"
39 #define WIFI_MAC_INFO_LENGTH 17
40 #define WIFI_DEV_NAME "wlan0"
42 GKeyFile *netconfig_keyfile_load(const char *pathname)
44 GKeyFile *keyfile = NULL;
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);
52 g_key_file_free(keyfile);
59 void netconfig_keyfile_save(GKeyFile *keyfile, const char *pathname)
63 gchar *keydata = NULL;
64 gchar *needle = NULL, *directory = NULL;
66 directory = g_strdup(pathname);
67 needle = g_strrstr(directory, "/");
72 if (directory == NULL || (*directory) == '\0') {
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) {
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);
92 if (chmod(pathname, S_IRUSR | S_IWUSR) != 0)
93 DBG("Unable to change permission of %s", pathname);
97 g_key_file_free(keyfile);
100 void netconfig_start_timer_seconds(guint secs,
101 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
105 if (callback == NULL) {
106 ERR("callback function is NULL");
110 if ((timer_id != NULL && *timer_id != 0)) {
111 ERR("timer already is registered");
115 t_id = g_timeout_add_seconds(secs, callback, user_data);
118 ERR("Can't add timer");
122 if (timer_id != NULL)
126 void netconfig_start_timer(guint msecs,
127 gboolean(*callback) (gpointer), void *user_data, guint *timer_id)
131 INFO("Register timer with callback pointer (%p)", callback);
133 if (callback == NULL) {
134 ERR("callback function is NULL");
138 if ((timer_id != NULL && *timer_id != 0)) {
139 ERR("timer already is registered");
143 t_id = g_timeout_add(msecs, callback, user_data);
146 ERR("Can't add timer");
150 if (timer_id != NULL)
154 void netconfig_stop_timer(guint *timer_id)
156 if (timer_id == NULL) {
157 ERR("timer is NULL");
161 if (*timer_id != 0) {
162 g_source_remove(*timer_id);
167 static gboolean __netconfig_test_device_picker()
169 char *favorite_wifi_service = NULL;
171 favorite_wifi_service = netconfig_wifi_get_favorite_service();
172 if (favorite_wifi_service != NULL) {
173 g_free(favorite_wifi_service);
180 static void __netconfig_pop_device_picker(void)
182 int wifi_ug_state = 0;
184 vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
185 if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
188 DBG("Launch Wi-Fi device picker");
189 // TODO : display a popup
193 static gboolean __netconfig_wifi_try_device_picker(gpointer data)
195 if (__netconfig_test_device_picker() == TRUE)
196 __netconfig_pop_device_picker();
201 static guint __netconfig_wifi_device_picker_timer_id(gboolean is_set_method,
204 static guint netconfig_wifi_device_picker_service_timer = 0;
206 if (is_set_method != TRUE)
207 return netconfig_wifi_device_picker_service_timer;
209 if (netconfig_wifi_device_picker_service_timer != timer_id)
210 netconfig_wifi_device_picker_service_timer = timer_id;
212 return netconfig_wifi_device_picker_service_timer;
215 static void __netconfig_wifi_device_picker_set_timer_id(guint timer_id)
217 __netconfig_wifi_device_picker_timer_id(TRUE, timer_id);
220 static guint __netconfig_wifi_device_picker_get_timer_id(void)
222 return __netconfig_wifi_device_picker_timer_id(FALSE, -1);
225 void netconfig_wifi_device_picker_service_start(void)
228 const int NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL = 700;
229 int hotspot_wifi_state = VCONFKEY_MOBILE_HOTSPOT_WIFI_OFF;
232 vconf_get_int(VCONFKEY_WIFI_UG_RUN_STATE, &wifi_ug_state);
233 if (wifi_ug_state == VCONFKEY_WIFI_UG_RUN_STATE_ON_FOREGROUND)
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);
243 DBG("Register device picker timer with %d milliseconds",
244 NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL);
246 netconfig_start_timer(NETCONFIG_WIFI_DEVICE_PICKER_INTERVAL,
247 __netconfig_wifi_try_device_picker, NULL, &timer_id);
249 __netconfig_wifi_device_picker_set_timer_id(timer_id);
252 void netconfig_wifi_device_picker_service_stop(void)
256 timer_id = __netconfig_wifi_device_picker_get_timer_id();
260 DBG("Clear device picker timer with timer_id %d", timer_id);
262 netconfig_stop_timer(&timer_id);
264 __netconfig_wifi_device_picker_set_timer_id(timer_id);
267 gboolean netconfig_is_wifi_direct_on(void)
269 int wifi_direct_state = 0;
271 vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
273 DBG("Wi-Fi direct mode %d", wifi_direct_state);
274 return (wifi_direct_state != 0) ? TRUE : FALSE;
277 gboolean netconfig_is_wifi_tethering_on(void)
279 int wifi_tethering_state = 0;
281 vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &wifi_tethering_state);
283 DBG("Wi-Ti tethering mode %d", wifi_tethering_state);
284 if (wifi_tethering_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
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[])
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);
304 while (args[index] != NULL) {
305 INFO(" %s", args[index]);
310 if (execve(file_path, args, env) == -1) {
311 DBG("Fail to execute command...(%s)",
315 } else if (pid > 0) {
316 if (waitpid(pid, &rv, 0) == -1) {
317 DBG("wait pid (%u) rv (%d)", pid, 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)) {
332 DBG("failed to fork()...(%s)", strerror(errno));
336 int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
342 memset(&rt, 0, sizeof(rt));
344 rt.rtmsg_dst_len = prefix_len;
346 rt.rtmsg_flags = RTF_UP | RTF_HOST;
348 if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
353 if (gateway != NULL) {
354 rt.rtmsg_flags |= RTF_GATEWAY;
355 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
363 fd = socket(AF_INET6, SOCK_DGRAM, 0);
367 rt.rtmsg_ifindex = 0;
371 memset(&ifr, 0, sizeof(ifr));
372 strcpy(ifr.ifr_name, interface);
373 ioctl(fd, SIOCGIFINDEX, &ifr);
374 rt.rtmsg_ifindex = ifr.ifr_ifindex;
377 if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
378 DBG("Failed to add route: %d\n", err);
388 int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
394 memset(&rt, 0, sizeof(rt));
396 rt.rtmsg_dst_len = prefix_len;
398 rt.rtmsg_flags = RTF_UP | RTF_HOST;
400 if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
405 if (gateway != NULL) {
406 rt.rtmsg_flags |= RTF_GATEWAY;
407 if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
415 fd = socket(AF_INET6, SOCK_DGRAM, 0);
419 rt.rtmsg_ifindex = 0;
423 memset(&ifr, 0, sizeof(ifr));
424 strcpy(ifr.ifr_name, interface);
425 ioctl(fd, SIOCGIFINDEX, &ifr);
426 rt.rtmsg_ifindex = ifr.ifr_ifindex;
429 if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
430 DBG("Failed to add route: %d\n", err);
440 gboolean netconfig_iface_wifi_launch_direct(NetconfigWifi *wifi, GError **error)
444 DBG("Launch Wi-Fi direct daemon");
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 };
450 ret = netconfig_execute_file(path, args, env);
453 INFO("Failed to launch Wi-Fi direct daemon");
455 netconfig_error_wifi_direct_failed(error);
461 void netconfig_add_wifi_found_notification(void)
463 INFO("Add wifi found notification");
466 void netconfig_del_wifi_found_notification(void)
468 INFO("Delete wifi found notification");
472 void netconfig_set_wifi_mac_address(void)
477 char buf[WIFI_MAC_INFO_LENGTH + 1];
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);
485 INFO("%s : %s", VCONFKEY_WIFI_BSSID_ADDRESS, mac_info);
487 fp = fopen(WIFI_MAC_INFO_FILE, "r");
489 if (fgets(buf, sizeof(buf), fp) == NULL) {
490 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
494 INFO("%s : %s", WIFI_MAC_INFO_FILE, buf);
496 if (strlen(buf) < WIFI_MAC_INFO_LENGTH) {
497 ERR("Failed to get MAC info from %s", WIFI_MAC_INFO_FILE);
501 buf[WIFI_MAC_INFO_LENGTH] = '\0';
503 // not MAC into file use ioctl to get MAC
504 ctl_sk = socket(PF_INET,SOCK_DGRAM,0);
506 ERR("Failed to open socket");
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;
514 if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr) != 0) {
515 ERR("Failed to SIOCGIFHWADDR ioctl");
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]);
528 INFO("%s MAC address: %s", WIFI_DEV_NAME, buf);
531 if (mac_info && (g_str_equal(mac_info, buf) == TRUE))
534 if (vconf_set_str(VCONFKEY_WIFI_BSSID_ADDRESS, buf) != 0)
535 ERR("Failed to set MAC info to %s", VCONFKEY_WIFI_BSSID_ADDRESS);
549 gboolean netconfig_interface_up(const char *ifname)
554 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
558 memset(&ifr, 0, sizeof(ifr));
559 g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
561 if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
566 ifr.ifr_flags |= (IFF_UP | IFF_DYNAMIC);
567 if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
574 INFO("Successfully activated wireless interface");
578 gboolean netconfig_interface_down(const char *ifname)
583 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
587 memset(&ifr, 0, sizeof(ifr));
588 g_strlcpy((char *)ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
590 if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
595 ifr.ifr_flags = (ifr.ifr_flags & ~IFF_UP) | IFF_DYNAMIC;
596 if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
603 DBG("Successfully de-activated wireless interface");