xref: /freebsd-src/contrib/wpa/wpa_supplicant/twt.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
1*c1d255d3SCy Schubert /*
2*c1d255d3SCy Schubert  * wpa_supplicant - TWT
3*c1d255d3SCy Schubert  * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
4*c1d255d3SCy Schubert  *
5*c1d255d3SCy Schubert  * This software may be distributed under the terms of the BSD license.
6*c1d255d3SCy Schubert  * See README for more details.
7*c1d255d3SCy Schubert  */
8*c1d255d3SCy Schubert 
9*c1d255d3SCy Schubert #include "includes.h"
10*c1d255d3SCy Schubert 
11*c1d255d3SCy Schubert #include "utils/common.h"
12*c1d255d3SCy Schubert #include "wpa_supplicant_i.h"
13*c1d255d3SCy Schubert #include "driver_i.h"
14*c1d255d3SCy Schubert 
15*c1d255d3SCy Schubert 
16*c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS
17*c1d255d3SCy Schubert 
18*c1d255d3SCy Schubert /**
19*c1d255d3SCy Schubert  * wpas_twt_send_setup - Send TWT Setup frame (Request) to our AP
20*c1d255d3SCy Schubert  * @wpa_s: Pointer to wpa_supplicant
21*c1d255d3SCy Schubert  * @dtok: Dialog token
22*c1d255d3SCy Schubert  * @exponent: Wake-interval exponent
23*c1d255d3SCy Schubert  * @mantissa: Wake-interval mantissa
24*c1d255d3SCy Schubert  * @min_twt: Minimum TWT wake duration in units of 256 usec
25*c1d255d3SCy Schubert  * @setup_cmd: 0 == request, 1 == suggest, etc.  Table 9-297
26*c1d255d3SCy Schubert  * Returns: 0 in case of success, negative error code otherwise
27*c1d255d3SCy Schubert  *
28*c1d255d3SCy Schubert  */
wpas_twt_send_setup(struct wpa_supplicant * wpa_s,u8 dtok,int exponent,int mantissa,u8 min_twt,int setup_cmd,u64 twt,bool requestor,bool trigger,bool implicit,bool flow_type,u8 flow_id,bool protection,u8 twt_channel,u8 control)29*c1d255d3SCy Schubert int wpas_twt_send_setup(struct wpa_supplicant *wpa_s, u8 dtok, int exponent,
30*c1d255d3SCy Schubert 			int mantissa, u8 min_twt, int setup_cmd, u64 twt,
31*c1d255d3SCy Schubert 			bool requestor, bool trigger, bool implicit,
32*c1d255d3SCy Schubert 			bool flow_type, u8 flow_id, bool protection,
33*c1d255d3SCy Schubert 			u8 twt_channel, u8 control)
34*c1d255d3SCy Schubert {
35*c1d255d3SCy Schubert 	struct wpabuf *buf;
36*c1d255d3SCy Schubert 	u16 req_type = 0;
37*c1d255d3SCy Schubert 	int ret = 0;
38*c1d255d3SCy Schubert 
39*c1d255d3SCy Schubert 	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
40*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
41*c1d255d3SCy Schubert 			   "TWT: No connection - cannot send TWT Setup frame");
42*c1d255d3SCy Schubert 		return -ENOTCONN;
43*c1d255d3SCy Schubert 	}
44*c1d255d3SCy Schubert 
45*c1d255d3SCy Schubert 	/* 3 = Action category + Action code + Dialog token */
46*c1d255d3SCy Schubert 	/* 17 = TWT element */
47*c1d255d3SCy Schubert 	buf = wpabuf_alloc(3 + 17);
48*c1d255d3SCy Schubert 	if (!buf) {
49*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
50*c1d255d3SCy Schubert 			   "TWT: Failed to allocate TWT Setup frame (Request)");
51*c1d255d3SCy Schubert 		return -ENOMEM;
52*c1d255d3SCy Schubert 	}
53*c1d255d3SCy Schubert 
54*c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG,
55*c1d255d3SCy Schubert 		   "TWT: Setup request, dtok: %d  exponent: %d  mantissa: %d  min-twt: %d",
56*c1d255d3SCy Schubert 		   dtok, exponent, mantissa, min_twt);
57*c1d255d3SCy Schubert 
58*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
59*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, S1G_ACT_TWT_SETUP);
60*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, dtok);
61*c1d255d3SCy Schubert 
62*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, WLAN_EID_TWT);
63*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, 15); /* len */
64*c1d255d3SCy Schubert 
65*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, control);
66*c1d255d3SCy Schubert 
67*c1d255d3SCy Schubert 	if (requestor)
68*c1d255d3SCy Schubert 		req_type |= BIT(0); /* This STA is a TWT Requesting STA */
69*c1d255d3SCy Schubert 	/* TWT Setup Command field */
70*c1d255d3SCy Schubert 	req_type |= (setup_cmd & 0x7) << 1;
71*c1d255d3SCy Schubert 	if (trigger)
72*c1d255d3SCy Schubert 		req_type |= BIT(4); /* TWT SP includes trigger frames */
73*c1d255d3SCy Schubert 	if (implicit)
74*c1d255d3SCy Schubert 		req_type |= BIT(5); /* Implicit TWT */
75*c1d255d3SCy Schubert 	if (flow_type)
76*c1d255d3SCy Schubert 		req_type |= BIT(6); /* Flow Type: Unannounced TWT */
77*c1d255d3SCy Schubert 	req_type |= (flow_id & 0x7) << 7;
78*c1d255d3SCy Schubert 	req_type |= (exponent & 0x1f) << 10; /* TWT Wake Interval Exponent */
79*c1d255d3SCy Schubert 	if (protection)
80*c1d255d3SCy Schubert 		req_type |= BIT(15);
81*c1d255d3SCy Schubert 	wpabuf_put_le16(buf, req_type);
82*c1d255d3SCy Schubert 	wpabuf_put_le64(buf, twt);
83*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, min_twt); /* Nominal Minimum TWT Wake Duration */
84*c1d255d3SCy Schubert 	wpabuf_put_le16(buf, mantissa); /* TWT Wake Interval Mantissa */
85*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, twt_channel); /* TWT Channel */
86*c1d255d3SCy Schubert 
87*c1d255d3SCy Schubert 	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
88*c1d255d3SCy Schubert 				wpa_s->own_addr, wpa_s->bssid,
89*c1d255d3SCy Schubert 				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
90*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Setup Request");
91*c1d255d3SCy Schubert 		ret = -ECANCELED;
92*c1d255d3SCy Schubert 	}
93*c1d255d3SCy Schubert 
94*c1d255d3SCy Schubert 	wpabuf_free(buf);
95*c1d255d3SCy Schubert 	return ret;
96*c1d255d3SCy Schubert }
97*c1d255d3SCy Schubert 
98*c1d255d3SCy Schubert 
99*c1d255d3SCy Schubert /**
100*c1d255d3SCy Schubert  * wpas_twt_send_teardown - Send TWT teardown request to our AP
101*c1d255d3SCy Schubert  * @wpa_s: Pointer to wpa_supplicant
102*c1d255d3SCy Schubert  * @flags: The byte that goes inside the TWT Teardown element
103*c1d255d3SCy Schubert  * Returns: 0 in case of success, negative error code otherwise
104*c1d255d3SCy Schubert  *
105*c1d255d3SCy Schubert  */
wpas_twt_send_teardown(struct wpa_supplicant * wpa_s,u8 flags)106*c1d255d3SCy Schubert int wpas_twt_send_teardown(struct wpa_supplicant *wpa_s, u8 flags)
107*c1d255d3SCy Schubert {
108*c1d255d3SCy Schubert 	struct wpabuf *buf;
109*c1d255d3SCy Schubert 	int ret = 0;
110*c1d255d3SCy Schubert 
111*c1d255d3SCy Schubert 	if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) {
112*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
113*c1d255d3SCy Schubert 			   "TWT: No connection - cannot send TWT Teardown frame");
114*c1d255d3SCy Schubert 		return -ENOTCONN;
115*c1d255d3SCy Schubert 	}
116*c1d255d3SCy Schubert 
117*c1d255d3SCy Schubert 	/* 3 = Action category + Action code + flags */
118*c1d255d3SCy Schubert 	buf = wpabuf_alloc(3);
119*c1d255d3SCy Schubert 	if (!buf) {
120*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG,
121*c1d255d3SCy Schubert 			   "TWT: Failed to allocate TWT Teardown frame");
122*c1d255d3SCy Schubert 		return -ENOMEM;
123*c1d255d3SCy Schubert 	}
124*c1d255d3SCy Schubert 
125*c1d255d3SCy Schubert 	wpa_printf(MSG_DEBUG, "TWT: Teardown request, flags: 0x%x", flags);
126*c1d255d3SCy Schubert 
127*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, WLAN_ACTION_S1G);
128*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, S1G_ACT_TWT_TEARDOWN);
129*c1d255d3SCy Schubert 	wpabuf_put_u8(buf, flags);
130*c1d255d3SCy Schubert 
131*c1d255d3SCy Schubert 	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
132*c1d255d3SCy Schubert 				wpa_s->own_addr, wpa_s->bssid,
133*c1d255d3SCy Schubert 				wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
134*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "TWT: Failed to send TWT Teardown frame");
135*c1d255d3SCy Schubert 		ret = -ECANCELED;
136*c1d255d3SCy Schubert 	}
137*c1d255d3SCy Schubert 
138*c1d255d3SCy Schubert 	wpabuf_free(buf);
139*c1d255d3SCy Schubert 	return ret;
140*c1d255d3SCy Schubert }
141*c1d255d3SCy Schubert 
142*c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */
143