~awe/wpasupplicant/add-fake-aps

« back to all changes in this revision

Viewing changes to src/p2p/p2p_dev_disc.c

  • Committer: Tony Espy
  • Date: 2015-09-03 17:55:32 UTC
  • Revision ID: espy@canonical.com-20150903175532-7uv6rqya9iqco340
Initial personal branch for feature devel (LP: #1480877).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Wi-Fi Direct - P2P Device Discoverability procedure
 
3
 * Copyright (c) 2010, Atheros Communications
 
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 "common.h"
 
12
#include "common/ieee802_11_defs.h"
 
13
#include "p2p_i.h"
 
14
#include "p2p.h"
 
15
 
 
16
 
 
17
static struct wpabuf * p2p_build_dev_disc_req(struct p2p_data *p2p,
 
18
                                              struct p2p_device *go,
 
19
                                              const u8 *dev_id)
 
20
{
 
21
        struct wpabuf *buf;
 
22
        u8 *len;
 
23
 
 
24
        buf = wpabuf_alloc(100);
 
25
        if (buf == NULL)
 
26
                return NULL;
 
27
 
 
28
        go->dialog_token++;
 
29
        if (go->dialog_token == 0)
 
30
                go->dialog_token = 1;
 
31
        p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_REQ, go->dialog_token);
 
32
 
 
33
        len = p2p_buf_add_ie_hdr(buf);
 
34
        p2p_buf_add_device_id(buf, dev_id);
 
35
        p2p_buf_add_group_id(buf, go->info.p2p_device_addr, go->oper_ssid,
 
36
                             go->oper_ssid_len);
 
37
        p2p_buf_update_ie_hdr(buf, len);
 
38
 
 
39
        return buf;
 
40
}
 
41
 
 
42
 
 
43
void p2p_dev_disc_req_cb(struct p2p_data *p2p, int success)
 
44
{
 
45
        p2p_dbg(p2p, "Device Discoverability Request TX callback: success=%d",
 
46
                success);
 
47
 
 
48
        if (!success) {
 
49
                /*
 
50
                 * Use P2P find, if needed, to find the other device or to
 
51
                 * retry device discoverability.
 
52
                 */
 
53
                p2p_set_state(p2p, P2P_CONNECT);
 
54
                p2p_set_timeout(p2p, 0, 100000);
 
55
                return;
 
56
        }
 
57
 
 
58
        p2p_dbg(p2p, "GO acknowledged Device Discoverability Request - wait for response");
 
59
        /*
 
60
         * TODO: is the remain-on-channel from Action frame TX long enough for
 
61
         * most cases or should we try to increase its duration and/or start
 
62
         * another remain-on-channel if needed once the previous one expires?
 
63
         */
 
64
}
 
65
 
 
66
 
 
67
int p2p_send_dev_disc_req(struct p2p_data *p2p, struct p2p_device *dev)
 
68
{
 
69
        struct p2p_device *go;
 
70
        struct wpabuf *req;
 
71
 
 
72
        go = p2p_get_device(p2p, dev->member_in_go_dev);
 
73
        if (go == NULL || dev->oper_freq <= 0) {
 
74
                p2p_dbg(p2p, "Could not find peer entry for GO and frequency to send Device Discoverability Request");
 
75
                return -1;
 
76
        }
 
77
 
 
78
        req = p2p_build_dev_disc_req(p2p, go, dev->info.p2p_device_addr);
 
79
        if (req == NULL)
 
80
                return -1;
 
81
 
 
82
        p2p_dbg(p2p, "Sending Device Discoverability Request to GO " MACSTR
 
83
                " for client " MACSTR,
 
84
                MAC2STR(go->info.p2p_device_addr),
 
85
                MAC2STR(dev->info.p2p_device_addr));
 
86
 
 
87
        p2p->pending_client_disc_go = go;
 
88
        os_memcpy(p2p->pending_client_disc_addr, dev->info.p2p_device_addr,
 
89
                  ETH_ALEN);
 
90
        p2p->pending_action_state = P2P_PENDING_DEV_DISC_REQUEST;
 
91
        if (p2p_send_action(p2p, dev->oper_freq, go->info.p2p_device_addr,
 
92
                            p2p->cfg->dev_addr, go->info.p2p_device_addr,
 
93
                            wpabuf_head(req), wpabuf_len(req), 1000) < 0) {
 
94
                p2p_dbg(p2p, "Failed to send Action frame");
 
95
                wpabuf_free(req);
 
96
                /* TODO: how to recover from failure? */
 
97
                return -1;
 
98
        }
 
99
 
 
100
        wpabuf_free(req);
 
101
 
 
102
        return 0;
 
103
}
 
104
 
 
105
 
 
106
static struct wpabuf * p2p_build_dev_disc_resp(u8 dialog_token, u8 status)
 
