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)
31 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
46 #include <tzplatform_config.h>
47 #include <system_info.h>
48 #if defined(TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT)
49 #include <systemd/sd-login.h>
52 #include <wifi-direct.h>
54 #include "wifi-direct-ipc.h"
55 #include "wifi-direct-manager.h"
56 #include "wifi-direct-state.h"
57 #include "wifi-direct-util.h"
58 #include "wifi-direct-oem.h"
59 #include "wifi-direct-group.h"
60 #include "wifi-direct-session.h"
61 #include "wifi-direct-error.h"
62 #include "wifi-direct-log.h"
63 #include "wifi-direct-dbus.h"
64 #include "wifi-direct-asp.h"
66 #include <linux/unistd.h>
67 #include <asm/types.h>
68 #include <linux/netlink.h>
69 #include <linux/rtnetlink.h>
71 #include <netlink/netlink.h>
72 #include <netlink/socket.h>
73 #include <netlink/route/neighbour.h>
75 #define ASP_FEATURE "http://tizen.org/feature/network.asp"
76 #define WIFI_DIRECT_DISPLAY_FEATURE "http://tizen.org/feature/network.wifi.direct.display"
77 #define WIFI_DIRECT_SERVICE_DISCOVERY_FEATURE "http://tizen.org/feature/network.wifi.direct.service_discovery"
78 #define TETHERING_WIFI_FEATURE "http://tizen.org/feature/network.tethering.wifi"
79 #define TETHERING_WIFI_DIRECT_FEATURE "http://tizen.org/feature/network.tethering.wifi.direct"
81 #define TIZEN_P2P_GO_IPADDR "192.168.49.1"
82 #define MAX_SIZE_ERROR_BUFFER 256
84 #if defined TIZEN_PROFILE_TV
85 # define DEFAULT_MAC_FILE_PATH "/sys/class/net/p2p0/address"
86 #endif /* TIZEN_PROFILE_TV */
88 #ifndef DEFAULT_MAC_FILE_PATH
89 # define DEFAULT_MAC_FILE_PATH "/sys/class/net/p2p0/address"
92 #define COUNTRY_CODE_FILE tzplatform_mkpath(TZ_SYS_RO_ETC, "wifi-direct/ccode.conf")
94 static int _txt_to_mac(char *txt, unsigned char *mac)
99 mac[i++] = (char) strtoul(txt, &txt, 16);
100 if (i == MACADDR_LEN || !*txt++)
104 if (i != MACADDR_LEN)
107 WDS_LOGD("Converted MAC address [" MACSECSTR "]",
112 static int _txt_to_ip(char *txt, unsigned char *ip)
117 ip[i++] = (char) strtoul(txt, &txt, 10);
118 if (i == IPADDR_LEN || !*txt++)
125 WDS_LOGD("Converted IP address [" IPSECSTR "]", IP2SECSTR(ip));
129 #if !(__GNUC__ <= 4 && __GNUC_MINOR__ < 8)
130 int wfd_util_get_current_time(unsigned long *cur_time)
132 struct timespec time;
134 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
137 res = clock_gettime(CLOCK_REALTIME, &time);
139 WDS_LOGD("Succeeded to get current real time");
140 *cur_time = time.tv_sec;
143 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
144 WDS_LOGE("Failed to get current real time(%s)", error_buf);
147 res = clock_gettime(CLOCK_MONOTONIC, &time);
149 WDS_LOGD("Succeeded to get current system time");
150 *cur_time = time.tv_sec;
153 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
154 WDS_LOGE("Failed to get current system time(%s)", error_buf);
160 #if defined(TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT)
161 static int __wfd_util_find_login_user(uid_t *uid)
167 ret = sd_get_uids(&uids);
171 for (i = 0; i < ret ; i++) {
172 if (sd_uid_get_state(uids[i], &state) < 0) {
176 if (!strncmp(state, "online", 6)) {
190 gboolean wfd_util_execute_file(const char *file_path,
191 char *const args[], char *const envs[])
196 register unsigned int index = 0;
197 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
199 while (args[index] != NULL) {
200 WDS_LOGD("[%s]", args[index]);
204 if (!(pid = fork())) {
205 WDS_LOGD("pid(%d), ppid(%d)", getpid(), getppid());
206 WDS_LOGD("Inside child, exec (%s) command", file_path);
209 if (execve(file_path, args, envs) == -1) {
210 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
211 WDS_LOGE("Fail to execute command (%s)", error_buf);
214 } else if (pid > 0) {
215 if (waitpid(pid, &rv, 0) == -1)
216 WDS_LOGD("wait pid (%u) rv (%d)", pid, rv);
218 WDS_LOGD("exited, rv=%d", WEXITSTATUS(rv));
219 else if (WIFSIGNALED(rv))
220 WDS_LOGD("killed by signal %d", WTERMSIG(rv));
221 else if (WIFSTOPPED(rv))
222 WDS_LOGD("stopped by signal %d", WSTOPSIG(rv));
223 else if (WIFCONTINUED(rv))
224 WDS_LOGD("continued");
228 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
229 WDS_LOGE("failed to fork (%s)", error_buf);
233 int wfd_util_channel_to_freq(int channel)
235 if (channel < 1 || channel > 161 ||
236 (channel > 48 && channel < 149) ||
237 (channel > 14 && channel < 36)) {
238 WDS_LOGE("Unsupported channel[%d]", channel);
243 return 5000 + 5*channel;
244 else if (channel == 14)
247 return 2407 + 5*channel;
250 int wfd_util_freq_to_channel(int freq)
252 if (freq < 2412 || freq > 5825 ||
253 (freq > 2484 && freq < 5180)) {
254 WDS_LOGE("Unsupported frequency[%d]", freq);
259 return 36 + (freq - 5180)/5;
260 else if (freq <= 2472)
261 return 1 + (freq - 2412)/5;
262 else if (freq == 2484)
268 int wfd_util_get_phone_name(char *phone_name)
270 __WDS_LOG_FUNC_ENTER__;
273 name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
275 WDS_LOGE("Failed to get vconf value for %s", VCONFKEY_SETAPPL_DEVICE_NAME_STR);
278 g_strlcpy(phone_name, name, DEV_NAME_LEN + 1);
279 WDS_LOGD("[%s: %s]", VCONFKEY_SETAPPL_DEVICE_NAME_STR, phone_name);
281 __WDS_LOG_FUNC_EXIT__;
285 void _wfd_util_dev_name_changed_cb(keynode_t *key, void *data)
287 __WDS_LOG_FUNC_ENTER__;
288 char dev_name[DEV_NAME_LEN+1] = {0, };
291 res = wfd_util_get_phone_name(dev_name);
293 WDS_LOGE("Failed to get phone name(vconf)");
296 WDS_LOGD("Device name changed as [%s]", dev_name);
298 res = wfd_local_set_dev_name(dev_name);
300 WDS_LOGE("Failed to set device name");
301 __WDS_LOG_FUNC_EXIT__;
305 void wfd_util_set_dev_name_notification()
307 __WDS_LOG_FUNC_ENTER__;
310 res = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb, NULL);
312 WDS_LOGE("Failed to set vconf notification callback(SETAPPL_DEVICE_NAME_STR)");
316 __WDS_LOG_FUNC_EXIT__;
320 void wfd_util_unset_dev_name_notification()
322 __WDS_LOG_FUNC_ENTER__;
325 res = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb);
327 WDS_LOGE("Failed to set vconf notification callback(SETAPPL_DEVICE_NAME_STR)");
331 __WDS_LOG_FUNC_EXIT__;
336 void _wfd_util_check_country_cb(keynode_t *key, void *data)
338 __WDS_LOG_FUNC_ENTER__;
339 wfd_manager_s *manager = (wfd_manager_s*) data;
344 GKeyFile *keyfile = NULL;
345 const char *file_path = COUNTRY_CODE_FILE;
349 WDS_LOGE("Invalid parameter");
353 res = vconf_get_int(VCONFKEY_TELEPHONY_PLMN, &plmn);
355 WDS_LOGE("Failed to get vconf value for PLMN(%d)", res);
359 snprintf(mcc, 4, "%d", plmn);
361 keyfile = g_key_file_new();
362 res = g_key_file_load_from_file(keyfile, file_path, 0, &err);
364 WDS_LOGE("Failed to load key file(%s)", err->message);
365 g_key_file_free(keyfile);
369 ccode = g_key_file_get_string(keyfile, "ccode_map", mcc, &err);
371 WDS_LOGE("Failed to get country code string(%s)", err->message);
372 g_key_file_free(keyfile);
376 res = wfd_oem_set_country(manager->oem_ops, ccode);
378 WDS_LOGE("Failed to set contry code");
380 WDS_LOGD("Succeeded to set country code(%s)", ccode);
382 g_key_file_free(keyfile);
385 __WDS_LOG_FUNC_EXIT__;
389 int wfd_util_set_country()
391 __WDS_LOG_FUNC_ENTER__;
392 wfd_manager_s *manager = wfd_get_manager();
395 _wfd_util_check_country_cb(NULL, manager);
397 res = vconf_notify_key_changed(VCONFKEY_TELEPHONY_PLMN, _wfd_util_check_country_cb, manager);
399 WDS_LOGE("Failed to set vconf notification callback(TELEPHONY_PLMN)");
403 __WDS_LOG_FUNC_EXIT__;
407 int wfd_util_unset_country()
409 __WDS_LOG_FUNC_ENTER__;
412 res = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_PLMN, _wfd_util_check_country_cb);
414 WDS_LOGE("Failed to unset vconf notification callback(TELEPHONY_PLMN)");
418 __WDS_LOG_FUNC_EXIT__;
422 int wfd_util_check_wifi_state()
424 __WDS_LOG_FUNC_ENTER__;
428 /* vconf key and value (vconf-keys.h)
429 #define VCONFKEY_WIFI_STATE "memory/wifi/state"
431 VCONFKEY_WIFI_OFF = 0x00,
432 VCONFKEY_WIFI_UNCONNECTED,
433 VCONFKEY_WIFI_CONNECTED,
434 VCONFKEY_WIFI_TRANSFER,
435 VCONFKEY_WIFI_STATE_MAX
438 res = vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
440 WDS_LOGE("Failed to get vconf value [%s]", VCONFKEY_WIFI_STATE);
441 __WDS_LOG_FUNC_EXIT__;
444 WDS_LOGD("[%s: %d]", VCONFKEY_WIFI_STATE, wifi_state);
446 if (wifi_state > VCONFKEY_WIFI_OFF) {
447 WDS_LOGD("Wi-Fi is on");
448 __WDS_LOG_FUNC_EXIT__;
451 WDS_LOGD("OK. Wi-Fi is off\n");
453 __WDS_LOG_FUNC_EXIT__;
457 int wfd_util_check_mobile_ap_state()
459 __WDS_LOG_FUNC_ENTER__;
460 int mobile_ap_state = 0;
463 res = vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobile_ap_state);
465 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_MOBILE_HOTSPOT_MODE);
466 __WDS_LOG_FUNC_EXIT__;
469 WDS_LOGD("[%s: %d]", VCONFKEY_MOBILE_HOTSPOT_MODE, mobile_ap_state);
471 if ((mobile_ap_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
472 || (mobile_ap_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI_AP)) {
473 WDS_LOGD("Mobile AP is on");
474 __WDS_LOG_FUNC_EXIT__;
477 WDS_LOGD("OK. Mobile AP is off\n");
479 __WDS_LOG_FUNC_EXIT__;
483 static void __check_feature_supported(const char *key,
484 bool *feature_supported)
486 if (system_info_get_platform_bool(key, feature_supported) < 0) {
487 WDS_LOGE("system-info failed to get feature supported flag");
488 *feature_supported = false;
493 static bool __is_wifi_direct_display_feature_supported()
497 __check_feature_supported(WIFI_DIRECT_DISPLAY_FEATURE, &supported);
502 static bool __is_wifi_direct_service_discovery_feature_supported()
506 __check_feature_supported(WIFI_DIRECT_SERVICE_DISCOVERY_FEATURE, &supported);
511 static bool __is_asp_feature_supported()
515 __check_feature_supported(ASP_FEATURE, &supported);
520 static bool __is_tethering_wifi_feature_supported()
524 __check_feature_supported(TETHERING_WIFI_FEATURE, &supported);
529 static bool __is_tethering_wifi_direct_feature_supported()
533 __check_feature_supported(TETHERING_WIFI_DIRECT_FEATURE, &supported);
538 void wfd_util_check_features()
540 __WDS_LOG_FUNC_ENTER__;
541 wfd_manager_s * manager = NULL;
543 manager = wfd_get_manager();
547 manager->is_on_demand_supported = TRUE;
549 if (__is_wifi_direct_display_feature_supported())
550 manager->is_wifi_display_supported = TRUE;
552 manager->is_wifi_display_supported = FALSE;
554 if (__is_wifi_direct_service_discovery_feature_supported())
555 manager->is_service_discovery_supported = TRUE;
557 manager->is_service_discovery_supported = FALSE;
559 if (__is_asp_feature_supported())
560 manager->is_asp_supported = TRUE;
562 manager->is_asp_supported = FALSE;
564 if (__is_tethering_wifi_feature_supported())
565 manager->is_tethering_wifi_supported = TRUE;
567 manager->is_tethering_wifi_supported = FALSE;
569 if (__is_tethering_wifi_direct_feature_supported())
570 manager->is_tethering_wifi_direct_supported = TRUE;
572 manager->is_tethering_wifi_direct_supported = FALSE;
578 int wfd_util_check_p2p_hotspot_state()
580 __WDS_LOG_FUNC_ENTER__;
581 int hotspot_state = 0;
584 wfd_manager_s * manager = wfd_get_manager();
588 if (!manager->is_tethering_wifi_direct_supported)
591 res = vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &hotspot_state);
593 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_MOBILE_HOTSPOT_MODE);
594 __WDS_LOG_FUNC_EXIT__;
598 if (hotspot_state & VCONFKEY_MOBILE_HOTSPOT_MODE_P2P) {
599 WDS_LOGD("P2P Hotspot is on");
600 __WDS_LOG_FUNC_EXIT__;
604 WDS_LOGD("P2P Hotspot is off");
605 __WDS_LOG_FUNC_EXIT__;
609 int wfd_util_wifi_direct_activatable()
611 __WDS_LOG_FUNC_ENTER__;
613 #if defined TIZEN_TETHERING_ENABLE
616 res_mobap = wfd_util_check_mobile_ap_state();
618 WDS_LOGE("Failed to check Mobile AP state");
619 __WDS_LOG_FUNC_EXIT__;
620 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
621 } else if (res_mobap > 0) {
622 WDS_LOGE("Mobile AP is On");
623 __WDS_LOG_FUNC_EXIT__;
624 return WIFI_DIRECT_ERROR_MOBILE_AP_USED;
626 WDS_LOGE("Mobile AP is Off");
627 __WDS_LOG_FUNC_EXIT__;
628 return WIFI_DIRECT_ERROR_NONE;
632 __WDS_LOG_FUNC_EXIT__;
633 return WIFI_DIRECT_ERROR_NONE;
637 int wfd_util_get_wifi_direct_state()
639 __WDS_LOG_FUNC_ENTER__;
643 res = vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &state);
645 WDS_LOGE("Failed to get vconf value [%s]\n", VCONFKEY_WIFI_DIRECT_STATE);
646 __WDS_LOG_FUNC_EXIT__;
650 __WDS_LOG_FUNC_EXIT__;
655 int wfd_util_set_wifi_direct_state(int state)
657 __WDS_LOG_FUNC_ENTER__;
658 static int last_state = WIFI_DIRECT_STATE_DEACTIVATED;
659 int vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATED;
662 if (state < WIFI_DIRECT_STATE_DEACTIVATED ||
663 state > WIFI_DIRECT_STATE_GROUP_OWNER) {
664 WDS_LOGE("Invalid parameter");
665 __WDS_LOG_FUNC_EXIT__;
669 if (last_state == state) {
670 WDS_LOGD("No change in state, not updating vconf [%s]",
671 VCONFKEY_WIFI_DIRECT_STATE);
672 __WDS_LOG_FUNC_EXIT__;
676 if (state == WIFI_DIRECT_STATE_ACTIVATED)
677 vconf_state = VCONFKEY_WIFI_DIRECT_ACTIVATED;
678 else if (state == WIFI_DIRECT_STATE_DEACTIVATED)
679 vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATED;
680 else if (state == WIFI_DIRECT_STATE_CONNECTED)
681 vconf_state = VCONFKEY_WIFI_DIRECT_CONNECTED;
682 else if (state == WIFI_DIRECT_STATE_GROUP_OWNER)
683 vconf_state = VCONFKEY_WIFI_DIRECT_GROUP_OWNER;
684 else if (state == WIFI_DIRECT_STATE_DISCOVERING)
685 vconf_state = VCONFKEY_WIFI_DIRECT_DISCOVERING;
686 else if (state == WIFI_DIRECT_STATE_DEACTIVATING)
687 vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATING;
688 else if (state == WIFI_DIRECT_STATE_ACTIVATING)
689 vconf_state = VCONFKEY_WIFI_DIRECT_ACTIVATING;
690 else if (state == WIFI_DIRECT_STATE_CONNECTING)
691 vconf_state = VCONFKEY_WIFI_DIRECT_CONNECTING;
692 else if (state == WIFI_DIRECT_STATE_DISCONNECTING)
693 vconf_state = VCONFKEY_WIFI_DIRECT_DISCONNECTING;
695 WDS_LOGE("This state cannot be set as wifi_direct vconf state[%d]", state);
699 WDS_LOGD("Vconf key set [%s: %d]", VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
701 res = vconf_set_int(VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
703 WDS_LOGE("Failed to set vconf [%s]", VCONFKEY_WIFI_DIRECT_STATE);
704 __WDS_LOG_FUNC_EXIT__;
710 __WDS_LOG_FUNC_EXIT__;
714 int wfd_util_get_local_dev_mac(unsigned char *dev_mac)
716 __WDS_LOG_FUNC_ENTER__;
717 const char *file_path = DEFAULT_MAC_FILE_PATH;
719 char local_mac[MACSTR_LEN] = {0, };
722 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
725 fd = fopen(file_path, "r");
727 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
728 WDS_LOGE("Failed to open MAC info file [%s] (%s)", file_path , error_buf);
729 __WDS_LOG_FUNC_EXIT__;
734 ptr = fgets(local_mac, MACSTR_LEN, fd);
736 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
737 WDS_LOGE("Failed to read file or no data read(%s)", error_buf);
739 __WDS_LOG_FUNC_EXIT__;
742 WDS_SECLOGD("Local MAC address [%s]", ptr);
744 res = _txt_to_mac(local_mac, dev_mac);
746 WDS_LOGE("Failed to convert text to MAC address");
748 __WDS_LOG_FUNC_EXIT__;
752 WDS_LOGD("Local Device MAC address [" MACSECSTR "]", MAC2SECSTR(dev_mac));
755 __WDS_LOG_FUNC_EXIT__;
759 #ifdef TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT
760 int wfd_util_start_wifi_direct_popup()
762 __WDS_LOG_FUNC_ENTER__;
766 ret = __wfd_util_find_login_user(&uid);
768 WDS_LOGE("__wfd_util_find_login_user Failed !");
772 if (AUL_R_OK != aul_launch_app_for_uid(
773 "org.tizen.wifi-direct-popup", NULL, uid)) {
774 WDS_LOGE("aul_launch_for_uid Failed !");
778 WDS_LOGD("Succeeded to launch wifi-direct-popup");
779 __WDS_LOG_FUNC_EXIT__;
783 int wfd_util_stop_wifi_direct_popup()
785 __WDS_LOG_FUNC_ENTER__;
789 ret = __wfd_util_find_login_user(&uid);
791 WDS_LOGE("__wfd_util_find_login_user Failed !");
795 int pid = aul_app_get_pid_for_uid("org.tizen.wifi-direct-popup", uid);
797 if (aul_terminate_pid_for_uid(pid, uid) != AUL_R_OK) {
798 WDS_LOGD("Failed to destroy wifi-direct-popup pid[%d]", pid);
801 WDS_LOGD("Succeeded to destroy wifi-direct-popup");
804 WDS_LOGD("Wifi-direct-popup not running");
807 __WDS_LOG_FUNC_EXIT__;
810 #endif /* TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT */
812 int _connect_remote_device(char *ip_str)
817 struct sockaddr_in remo_addr;
818 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
821 sock = socket(PF_INET, SOCK_STREAM, 0);
823 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
824 WDS_LOGE("Failed to create socket to remote device(%s)", error_buf);
828 flags = fcntl(sock, F_GETFL, 0);
829 res = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
831 WDS_LOGE("File descriptor create failed");
833 __WDS_LOG_FUNC_EXIT__;
837 memset(&remo_addr, 0x0, sizeof(remo_addr));
838 remo_addr.sin_family = AF_INET;
839 remo_addr.sin_addr.s_addr = inet_addr(ip_str);
840 remo_addr.sin_port = htons(9999);
843 res = connect(sock, (struct sockaddr*) &remo_addr, sizeof(remo_addr));
845 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
846 WDS_LOGE("Failed to connect to server socket [%s]", error_buf);
848 __WDS_LOG_FUNC_EXIT__;
852 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
853 WDS_SECLOGD("Status of connection to remote device[%s] - (%s)", ip_str, error_buf);
860 static void _dhcps_ip_leased_cb(keynode_t *key, void* data)
862 __WDS_LOG_FUNC_ENTER__;
863 wfd_device_s *peer = (wfd_device_s*) data;
865 char buf[MAX_DHCP_DUMP_SIZE];
866 char ip_str[IPSTR_LEN] = {0, };
867 char intf_str[MACSTR_LEN];
868 unsigned char intf_addr[MACADDR_LEN];
869 char peer_mac_address[MACSTR_LEN+1] = {0,};
870 char assigned_ip_address[IPSTR_LEN+1] = {0,};
872 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
875 WDS_LOGD("Invalid parameter");
878 WDS_LOGD("DHCP server: IP leased");
881 fp = fopen(DHCP_DUMP_FILE, "r");
883 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
884 WDS_LOGE("Could not read the file(%s). [%s]", DHCP_DUMP_FILE, error_buf);
888 while (fgets(buf, MAX_DHCP_DUMP_SIZE, fp) != NULL) {
889 WDS_LOGD("Read line [%s]", buf);
890 n = sscanf(buf, "%17s %15s", intf_str, ip_str);
891 WDS_LOGD("ip=[%s], mac=[%s]", ip_str, intf_str);
895 _txt_to_mac(intf_str, intf_addr);
896 if (!memcmp(peer->intf_addr, intf_addr, MACADDR_LEN)) {
897 WDS_LOGD("Peer intf mac found");
898 _txt_to_ip(ip_str, peer->ip_addr);
899 _connect_remote_device(ip_str);
900 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
901 g_snprintf(assigned_ip_address, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
902 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
904 g_variant_new("(ss)", peer_mac_address,
905 assigned_ip_address));
908 WDS_LOGD("Different interface address peer[" MACSECSTR "] vs dhcp[" MACSECSTR "]",
909 MAC2SECSTR(peer->intf_addr), MAC2SECSTR(intf_addr));
914 vconf_ignore_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb);
915 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
917 __WDS_LOG_FUNC_EXIT__;
921 static gboolean _polling_ip(gpointer user_data)
923 __WDS_LOG_FUNC_ENTER__;
924 wfd_manager_s *manager = wfd_get_manager();
925 wfd_device_s *local = (wfd_device_s*) manager->local;
926 wfd_device_s *peer = (wfd_device_s*) user_data;
928 char ip_str[IPSTR_LEN] = {0, };
929 static int count = 0;
933 WDS_LOGE("peer data is not exists");
937 res = wfd_manager_get_goup_ifname(&ifname);
938 if (res < 0 || !ifname) {
939 WDS_LOGE("Failed to get group interface name");
944 WDS_LOGE("Failed to get IP");
946 wfd_oem_destroy_group(manager->oem_ops, ifname);
947 __WDS_LOG_FUNC_EXIT__;
950 res = wfd_util_local_get_ip(ifname, local->ip_addr, 0);
952 WDS_LOGE("Failed to get local IP for interface %s(count=%d)", ifname, count++);
953 __WDS_LOG_FUNC_EXIT__;
956 WDS_LOGD("Succeeded to get local(client) IP [" IPSECSTR "] for iface[%s]",
957 IP2SECSTR(local->ip_addr), ifname);
959 res = wfd_util_dhcpc_get_server_ip(peer->ip_addr);
961 WDS_LOGE("Failed to get peer(server) IP(count=%d)", count++);
962 __WDS_LOG_FUNC_EXIT__;
965 WDS_LOGD("Succeeded to get server IP [" IPSECSTR "]", IP2SECSTR(peer->ip_addr));
968 g_snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
969 _connect_remote_device(ip_str);
971 char peer_mac_address[MACSTR_LEN+1] = {0, };
973 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
974 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
976 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
977 WFD_EVENT_CONNECTION_RSP,
980 wfd_session_s *session = manager->session;
981 if (wfd_asp_is_asp_session(session)) {
982 wfd_asp_connect_status(session->session_mac,
984 ASP_CONNECT_STATUS_GROUP_FORMATION_COMPLETED,
988 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTED);
989 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTED);
990 wfd_destroy_session(manager);
992 __WDS_LOG_FUNC_EXIT__;
996 int wfd_util_dhcps_start(char *ifname)
998 __WDS_LOG_FUNC_ENTER__;
1000 char *const iface = ifname;
1001 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
1002 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "server", iface, NULL };
1003 char *const envs[] = { NULL };
1004 wfd_manager_s *manager = wfd_get_manager();
1006 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
1008 rv = wfd_util_execute_file(path, args, envs);
1011 WDS_LOGE("Failed to start wifi-direct-dhcp.sh server");
1016 * As we are GO so IP should be updated
1017 * before sending Group Created Event
1019 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_IFNAME, GROUP_IFNAME);
1020 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_LOCAL_IP, "192.168.49.1");
1021 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_SUBNET_MASK, "255.255.255.0");
1022 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_GATEWAY, "192.168.49.1");
1024 WDS_LOGD("Successfully started wifi-direct-dhcp.sh server");
1026 _txt_to_ip(TIZEN_P2P_GO_IPADDR, manager->local->ip_addr);
1028 __WDS_LOG_FUNC_EXIT__;
1032 int wfd_util_dhcps_wait_ip_leased(wfd_device_s *peer)
1034 __WDS_LOG_FUNC_ENTER__;
1037 WDS_LOGE("Invalid parameter");
1041 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
1042 vconf_notify_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb, peer);
1044 __WDS_LOG_FUNC_EXIT__;
1048 int wfd_util_dhcps_stop(char *ifname)
1050 __WDS_LOG_FUNC_ENTER__;
1051 gboolean rv = FALSE;
1052 char *const iface = ifname;
1053 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
1054 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "stop", iface, NULL };
1055 char *const envs[] = { NULL };
1057 vconf_ignore_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb);
1058 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
1060 rv = wfd_util_execute_file(path, args, envs);
1063 WDS_LOGE("Failed to stop wifi-direct-dhcp.sh");
1066 WDS_LOGD("Successfully stopped wifi-direct-dhcp.sh");
1068 __WDS_LOG_FUNC_EXIT__;
1072 int wfd_util_dhcpc_start(char *ifname, wfd_device_s *peer)
1074 __WDS_LOG_FUNC_ENTER__;
1075 gboolean rv = FALSE;
1076 char *const iface = ifname;
1077 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
1078 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "client", iface, NULL };
1079 char *const envs[] = { NULL };
1082 WDS_LOGE("Invalid parameter");
1086 rv = wfd_util_execute_file(path, args, envs);
1088 WDS_LOGE("Failed to start wifi-direct-dhcp.sh client");
1091 WDS_LOGD("Successfully started wifi-direct-dhcp.sh client");
1093 g_timeout_add(250, (GSourceFunc) _polling_ip, peer);
1095 __WDS_LOG_FUNC_EXIT__;
1099 int wfd_util_dhcpc_stop(char *ifname)
1101 __WDS_LOG_FUNC_ENTER__;
1102 gboolean rv = FALSE;
1103 char *const iface = ifname;
1104 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
1105 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "stop", iface, NULL };
1106 char *const envs[] = { NULL };
1108 rv = wfd_util_execute_file(path, args, envs);
1111 WDS_LOGE("Failed to stop wifi-direct-dhcp.sh");
1114 WDS_LOGD("Successfully stopped wifi-direct-dhcp.sh");
1116 __WDS_LOG_FUNC_EXIT__;
1120 int wfd_util_local_get_ip(char *ifname, unsigned char *ip_addr, int is_IPv6)
1122 __WDS_LOG_FUNC_ENTER__;
1124 struct sockaddr_in *sin = NULL;
1125 char *ip_str = NULL;
1128 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1130 if (!ifname || !ip_addr) {
1131 WDS_LOGE("Invalid parameter");
1132 __WDS_LOG_FUNC_EXIT__;
1137 sock = socket(AF_INET, SOCK_DGRAM, 0);
1138 if (sock < SOCK_FD_MIN) {
1139 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1140 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1143 __WDS_LOG_FUNC_EXIT__;
1147 ifr.ifr_addr.sa_family = AF_INET;
1148 memset(ifr.ifr_name, 0x00, IFNAMSIZ);
1149 g_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1152 res = ioctl(sock, SIOCGIFADDR, &ifr);
1154 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1155 WDS_LOGE("Failed to get IP from socket. [%s]", error_buf);
1157 __WDS_LOG_FUNC_EXIT__;
1162 sin = (struct sockaddr_in*) &ifr.ifr_broadaddr;
1163 ip_str = inet_ntoa(sin->sin_addr);
1164 _txt_to_ip(ip_str, ip_addr);
1165 __WDS_LOG_FUNC_EXIT__;
1169 int wfd_util_dhcpc_get_server_ip(unsigned char* ip_addr)
1171 __WDS_LOG_FUNC_ENTER__;
1172 char* get_str = NULL;
1176 WDS_LOGE("Invalid parameter");
1177 __WDS_LOG_FUNC_EXIT__;
1181 while (count < 10) {
1182 get_str = vconf_get_str(VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1184 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1185 __WDS_LOG_FUNC_EXIT__;
1189 if (strcmp(get_str, ZEROIP) == 0) {
1190 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1192 __WDS_LOG_FUNC_EXIT__;
1196 WDS_LOGD("VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP(%s) : %s\n", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP, get_str);
1197 _txt_to_ip(get_str, ip_addr);
1204 __WDS_LOG_FUNC_EXIT__;
1208 #ifdef TIZEN_FEATURE_IP_OVER_EAPOL
1209 static int _wfd_util_set_vconf_for_static_ip(const char *ifname, char *static_ip)
1211 __WDS_LOG_FUNC_ENTER__;
1213 if (!ifname || !static_ip)
1216 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_IFNAME, ifname);
1217 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_LOCAL_IP, static_ip);
1218 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_SUBNET_MASK, "255.255.255.0");
1219 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_GATEWAY, "192.168.49.1");
1221 __WDS_LOG_FUNC_EXIT__;
1227 static int _wfd_util_static_ip_set(const char *ifname, unsigned char *static_ip)
1229 __WDS_LOG_FUNC_ENTER__;
1231 unsigned char ip_addr[IPADDR_LEN];
1232 char ip_str[IPSTR_LEN] = {0, };
1236 struct sockaddr_nl dst_addr;
1240 struct ifaddrmsg ifa;
1245 struct msghdr nl_msg;
1247 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1249 if (!ifname || !static_ip) {
1250 WDS_LOGE("Invalid parameter");
1251 __WDS_LOG_FUNC_EXIT__;
1255 /* Get index of interface */
1256 if_index = if_nametoindex(ifname);
1258 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1259 WDS_LOGE("Failed to get interface index. [%s]", error_buf);
1260 __WDS_LOG_FUNC_EXIT__;
1264 WDS_LOGD("Creating a Netlink Socket");
1265 nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1267 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1268 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1269 __WDS_LOG_FUNC_EXIT__;
1273 memset(&dst_addr, 0, sizeof(dst_addr));
1274 dst_addr.nl_family = AF_NETLINK;
1275 dst_addr.nl_pid = 0;
1277 memset(&req, 0, sizeof(req));
1278 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1279 req.nh.nlmsg_type = RTM_NEWADDR;
1280 req.nh.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST;
1282 req.ifa.ifa_family = AF_INET;
1283 req.ifa.ifa_prefixlen = 24;
1284 req.ifa.ifa_flags = IFA_F_PERMANENT;
1285 req.ifa.ifa_scope = 0;
1286 req.ifa.ifa_index = if_index;
1288 rta = (struct rtattr *)(req.attrbuf);
1289 rta->rta_type = IFA_LOCAL;
1290 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1291 memcpy(RTA_DATA(rta), static_ip, IPADDR_LEN);
1292 req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
1294 rta = (struct rtattr *)(req.attrbuf + rta->rta_len);
1295 rta->rta_type = IFA_BROADCAST;
1296 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1297 memcpy(ip_addr, static_ip, IPADDR_LEN);
1299 memcpy(RTA_DATA(rta), ip_addr, IPADDR_LEN);
1300 req.nh.nlmsg_len += rta->rta_len;
1302 memset(&iov, 0, sizeof(iov));
1303 iov.iov_base = &req;
1304 iov.iov_len = req.nh.nlmsg_len;
1306 memset(&nl_msg, 0, sizeof(nl_msg));
1307 nl_msg.msg_name = (void *)&dst_addr;
1308 nl_msg.msg_namelen = sizeof(dst_addr);
1309 nl_msg.msg_iov = &iov;
1310 nl_msg.msg_iovlen = 1;
1312 res = sendmsg(nl_sock, &nl_msg, 0);
1314 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1315 WDS_LOGE("Failed to sendmsg. [%s]", error_buf);
1317 WDS_LOGD("Succed to sendmsg. [%d]", res);
1321 WDS_LOGE("Succeeded to set local(client) IP [" IPSTR "] for iface[%s]",
1322 IP2STR(static_ip), ifname);
1324 snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(static_ip));
1325 _wfd_util_set_vconf_for_static_ip(ifname, ip_str);
1327 __WDS_LOG_FUNC_EXIT__;
1331 int wfd_util_ip_over_eap_assign(wfd_device_s *peer, const char *ifname)
1333 __WDS_LOG_FUNC_ENTER__;
1334 wfd_manager_s *manager = wfd_get_manager();
1335 wfd_device_s *local = (wfd_device_s*) manager->local;
1337 char ip_str[IPSTR_LEN] = {0, };
1340 WDS_LOGE("Invalid paramater");
1344 _wfd_util_static_ip_set(ifname, peer->client_ip_addr);
1345 memcpy(peer->ip_addr, peer->go_ip_addr, IPADDR_LEN);
1346 memcpy(local->ip_addr, peer->client_ip_addr, IPADDR_LEN);
1348 g_snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
1349 _connect_remote_device(ip_str);
1351 __WDS_LOG_FUNC_EXIT__;
1354 #endif /* TIZEN_FEATURE_IP_OVER_EAPOL */
1356 int wfd_util_ip_unset(const char *ifname)
1358 __WDS_LOG_FUNC_ENTER__;
1360 unsigned char ip_addr[IPADDR_LEN];
1361 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1365 struct sockaddr_nl dst_addr;
1369 struct ifaddrmsg ifa;
1374 struct msghdr nl_msg;
1377 WDS_LOGE("Invalid parameter");
1378 __WDS_LOG_FUNC_EXIT__;
1382 res = wfd_util_local_get_ip((char *)ifname, ip_addr, 0);
1384 WDS_LOGE("Failed to get local IP for interface %s", ifname);
1385 __WDS_LOG_FUNC_EXIT__;
1388 WDS_LOGE("Succeeded to get local(client) IP [" IPSTR "] for iface[%s]",
1389 IP2STR(ip_addr), ifname);
1391 if_index = if_nametoindex(ifname);
1393 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1394 WDS_LOGE("Failed to get interface index. [%s]", error_buf);
1395 __WDS_LOG_FUNC_EXIT__;
1399 WDS_LOGD("Creating a Netlink Socket");
1400 nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1402 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1403 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1404 __WDS_LOG_FUNC_EXIT__;
1408 WDS_LOGD("Set dst socket address to kernel");
1409 memset(&dst_addr, 0, sizeof(dst_addr));
1410 dst_addr.nl_family = AF_NETLINK;
1411 dst_addr.nl_pid = 0;
1413 memset(&req, 0, sizeof(req));
1414 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1415 req.nh.nlmsg_type = RTM_DELADDR;
1416 req.nh.nlmsg_flags = NLM_F_REQUEST;
1418 req.ifa.ifa_family = AF_INET;
1419 req.ifa.ifa_prefixlen = 32;
1420 req.ifa.ifa_flags = IFA_F_PERMANENT;
1421 req.ifa.ifa_scope = 0;
1422 req.ifa.ifa_index = if_index;
1424 rta = (struct rtattr *)(req.attrbuf);
1425 rta->rta_type = IFA_LOCAL;
1426 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1427 memcpy(RTA_DATA(rta), ip_addr, IPADDR_LEN);
1428 req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
1430 memset(&iov, 0, sizeof(iov));
1431 iov.iov_base = &req;
1432 iov.iov_len = req.nh.nlmsg_len;
1434 memset(&nl_msg, 0, sizeof(nl_msg));
1435 nl_msg.msg_name = (void *)&dst_addr;
1436 nl_msg.msg_namelen = sizeof(dst_addr);
1437 nl_msg.msg_iov = &iov;
1438 nl_msg.msg_iovlen = 1;
1440 res = sendmsg(nl_sock, &nl_msg, 0);
1442 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1443 WDS_LOGE("Failed to sendmsg. [%s]", error_buf);
1445 WDS_LOGD("Succeed to sendmsg. [%d]", res);
1450 __WDS_LOG_FUNC_EXIT__;
1454 gboolean wfd_util_is_remove_group_allowed(void)
1456 wfd_manager_s *manager = wfd_get_manager();
1458 if (!manager->auto_group_remove_enable)