2 * Network Configuration Module
4 * Copyright (c) 2012 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.
21 * This file implements wifi direct utility functions.
23 * @file wifi-direct-util.c
24 * @author Gibyoung Kim (lastkgb.kim@samsung.com)
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
41 #include <app_service.h>
42 #include <wifi-direct.h>
43 #include <wifi-direct-internal.h>
45 #include "wifi-direct-manager.h"
46 #include "wifi-direct-state.h"
47 #include "wifi-direct-client.h"
48 #include "wifi-direct-util.h"
50 static int _txt_to_mac(char *txt, unsigned char *mac)
55 mac[i++] = (char) strtoul(txt, &txt, 16);
56 if (!*txt++ || i == 6)
63 WDS_LOGD("Converted MAC address [" MACSTR "]", MAC2STR(mac));
67 static int _txt_to_ip(char *txt, unsigned char *ip)
72 ip[i++] = (char) strtoul(txt, &txt, 10);
73 if (!*txt++ || i == 4)
80 WDS_LOGD("Converted IP address [" IPSTR "]", IP2STR(ip));
84 int wfd_util_freq_to_channel(int freq)
86 if (freq < 2412 || freq > 5825) {
87 WDS_LOGE("Invalid parameter");
92 return 36 + (freq - 5180)/5;
93 else if (freq <= 2472)
94 return 1 + (freq - 2412)/5;
95 else if (freq == 2484)
101 int wfd_util_get_phone_name(char *phone_name)
103 __WDS_LOG_FUNC_ENTER__;
106 name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
108 WDS_LOGE( "Failed to get vconf value for %s", VCONFKEY_SETAPPL_DEVICE_NAME_STR);
111 strncpy(phone_name, name, DEV_NAME_LEN);
112 phone_name[DEV_NAME_LEN] = '\0';
114 WDS_LOGD( "[%s: %s]", VCONFKEY_SETAPPL_DEVICE_NAME_STR, phone_name);
116 __WDS_LOG_FUNC_EXIT__;
120 void _wfd_util_dev_name_changed_cb(keynode_t *key, void* data)
122 __WDS_LOG_FUNC_ENTER__;
123 char dev_name[DEV_NAME_LEN+1] = {0, };
126 res = wfd_util_get_phone_name(dev_name);
128 WDS_LOGE("Failed to get phone name(vconf)");
131 WDS_LOGD("Device name changed as [%s]", dev_name);
133 res = wfd_local_set_dev_name(dev_name);
135 WDS_LOGE("Failed to set device name");
136 __WDS_LOG_FUNC_EXIT__;
140 void wfd_util_set_dev_name_notification()
142 __WDS_LOG_FUNC_ENTER__;
144 vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb, NULL);
146 __WDS_LOG_FUNC_EXIT__;
150 void wfd_util_unset_dev_name_notification()
152 __WDS_LOG_FUNC_ENTER__;
154 vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb);
156 __WDS_LOG_FUNC_EXIT__;
160 int wfd_util_check_wifi_state()
162 __WDS_LOG_FUNC_ENTER__;
166 /* vconf key and value (vconf-keys.h)
167 #define VCONFKEY_WIFI_STATE "memory/wifi/state"
169 VCONFKEY_WIFI_OFF = 0x00,
170 VCONFKEY_WIFI_UNCONNECTED,
171 VCONFKEY_WIFI_CONNECTED,
172 VCONFKEY_WIFI_TRANSFER,
173 VCONFKEY_WIFI_STATE_MAX
177 res = vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
179 WDS_LOGE("Failed to get vconf value [%s]", VCONFKEY_WIFI_STATE);
180 __WDS_LOG_FUNC_EXIT__;
183 WDS_LOGD("[%s: %d]", VCONFKEY_WIFI_STATE, wifi_state);
185 if (wifi_state > VCONFKEY_WIFI_OFF) {
186 WDS_LOGD("Wi-Fi is on");
187 __WDS_LOG_FUNC_EXIT__;
190 WDS_LOGD( "OK. Wi-Fi is off\n");
192 __WDS_LOG_FUNC_EXIT__;
196 int wfd_util_check_mobile_ap_state()
198 __WDS_LOG_FUNC_ENTER__;
199 int mobile_ap_state = 0;
202 res = vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobile_ap_state);
204 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_MOBILE_HOTSPOT_MODE);
205 __WDS_LOG_FUNC_EXIT__;
208 WDS_LOGD("[%s: %d]", VCONFKEY_MOBILE_HOTSPOT_MODE, mobile_ap_state);
210 if (mobile_ap_state != VCONFKEY_MOBILE_HOTSPOT_MODE_NONE) {
211 WDS_LOGD("Mobile AP is on");
212 __WDS_LOG_FUNC_EXIT__;
215 WDS_LOGD( "OK. Mobile AP is off\n");
217 __WDS_LOG_FUNC_EXIT__;
221 int wfd_util_wifi_direct_activatable()
223 __WDS_LOG_FUNC_ENTER__;
226 res = wfd_util_check_wifi_state();
228 WDS_LOGE("Failed to check Wi-Fi state");
229 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
230 } else if (res > 0) {
231 WDS_LOGE("Wi-Fi is On");
232 return WIFI_DIRECT_ERROR_WIFI_USED;
234 WDS_LOGE("Wi-Fi is Off");
235 return WIFI_DIRECT_ERROR_NONE;
238 res = wfd_util_check_mobile_ap_state();
240 WDS_LOGE("Failed to check Mobile AP state");
241 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
242 } else if (res > 0) {
243 WDS_LOGE("Mobile AP is On");
244 return WIFI_DIRECT_ERROR_MOBILE_AP_USED;
246 WDS_LOGE("Mobile AP is Off");
247 return WIFI_DIRECT_ERROR_NONE;
251 int wfd_util_get_wifi_direct_state()
253 __WDS_LOG_FUNC_ENTER__;
257 res = vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &state);
259 WDS_LOGE("Failed to get vconf value [%s]\n", VCONFKEY_WIFI_DIRECT_STATE);
260 __WDS_LOG_FUNC_EXIT__;
264 __WDS_LOG_FUNC_EXIT__;
268 int wfd_util_set_wifi_direct_state(int state)
270 __WDS_LOG_FUNC_ENTER__;
274 // TODO: check validity of state
276 if (state == WIFI_DIRECT_STATE_ACTIVATED)
277 vconf_state = VCONFKEY_WIFI_DIRECT_ACTIVATED;
278 else if (state == WIFI_DIRECT_STATE_DEACTIVATED)
279 vconf_state= VCONFKEY_WIFI_DIRECT_DEACTIVATED;
280 else if (state == WIFI_DIRECT_STATE_CONNECTED)
281 vconf_state = VCONFKEY_WIFI_DIRECT_CONNECTED;
282 else if (state == WIFI_DIRECT_STATE_GROUP_OWNER)
283 vconf_state = VCONFKEY_WIFI_DIRECT_GROUP_OWNER;
284 else if (state == WIFI_DIRECT_STATE_DISCOVERING)
285 vconf_state = VCONFKEY_WIFI_DIRECT_DISCOVERING;
286 WDS_LOGD("Vconf key set [%s: %d]", VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
288 res = vconf_set_int(VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
290 WDS_LOGE("Failed to set vconf [%s]", VCONFKEY_WIFI_DIRECT_STATE);
291 __WDS_LOG_FUNC_EXIT__;
295 __WDS_LOG_FUNC_EXIT__;
299 int wfd_util_get_local_dev_mac(unsigned char *dev_mac)
301 __WDS_LOG_FUNC_ENTER__;
303 char local_mac[MACSTR_LEN] = {0, };
308 fd = fopen(DEFAULT_MAC_FILE_PATH, "r");
310 WDS_LOGE("Failed to open MAC info file (%s)", strerror(errno));
311 __WDS_LOG_FUNC_EXIT__;
316 ptr = fgets(local_mac, MACSTR_LEN, fd);
318 WDS_LOGE("Failed to read file or no data read(%s)", strerror(errno));
320 __WDS_LOG_FUNC_EXIT__;
323 WDS_LOGD("Local MAC address [%s]", ptr);
325 res = _txt_to_mac(local_mac, dev_mac);
327 WDS_LOGE("Failed to convert text to MAC address");
329 __WDS_LOG_FUNC_EXIT__;
334 WDS_LOGD("Local Device MAC address [" MACSTR "]", MAC2STR(dev_mac));
337 __WDS_LOG_FUNC_EXIT__;
341 int wfd_util_start_wifi_direct_popup()
343 __WDS_LOG_FUNC_ENTER__;
346 service_create(&service);
347 service_set_operation(service, SERVICE_OPERATION_DEFAULT);
348 service_set_package(service, "org.tizen.wifi-direct-popup");
349 service_send_launch_request(service, NULL, NULL);
350 service_destroy(service);
351 WDS_LOGD("Succeeded to launch wifi-direct-popup");
352 __WDS_LOG_FUNC_EXIT__;
357 static void _dhcps_ip_leased_cb(keynode_t *key, void* data)
359 __WDS_LOG_FUNC_ENTER__;
360 wfd_manager_s *manager = wfd_get_manager();
361 wfd_device_s *peer = (wfd_device_s*) data;
362 wifi_direct_client_noti_s noti;
364 char buf[MAX_DHCP_DUMP_SIZE];
365 char ip_str[IPSTR_LEN];
366 char intf_str[MACSTR_LEN];
367 unsigned char intf_addr[MACADDR_LEN];
371 WDS_LOGD("Invalid parameter");
374 WDS_LOGD("DHCP server: IP leased");
375 memset(¬i, 0, sizeof(wifi_direct_client_noti_s));
378 fp = fopen(DHCP_DUMP_FILE, "r");
380 WDS_LOGE("Could not read the file(%s). [%s]", DHCP_DUMP_FILE, strerror(errno));
384 while(fgets(buf, MAX_DHCP_DUMP_SIZE, fp) != NULL) {
385 WDS_LOGD("Read line [%s]", buf);
386 n = sscanf(buf,"%s %s", intf_str, ip_str);
387 WDS_LOGD("ip=[%s], mac=[%s]",ip_str, intf_str);
391 _txt_to_mac(intf_str, intf_addr);
392 if (!memcmp(peer->intf_addr, intf_addr, MACADDR_LEN)) {
393 WDS_LOGD("Peer intf mac found");
394 _txt_to_ip(ip_str, peer->ip_addr);
395 noti.event = WIFI_DIRECT_CLI_EVENT_IP_LEASED_IND;
396 snprintf(noti.param1, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
397 snprintf(noti.param2, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
398 wfd_client_send_event(manager, ¬i);
401 WDS_LOGE("Different interface address peer[" MACSTR "] vs dhcp[" MACSTR "]", MAC2STR(peer->intf_addr), MAC2STR(intf_addr));
406 __WDS_LOG_FUNC_EXIT__;
410 static gboolean _polling_ip(gpointer user_data)
412 __WDS_LOG_FUNC_ENTER__;
413 wfd_manager_s *manager = wfd_get_manager();
414 wfd_device_s *local = (wfd_device_s*) manager->local;
415 wfd_device_s *peer = (wfd_device_s*) user_data;
417 static int count = 0;
421 WDS_LOGE("Failed to get IP");
423 __WDS_LOG_FUNC_EXIT__;
426 res = wfd_manager_get_goup_ifname(&ifname);
427 if (res < 0 || !ifname) {
428 WDS_LOGE("Failed to get group interface name");
432 res = wfd_util_dhcpc_get_ip(ifname, local->ip_addr, 0);
434 WDS_LOGE("Failed to get local IP for interface %s(count=%d)", ifname, count++);
435 __WDS_LOG_FUNC_EXIT__;
438 WDS_LOGD("Succeeded to get local(client) IP [" IPSTR "] for iface[%s]",
439 IP2STR(local->ip_addr), ifname);
441 res = wfd_util_dhcpc_get_server_ip(peer->ip_addr);
443 WDS_LOGE("Failed to get peer(server) IP(count=%d)", count++);
444 __WDS_LOG_FUNC_EXIT__;
447 WDS_LOGD("Succeeded to get server IP [" IPSTR "]", IP2STR(peer->ip_addr));
450 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTED);
451 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTED);
452 wifi_direct_client_noti_s noti;
453 memset(¬i, 0x0, sizeof(wifi_direct_client_noti_s));
454 noti.event = WIFI_DIRECT_CLI_EVENT_CONNECTION_RSP;
455 noti.error = WIFI_DIRECT_ERROR_NONE;
456 snprintf(noti.param1, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
457 wfd_client_send_event(manager, ¬i);
459 __WDS_LOG_FUNC_EXIT__;
463 int wfd_util_dhcps_start()
465 __WDS_LOG_FUNC_ENTER__;
468 vconf_set_int(VCONFKEY_DHCPS_IP_LEASE, 0);
469 res = system("/usr/bin/wifi-direct-dhcp.sh server");
470 WDS_LOGD("[/usr/bin/wifi-direct-dhcp.sh server] returns %d", res);
472 __WDS_LOG_FUNC_EXIT__;
476 int wfd_util_dhcps_wait_ip_leased(wfd_device_s *peer)
478 __WDS_LOG_FUNC_ENTER__;
481 WDS_LOGE("Invalid parameter");
485 vconf_set_int(VCONFKEY_DHCPS_IP_LEASE, 0);
486 vconf_notify_key_changed(VCONFKEY_DHCPS_IP_LEASE, _dhcps_ip_leased_cb, peer);
488 __WDS_LOG_FUNC_EXIT__;
492 int wfd_util_dhcps_stop()
494 __WDS_LOG_FUNC_ENTER__;
497 vconf_ignore_key_changed(VCONFKEY_DHCPS_IP_LEASE, _dhcps_ip_leased_cb);
498 vconf_set_int(VCONFKEY_DHCPS_IP_LEASE, 0);
500 res = system("/usr/bin/wifi-direct-dhcp.sh stop");
501 WDS_LOGD("[/usr/bin/wifi-direct-dhcp.sh stop] returns %d", res);
503 __WDS_LOG_FUNC_EXIT__;
507 int wfd_util_dhcpc_start(wfd_device_s *peer)
509 __WDS_LOG_FUNC_ENTER__;
513 WDS_LOGE("Invalid parameter");
517 res = system("/usr/bin/wifi-direct-dhcp.sh client");
518 WDS_LOGD("[/usr/bin/wifi-direct-dhcp.sh client] returns %d", res);
519 g_timeout_add(250, (GSourceFunc) _polling_ip, peer);
521 __WDS_LOG_FUNC_EXIT__;
525 int wfd_util_dhcpc_stop()
527 __WDS_LOG_FUNC_ENTER__;
530 res = system("/usr/bin/wifi-direct-dhcp.sh stop");
531 WDS_LOGD("[/usr/bin/wifi-direct-dhcp.sh stop] returns %d", res);
533 __WDS_LOG_FUNC_EXIT__;
537 int wfd_util_dhcpc_get_ip(char *ifname, unsigned char *ip_addr, int is_IPv6)
539 __WDS_LOG_FUNC_ENTER__;
541 struct sockaddr_in *sin = NULL;
546 if (!ifname || !ip_addr) {
547 WDS_LOGE("Invalid parameter");
548 __WDS_LOG_FUNC_EXIT__;
553 sock = socket(AF_INET, SOCK_DGRAM, 0);
554 if (sock < SOCK_FD_MIN) {
555 WDS_LOGE("Failed to create socket. [%s]", strerror(errno));
558 __WDS_LOG_FUNC_EXIT__;
562 ifr.ifr_addr.sa_family = AF_INET;
563 memset(ifr.ifr_name, 0x00, 16);
564 strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
567 res = ioctl(sock, SIOCGIFADDR, &ifr);
569 WDS_LOGE("Failed to get IP from socket. [%s]", strerror(errno));
571 __WDS_LOG_FUNC_EXIT__;
576 sin = (struct sockaddr_in*) &ifr.ifr_broadaddr;
577 ip_str = inet_ntoa(sin->sin_addr);
578 _txt_to_ip(ip_str, ip_addr);
580 __WDS_LOG_FUNC_EXIT__;
584 int wfd_util_dhcpc_get_server_ip(unsigned char* ip_addr)
586 __WDS_LOG_FUNC_ENTER__;
587 char* get_str = NULL;
591 WDS_LOGE("Invalid parameter");
592 __WDS_LOG_FUNC_EXIT__;
597 get_str = vconf_get_str(VCONFKEY_DHCPC_SERVER_IP);
599 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_DHCPC_SERVER_IP);
600 __WDS_LOG_FUNC_EXIT__;
603 WDS_LOGD("VCONFKEY_DHCPC_SERVER_IP(%s) : %s\n", VCONFKEY_DHCPC_SERVER_IP, get_str);
604 _txt_to_ip(get_str, ip_addr);
610 __WDS_LOG_FUNC_EXIT__;