107
{
 
108
        struct wpabuf *buf;
 
109
        u8 *len;
 
110
 
 
111
        buf = wpabuf_alloc(100);
 
112
        if (buf == NULL)
 
113
                return NULL;
 
114
 
 
115
        p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_RESP, dialog_token);
 
116
 
 
117
        len = p2p_buf_add_ie_hdr(buf);
 
118
        p2p_buf_add_status(buf, status);
 
119
        p2p_buf_update_ie_hdr(buf, len);
 
120
 
 
121
        return buf;
 
122
}
 
123
 
 
124
 
 
125
void p2p_dev_disc_resp_cb(struct p2p_data *p2p, int success)
 
126
{
 
127
        p2p_dbg(p2p, "Device Discoverability Response TX callback: success=%d",
 
128
                success);
 
129
        p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 
130
}
 
131
 
 
132
 
 
133
static void p2p_send_dev_disc_resp(struct p2p_data *p2p, u8 dialog_token,
 
134
                                   const u8 *addr, int freq, u8 status)
 
135
{
 
136
        struct wpabuf *resp;
 
137
 
 
138
        resp = p2p_build_dev_disc_resp(dialog_token, status);
 
139
        if (resp == NULL)
 
140
                return;
 
141
 
 
142
        p2p_dbg(p2p, "Sending Device Discoverability Response to " MACSTR
 
143
                " (status %u freq %d)",
 
144
                MAC2STR(addr), status, freq);
 
145
 
 
146
        p2p->pending_action_state = P2P_PENDING_DEV_DISC_RESPONSE;
 
147
        if (p2p_send_action(p2p, freq, addr, p2p->cfg->dev_addr,
 
148
                            p2p->cfg->dev_addr,
 
149
                            wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 
150
                p2p_dbg(p2p, "Failed to send Action frame");
 
151
        }
 
152
 
 
153
        wpabuf_free(resp);
 
154
}
 
155
 
 
156
 
 
157
void p2p_process_dev_disc_req(struct p2p_data *p2p, const u8 *sa,
 
158
                              const u8 *data, size_t len, int rx_freq)
 
159
{
 
160
        struct p2p_message msg;
 
161
        size_t g;
 
162
 
 
163
        p2p_dbg(p2p, "Received Device Discoverability Request from " MACSTR
 
164
                " (freq=%d)", MAC2STR(sa), rx_freq);
 
165
 
 
166
        if (p2p_parse(data, len, &msg))
 
167
                return;
 
168
 
 
169
        if (msg.dialog_token == 0) {
 
170
                p2p_dbg(p2p, "Invalid Dialog Token 0 (must be nonzero) in Device Discoverability Request");
 
171
                p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
 
172
                                       P2P_SC_FAIL_INVALID_PARAMS);
 
173
                p2p_parse_free(&msg);
 
174
                return;
 
175
        }
 
176
 
 
177
        if (msg.device_id == NULL) {
 
178
                p2p_dbg(p2p, "P2P Device ID attribute missing from Device Discoverability Request");
 
179
                p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
 
180
                                       P2P_SC_FAIL_INVALID_PARAMS);
 
181
                p2p_parse_free(&msg);
 
182
                return;
 
183
        }
 
184
 
 
185
        for (g = 0; g < p2p->num_groups; g++) {
 
186
                if (p2p_group_go_discover(p2p->groups[g], msg.device_id, sa,
 
187
                                          rx_freq) == 0) {
 
188
                        p2p_dbg(p2p, "Scheduled GO Discoverability Request for the target device");
 
189
                        /*
 
190
                         * P2P group code will use a callback to indicate TX
 
191
                         * status, so that we can reply to the request once the
 
192
                         * target client has acknowledged the request or it has
 
193
                         * timed out.
 
194
                         */
 
195
                        p2p->pending_dev_disc_dialog_token = msg.dialog_token;
 
196
                        os_memcpy(p2p->pending_dev_disc_addr, sa, ETH_ALEN);
 
197
                        p2p->pending_dev_disc_freq = rx_freq;
 
198
                        p2p_parse_free(&msg);
 
199
                        return;
 
200
                }
 
201
        }
 
202
 
 
203
        p2p_dbg(p2p, "Requested client was not found in any group or did not support client discoverability");
 
204
        p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq,
 
205
                               P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE);
 
206
        p2p_parse_free(&msg);
 
207
}
 
208
 
 
209
 
 
210
void p2p_process_dev_disc_resp(struct p2p_data *p2p, const u8 *sa,
 
211
                               const u8 *data, size_t len)
 
