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