mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-02-22 11:53:06 -05:00
Add a driver op for enabling Probe Request reporting in station mode
This commit is contained in:
parent
9646a8ab8b
commit
504e905c6e
@ -1518,6 +1518,22 @@ struct wpa_driver_ops {
|
|||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
|
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* probe_req_report - Request Probe Request frames to be indicated
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @report: Whether to report received Probe Request frames
|
||||||
|
* Returns: 0 on success, -1 on failure (or if not supported)
|
||||||
|
*
|
||||||
|
* This command can be used to request the driver to indicate when
|
||||||
|
* Probe Request frames are received with EVENT_RX_PROBE_REQ events.
|
||||||
|
* Since this operation may require extra resources, e.g., due to less
|
||||||
|
* optimal hardware/firmware RX filtering, many drivers may disable
|
||||||
|
* Probe Request reporting at least in station mode. This command is
|
||||||
|
* used to notify the driver when the Probe Request frames need to be
|
||||||
|
* reported, e.g., during remain-on-channel operations.
|
||||||
|
*/
|
||||||
|
int (*probe_req_report)(void *priv, int report);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1732,7 +1748,11 @@ enum wpa_event_type {
|
|||||||
*
|
*
|
||||||
* This event is used to indicate when a Probe Request frame has been
|
* This event is used to indicate when a Probe Request frame has been
|
||||||
* received. Information about the received frame is included in
|
* received. Information about the received frame is included in
|
||||||
* union wpa_event_data::rx_probe_req.
|
* union wpa_event_data::rx_probe_req. The driver is required to report
|
||||||
|
* these events only after successfully completed probe_req_report()
|
||||||
|
* commands to request the events (i.e., report parameter is non-zero)
|
||||||
|
* in station mode. In AP mode, Probe Request frames should always be
|
||||||
|
* reported.
|
||||||
*/
|
*/
|
||||||
EVENT_RX_PROBE_REQ
|
EVENT_RX_PROBE_REQ
|
||||||
};
|
};
|
||||||
|
@ -3245,5 +3245,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
|||||||
NULL /* set_ht_params */,
|
NULL /* set_ht_params */,
|
||||||
NULL /* set_ap_wps_ie */,
|
NULL /* set_ap_wps_ie */,
|
||||||
NULL /* set_supp_port */,
|
NULL /* set_supp_port */,
|
||||||
NULL /* set_wds_sta */
|
NULL /* set_wds_sta */,
|
||||||
|
NULL /* probe_req_report */
|
||||||
};
|
};
|
||||||
|
@ -95,6 +95,7 @@ struct wpa_driver_nl80211_data {
|
|||||||
|
|
||||||
int monitor_sock;
|
int monitor_sock;
|
||||||
int monitor_ifidx;
|
int monitor_ifidx;
|
||||||
|
int probe_req_report;
|
||||||
|
|
||||||
unsigned int beacon_set:1;
|
unsigned int beacon_set:1;
|
||||||
|
|
||||||
@ -134,6 +135,9 @@ static int wpa_driver_nl80211_if_remove(void *priv,
|
|||||||
const char *ifname);
|
const char *ifname);
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
|
static void wpa_driver_nl80211_probe_req_report_timeout(void *eloop_ctx,
|
||||||
|
void *timeout_ctx);
|
||||||
|
|
||||||
|
|
||||||
/* nl80211 code */
|
/* nl80211 code */
|
||||||
static int ack_handler(struct nl_msg *msg, void *arg)
|
static int ack_handler(struct nl_msg *msg, void *arg)
|
||||||
@ -1292,10 +1296,6 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
|||||||
struct wpa_driver_nl80211_data *drv = priv;
|
struct wpa_driver_nl80211_data *drv = priv;
|
||||||
|
|
||||||
nl80211_remove_monitor_interface(drv);
|
nl80211_remove_monitor_interface(drv);
|
||||||
if (drv->monitor_sock >= 0) {
|
|
||||||
eloop_unregister_read_sock(drv->monitor_sock);
|
|
||||||
close(drv->monitor_sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drv->nlmode == NL80211_IFTYPE_AP)
|
if (drv->nlmode == NL80211_IFTYPE_AP)
|
||||||
wpa_driver_nl80211_del_beacon(drv);
|
wpa_driver_nl80211_del_beacon(drv);
|
||||||
@ -1339,6 +1339,9 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
|||||||
nl_handle_destroy(drv->nl_handle_event);
|
nl_handle_destroy(drv->nl_handle_event);
|
||||||
nl_cb_put(drv->nl_cb);
|
nl_cb_put(drv->nl_cb);
|
||||||
|
|
||||||
|
eloop_cancel_timeout(wpa_driver_nl80211_probe_req_report_timeout,
|
||||||
|
drv, NULL);
|
||||||
|
|
||||||
os_free(drv);
|
os_free(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2772,6 +2775,12 @@ static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drv->nlmode == NL80211_IFTYPE_STATION && !drv->probe_req_report) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Ignore monitor interface "
|
||||||
|
"frame since Probe Request reporting is disabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
|
if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
|
||||||
printf("received invalid radiotap frame\n");
|
printf("received invalid radiotap frame\n");
|
||||||
return;
|
return;
|
||||||
@ -2975,6 +2984,11 @@ static void nl80211_remove_monitor_interface(
|
|||||||
nl80211_remove_iface(drv, drv->monitor_ifidx);
|
nl80211_remove_iface(drv, drv->monitor_ifidx);
|
||||||
drv->monitor_ifidx = -1;
|
drv->monitor_ifidx = -1;
|
||||||
}
|
}
|
||||||
|
if (drv->monitor_sock >= 0) {
|
||||||
|
eloop_unregister_read_sock(drv->monitor_sock);
|
||||||
|
close(drv->monitor_sock);
|
||||||
|
drv->monitor_sock = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4403,6 +4417,62 @@ static int wpa_driver_nl80211_if_remove(void *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_nl80211_probe_req_report_timeout(void *eloop_ctx,
|
||||||
|
void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||||
|
if (drv->monitor_ifidx < 0)
|
||||||
|
return; /* monitor interface already removed */
|
||||||
|
|
||||||
|
if (drv->nlmode != NL80211_IFTYPE_STATION)
|
||||||
|
return; /* not in station mode anymore */
|
||||||
|
|
||||||
|
if (drv->probe_req_report)
|
||||||
|
return; /* reporting enabled */
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Remove monitor interface due to no "
|
||||||
|
"Probe Request reporting needed anymore");
|
||||||
|
nl80211_remove_monitor_interface(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = priv;
|
||||||
|
|
||||||
|
if (drv->nlmode != NL80211_IFTYPE_STATION) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
|
||||||
|
"allowed in station mode (iftype=%d)",
|
||||||
|
drv->nlmode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
drv->probe_req_report = report;
|
||||||
|
|
||||||
|
if (report) {
|
||||||
|
eloop_cancel_timeout(
|
||||||
|
wpa_driver_nl80211_probe_req_report_timeout,
|
||||||
|
drv, NULL);
|
||||||
|
if (drv->monitor_ifidx < 0 &&
|
||||||
|
nl80211_create_monitor_interface(drv))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* It takes a while to remove the monitor interface, so try to
|
||||||
|
* avoid doing this if it is needed again shortly. Instead,
|
||||||
|
* schedule the interface to be removed later if no need for it
|
||||||
|
* is seen.
|
||||||
|
*/
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Scheduling monitor interface "
|
||||||
|
"to be removed after 10 seconds of no use");
|
||||||
|
eloop_register_timeout(
|
||||||
|
10, 0, wpa_driver_nl80211_probe_req_report_timeout,
|
||||||
|
drv, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.name = "nl80211",
|
.name = "nl80211",
|
||||||
.desc = "Linux nl80211/cfg80211",
|
.desc = "Linux nl80211/cfg80211",
|
||||||
@ -4451,4 +4521,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||||||
.set_sta_vlan = i802_set_sta_vlan,
|
.set_sta_vlan = i802_set_sta_vlan,
|
||||||
.set_wds_sta = i802_set_wds_sta,
|
.set_wds_sta = i802_set_wds_sta,
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
.probe_req_report = wpa_driver_nl80211_probe_req_report,
|
||||||
};
|
};
|
||||||
|
@ -100,6 +100,8 @@ struct wpa_driver_test_data {
|
|||||||
struct test_client_socket *cli;
|
struct test_client_socket *cli;
|
||||||
struct test_driver_bss *bss;
|
struct test_driver_bss *bss;
|
||||||
int udp_port;
|
int udp_port;
|
||||||
|
|
||||||
|
int probe_req_report;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1779,6 +1781,24 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
|
|||||||
event.mlme_rx.buf = data;
|
event.mlme_rx.buf = data;
|
||||||
event.mlme_rx.len = data_len;
|
event.mlme_rx.len = data_len;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event);
|
wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event);
|
||||||
|
|
||||||
|
if (drv->probe_req_report && data_len >= 24) {
|
||||||
|
const struct ieee80211_mgmt *mgmt;
|
||||||
|
u16 fc;
|
||||||
|
|
||||||
|
mgmt = (const struct ieee80211_mgmt *) data;
|
||||||
|
fc = le_to_host16(mgmt->frame_control);
|
||||||
|
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
||||||
|
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) {
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
event.rx_probe_req.sa = mgmt->sa;
|
||||||
|
event.rx_probe_req.ie = mgmt->u.probe_req.variable;
|
||||||
|
event.rx_probe_req.ie_len =
|
||||||
|
data_len - (mgmt->u.probe_req.variable - data);
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
|
||||||
|
&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2442,6 +2462,15 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_probe_req_report(void *priv, int report)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
wpa_printf(MSG_DEBUG, "%s(report=%d)", __func__, report);
|
||||||
|
drv->probe_req_report = report;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_test_ops = {
|
const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
"test",
|
"test",
|
||||||
"wpa_supplicant test driver",
|
"wpa_supplicant test driver",
|
||||||
@ -2485,4 +2514,5 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
|||||||
.init2 = wpa_driver_test_init2,
|
.init2 = wpa_driver_test_init2,
|
||||||
.get_interfaces = wpa_driver_test_get_interfaces,
|
.get_interfaces = wpa_driver_test_get_interfaces,
|
||||||
.scan2 = wpa_driver_test_scan,
|
.scan2 = wpa_driver_test_scan,
|
||||||
|
.probe_req_report = wpa_driver_test_probe_req_report,
|
||||||
};
|
};
|
||||||
|
@ -383,4 +383,13 @@ static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_probe_req_report(struct wpa_supplicant *wpa_s,
|
||||||
|
int report)
|
||||||
|
{
|
||||||
|
if (wpa_s->driver->probe_req_report)
|
||||||
|
return wpa_s->driver->probe_req_report(wpa_s->drv_priv,
|
||||||
|
report);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DRIVER_I_H */
|
#endif /* DRIVER_I_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user