212
{
 
213
        struct p2p_message msg;
 
214
        struct p2p_device *go;
 
215
        u8 status;
 
216
 
 
217
        p2p_dbg(p2p, "Received Device Discoverability Response from " MACSTR,
 
218
                MAC2STR(sa));
 
219
 
 
220
        go = p2p->pending_client_disc_go;
 
221
        if (go == NULL ||
 
222
            os_memcmp(sa, go->info.p2p_device_addr, ETH_ALEN) != 0) {
 
223
                p2p_dbg(p2p, "Ignore unexpected Device Discoverability Response");
 
224
                return;
 
225
        }
 
226
 
 
227
        if (p2p_parse(data, len, &msg))
 
228
                return;
 
229
 
 
230
        if (msg.status == NULL) {
 
231
                p2p_parse_free(&msg);
 
232
                return;
 
233
        }
 
234
 
 
235
        if (msg.dialog_token != go->dialog_token) {
 
236
                p2p_dbg(p2p, "Ignore Device Discoverability Response with unexpected dialog token %u (expected %u)",
 
237
                        msg.dialog_token, go->dialog_token);
 
238
                p2p_parse_free(&msg);
 
239
                return;
 
240
        }
 
241
 
 
242
        status = *msg.status;
 
243
        p2p_parse_free(&msg);
 
244
 
 
245
        p2p_dbg(p2p, "Device Discoverability Response status %u", status);
 
246
 
 
247
        if (p2p->go_neg_peer == NULL ||
 
248
            os_memcmp(p2p->pending_client_disc_addr,
 
249
                      p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) != 0 ||
 
250
            os_memcmp(p2p->go_neg_peer->member_in_go_dev,
 
251
                      go->info.p2p_device_addr, ETH_ALEN) != 0) {
 
252
                p2p_dbg(p2p, "No pending operation with the client discoverability peer anymore");
 
253
                return;
 
254
        }
 
255
 
 
256
        if (status == 0) {
 
257
                /*
 
258
                 * Peer is expected to be awake for at least 100 TU; try to
 
259
                 * connect immediately.
 
260
                 */
 
261
                p2p_dbg(p2p, "Client discoverability request succeeded");
 
262
                if (p2p->state == P2P_CONNECT) {
 
263
                        /*
 
264
                         * Change state to force the timeout to start in
 
265
                         * P2P_CONNECT again without going through the short
 
266
                         * Listen state.
 
267
                         */
 
268
                        p2p_set_state(p2p, P2P_CONNECT_LISTEN);
 
269
                        p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 
270
                }
 
271
                p2p_set_timeout(p2p, 0, 0);
 
272
        } else {
 
273
                /*
 
274
                 * Client discoverability request failed; try to connect from
 
275
                 * timeout.
 
276
                 */
 
277
                p2p_dbg(p2p, "Client discoverability request failed");
 
278
                p2p_set_timeout(p2p, 0, 500000);
 
279
        }
 
280
 
 
281
}
 
282
 
 
283
 
 
284
void p2p_go_disc_req_cb(struct p2p_data *p2p, int success)
 
285
{
 
286
        p2p_dbg(p2p, "GO Discoverability Request TX callback: success=%d",
 
287
                success);
 
288
        p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
 
289
 
 
290
        if (p2p->pending_dev_disc_dialog_token == 0) {
 
291
                p2p_dbg(p2p, "No pending Device Discoverability Request");
 
292
                return;
 
293
        }
 
294
 
 
295
        p2p_send_dev_disc_resp(p2p, p2p->pending_dev_disc_dialog_token,
 
296
                               p2p->pending_dev_disc_addr,
 
297
                               p2p->pending_dev_disc_freq,
 
298
                               success ? P2P_SC_SUCCESS :
 
299
                               P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE);
 
300
 
 
301
        p2p->pending_dev_disc_dialog_token = 0;
 
302
}
 
303
 
 
304
 
 
305
void p2p_process_go_disc_req(struct p2p_data *p2p, const u8 *da, const u8 *sa,
 
306
                             const u8 *data, size_t len, int rx_freq)
 
307
{
 
308
        unsigned int tu;
 
309
        struct wpabuf *ies;
 
310
 
 
311
        p2p_dbg(p2p, "Received GO Discoverability Request - remain awake for 100 TU");
 
312
 
 
313
        ies = p2p_build_probe_resp_ies(p2p);
 
314
        if (ies == NULL)
 
315
                return;
 
316
 
 
317
        /* Remain awake 100 TU on operating channel */
 
318
        p2p->pending_client_disc_freq = rx_freq;
 
319
        tu = 100;
 
320
        if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, rx_freq, 1024 * tu / 1000,
 
321
                    ies) < 0) {
 
322
                p2p_dbg(p2p, "Failed to start listen mode for client discoverability");
 
323
        }
 
324
        wpabuf_free(ies);
 
325
}