xref: /dragonfly/contrib/wpa_supplicant/src/drivers/driver_nl80211_android.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
1 /*
2  * Driver interaction with Linux nl80211/cfg80211 - Android specific
3  * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
5  * Copyright (c) 2009-2010, Atheros Communications
6  *
7  * This software may be distributed under the terms of the BSD license.
8  * See README for more details.
9  */
10 
11 #include "includes.h"
12 #include <sys/ioctl.h>
13 #include <net/if.h>
14 #include <netlink/genl/genl.h>
15 #include <netlink/genl/family.h>
16 #include <netlink/genl/ctrl.h>
17 #include <fcntl.h>
18 
19 #include "utils/common.h"
20 #include "driver_nl80211.h"
21 #include "android_drv.h"
22 
23 
24 typedef struct android_wifi_priv_cmd {
25           char *buf;
26           int used_len;
27           int total_len;
28 } android_wifi_priv_cmd;
29 
30 static int drv_errors = 0;
31 
wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data * drv)32 static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
33 {
34           drv_errors++;
35           if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
36                     drv_errors = 0;
37                     wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
38           }
39 }
40 
41 
android_priv_cmd(struct i802_bss * bss,const char * cmd)42 static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
43 {
44           struct wpa_driver_nl80211_data *drv = bss->drv;
45           struct ifreq ifr;
46           android_wifi_priv_cmd priv_cmd;
47           char buf[MAX_DRV_CMD_SIZE];
48           int ret;
49 
50           os_memset(&ifr, 0, sizeof(ifr));
51           os_memset(&priv_cmd, 0, sizeof(priv_cmd));
52           os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
53 
54           os_memset(buf, 0, sizeof(buf));
55           os_strlcpy(buf, cmd, sizeof(buf));
56 
57           priv_cmd.buf = buf;
58           priv_cmd.used_len = sizeof(buf);
59           priv_cmd.total_len = sizeof(buf);
60           ifr.ifr_data = &priv_cmd;
61 
62           ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
63           if (ret < 0) {
64                     wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
65                                  __func__);
66                     wpa_driver_send_hang_msg(drv);
67                     return ret;
68           }
69 
70           drv_errors = 0;
71           return 0;
72 }
73 
74 
android_pno_start(struct i802_bss * bss,struct wpa_driver_scan_params * params)75 int android_pno_start(struct i802_bss *bss,
76                           struct wpa_driver_scan_params *params)
77 {
78           struct wpa_driver_nl80211_data *drv = bss->drv;
79           struct ifreq ifr;
80           android_wifi_priv_cmd priv_cmd;
81           int ret = 0, i = 0, bp;
82           char buf[WEXT_PNO_MAX_COMMAND_SIZE];
83 
84           bp = WEXT_PNOSETUP_HEADER_SIZE;
85           os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
86           buf[bp++] = WEXT_PNO_TLV_PREFIX;
87           buf[bp++] = WEXT_PNO_TLV_VERSION;
88           buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
89           buf[bp++] = WEXT_PNO_TLV_RESERVED;
90 
91           while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
92                     /* Check that there is enough space needed for 1 more SSID, the
93                      * other sections and null termination */
94                     if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
95                          WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
96                               break;
97                     wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
98                                           params->ssids[i].ssid,
99                                           params->ssids[i].ssid_len);
100                     buf[bp++] = WEXT_PNO_SSID_SECTION;
101                     buf[bp++] = params->ssids[i].ssid_len;
102                     os_memcpy(&buf[bp], params->ssids[i].ssid,
103                                 params->ssids[i].ssid_len);
104                     bp += params->ssids[i].ssid_len;
105                     i++;
106           }
107 
108           buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
109           os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
110                         WEXT_PNO_SCAN_INTERVAL);
111           bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
112 
113           buf[bp++] = WEXT_PNO_REPEAT_SECTION;
114           os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
115                         WEXT_PNO_REPEAT);
116           bp += WEXT_PNO_REPEAT_LENGTH;
117 
118           buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
119           os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
120                         WEXT_PNO_MAX_REPEAT);
121           bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
122 
123           memset(&ifr, 0, sizeof(ifr));
124           memset(&priv_cmd, 0, sizeof(priv_cmd));
125           os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
126 
127           priv_cmd.buf = buf;
128           priv_cmd.used_len = bp;
129           priv_cmd.total_len = bp;
130           ifr.ifr_data = &priv_cmd;
131 
132           ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
133 
134           if (ret < 0) {
135                     wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
136                                  ret);
137                     wpa_driver_send_hang_msg(drv);
138                     return ret;
139           }
140 
141           drv_errors = 0;
142 
143           return android_priv_cmd(bss, "PNOFORCE 1");
144 }
145 
146 
android_pno_stop(struct i802_bss * bss)147 int android_pno_stop(struct i802_bss *bss)
148 {
149           return android_priv_cmd(bss, "PNOFORCE 0");
150 }
151 
152 
153 #ifdef ANDROID_P2P
154 #ifdef ANDROID_LIB_STUB
155 
wpa_driver_set_p2p_noa(void * priv,u8 count,int start,int duration)156 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
157 {
158           return 0;
159 }
160 
161 
wpa_driver_get_p2p_noa(void * priv,u8 * buf,size_t len)162 int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
163 {
164           return 0;
165 }
166 
167 
wpa_driver_set_p2p_ps(void * priv,int legacy_ps,int opp_ps,int ctwindow)168 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
169 {
170           return -1;
171 }
172 
173 
wpa_driver_set_ap_wps_p2p_ie(void * priv,const struct wpabuf * beacon,const struct wpabuf * proberesp,const struct wpabuf * assocresp)174 int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
175                                          const struct wpabuf *proberesp,
176                                          const struct wpabuf *assocresp)
177 {
178           return 0;
179 }
180 
181 #endif /* ANDROID_LIB_STUB */
182 #endif /* ANDROID_P2P */
183 
184 
android_nl_socket_set_nonblocking(struct nl_handle * handle)185 int android_nl_socket_set_nonblocking(struct nl_handle *handle)
186 {
187           return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
188 }
189 
190 
191