xref: /freebsd/contrib/wpa/src/drivers/driver_nl80211_android.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
15b9c547cSRui Paulo /*
25b9c547cSRui Paulo  * Driver interaction with Linux nl80211/cfg80211 - Android specific
35b9c547cSRui Paulo  * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
45b9c547cSRui Paulo  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
55b9c547cSRui Paulo  * Copyright (c) 2009-2010, Atheros Communications
65b9c547cSRui Paulo  *
75b9c547cSRui Paulo  * This software may be distributed under the terms of the BSD license.
85b9c547cSRui Paulo  * See README for more details.
95b9c547cSRui Paulo  */
105b9c547cSRui Paulo 
115b9c547cSRui Paulo #include "includes.h"
125b9c547cSRui Paulo #include <sys/ioctl.h>
135b9c547cSRui Paulo #include <net/if.h>
145b9c547cSRui Paulo #include <netlink/genl/genl.h>
155b9c547cSRui Paulo #include <netlink/genl/family.h>
165b9c547cSRui Paulo #include <netlink/genl/ctrl.h>
175b9c547cSRui Paulo #include <fcntl.h>
185b9c547cSRui Paulo 
195b9c547cSRui Paulo #include "utils/common.h"
205b9c547cSRui Paulo #include "driver_nl80211.h"
215b9c547cSRui Paulo #include "android_drv.h"
225b9c547cSRui Paulo 
235b9c547cSRui Paulo 
245b9c547cSRui Paulo typedef struct android_wifi_priv_cmd {
255b9c547cSRui Paulo 	char *buf;
265b9c547cSRui Paulo 	int used_len;
275b9c547cSRui Paulo 	int total_len;
285b9c547cSRui Paulo } android_wifi_priv_cmd;
295b9c547cSRui Paulo 
305b9c547cSRui Paulo static int drv_errors = 0;
315b9c547cSRui Paulo 
wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data * drv)325b9c547cSRui Paulo static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
335b9c547cSRui Paulo {
345b9c547cSRui Paulo 	drv_errors++;
355b9c547cSRui Paulo 	if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
365b9c547cSRui Paulo 		drv_errors = 0;
375b9c547cSRui Paulo 		wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
385b9c547cSRui Paulo 	}
395b9c547cSRui Paulo }
405b9c547cSRui Paulo 
415b9c547cSRui Paulo 
android_priv_cmd(struct i802_bss * bss,const char * cmd)425b9c547cSRui Paulo static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
435b9c547cSRui Paulo {
445b9c547cSRui Paulo 	struct wpa_driver_nl80211_data *drv = bss->drv;
455b9c547cSRui Paulo 	struct ifreq ifr;
465b9c547cSRui Paulo 	android_wifi_priv_cmd priv_cmd;
475b9c547cSRui Paulo 	char buf[MAX_DRV_CMD_SIZE];
485b9c547cSRui Paulo 	int ret;
495b9c547cSRui Paulo 
505b9c547cSRui Paulo 	os_memset(&ifr, 0, sizeof(ifr));
515b9c547cSRui Paulo 	os_memset(&priv_cmd, 0, sizeof(priv_cmd));
525b9c547cSRui Paulo 	os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
535b9c547cSRui Paulo 
545b9c547cSRui Paulo 	os_memset(buf, 0, sizeof(buf));
555b9c547cSRui Paulo 	os_strlcpy(buf, cmd, sizeof(buf));
565b9c547cSRui Paulo 
575b9c547cSRui Paulo 	priv_cmd.buf = buf;
585b9c547cSRui Paulo 	priv_cmd.used_len = sizeof(buf);
595b9c547cSRui Paulo 	priv_cmd.total_len = sizeof(buf);
605b9c547cSRui Paulo 	ifr.ifr_data = &priv_cmd;
615b9c547cSRui Paulo 
625b9c547cSRui Paulo 	ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
635b9c547cSRui Paulo 	if (ret < 0) {
645b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
655b9c547cSRui Paulo 			   __func__);
665b9c547cSRui Paulo 		wpa_driver_send_hang_msg(drv);
675b9c547cSRui Paulo 		return ret;
685b9c547cSRui Paulo 	}
695b9c547cSRui Paulo 
705b9c547cSRui Paulo 	drv_errors = 0;
715b9c547cSRui Paulo 	return 0;
725b9c547cSRui Paulo }
735b9c547cSRui Paulo 
745b9c547cSRui Paulo 
android_pno_start(struct i802_bss * bss,struct wpa_driver_scan_params * params)755b9c547cSRui Paulo int android_pno_start(struct i802_bss *bss,
765b9c547cSRui Paulo 		      struct wpa_driver_scan_params *params)
775b9c547cSRui Paulo {
785b9c547cSRui Paulo 	struct wpa_driver_nl80211_data *drv = bss->drv;
795b9c547cSRui Paulo 	struct ifreq ifr;
805b9c547cSRui Paulo 	android_wifi_priv_cmd priv_cmd;
815b9c547cSRui Paulo 	int ret = 0, i = 0, bp;
825b9c547cSRui Paulo 	char buf[WEXT_PNO_MAX_COMMAND_SIZE];
835b9c547cSRui Paulo 
845b9c547cSRui Paulo 	bp = WEXT_PNOSETUP_HEADER_SIZE;
855b9c547cSRui Paulo 	os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
865b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_TLV_PREFIX;
875b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_TLV_VERSION;
885b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
895b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_TLV_RESERVED;
905b9c547cSRui Paulo 
915b9c547cSRui Paulo 	while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
925b9c547cSRui Paulo 		/* Check that there is enough space needed for 1 more SSID, the
935b9c547cSRui Paulo 		 * other sections and null termination */
945b9c547cSRui Paulo 		if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
955b9c547cSRui Paulo 		     WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
965b9c547cSRui Paulo 			break;
975b9c547cSRui Paulo 		wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
985b9c547cSRui Paulo 				  params->ssids[i].ssid,
995b9c547cSRui Paulo 				  params->ssids[i].ssid_len);
1005b9c547cSRui Paulo 		buf[bp++] = WEXT_PNO_SSID_SECTION;
1015b9c547cSRui Paulo 		buf[bp++] = params->ssids[i].ssid_len;
1025b9c547cSRui Paulo 		os_memcpy(&buf[bp], params->ssids[i].ssid,
1035b9c547cSRui Paulo 			  params->ssids[i].ssid_len);
1045b9c547cSRui Paulo 		bp += params->ssids[i].ssid_len;
1055b9c547cSRui Paulo 		i++;
1065b9c547cSRui Paulo 	}
1075b9c547cSRui Paulo 
1085b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
1095b9c547cSRui Paulo 	os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
1105b9c547cSRui Paulo 		    WEXT_PNO_SCAN_INTERVAL);
1115b9c547cSRui Paulo 	bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
1125b9c547cSRui Paulo 
1135b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_REPEAT_SECTION;
1145b9c547cSRui Paulo 	os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
1155b9c547cSRui Paulo 		    WEXT_PNO_REPEAT);
1165b9c547cSRui Paulo 	bp += WEXT_PNO_REPEAT_LENGTH;
1175b9c547cSRui Paulo 
1185b9c547cSRui Paulo 	buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
1195b9c547cSRui Paulo 	os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
1205b9c547cSRui Paulo 		    WEXT_PNO_MAX_REPEAT);
1215b9c547cSRui Paulo 	bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
1225b9c547cSRui Paulo 
1235b9c547cSRui Paulo 	memset(&ifr, 0, sizeof(ifr));
1245b9c547cSRui Paulo 	memset(&priv_cmd, 0, sizeof(priv_cmd));
1255b9c547cSRui Paulo 	os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
1265b9c547cSRui Paulo 
1275b9c547cSRui Paulo 	priv_cmd.buf = buf;
1285b9c547cSRui Paulo 	priv_cmd.used_len = bp;
1295b9c547cSRui Paulo 	priv_cmd.total_len = bp;
1305b9c547cSRui Paulo 	ifr.ifr_data = &priv_cmd;
1315b9c547cSRui Paulo 
1325b9c547cSRui Paulo 	ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
1335b9c547cSRui Paulo 
1345b9c547cSRui Paulo 	if (ret < 0) {
1355b9c547cSRui Paulo 		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
1365b9c547cSRui Paulo 			   ret);
1375b9c547cSRui Paulo 		wpa_driver_send_hang_msg(drv);
1385b9c547cSRui Paulo 		return ret;
1395b9c547cSRui Paulo 	}
1405b9c547cSRui Paulo 
1415b9c547cSRui Paulo 	drv_errors = 0;
1425b9c547cSRui Paulo 
1435b9c547cSRui Paulo 	return android_priv_cmd(bss, "PNOFORCE 1");
1445b9c547cSRui Paulo }
1455b9c547cSRui Paulo 
1465b9c547cSRui Paulo 
android_pno_stop(struct i802_bss * bss)1475b9c547cSRui Paulo int android_pno_stop(struct i802_bss *bss)
1485b9c547cSRui Paulo {
1495b9c547cSRui Paulo 	return android_priv_cmd(bss, "PNOFORCE 0");
1505b9c547cSRui Paulo }
1515b9c547cSRui Paulo 
1525b9c547cSRui Paulo 
1535b9c547cSRui Paulo #ifdef ANDROID_P2P
154325151a3SRui Paulo #ifdef ANDROID_LIB_STUB
1555b9c547cSRui Paulo 
wpa_driver_set_p2p_noa(void * priv,u8 count,int start,int duration)1565b9c547cSRui Paulo int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
1575b9c547cSRui Paulo {
1585b9c547cSRui Paulo 	return 0;
1595b9c547cSRui Paulo }
1605b9c547cSRui Paulo 
1615b9c547cSRui Paulo 
wpa_driver_get_p2p_noa(void * priv,u8 * buf,size_t len)1625b9c547cSRui Paulo int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
1635b9c547cSRui Paulo {
1645b9c547cSRui Paulo 	return 0;
1655b9c547cSRui Paulo }
1665b9c547cSRui Paulo 
1675b9c547cSRui Paulo 
wpa_driver_set_p2p_ps(void * priv,int legacy_ps,int opp_ps,int ctwindow)1685b9c547cSRui Paulo int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
1695b9c547cSRui Paulo {
1705b9c547cSRui Paulo 	return -1;
1715b9c547cSRui Paulo }
1725b9c547cSRui Paulo 
1735b9c547cSRui Paulo 
wpa_driver_set_ap_wps_p2p_ie(void * priv,const struct wpabuf * beacon,const struct wpabuf * proberesp,const struct wpabuf * assocresp)1745b9c547cSRui Paulo int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
1755b9c547cSRui Paulo 				 const struct wpabuf *proberesp,
1765b9c547cSRui Paulo 				 const struct wpabuf *assocresp)
1775b9c547cSRui Paulo {
1785b9c547cSRui Paulo 	return 0;
1795b9c547cSRui Paulo }
1805b9c547cSRui Paulo 
181325151a3SRui Paulo #endif /* ANDROID_LIB_STUB */
1825b9c547cSRui Paulo #endif /* ANDROID_P2P */
1835b9c547cSRui Paulo 
1845b9c547cSRui Paulo 
android_nl_socket_set_nonblocking(struct nl_sock * handle)185*c1d255d3SCy Schubert int android_nl_socket_set_nonblocking(struct nl_sock *handle)
1865b9c547cSRui Paulo {
1875b9c547cSRui Paulo 	return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
1885b9c547cSRui Paulo }
189