• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Control interface for shared AP commands
3  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "hostapd.h"
14 #include "ieee802_1x.h"
15 #include "wpa_auth.h"
16 #include "ieee802_11.h"
17 #include "sta_info.h"
18 #include "wps_hostapd.h"
19 #include "p2p_hostapd.h"
20 #include "ctrl_iface_ap.h"
21 #include "ap_drv_ops.h"
22 
23 
hostapd_ctrl_iface_sta_mib(struct hostapd_data * hapd,struct sta_info * sta,char * buf,size_t buflen)24 static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
25 				      struct sta_info *sta,
26 				      char *buf, size_t buflen)
27 {
28 	int len, res, ret;
29 
30 	if (sta == NULL) {
31 		ret = os_snprintf(buf, buflen, "FAIL\n");
32 		if (ret < 0 || (size_t) ret >= buflen)
33 			return 0;
34 		return ret;
35 	}
36 
37 	len = 0;
38 	ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
39 			  MAC2STR(sta->addr));
40 	if (ret < 0 || (size_t) ret >= buflen - len)
41 		return len;
42 	len += ret;
43 
44 	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
45 	if (res >= 0)
46 		len += res;
47 	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
48 	if (res >= 0)
49 		len += res;
50 	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
51 	if (res >= 0)
52 		len += res;
53 	res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
54 				      buflen - len);
55 	if (res >= 0)
56 		len += res;
57 	res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
58 	if (res >= 0)
59 		len += res;
60 
61 	return len;
62 }
63 
64 
hostapd_ctrl_iface_sta_first(struct hostapd_data * hapd,char * buf,size_t buflen)65 int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
66 				 char *buf, size_t buflen)
67 {
68 	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
69 }
70 
71 
hostapd_ctrl_iface_sta(struct hostapd_data * hapd,const char * txtaddr,char * buf,size_t buflen)72 int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
73 			   char *buf, size_t buflen)
74 {
75 	u8 addr[ETH_ALEN];
76 	int ret;
77 
78 	if (hwaddr_aton(txtaddr, addr)) {
79 		ret = os_snprintf(buf, buflen, "FAIL\n");
80 		if (ret < 0 || (size_t) ret >= buflen)
81 			return 0;
82 		return ret;
83 	}
84 	return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
85 					  buf, buflen);
86 }
87 
88 
hostapd_ctrl_iface_sta_next(struct hostapd_data * hapd,const char * txtaddr,char * buf,size_t buflen)89 int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
90 				char *buf, size_t buflen)
91 {
92 	u8 addr[ETH_ALEN];
93 	struct sta_info *sta;
94 	int ret;
95 
96 	if (hwaddr_aton(txtaddr, addr) ||
97 	    (sta = ap_get_sta(hapd, addr)) == NULL) {
98 		ret = os_snprintf(buf, buflen, "FAIL\n");
99 		if (ret < 0 || (size_t) ret >= buflen)
100 			return 0;
101 		return ret;
102 	}
103 	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
104 }
105 
106 
107 #ifdef CONFIG_P2P_MANAGER
p2p_manager_disconnect(struct hostapd_data * hapd,u16 stype,u8 minor_reason_code,const u8 * addr)108 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
109 				  u8 minor_reason_code, const u8 *addr)
110 {
111 	struct ieee80211_mgmt *mgmt;
112 	int ret;
113 	u8 *pos;
114 
115 	if (hapd->driver->send_frame == NULL)
116 		return -1;
117 
118 	mgmt = os_zalloc(sizeof(*mgmt) + 100);
119 	if (mgmt == NULL)
120 		return -1;
121 
122 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
123 		" with minor reason code %u (stype=%u)",
124 		MAC2STR(addr), minor_reason_code, stype);
125 
126 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
127 	os_memcpy(mgmt->da, addr, ETH_ALEN);
128 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
129 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
130 	if (stype == WLAN_FC_STYPE_DEAUTH) {
131 		mgmt->u.deauth.reason_code =
132 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
133 		pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
134 	} else {
135 		mgmt->u.disassoc.reason_code =
136 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
137 		pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
138 	}
139 
140 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
141 	*pos++ = 4 + 3 + 1;
142 	WPA_PUT_BE24(pos, OUI_WFA);
143 	pos += 3;
144 	*pos++ = P2P_OUI_TYPE;
145 
146 	*pos++ = P2P_ATTR_MINOR_REASON_CODE;
147 	WPA_PUT_LE16(pos, 1);
148 	pos += 2;
149 	*pos++ = minor_reason_code;
150 
151 	ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
152 				       pos - (u8 *) mgmt, 1);
153 	os_free(mgmt);
154 
155 	return ret < 0 ? -1 : 0;
156 }
157 #endif /* CONFIG_P2P_MANAGER */
158 
159 
hostapd_ctrl_iface_deauthenticate(struct hostapd_data * hapd,const char * txtaddr)160 int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
161 				      const char *txtaddr)
162 {
163 	u8 addr[ETH_ALEN];
164 	struct sta_info *sta;
165 	const char *pos;
166 
167 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
168 		txtaddr);
169 
170 	if (hwaddr_aton(txtaddr, addr))
171 		return -1;
172 
173 	pos = os_strstr(txtaddr, " test=");
174 	if (pos) {
175 		struct ieee80211_mgmt mgmt;
176 		int encrypt;
177 		if (hapd->driver->send_frame == NULL)
178 			return -1;
179 		pos += 6;
180 		encrypt = atoi(pos);
181 		os_memset(&mgmt, 0, sizeof(mgmt));
182 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
183 						  WLAN_FC_STYPE_DEAUTH);
184 		os_memcpy(mgmt.da, addr, ETH_ALEN);
185 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
186 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
187 		mgmt.u.deauth.reason_code =
188 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
189 		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
190 					     IEEE80211_HDRLEN +
191 					     sizeof(mgmt.u.deauth),
192 					     encrypt) < 0)
193 			return -1;
194 		return 0;
195 	}
196 
197 #ifdef CONFIG_P2P_MANAGER
198 	pos = os_strstr(txtaddr, " p2p=");
199 	if (pos) {
200 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
201 					      atoi(pos + 5), addr);
202 	}
203 #endif /* CONFIG_P2P_MANAGER */
204 
205 	hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
206 	sta = ap_get_sta(hapd, addr);
207 	if (sta)
208 		ap_sta_deauthenticate(hapd, sta,
209 				      WLAN_REASON_PREV_AUTH_NOT_VALID);
210 	else if (addr[0] == 0xff)
211 		hostapd_free_stas(hapd);
212 
213 	return 0;
214 }
215 
216 
hostapd_ctrl_iface_disassociate(struct hostapd_data * hapd,const char * txtaddr)217 int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
218 				    const char *txtaddr)
219 {
220 	u8 addr[ETH_ALEN];
221 	struct sta_info *sta;
222 	const char *pos;
223 
224 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
225 		txtaddr);
226 
227 	if (hwaddr_aton(txtaddr, addr))
228 		return -1;
229 
230 	pos = os_strstr(txtaddr, " test=");
231 	if (pos) {
232 		struct ieee80211_mgmt mgmt;
233 		int encrypt;
234 		if (hapd->driver->send_frame == NULL)
235 			return -1;
236 		pos += 6;
237 		encrypt = atoi(pos);
238 		os_memset(&mgmt, 0, sizeof(mgmt));
239 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
240 						  WLAN_FC_STYPE_DISASSOC);
241 		os_memcpy(mgmt.da, addr, ETH_ALEN);
242 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
243 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
244 		mgmt.u.disassoc.reason_code =
245 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
246 		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
247 					     IEEE80211_HDRLEN +
248 					     sizeof(mgmt.u.deauth),
249 					     encrypt) < 0)
250 			return -1;
251 		return 0;
252 	}
253 
254 #ifdef CONFIG_P2P_MANAGER
255 	pos = os_strstr(txtaddr, " p2p=");
256 	if (pos) {
257 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
258 					      atoi(pos + 5), addr);
259 	}
260 #endif /* CONFIG_P2P_MANAGER */
261 
262 	hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
263 	sta = ap_get_sta(hapd, addr);
264 	if (sta)
265 		ap_sta_disassociate(hapd, sta,
266 				    WLAN_REASON_PREV_AUTH_NOT_VALID);
267 	else if (addr[0] == 0xff)
268 		hostapd_free_stas(hapd);
269 
270 	return 0;
271 }
272