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 #if defined(TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT)
48 #include <systemd/sd-login.h>
51 #include <wifi-direct.h>
53 #include "wifi-direct-ipc.h"
54 #include "wifi-direct-manager.h"
55 #include "wifi-direct-state.h"
56 #include "wifi-direct-util.h"
57 #include "wifi-direct-oem.h"
58 #include "wifi-direct-group.h"
59 #include "wifi-direct-session.h"
60 #include "wifi-direct-error.h"
61 #include "wifi-direct-log.h"
62 #include "wifi-direct-dbus.h"
63 #if defined(TIZEN_FEATURE_ASP)
64 #include "wifi-direct-asp.h"
67 #include <linux/unistd.h>
68 #include <asm/types.h>
69 #include <linux/netlink.h>
70 #include <linux/rtnetlink.h>
72 #include <netlink/netlink.h>
73 #include <netlink/socket.h>
74 #include <netlink/route/neighbour.h>
76 #define TIZEN_P2P_GO_IPADDR "192.168.49.1"
77 #define MAX_SIZE_ERROR_BUFFER 256
79 #if defined TIZEN_PROFILE_TV
80 # if defined TIZEN_WIFI_MODULE_BUNDLE
81 # define DEFAULT_MAC_FILE_PATH "/sys/class/net/wlan0/address"
82 # else /* TIZEN_WIFI_MODULE_BUNDLE */
83 # define DEFAULT_MAC_FILE_PATH "/sys/class/net/p2p0/address"
84 # endif /* TIZEN_WIFI_MODULE_BUNDLE */
85 #endif /* TIZEN_PROFILE_TV */
87 #ifndef DEFAULT_MAC_FILE_PATH
88 # define DEFAULT_MAC_FILE_PATH "/sys/class/net/p2p0/address"
91 #define COUNTRY_CODE_FILE tzplatform_mkpath(TZ_SYS_RO_ETC, "wifi-direct/ccode.conf")
93 static int _txt_to_mac(char *txt, unsigned char *mac)
98 mac[i++] = (char) strtoul(txt, &txt, 16);
99 if (i == MACADDR_LEN || !*txt++)
103 if (i != MACADDR_LEN)
106 WDS_LOGD("Converted MAC address [" MACSECSTR "]",
111 static int _txt_to_ip(char *txt, unsigned char *ip)
116 ip[i++] = (char) strtoul(txt, &txt, 10);
117 if (i == IPADDR_LEN || !*txt++)
124 WDS_LOGD("Converted IP address [" IPSECSTR "]", IP2SECSTR(ip));
128 #if !(__GNUC__ <= 4 && __GNUC_MINOR__ < 8)
129 int wfd_util_get_current_time(unsigned long *cur_time)
131 struct timespec time;
133 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
136 res = clock_gettime(CLOCK_REALTIME, &time);
138 WDS_LOGD("Succeeded to get current real time");
139 *cur_time = time.tv_sec;
142 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
143 WDS_LOGE("Failed to get current real time(%s)", error_buf);
146 res = clock_gettime(CLOCK_MONOTONIC, &time);
148 WDS_LOGD("Succeeded to get current system time");
149 *cur_time = time.tv_sec;
152 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
153 WDS_LOGE("Failed to get current system time(%s)", error_buf);
159 #if defined(TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT)
160 static int __wfd_util_find_login_user(uid_t *uid)
166 ret = sd_get_uids(&uids);
170 for (i = 0; i < ret ; i++) {
171 if (sd_uid_get_state(uids[i], &state) < 0) {
175 if (!strncmp(state, "online", 6)) {
189 gboolean wfd_util_execute_file(const char *file_path,
190 char *const args[], char *const envs[])
195 register unsigned int index = 0;
196 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
198 while (args[index] != NULL) {
199 WDS_LOGD("[%s]", args[index]);
203 if (!(pid = fork())) {
204 WDS_LOGD("pid(%d), ppid(%d)", getpid(), getppid());
205 WDS_LOGD("Inside child, exec (%s) command", file_path);
208 if (execve(file_path, args, envs) == -1) {
209 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
210 WDS_LOGE("Fail to execute command (%s)", error_buf);
213 } else if (pid > 0) {
214 if (waitpid(pid, &rv, 0) == -1)
215 WDS_LOGD("wait pid (%u) rv (%d)", pid, rv);
217 WDS_LOGD("exited, rv=%d", WEXITSTATUS(rv));
218 else if (WIFSIGNALED(rv))
219 WDS_LOGD("killed by signal %d", WTERMSIG(rv));
220 else if (WIFSTOPPED(rv))
221 WDS_LOGD("stopped by signal %d", WSTOPSIG(rv));
222 else if (WIFCONTINUED(rv))
223 WDS_LOGD("continued");
227 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
228 WDS_LOGE("failed to fork (%s)", error_buf);
232 int wfd_util_channel_to_freq(int channel)
234 if (channel < 1 || channel > 161 ||
235 (channel > 48 && channel < 149) ||
236 (channel > 14 && channel < 36)) {
237 WDS_LOGE("Unsupported channel[%d]", channel);
242 return 5000 + 5*channel;
243 else if (channel == 14)
246 return 2407 + 5*channel;
249 int wfd_util_freq_to_channel(int freq)
251 if (freq < 2412 || freq > 5825 ||
252 (freq > 2484 && freq < 5180)) {
253 WDS_LOGE("Unsupported frequency[%d]", freq);
258 return 36 + (freq - 5180)/5;
259 else if (freq <= 2472)
260 return 1 + (freq - 2412)/5;
261 else if (freq == 2484)
267 int wfd_util_get_phone_name(char *phone_name)
269 __WDS_LOG_FUNC_ENTER__;
272 name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
274 WDS_LOGE("Failed to get vconf value for %s", VCONFKEY_SETAPPL_DEVICE_NAME_STR);
277 g_strlcpy(phone_name, name, DEV_NAME_LEN + 1);
278 WDS_LOGD("[%s: %s]", VCONFKEY_SETAPPL_DEVICE_NAME_STR, phone_name);
280 __WDS_LOG_FUNC_EXIT__;
284 void _wfd_util_dev_name_changed_cb(keynode_t *key, void *data)
286 __WDS_LOG_FUNC_ENTER__;
287 char dev_name[DEV_NAME_LEN+1] = {0, };
290 res = wfd_util_get_phone_name(dev_name);
292 WDS_LOGE("Failed to get phone name(vconf)");
295 WDS_LOGD("Device name changed as [%s]", dev_name);
297 res = wfd_local_set_dev_name(dev_name);
299 WDS_LOGE("Failed to set device name");
300 __WDS_LOG_FUNC_EXIT__;
304 void wfd_util_set_dev_name_notification()
306 __WDS_LOG_FUNC_ENTER__;
309 res = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb, NULL);
311 WDS_LOGE("Failed to set vconf notification callback(SETAPPL_DEVICE_NAME_STR)");
315 __WDS_LOG_FUNC_EXIT__;
319 void wfd_util_unset_dev_name_notification()
321 __WDS_LOG_FUNC_ENTER__;
324 res = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, _wfd_util_dev_name_changed_cb);
326 WDS_LOGE("Failed to set vconf notification callback(SETAPPL_DEVICE_NAME_STR)");
330 __WDS_LOG_FUNC_EXIT__;
335 void _wfd_util_check_country_cb(keynode_t *key, void *data)
337 __WDS_LOG_FUNC_ENTER__;
338 wfd_manager_s *manager = (wfd_manager_s*) data;
343 GKeyFile *keyfile = NULL;
344 const char *file_path = COUNTRY_CODE_FILE;
348 WDS_LOGE("Invalid parameter");
352 res = vconf_get_int(VCONFKEY_TELEPHONY_PLMN, &plmn);
354 WDS_LOGE("Failed to get vconf value for PLMN(%d)", res);
358 snprintf(mcc, 4, "%d", plmn);
360 keyfile = g_key_file_new();
361 res = g_key_file_load_from_file(keyfile, file_path, 0, &err);
363 WDS_LOGE("Failed to load key file(%s)", err->message);
364 g_key_file_free(keyfile);
368 ccode = g_key_file_get_string(keyfile, "ccode_map", mcc, &err);
370 WDS_LOGE("Failed to get country code string(%s)", err->message);
371 g_key_file_free(keyfile);
375 res = wfd_oem_set_country(manager->oem_ops, ccode);
377 WDS_LOGE("Failed to set contry code");
379 WDS_LOGD("Succeeded to set country code(%s)", ccode);
381 g_key_file_free(keyfile);
384 __WDS_LOG_FUNC_EXIT__;
388 int wfd_util_set_country()
390 __WDS_LOG_FUNC_ENTER__;
391 wfd_manager_s *manager = wfd_get_manager();
394 _wfd_util_check_country_cb(NULL, manager);
396 res = vconf_notify_key_changed(VCONFKEY_TELEPHONY_PLMN, _wfd_util_check_country_cb, manager);
398 WDS_LOGE("Failed to set vconf notification callback(TELEPHONY_PLMN)");
402 __WDS_LOG_FUNC_EXIT__;
406 int wfd_util_unset_country()
408 __WDS_LOG_FUNC_ENTER__;
411 res = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_PLMN, _wfd_util_check_country_cb);
413 WDS_LOGE("Failed to unset vconf notification callback(TELEPHONY_PLMN)");
417 __WDS_LOG_FUNC_EXIT__;
421 int wfd_util_check_wifi_state()
423 __WDS_LOG_FUNC_ENTER__;
427 /* vconf key and value (vconf-keys.h)
428 #define VCONFKEY_WIFI_STATE "memory/wifi/state"
430 VCONFKEY_WIFI_OFF = 0x00,
431 VCONFKEY_WIFI_UNCONNECTED,
432 VCONFKEY_WIFI_CONNECTED,
433 VCONFKEY_WIFI_TRANSFER,
434 VCONFKEY_WIFI_STATE_MAX
437 res = vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
439 WDS_LOGE("Failed to get vconf value [%s]", VCONFKEY_WIFI_STATE);
440 __WDS_LOG_FUNC_EXIT__;
443 WDS_LOGD("[%s: %d]", VCONFKEY_WIFI_STATE, wifi_state);
445 if (wifi_state > VCONFKEY_WIFI_OFF) {
446 WDS_LOGD("Wi-Fi is on");
447 __WDS_LOG_FUNC_EXIT__;
450 WDS_LOGD("OK. Wi-Fi is off\n");
452 __WDS_LOG_FUNC_EXIT__;
456 int wfd_util_check_mobile_ap_state()
458 __WDS_LOG_FUNC_ENTER__;
459 int mobile_ap_state = 0;
462 res = vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobile_ap_state);
464 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_MOBILE_HOTSPOT_MODE);
465 __WDS_LOG_FUNC_EXIT__;
468 WDS_LOGD("[%s: %d]", VCONFKEY_MOBILE_HOTSPOT_MODE, mobile_ap_state);
470 if ((mobile_ap_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI)
471 || (mobile_ap_state & VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI_AP)) {
472 WDS_LOGD("Mobile AP is on");
473 __WDS_LOG_FUNC_EXIT__;
476 WDS_LOGD("OK. Mobile AP is off\n");
478 __WDS_LOG_FUNC_EXIT__;
482 int wfd_util_wifi_direct_activatable()
484 __WDS_LOG_FUNC_ENTER__;
486 #ifndef TIZEN_WLAN_CONCURRENT_ENABLE
489 res_wifi = wfd_util_check_wifi_state();
491 WDS_LOGE("Failed to check Wi-Fi state");
492 __WDS_LOG_FUNC_EXIT__;
493 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
494 } else if (res_wifi > 0) {
495 WDS_LOGE("Wi-Fi is On");
496 __WDS_LOG_FUNC_EXIT__;
497 return WIFI_DIRECT_ERROR_WIFI_USED;
499 WDS_LOGE("Wi-Fi is Off");
500 __WDS_LOG_FUNC_EXIT__;
501 return WIFI_DIRECT_ERROR_NONE;
505 #if defined TIZEN_TETHERING_ENABLE
508 res_mobap = wfd_util_check_mobile_ap_state();
510 WDS_LOGE("Failed to check Mobile AP state");
511 __WDS_LOG_FUNC_EXIT__;
512 return WIFI_DIRECT_ERROR_OPERATION_FAILED;
513 } else if (res_mobap > 0) {
514 WDS_LOGE("Mobile AP is On");
515 __WDS_LOG_FUNC_EXIT__;
516 return WIFI_DIRECT_ERROR_MOBILE_AP_USED;
518 WDS_LOGE("Mobile AP is Off");
519 __WDS_LOG_FUNC_EXIT__;
520 return WIFI_DIRECT_ERROR_NONE;
524 __WDS_LOG_FUNC_EXIT__;
525 return WIFI_DIRECT_ERROR_NONE;
529 int wfd_util_get_wifi_direct_state()
531 __WDS_LOG_FUNC_ENTER__;
535 res = vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &state);
537 WDS_LOGE("Failed to get vconf value [%s]\n", VCONFKEY_WIFI_DIRECT_STATE);
538 __WDS_LOG_FUNC_EXIT__;
542 __WDS_LOG_FUNC_EXIT__;
547 int wfd_util_set_wifi_direct_state(int state)
549 __WDS_LOG_FUNC_ENTER__;
550 static int last_state = WIFI_DIRECT_STATE_DEACTIVATED;
551 int vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATED;
554 if (state < WIFI_DIRECT_STATE_DEACTIVATED ||
555 state > WIFI_DIRECT_STATE_GROUP_OWNER) {
556 WDS_LOGE("Invalid parameter");
557 __WDS_LOG_FUNC_EXIT__;
561 if (last_state == state) {
562 WDS_LOGD("No change in state, not updating vconf [%s]",
563 VCONFKEY_WIFI_DIRECT_STATE);
564 __WDS_LOG_FUNC_EXIT__;
568 if (state == WIFI_DIRECT_STATE_ACTIVATED)
569 vconf_state = VCONFKEY_WIFI_DIRECT_ACTIVATED;
570 else if (state == WIFI_DIRECT_STATE_DEACTIVATED)
571 vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATED;
572 else if (state == WIFI_DIRECT_STATE_CONNECTED)
573 vconf_state = VCONFKEY_WIFI_DIRECT_CONNECTED;
574 else if (state == WIFI_DIRECT_STATE_GROUP_OWNER)
575 vconf_state = VCONFKEY_WIFI_DIRECT_GROUP_OWNER;
576 else if (state == WIFI_DIRECT_STATE_DISCOVERING)
577 vconf_state = VCONFKEY_WIFI_DIRECT_DISCOVERING;
578 else if (state == WIFI_DIRECT_STATE_DEACTIVATING)
579 vconf_state = VCONFKEY_WIFI_DIRECT_DEACTIVATING;
580 else if (state == WIFI_DIRECT_STATE_ACTIVATING)
581 vconf_state = VCONFKEY_WIFI_DIRECT_ACTIVATING;
582 else if (state == WIFI_DIRECT_STATE_CONNECTING)
583 vconf_state = VCONFKEY_WIFI_DIRECT_CONNECTING;
584 else if (state == WIFI_DIRECT_STATE_DISCONNECTING)
585 vconf_state = VCONFKEY_WIFI_DIRECT_DISCONNECTING;
587 WDS_LOGE("This state cannot be set as wifi_direct vconf state[%d]", state);
591 WDS_LOGD("Vconf key set [%s: %d]", VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
593 res = vconf_set_int(VCONFKEY_WIFI_DIRECT_STATE, vconf_state);
595 WDS_LOGE("Failed to set vconf [%s]", VCONFKEY_WIFI_DIRECT_STATE);
596 __WDS_LOG_FUNC_EXIT__;
602 __WDS_LOG_FUNC_EXIT__;
606 int wfd_util_get_local_dev_mac(unsigned char *dev_mac)
608 __WDS_LOG_FUNC_ENTER__;
609 const char *file_path = DEFAULT_MAC_FILE_PATH;
611 char local_mac[MACSTR_LEN] = {0, };
614 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
617 fd = fopen(file_path, "r");
619 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
620 WDS_LOGE("Failed to open MAC info file [%s] (%s)", file_path , error_buf);
621 __WDS_LOG_FUNC_EXIT__;
626 ptr = fgets(local_mac, MACSTR_LEN, fd);
628 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
629 WDS_LOGE("Failed to read file or no data read(%s)", error_buf);
631 __WDS_LOG_FUNC_EXIT__;
634 WDS_SECLOGD("Local MAC address [%s]", ptr);
636 res = _txt_to_mac(local_mac, dev_mac);
638 WDS_LOGE("Failed to convert text to MAC address");
640 __WDS_LOG_FUNC_EXIT__;
644 WDS_LOGD("Local Device MAC address [" MACSECSTR "]", MAC2SECSTR(dev_mac));
647 __WDS_LOG_FUNC_EXIT__;
651 #ifdef TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT
652 int wfd_util_start_wifi_direct_popup()
654 __WDS_LOG_FUNC_ENTER__;
658 ret = __wfd_util_find_login_user(&uid);
660 WDS_LOGE("__wfd_util_find_login_user Failed !");
664 if (AUL_R_OK != aul_launch_app_for_uid(
665 "org.tizen.wifi-direct-popup", NULL, uid)) {
666 WDS_LOGE("aul_launch_for_uid Failed !");
670 WDS_LOGD("Succeeded to launch wifi-direct-popup");
671 __WDS_LOG_FUNC_EXIT__;
675 int wfd_util_stop_wifi_direct_popup()
677 __WDS_LOG_FUNC_ENTER__;
681 ret = __wfd_util_find_login_user(&uid);
683 WDS_LOGE("__wfd_util_find_login_user Failed !");
687 int pid = aul_app_get_pid_for_uid("org.tizen.wifi-direct-popup", uid);
689 if (aul_terminate_pid_for_uid(pid, uid) != AUL_R_OK) {
690 WDS_LOGD("Failed to destroy wifi-direct-popup pid[%d]", pid);
693 WDS_LOGD("Succeeded to destroy wifi-direct-popup");
696 WDS_LOGD("Wifi-direct-popup not running");
699 __WDS_LOG_FUNC_EXIT__;
702 #endif /* TIZEN_FEATURE_DEFAULT_CONNECTION_AGENT */
704 int _connect_remote_device(char *ip_str)
709 struct sockaddr_in remo_addr;
710 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
713 sock = socket(PF_INET, SOCK_STREAM, 0);
715 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
716 WDS_LOGE("Failed to create socket to remote device(%s)", error_buf);
720 flags = fcntl(sock, F_GETFL, 0);
721 res = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
723 WDS_LOGE("File descriptor create failed");
725 __WDS_LOG_FUNC_EXIT__;
729 memset(&remo_addr, 0x0, sizeof(remo_addr));
730 remo_addr.sin_family = AF_INET;
731 remo_addr.sin_addr.s_addr = inet_addr(ip_str);
732 remo_addr.sin_port = htons(9999);
735 res = connect(sock, (struct sockaddr*) &remo_addr, sizeof(remo_addr));
737 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
738 WDS_LOGE("Failed to connect to server socket [%s]", error_buf);
740 __WDS_LOG_FUNC_EXIT__;
744 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
745 WDS_SECLOGD("Status of connection to remote device[%s] - (%s)", ip_str, error_buf);
752 static void _dhcps_ip_leased_cb(keynode_t *key, void* data)
754 __WDS_LOG_FUNC_ENTER__;
755 wfd_device_s *peer = (wfd_device_s*) data;
757 char buf[MAX_DHCP_DUMP_SIZE];
758 char ip_str[IPSTR_LEN] = {0, };
759 char intf_str[MACSTR_LEN];
760 unsigned char intf_addr[MACADDR_LEN];
761 char peer_mac_address[MACSTR_LEN+1] = {0,};
762 char assigned_ip_address[IPSTR_LEN+1] = {0,};
764 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
767 WDS_LOGD("Invalid parameter");
770 WDS_LOGD("DHCP server: IP leased");
773 fp = fopen(DHCP_DUMP_FILE, "r");
775 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
776 WDS_LOGE("Could not read the file(%s). [%s]", DHCP_DUMP_FILE, error_buf);
780 while (fgets(buf, MAX_DHCP_DUMP_SIZE, fp) != NULL) {
781 WDS_LOGD("Read line [%s]", buf);
782 n = sscanf(buf, "%17s %15s", intf_str, ip_str);
783 WDS_LOGD("ip=[%s], mac=[%s]", ip_str, intf_str);
787 _txt_to_mac(intf_str, intf_addr);
788 if (!memcmp(peer->intf_addr, intf_addr, MACADDR_LEN)) {
789 WDS_LOGD("Peer intf mac found");
790 _txt_to_ip(ip_str, peer->ip_addr);
791 _connect_remote_device(ip_str);
792 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
793 g_snprintf(assigned_ip_address, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
794 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
796 g_variant_new("(ss)", peer_mac_address,
797 assigned_ip_address));
800 WDS_LOGD("Different interface address peer[" MACSECSTR "] vs dhcp[" MACSECSTR "]",
801 MAC2SECSTR(peer->intf_addr), MAC2SECSTR(intf_addr));
806 vconf_ignore_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb);
807 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
809 __WDS_LOG_FUNC_EXIT__;
813 static gboolean _polling_ip(gpointer user_data)
815 __WDS_LOG_FUNC_ENTER__;
816 wfd_manager_s *manager = wfd_get_manager();
817 wfd_device_s *local = (wfd_device_s*) manager->local;
818 wfd_device_s *peer = (wfd_device_s*) user_data;
820 char ip_str[IPSTR_LEN] = {0, };
821 static int count = 0;
825 WDS_LOGE("peer data is not exists");
829 res = wfd_manager_get_goup_ifname(&ifname);
830 if (res < 0 || !ifname) {
831 WDS_LOGE("Failed to get group interface name");
836 WDS_LOGE("Failed to get IP");
838 wfd_oem_destroy_group(manager->oem_ops, ifname);
839 __WDS_LOG_FUNC_EXIT__;
842 res = wfd_util_local_get_ip(ifname, local->ip_addr, 0);
844 WDS_LOGE("Failed to get local IP for interface %s(count=%d)", ifname, count++);
845 __WDS_LOG_FUNC_EXIT__;
848 WDS_LOGD("Succeeded to get local(client) IP [" IPSECSTR "] for iface[%s]",
849 IP2SECSTR(local->ip_addr), ifname);
851 res = wfd_util_dhcpc_get_server_ip(peer->ip_addr);
853 WDS_LOGE("Failed to get peer(server) IP(count=%d)", count++);
854 __WDS_LOG_FUNC_EXIT__;
857 WDS_LOGD("Succeeded to get server IP [" IPSECSTR "]", IP2SECSTR(peer->ip_addr));
860 g_snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
861 _connect_remote_device(ip_str);
863 char peer_mac_address[MACSTR_LEN+1] = {0, };
865 g_snprintf(peer_mac_address, MACSTR_LEN, MACSTR, MAC2STR(peer->dev_addr));
866 wfd_manager_dbus_emit_signal(WFD_MANAGER_MANAGE_INTERFACE,
868 g_variant_new("(iis)", WIFI_DIRECT_ERROR_NONE,
869 WFD_EVENT_CONNECTION_RSP,
872 #if defined(TIZEN_FEATURE_ASP)
873 wfd_session_s *session = manager->session;
874 if (session && !ISZEROMACADDR(session->session_mac))
875 wfd_asp_connect_status(session->session_mac,
877 ASP_CONNECT_STATUS_GROUP_FORMATION_COMPLETED,
881 wfd_state_set(manager, WIFI_DIRECT_STATE_CONNECTED);
882 wfd_util_set_wifi_direct_state(WIFI_DIRECT_STATE_CONNECTED);
883 wfd_destroy_session(manager);
885 __WDS_LOG_FUNC_EXIT__;
889 int wfd_util_dhcps_start(char *ifname)
891 __WDS_LOG_FUNC_ENTER__;
893 char *const iface = ifname;
894 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
895 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "server", iface, NULL };
896 char *const envs[] = { NULL };
897 wfd_manager_s *manager = wfd_get_manager();
899 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
901 rv = wfd_util_execute_file(path, args, envs);
904 WDS_LOGE("Failed to start wifi-direct-dhcp.sh server");
909 * As we are GO so IP should be updated
910 * before sending Group Created Event
912 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_IFNAME, GROUP_IFNAME);
913 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_LOCAL_IP, "192.168.49.1");
914 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_SUBNET_MASK, "255.255.255.0");
915 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_GATEWAY, "192.168.49.1");
917 WDS_LOGD("Successfully started wifi-direct-dhcp.sh server");
919 _txt_to_ip(TIZEN_P2P_GO_IPADDR, manager->local->ip_addr);
921 __WDS_LOG_FUNC_EXIT__;
925 int wfd_util_dhcps_wait_ip_leased(wfd_device_s *peer)
927 __WDS_LOG_FUNC_ENTER__;
930 WDS_LOGE("Invalid parameter");
934 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
935 vconf_notify_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb, peer);
937 __WDS_LOG_FUNC_EXIT__;
941 int wfd_util_dhcps_stop(char *ifname)
943 __WDS_LOG_FUNC_ENTER__;
945 char *const iface = ifname;
946 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
947 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "stop", iface, NULL };
948 char *const envs[] = { NULL };
950 vconf_ignore_key_changed(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, _dhcps_ip_leased_cb);
951 vconf_set_int(VCONFKEY_WIFI_DIRECT_DHCP_IP_LEASE, 0);
953 rv = wfd_util_execute_file(path, args, envs);
956 WDS_LOGE("Failed to stop wifi-direct-dhcp.sh");
959 WDS_LOGD("Successfully stopped wifi-direct-dhcp.sh");
961 __WDS_LOG_FUNC_EXIT__;
965 int wfd_util_dhcpc_start(char *ifname, wfd_device_s *peer)
967 __WDS_LOG_FUNC_ENTER__;
969 char *const iface = ifname;
970 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
971 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "client", iface, NULL };
972 char *const envs[] = { NULL };
975 WDS_LOGE("Invalid parameter");
979 rv = wfd_util_execute_file(path, args, envs);
981 WDS_LOGE("Failed to start wifi-direct-dhcp.sh client");
984 WDS_LOGD("Successfully started wifi-direct-dhcp.sh client");
986 g_timeout_add(250, (GSourceFunc) _polling_ip, peer);
988 __WDS_LOG_FUNC_EXIT__;
992 int wfd_util_dhcpc_stop(char *ifname)
994 __WDS_LOG_FUNC_ENTER__;
996 char *const iface = ifname;
997 const char *path = "/usr/bin/wifi-direct-dhcp.sh";
998 char *const args[] = { "/usr/bin/wifi-direct-dhcp.sh", "stop", iface, NULL };
999 char *const envs[] = { NULL };
1001 rv = wfd_util_execute_file(path, args, envs);
1004 WDS_LOGE("Failed to stop wifi-direct-dhcp.sh");
1007 WDS_LOGD("Successfully stopped wifi-direct-dhcp.sh");
1009 __WDS_LOG_FUNC_EXIT__;
1013 int wfd_util_local_get_ip(char *ifname, unsigned char *ip_addr, int is_IPv6)
1015 __WDS_LOG_FUNC_ENTER__;
1017 struct sockaddr_in *sin = NULL;
1018 char *ip_str = NULL;
1021 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1023 if (!ifname || !ip_addr) {
1024 WDS_LOGE("Invalid parameter");
1025 __WDS_LOG_FUNC_EXIT__;
1030 sock = socket(AF_INET, SOCK_DGRAM, 0);
1031 if (sock < SOCK_FD_MIN) {
1032 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1033 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1036 __WDS_LOG_FUNC_EXIT__;
1040 ifr.ifr_addr.sa_family = AF_INET;
1041 memset(ifr.ifr_name, 0x00, IFNAMSIZ);
1042 g_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1045 res = ioctl(sock, SIOCGIFADDR, &ifr);
1047 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1048 WDS_LOGE("Failed to get IP from socket. [%s]", error_buf);
1050 __WDS_LOG_FUNC_EXIT__;
1055 sin = (struct sockaddr_in*) &ifr.ifr_broadaddr;
1056 ip_str = inet_ntoa(sin->sin_addr);
1057 _txt_to_ip(ip_str, ip_addr);
1058 __WDS_LOG_FUNC_EXIT__;
1062 int wfd_util_dhcpc_get_server_ip(unsigned char* ip_addr)
1064 __WDS_LOG_FUNC_ENTER__;
1065 char* get_str = NULL;
1069 WDS_LOGE("Invalid parameter");
1070 __WDS_LOG_FUNC_EXIT__;
1074 while (count < 10) {
1075 get_str = vconf_get_str(VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1077 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1078 __WDS_LOG_FUNC_EXIT__;
1082 if (strcmp(get_str, ZEROIP) == 0) {
1083 WDS_LOGE("Failed to get vconf value[%s]", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP);
1085 __WDS_LOG_FUNC_EXIT__;
1089 WDS_LOGD("VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP(%s) : %s\n", VCONFKEY_WIFI_DIRECT_DHCPC_SERVER_IP, get_str);
1090 _txt_to_ip(get_str, ip_addr);
1097 __WDS_LOG_FUNC_EXIT__;
1101 #ifdef TIZEN_FEATURE_IP_OVER_EAPOL
1102 static int _wfd_util_set_vconf_for_static_ip(const char *ifname, char *static_ip)
1104 __WDS_LOG_FUNC_ENTER__;
1106 if (!ifname || !static_ip)
1109 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_IFNAME, ifname);
1110 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_LOCAL_IP, static_ip);
1111 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_SUBNET_MASK, "255.255.255.0");
1112 vconf_set_str(VCONFKEY_WIFI_DIRECT_P2P_GATEWAY, "192.168.49.1");
1114 __WDS_LOG_FUNC_EXIT__;
1120 static int _wfd_util_static_ip_set(const char *ifname, unsigned char *static_ip)
1122 __WDS_LOG_FUNC_ENTER__;
1124 unsigned char ip_addr[IPADDR_LEN];
1125 char ip_str[IPSTR_LEN] = {0, };
1129 struct sockaddr_nl dst_addr;
1133 struct ifaddrmsg ifa;
1138 struct msghdr nl_msg;
1140 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1142 if (!ifname || !static_ip) {
1143 WDS_LOGE("Invalid parameter");
1144 __WDS_LOG_FUNC_EXIT__;
1148 /* Get index of interface */
1149 if_index = if_nametoindex(ifname);
1151 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1152 WDS_LOGE("Failed to get interface index. [%s]", error_buf);
1153 __WDS_LOG_FUNC_EXIT__;
1157 WDS_LOGD("Creating a Netlink Socket");
1158 nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1160 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1161 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1162 __WDS_LOG_FUNC_EXIT__;
1166 memset(&dst_addr, 0, sizeof(dst_addr));
1167 dst_addr.nl_family = AF_NETLINK;
1168 dst_addr.nl_pid = 0;
1170 memset(&req, 0, sizeof(req));
1171 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1172 req.nh.nlmsg_type = RTM_NEWADDR;
1173 req.nh.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST;
1175 req.ifa.ifa_family = AF_INET;
1176 req.ifa.ifa_prefixlen = 24;
1177 req.ifa.ifa_flags = IFA_F_PERMANENT;
1178 req.ifa.ifa_scope = 0;
1179 req.ifa.ifa_index = if_index;
1181 rta = (struct rtattr *)(req.attrbuf);
1182 rta->rta_type = IFA_LOCAL;
1183 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1184 memcpy(RTA_DATA(rta), static_ip, IPADDR_LEN);
1185 req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
1187 rta = (struct rtattr *)(req.attrbuf + rta->rta_len);
1188 rta->rta_type = IFA_BROADCAST;
1189 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1190 memcpy(ip_addr, static_ip, IPADDR_LEN);
1192 memcpy(RTA_DATA(rta), ip_addr, IPADDR_LEN);
1193 req.nh.nlmsg_len += rta->rta_len;
1195 memset(&iov, 0, sizeof(iov));
1196 iov.iov_base = &req;
1197 iov.iov_len = req.nh.nlmsg_len;
1199 memset(&nl_msg, 0, sizeof(nl_msg));
1200 nl_msg.msg_name = (void *)&dst_addr;
1201 nl_msg.msg_namelen = sizeof(dst_addr);
1202 nl_msg.msg_iov = &iov;
1203 nl_msg.msg_iovlen = 1;
1205 res = sendmsg(nl_sock, &nl_msg, 0);
1207 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1208 WDS_LOGE("Failed to sendmsg. [%s]", error_buf);
1210 WDS_LOGD("Succed to sendmsg. [%d]", res);
1214 WDS_LOGE("Succeeded to set local(client) IP [" IPSTR "] for iface[%s]",
1215 IP2STR(static_ip), ifname);
1217 snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(static_ip));
1218 _wfd_util_set_vconf_for_static_ip(ifname, ip_str);
1220 __WDS_LOG_FUNC_EXIT__;
1224 int wfd_util_ip_over_eap_assign(wfd_device_s *peer, const char *ifname)
1226 __WDS_LOG_FUNC_ENTER__;
1227 wfd_manager_s *manager = wfd_get_manager();
1228 wfd_device_s *local = (wfd_device_s*) manager->local;
1230 char ip_str[IPSTR_LEN] = {0, };
1233 WDS_LOGE("Invalid paramater");
1237 _wfd_util_static_ip_set(ifname, peer->client_ip_addr);
1238 memcpy(peer->ip_addr, peer->go_ip_addr, IPADDR_LEN);
1239 memcpy(local->ip_addr, peer->client_ip_addr, IPADDR_LEN);
1241 g_snprintf(ip_str, IPSTR_LEN, IPSTR, IP2STR(peer->ip_addr));
1242 _connect_remote_device(ip_str);
1244 __WDS_LOG_FUNC_EXIT__;
1247 #endif /* TIZEN_FEATURE_IP_OVER_EAPOL */
1249 int wfd_util_ip_unset(const char *ifname)
1251 __WDS_LOG_FUNC_ENTER__;
1253 unsigned char ip_addr[IPADDR_LEN];
1254 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
1258 struct sockaddr_nl dst_addr;
1262 struct ifaddrmsg ifa;
1267 struct msghdr nl_msg;
1270 WDS_LOGE("Invalid parameter");
1271 __WDS_LOG_FUNC_EXIT__;
1275 res = wfd_util_local_get_ip((char *)ifname, ip_addr, 0);
1277 WDS_LOGE("Failed to get local IP for interface %s", ifname);
1278 __WDS_LOG_FUNC_EXIT__;
1281 WDS_LOGE("Succeeded to get local(client) IP [" IPSTR "] for iface[%s]",
1282 IP2STR(ip_addr), ifname);
1284 if_index = if_nametoindex(ifname);
1286 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1287 WDS_LOGE("Failed to get interface index. [%s]", error_buf);
1288 __WDS_LOG_FUNC_EXIT__;
1292 WDS_LOGD("Creating a Netlink Socket");
1293 nl_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1295 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1296 WDS_LOGE("Failed to create socket. [%s]", error_buf);
1297 __WDS_LOG_FUNC_EXIT__;
1301 WDS_LOGD("Set dst socket address to kernel");
1302 memset(&dst_addr, 0, sizeof(dst_addr));
1303 dst_addr.nl_family = AF_NETLINK;
1304 dst_addr.nl_pid = 0;
1306 memset(&req, 0, sizeof(req));
1307 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1308 req.nh.nlmsg_type = RTM_DELADDR;
1309 req.nh.nlmsg_flags = NLM_F_REQUEST;
1311 req.ifa.ifa_family = AF_INET;
1312 req.ifa.ifa_prefixlen = 32;
1313 req.ifa.ifa_flags = IFA_F_PERMANENT;
1314 req.ifa.ifa_scope = 0;
1315 req.ifa.ifa_index = if_index;
1317 rta = (struct rtattr *)(req.attrbuf);
1318 rta->rta_type = IFA_LOCAL;
1319 rta->rta_len = RTA_LENGTH(IPADDR_LEN);
1320 memcpy(RTA_DATA(rta), ip_addr, IPADDR_LEN);
1321 req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
1323 memset(&iov, 0, sizeof(iov));
1324 iov.iov_base = &req;
1325 iov.iov_len = req.nh.nlmsg_len;
1327 memset(&nl_msg, 0, sizeof(nl_msg));
1328 nl_msg.msg_name = (void *)&dst_addr;
1329 nl_msg.msg_namelen = sizeof(dst_addr);
1330 nl_msg.msg_iov = &iov;
1331 nl_msg.msg_iovlen = 1;
1333 res = sendmsg(nl_sock, &nl_msg, 0);
1335 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
1336 WDS_LOGE("Failed to sendmsg. [%s]", error_buf);
1338 WDS_LOGD("Succeed to sendmsg. [%d]", res);
1343 __WDS_LOG_FUNC_EXIT__;
1347 gboolean wfd_util_is_remove_group_allowed(void)
1349 wfd_manager_s *manager = wfd_get_manager();
1351 if (!manager->auto_group_remove_enable)