TDLS: Implement low-ack event for lost TDLS peers
[mech_eap.git] / src / rsn_supp / tdls.c
1 /*
2  * wpa_supplicant - TDLS
3  * Copyright (c) 2010-2011, Atheros Communications
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "utils/eloop.h"
19 #include "utils/os.h"
20 #include "common/ieee802_11_defs.h"
21 #include "crypto/sha256.h"
22 #include "crypto/crypto.h"
23 #include "crypto/aes_wrap.h"
24 #include "rsn_supp/wpa.h"
25 #include "rsn_supp/wpa_ie.h"
26 #include "rsn_supp/wpa_i.h"
27 #include "drivers/driver.h"
28 #include "l2_packet/l2_packet.h"
29
30 #ifdef CONFIG_TDLS_TESTING
31 #define TDLS_TESTING_LONG_FRAME BIT(0)
32 #define TDLS_TESTING_ALT_RSN_IE BIT(1)
33 #define TDLS_TESTING_DIFF_BSSID BIT(2)
34 #define TDLS_TESTING_SHORT_LIFETIME BIT(3)
35 #define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4)
36 #define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5)
37 #define TDLS_TESTING_LONG_LIFETIME BIT(6)
38 #define TDLS_TESTING_CONCURRENT_INIT BIT(7)
39 #define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8)
40 #define TDLS_TESTING_DECLINE_RESP BIT(9)
41 #define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10)
42 unsigned int tdls_testing = 0;
43 #endif /* CONFIG_TDLS_TESTING */
44
45 #define TPK_LIFETIME 43200 /* 12 hours */
46 #define TPK_RETRY_COUNT 3
47 #define TPK_TIMEOUT 5000 /* in milliseconds */
48
49 #define TDLS_MIC_LEN            16
50
51 #define TDLS_TIMEOUT_LEN        4
52
53 struct wpa_tdls_ftie {
54         u8 ie_type; /* FTIE */
55         u8 ie_len;
56         u8 mic_ctrl[2];
57         u8 mic[TDLS_MIC_LEN];
58         u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */
59         u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */
60         /* followed by optional elements */
61 } STRUCT_PACKED;
62
63 struct wpa_tdls_timeoutie {
64         u8 ie_type; /* Timeout IE */
65         u8 ie_len;
66         u8 interval_type;
67         u8 value[TDLS_TIMEOUT_LEN];
68 } STRUCT_PACKED;
69
70 struct wpa_tdls_lnkid {
71         u8 ie_type; /* Link Identifier IE */
72         u8 ie_len;
73         u8 bssid[ETH_ALEN];
74         u8 init_sta[ETH_ALEN];
75         u8 resp_sta[ETH_ALEN];
76 } STRUCT_PACKED;
77
78 /* TDLS frame headers as per IEEE Std 802.11z-2010 */
79 struct wpa_tdls_frame {
80         u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */
81         u8 category; /* Category */
82         u8 action; /* Action (enum tdls_frame_type) */
83 } STRUCT_PACKED;
84
85 static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs);
86 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx);
87 static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
88
89
90 #define TDLS_MAX_IE_LEN 80
91 struct wpa_tdls_peer {
92         struct wpa_tdls_peer *next;
93         int initiator; /* whether this end was initiator for TDLS setup */
94         u8 addr[ETH_ALEN]; /* other end MAC address */
95         u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
96         u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */
97         u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */
98         size_t rsnie_i_len;
99         u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */
100         size_t rsnie_p_len;
101         u32 lifetime;
102         int cipher; /* Selected cipher (WPA_CIPHER_*) */
103         u8 dtoken;
104
105         struct tpk {
106                 u8 kck[16]; /* TPK-KCK */
107                 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
108         } tpk;
109         int tpk_set;
110         int tpk_success;
111
112         struct tpk_timer {
113                 u8 dest[ETH_ALEN];
114                 int count;      /* Retry Count */
115                 int timer;      /* Timeout in milliseconds */
116                 u8 action_code; /* TDLS frame type */
117                 u8 dialog_token;
118                 u16 status_code;
119                 int buf_len;    /* length of TPK message for retransmission */
120                 u8 *buf;        /* buffer for TPK message */
121         } sm_tmr;
122 };
123
124
125 static int wpa_tdls_get_privacy(struct wpa_sm *sm)
126 {
127         /*
128          * Get info needed from supplicant to check if the current BSS supports
129          * security. Other than OPEN mode, rest are considered secured
130          * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
131          */
132         return sm->pairwise_cipher != WPA_CIPHER_NONE;
133 }
134
135
136 static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
137 {
138         os_memcpy(pos, ie, ie_len);
139         return pos + ie_len;
140 }
141
142
143 static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
144 {
145         if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
146                            0, 0, NULL, 0, NULL, 0) < 0) {
147                 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
148                            "the driver");
149                 return -1;
150         }
151
152         return 0;
153 }
154
155
156 static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
157 {
158         u8 key_len;
159         u8 rsc[6];
160         enum wpa_alg alg;
161
162         os_memset(rsc, 0, 6);
163
164         switch (peer->cipher) {
165         case WPA_CIPHER_CCMP:
166                 alg = WPA_ALG_CCMP;
167                 key_len = 16;
168                 break;
169         case WPA_CIPHER_NONE:
170                 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
171                            "NONE - do not use pairwise keys");
172                 return -1;
173         default:
174                 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
175                            sm->pairwise_cipher);
176                 return -1;
177         }
178
179         if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
180                            rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
181                 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
182                            "driver");
183                 return -1;
184         }
185         return 0;
186 }
187
188
189 static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
190                                  u8 action_code, u8 dialog_token,
191                                  u16 status_code, const u8 *buf, size_t len)
192 {
193         return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
194                                      status_code, buf, len);
195 }
196
197
198 static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
199                              u8 dialog_token, u16 status_code,
200                              const u8 *msg, size_t msg_len)
201 {
202         struct wpa_tdls_peer *peer;
203
204         wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
205                    "dialog_token=%u status_code=%u msg_len=%u",
206                    MAC2STR(dest), action_code, dialog_token, status_code,
207                    (unsigned int) msg_len);
208
209         if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
210                                   status_code, msg, msg_len)) {
211                 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
212                            "(action_code=%u)", action_code);
213                 return -1;
214         }
215
216         if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
217             action_code == WLAN_TDLS_TEARDOWN ||
218             action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
219             action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
220                 return 0; /* No retries */
221
222         for (peer = sm->tdls; peer; peer = peer->next) {
223                 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
224                         break;
225         }
226
227         if (peer == NULL) {
228                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
229                            "retry " MACSTR, MAC2STR(dest));
230                 return 0;
231         }
232
233         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
234
235         peer->sm_tmr.count = TPK_RETRY_COUNT;
236         peer->sm_tmr.timer = TPK_TIMEOUT;
237
238         /* Copy message to resend on timeout */
239         os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
240         peer->sm_tmr.action_code = action_code;
241         peer->sm_tmr.dialog_token = dialog_token;
242         peer->sm_tmr.status_code = status_code;
243         peer->sm_tmr.buf_len = msg_len;
244         os_free(peer->sm_tmr.buf);
245         peer->sm_tmr.buf = os_malloc(msg_len);
246         if (peer->sm_tmr.buf == NULL)
247                 return -1;
248         os_memcpy(peer->sm_tmr.buf, msg, msg_len);
249
250         wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
251                    "(action_code=%u)", action_code);
252         eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
253                                wpa_tdls_tpk_retry_timeout, sm, peer);
254         return 0;
255 }
256
257
258 static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
259                                 u16 reason_code)
260 {
261         int ret;
262
263         if (sm->tdls_external_setup) {
264                 ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
265
266                 /* disable the link after teardown was sent */
267                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
268         } else {
269                 ret = wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
270         }
271
272         wpa_tdls_peer_free(sm, peer);
273
274         return ret;
275 }
276
277
278 static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
279 {
280
281         struct wpa_sm *sm = eloop_ctx;
282         struct wpa_tdls_peer *peer = timeout_ctx;
283
284         if (peer->sm_tmr.count) {
285                 peer->sm_tmr.count--;
286                 peer->sm_tmr.timer = TPK_TIMEOUT;
287
288                 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
289                            "(action_code=%u)",
290                            peer->sm_tmr.action_code);
291
292                 if (peer->sm_tmr.buf == NULL) {
293                         wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
294                                    "for action_code=%u",
295                                    peer->sm_tmr.action_code);
296                         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
297                                              peer);
298                         return;
299                 }
300
301                 /* resend TPK Handshake Message to Peer */
302                 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
303                                           peer->sm_tmr.action_code,
304                                           peer->sm_tmr.dialog_token,
305                                           peer->sm_tmr.status_code,
306                                           peer->sm_tmr.buf,
307                                           peer->sm_tmr.buf_len)) {
308                         wpa_printf(MSG_INFO, "TDLS: Failed to retry "
309                                    "transmission");
310                 }
311
312                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
313                 eloop_register_timeout(peer->sm_tmr.timer / 1000, 0,
314                                        wpa_tdls_tpk_retry_timeout, sm, peer);
315         } else {
316                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
317
318                 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
319                 wpa_tdls_do_teardown(sm, peer,
320                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
321         }
322 }
323
324
325 static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
326                                               struct wpa_tdls_peer *peer,
327                                               u8 action_code)
328 {
329         if (action_code == peer->sm_tmr.action_code) {
330                 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
331                            "action_code=%u", action_code);
332
333                 /* Cancel Timeout registered */
334                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
335
336                 /* free all resources meant for retry */
337                 os_free(peer->sm_tmr.buf);
338                 peer->sm_tmr.buf = NULL;
339
340                 peer->sm_tmr.count = 0;
341                 peer->sm_tmr.timer = 0;
342                 peer->sm_tmr.buf_len = 0;
343                 peer->sm_tmr.action_code = 0xff;
344         } else {
345                 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
346                            "(Unknown action_code=%u)", action_code);
347         }
348 }
349
350
351 static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
352                                   const u8 *own_addr, const u8 *bssid)
353 {
354         u8 key_input[SHA256_MAC_LEN];
355         const u8 *nonce[2];
356         size_t len[2];
357         u8 data[3 * ETH_ALEN];
358
359         /* IEEE Std 802.11z-2010 8.5.9.1:
360          * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
361          */
362         len[0] = WPA_NONCE_LEN;
363         len[1] = WPA_NONCE_LEN;
364         if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
365                 nonce[0] = peer->inonce;
366                 nonce[1] = peer->rnonce;
367         } else {
368                 nonce[0] = peer->rnonce;
369                 nonce[1] = peer->inonce;
370         }
371         wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
372         wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
373         sha256_vector(2, nonce, len, key_input);
374         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
375                         key_input, SHA256_MAC_LEN);
376
377         /*
378          * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
379          *      min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
380          * TODO: is N_KEY really included in KDF Context and if so, in which
381          * presentation format (little endian 16-bit?) is it used? It gets
382          * added by the KDF anyway..
383          */
384
385         if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
386                 os_memcpy(data, own_addr, ETH_ALEN);
387                 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
388         } else {
389                 os_memcpy(data, peer->addr, ETH_ALEN);
390                 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
391         }
392         os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
393         wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
394
395         sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
396                    (u8 *) &peer->tpk, sizeof(peer->tpk));
397         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
398                         peer->tpk.kck, sizeof(peer->tpk.kck));
399         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
400                         peer->tpk.tk, sizeof(peer->tpk.tk));
401         peer->tpk_set = 1;
402 }
403
404
405 /**
406  * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
407  * @kck: TPK-KCK
408  * @lnkid: Pointer to the beginning of Link Identifier IE
409  * @rsnie: Pointer to the beginning of RSN IE used for handshake
410  * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
411  * @ftie: Pointer to the beginning of FT IE
412  * @mic: Pointer for writing MIC
413  *
414  * Calculate MIC for TDLS frame.
415  */
416 static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
417                              const u8 *rsnie, const u8 *timeoutie,
418                              const u8 *ftie, u8 *mic)
419 {
420         u8 *buf, *pos;
421         struct wpa_tdls_ftie *_ftie;
422         const struct wpa_tdls_lnkid *_lnkid;
423         int ret;
424         int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
425                 2 + timeoutie[1] + 2 + ftie[1];
426         buf = os_zalloc(len);
427         if (!buf) {
428                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
429                 return -1;
430         }
431
432         pos = buf;
433         _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
434         /* 1) TDLS initiator STA MAC address */
435         os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
436         pos += ETH_ALEN;
437         /* 2) TDLS responder STA MAC address */
438         os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
439         pos += ETH_ALEN;
440         /* 3) Transaction Sequence number */
441         *pos++ = trans_seq;
442         /* 4) Link Identifier IE */
443         os_memcpy(pos, lnkid, 2 + lnkid[1]);
444         pos += 2 + lnkid[1];
445         /* 5) RSN IE */
446         os_memcpy(pos, rsnie, 2 + rsnie[1]);
447         pos += 2 + rsnie[1];
448         /* 6) Timeout Interval IE */
449         os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
450         pos += 2 + timeoutie[1];
451         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
452         os_memcpy(pos, ftie, 2 + ftie[1]);
453         _ftie = (struct wpa_tdls_ftie *) pos;
454         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
455         pos += 2 + ftie[1];
456
457         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
458         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
459         ret = omac1_aes_128(kck, buf, pos - buf, mic);
460         os_free(buf);
461         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
462         return ret;
463 }
464
465
466 /**
467  * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
468  * @kck: TPK-KCK
469  * @trans_seq: Transaction Sequence Number (4 - Teardown)
470  * @rcode: Reason code for Teardown
471  * @dtoken: Dialog Token used for that particular link
472  * @lnkid: Pointer to the beginning of Link Identifier IE
473  * @ftie: Pointer to the beginning of FT IE
474  * @mic: Pointer for writing MIC
475  *
476  * Calculate MIC for TDLS frame.
477  */
478 static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
479                                      u8 dtoken, const u8 *lnkid,
480                                      const u8 *ftie, u8 *mic)
481 {
482         u8 *buf, *pos;
483         struct wpa_tdls_ftie *_ftie;
484         int ret;
485         int len;
486
487         if (lnkid == NULL)
488                 return -1;
489
490         len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
491                 sizeof(trans_seq) + 2 + ftie[1];
492
493         buf = os_zalloc(len);
494         if (!buf) {
495                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
496                 return -1;
497         }
498
499         pos = buf;
500         /* 1) Link Identifier IE */
501         os_memcpy(pos, lnkid, 2 + lnkid[1]);
502         pos += 2 + lnkid[1];
503         /* 2) Reason Code */
504         WPA_PUT_LE16(pos, rcode);
505         pos += sizeof(rcode);
506         /* 3) Dialog token */
507         *pos++ = dtoken;
508         /* 4) Transaction Sequence number */
509         *pos++ = trans_seq;
510         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
511         os_memcpy(pos, ftie, 2 + ftie[1]);
512         _ftie = (struct wpa_tdls_ftie *) pos;
513         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
514         pos += 2 + ftie[1];
515
516         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
517         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
518         ret = omac1_aes_128(kck, buf, pos - buf, mic);
519         os_free(buf);
520         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
521         return ret;
522 }
523
524
525 static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
526                                           struct wpa_tdls_peer *peer,
527                                           const u8 *lnkid, const u8 *timeoutie,
528                                           const struct wpa_tdls_ftie *ftie)
529 {
530         u8 mic[16];
531
532         if (peer->tpk_set) {
533                 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
534                                   peer->rsnie_p, timeoutie, (u8 *) ftie,
535                                   mic);
536                 if (os_memcmp(mic, ftie->mic, 16) != 0) {
537                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
538                                    "dropping packet");
539                         wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
540                                     ftie->mic, 16);
541                         wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
542                                     mic, 16);
543                         return -1;
544                 }
545         } else {
546                 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
547                            "TPK not set - dropping packet");
548                 return -1;
549         }
550         return 0;
551 }
552
553
554 static int wpa_supplicant_verify_tdls_mic_teardown(
555         u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
556         const u8 *lnkid, const struct wpa_tdls_ftie *ftie)
557 {
558         u8 mic[16];
559
560         if (peer->tpk_set) {
561                 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
562                                           dtoken, lnkid, (u8 *) ftie, mic);
563                 if (os_memcmp(mic, ftie->mic, 16) != 0) {
564                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
565                                    "dropping packet");
566                         return -1;
567                 }
568         } else {
569                 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
570                            "MIC, TPK not set - dropping packet");
571                 return -1;
572         }
573         return 0;
574 }
575
576
577 static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
578 {
579         struct wpa_sm *sm = eloop_ctx;
580         struct wpa_tdls_peer *peer = timeout_ctx;
581
582         /*
583          * On TPK lifetime expiration, we have an option of either tearing down
584          * the direct link or trying to re-initiate it. The selection of what
585          * to do is not strictly speaking controlled by our role in the expired
586          * link, but for now, use that to select whether to renew or tear down
587          * the link.
588          */
589
590         if (peer->initiator) {
591                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
592                            " - try to renew", MAC2STR(peer->addr));
593                 wpa_tdls_start(sm, peer->addr);
594         } else {
595                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
596                            " - tear down", MAC2STR(peer->addr));
597                 wpa_tdls_do_teardown(sm, peer,
598                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
599         }
600 }
601
602
603 static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
604 {
605         wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
606                    MAC2STR(peer->addr));
607         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
608         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
609         peer->initiator = 0;
610         os_free(peer->sm_tmr.buf);
611         peer->sm_tmr.buf = NULL;
612         peer->rsnie_i_len = peer->rsnie_p_len = 0;
613         peer->cipher = 0;
614         peer->tpk_set = peer->tpk_success = 0;
615         os_memset(&peer->tpk, 0, sizeof(peer->tpk));
616         os_memset(peer->inonce, 0, WPA_NONCE_LEN);
617         os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
618 }
619
620
621 static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
622                             struct wpa_tdls_lnkid *lnkid)
623 {
624         lnkid->ie_type = WLAN_EID_LINK_ID;
625         lnkid->ie_len = 3 * ETH_ALEN;
626         os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
627         if (peer->initiator) {
628                 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
629                 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
630         } else {
631                 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
632                 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
633         }
634 }
635
636
637 int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
638 {
639         struct wpa_tdls_peer *peer;
640         struct wpa_tdls_ftie *ftie;
641         struct wpa_tdls_lnkid lnkid;
642         u8 dialog_token;
643         u8 *rbuf, *pos;
644         int ielen;
645
646         if (sm->tdls_disabled || !sm->tdls_supported)
647                 return -1;
648
649         /* Find the node and free from the list */
650         for (peer = sm->tdls; peer; peer = peer->next) {
651                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
652                         break;
653         }
654
655         if (peer == NULL) {
656                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
657                            "Teardown " MACSTR, MAC2STR(addr));
658                 return 0;
659         }
660
661         dialog_token = peer->dtoken;
662
663         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
664                    MAC2STR(addr));
665
666         ielen = 0;
667         if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
668                 /* To add FTIE for Teardown request and compute MIC */
669                 ielen += sizeof(*ftie);
670 #ifdef CONFIG_TDLS_TESTING
671                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
672                         ielen += 170;
673 #endif /* CONFIG_TDLS_TESTING */
674         }
675
676         rbuf = os_zalloc(ielen + 1);
677         if (rbuf == NULL)
678                 return -1;
679         pos = rbuf;
680
681         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
682                 goto skip_ies;
683
684         ftie = (struct wpa_tdls_ftie *) pos;
685         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
686         /* Using the recent nonce which should be for CONFIRM frame */
687         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
688         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
689         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
690         pos = (u8 *) (ftie + 1);
691 #ifdef CONFIG_TDLS_TESTING
692         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
693                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
694                            "FTIE");
695                 ftie->ie_len += 170;
696                 *pos++ = 255; /* FTIE subelem */
697                 *pos++ = 168; /* FTIE subelem length */
698         }
699 #endif /* CONFIG_TDLS_TESTING */
700         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
701                     (u8 *) ftie, sizeof(*ftie));
702
703         /* compute MIC before sending */
704         wpa_tdls_linkid(sm, peer, &lnkid);
705         wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
706                                   dialog_token, (u8 *) &lnkid, (u8 *) ftie,
707                                   ftie->mic);
708
709 skip_ies:
710         /* TODO: register for a Timeout handler, if Teardown is not received at
711          * the other end, then try again another time */
712
713         /* request driver to send Teardown using this FTIE */
714         wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
715                           WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, rbuf,
716                           pos - rbuf);
717         os_free(rbuf);
718
719         /* clear the Peerkey statemachine */
720         wpa_tdls_peer_free(sm, peer);
721
722         return 0;
723 }
724
725
726 int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
727 {
728         struct wpa_tdls_peer *peer;
729
730         if (sm->tdls_disabled || !sm->tdls_supported)
731                 return -1;
732
733         for (peer = sm->tdls; peer; peer = peer->next) {
734                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
735                         break;
736         }
737
738         if (peer == NULL) {
739                 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
740                    " for link Teardown", MAC2STR(addr));
741                 return -1;
742         }
743
744         if (!peer->tpk_success) {
745                 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
746                    " not connected - cannot Teardown link", MAC2STR(addr));
747                 return -1;
748         }
749
750         return wpa_tdls_do_teardown(sm, peer, reason_code);
751 }
752
753
754 void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr)
755 {
756         struct wpa_tdls_peer *peer;
757
758         for (peer = sm->tdls; peer; peer = peer->next) {
759                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
760                         break;
761         }
762
763         if (peer) {
764                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
765                 wpa_tdls_peer_free(sm, peer);
766         }
767 }
768
769
770 static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
771                                   const u8 *buf, size_t len)
772 {
773         struct wpa_tdls_peer *peer = NULL;
774         struct wpa_tdls_ftie *ftie;
775         struct wpa_tdls_lnkid *lnkid;
776         struct wpa_eapol_ie_parse kde;
777         u16 reason_code;
778         const u8 *pos;
779         int ielen;
780
781         /* Find the node and free from the list */
782         for (peer = sm->tdls; peer; peer = peer->next) {
783                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
784                         break;
785         }
786
787         if (peer == NULL) {
788                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
789                            "Teardown " MACSTR, MAC2STR(src_addr));
790                 return 0;
791         }
792
793         pos = buf;
794         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
795
796         reason_code = WPA_GET_LE16(pos);
797         pos += 2;
798
799         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
800                    " (reason code %u)", MAC2STR(src_addr), reason_code);
801
802         ielen = len - (pos - buf); /* start of IE in buf */
803         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
804                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown");
805                 return -1;
806         }
807
808         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
809                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
810                            "Teardown");
811                 return -1;
812         }
813         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
814
815         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
816                 goto skip_ftie;
817
818         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
819                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
820                 return -1;
821         }
822
823         ftie = (struct wpa_tdls_ftie *) kde.ftie;
824
825         /* Process MIC check to see if TDLS Teardown is right */
826         if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
827                                                     peer->dtoken, peer,
828                                                     (u8 *) lnkid, ftie) < 0) {
829                 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
830                            "Teardown Request from " MACSTR, MAC2STR(src_addr));
831                 return -1;
832         }
833
834 skip_ftie:
835         /*
836          * Request the driver to disable the direct link and clear associated
837          * keys.
838          */
839         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
840
841         /* clear the Peerkey statemachine */
842         wpa_tdls_peer_free(sm, peer);
843
844         return 0;
845 }
846
847
848 /**
849  * wpa_tdls_send_error - To send suitable TDLS status response with
850  *      appropriate status code mentioning reason for error/failure.
851  * @dst         - MAC addr of Peer station
852  * @tdls_action - TDLS frame type for which error code is sent
853  * @status      - status code mentioning reason
854  */
855
856 static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
857                                u8 tdls_action, u8 dialog_token, u16 status)
858 {
859         wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
860                    " (action=%u status=%u)",
861                    MAC2STR(dst), tdls_action, status);
862         return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
863                                  NULL, 0);
864 }
865
866
867 static struct wpa_tdls_peer *
868 wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr)
869 {
870         struct wpa_tdls_peer *peer;
871
872         wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
873                    MAC2STR(addr));
874
875         peer = os_zalloc(sizeof(*peer));
876         if (peer == NULL)
877                 return NULL;
878
879         os_memcpy(peer->addr, addr, ETH_ALEN);
880         peer->next = sm->tdls;
881         sm->tdls = peer;
882
883         return peer;
884 }
885
886
887 static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
888                                 struct wpa_tdls_peer *peer)
889 {
890         size_t buf_len;
891         struct wpa_tdls_timeoutie timeoutie;
892         u16 rsn_capab;
893         struct wpa_tdls_ftie *ftie;
894         u8 *rbuf, *pos, *count_pos;
895         u16 count;
896         struct rsn_ie_hdr *hdr;
897
898         if (!wpa_tdls_get_privacy(sm)) {
899                 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
900                 peer->rsnie_i_len = 0;
901                 goto skip_rsnie;
902         }
903
904         /*
905          * TPK Handshake Message 1:
906          * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
907          * Timeout Interval IE))
908          */
909
910         /* Filling RSN IE */
911         hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
912         hdr->elem_id = WLAN_EID_RSN;
913         WPA_PUT_LE16(hdr->version, RSN_VERSION);
914
915         pos = (u8 *) (hdr + 1);
916         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
917         pos += RSN_SELECTOR_LEN;
918         count_pos = pos;
919         pos += 2;
920
921         count = 0;
922
923         /*
924          * AES-CCMP is the default Encryption preferred for TDLS, so
925          * RSN IE is filled only with CCMP CIPHER
926          * Note: TKIP is not used to encrypt TDLS link.
927          *
928          * Regardless of the cipher used on the AP connection, select CCMP
929          * here.
930          */
931         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
932         pos += RSN_SELECTOR_LEN;
933         count++;
934
935         WPA_PUT_LE16(count_pos, count);
936
937         WPA_PUT_LE16(pos, 1);
938         pos += 2;
939         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
940         pos += RSN_SELECTOR_LEN;
941
942         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
943         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
944 #ifdef CONFIG_TDLS_TESTING
945         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
946                 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
947                            "testing");
948                 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
949         }
950 #endif /* CONFIG_TDLS_TESTING */
951         WPA_PUT_LE16(pos, rsn_capab);
952         pos += 2;
953 #ifdef CONFIG_TDLS_TESTING
954         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
955                 /* Number of PMKIDs */
956                 *pos++ = 0x00;
957                 *pos++ = 0x00;
958         }
959 #endif /* CONFIG_TDLS_TESTING */
960
961         hdr->len = (pos - peer->rsnie_i) - 2;
962         peer->rsnie_i_len = pos - peer->rsnie_i;
963         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
964                     peer->rsnie_i, peer->rsnie_i_len);
965
966 skip_rsnie:
967         buf_len = 0;
968         if (wpa_tdls_get_privacy(sm))
969                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
970                         sizeof(struct wpa_tdls_timeoutie);
971 #ifdef CONFIG_TDLS_TESTING
972         if (wpa_tdls_get_privacy(sm) &&
973             (tdls_testing & TDLS_TESTING_LONG_FRAME))
974                 buf_len += 170;
975         if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
976                 buf_len += sizeof(struct wpa_tdls_lnkid);
977 #endif /* CONFIG_TDLS_TESTING */
978         rbuf = os_zalloc(buf_len + 1);
979         if (rbuf == NULL) {
980                 wpa_tdls_peer_free(sm, peer);
981                 return -1;
982         }
983         pos = rbuf;
984
985         if (!wpa_tdls_get_privacy(sm))
986                 goto skip_ies;
987
988         /* Initiator RSN IE */
989         pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
990
991         ftie = (struct wpa_tdls_ftie *) pos;
992         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
993         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
994
995         if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
996                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
997                         "TDLS: Failed to get random data for initiator Nonce");
998                 os_free(rbuf);
999                 wpa_tdls_peer_free(sm, peer);
1000                 return -1;
1001         }
1002         wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
1003                     peer->inonce, WPA_NONCE_LEN);
1004         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1005
1006         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
1007                     (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
1008
1009         pos = (u8 *) (ftie + 1);
1010
1011 #ifdef CONFIG_TDLS_TESTING
1012         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1013                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1014                            "FTIE");
1015                 ftie->ie_len += 170;
1016                 *pos++ = 255; /* FTIE subelem */
1017                 *pos++ = 168; /* FTIE subelem length */
1018                 pos += 168;
1019         }
1020 #endif /* CONFIG_TDLS_TESTING */
1021
1022         /* Lifetime */
1023         peer->lifetime = TPK_LIFETIME;
1024 #ifdef CONFIG_TDLS_TESTING
1025         if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
1026                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
1027                            "lifetime");
1028                 peer->lifetime = 301;
1029         }
1030         if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
1031                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
1032                            "lifetime");
1033                 peer->lifetime = 0xffffffff;
1034         }
1035 #endif /* CONFIG_TDLS_TESTING */
1036         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1037                                      sizeof(timeoutie), peer->lifetime);
1038         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1039
1040 skip_ies:
1041
1042 #ifdef CONFIG_TDLS_TESTING
1043         if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
1044                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
1045                            "Link Identifier");
1046                 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
1047                 wpa_tdls_linkid(sm, peer, l);
1048                 l->bssid[5] ^= 0x01;
1049                 pos += sizeof(*l);
1050         }
1051 #endif /* CONFIG_TDLS_TESTING */
1052
1053         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
1054                    "Handshake Message 1 (peer " MACSTR ")",
1055                    MAC2STR(peer->addr));
1056
1057         wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 1, 0,
1058                           rbuf, pos - rbuf);
1059         os_free(rbuf);
1060
1061         return 0;
1062 }
1063
1064
1065 static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
1066                                 const unsigned char *src_addr, u8 dtoken,
1067                                 struct wpa_tdls_lnkid *lnkid,
1068                                 const struct wpa_tdls_peer *peer)
1069 {
1070         u8 *rbuf, *pos;
1071         size_t buf_len;
1072         u32 lifetime;
1073         struct wpa_tdls_timeoutie timeoutie;
1074         struct wpa_tdls_ftie *ftie;
1075
1076         buf_len = 0;
1077         if (wpa_tdls_get_privacy(sm)) {
1078                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1079                  * Lifetime */
1080                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1081                         sizeof(struct wpa_tdls_timeoutie);
1082 #ifdef CONFIG_TDLS_TESTING
1083                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1084                         buf_len += 170;
1085 #endif /* CONFIG_TDLS_TESTING */
1086         }
1087
1088         rbuf = os_zalloc(buf_len + 1);
1089         if (rbuf == NULL)
1090                 return -1;
1091         pos = rbuf;
1092
1093         if (!wpa_tdls_get_privacy(sm))
1094                 goto skip_ies;
1095
1096         /* Peer RSN IE */
1097         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1098
1099         ftie = (struct wpa_tdls_ftie *) pos;
1100         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1101         /* TODO: ftie->mic_control to set 2-RESPONSE */
1102         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1103         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1104         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1105         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
1106                     (u8 *) ftie, sizeof(*ftie));
1107
1108         pos = (u8 *) (ftie + 1);
1109
1110 #ifdef CONFIG_TDLS_TESTING
1111         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1112                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1113                            "FTIE");
1114                 ftie->ie_len += 170;
1115                 *pos++ = 255; /* FTIE subelem */
1116                 *pos++ = 168; /* FTIE subelem length */
1117                 pos += 168;
1118         }
1119 #endif /* CONFIG_TDLS_TESTING */
1120
1121         /* Lifetime */
1122         lifetime = peer->lifetime;
1123 #ifdef CONFIG_TDLS_TESTING
1124         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
1125                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1126                            "lifetime in response");
1127                 lifetime++;
1128         }
1129 #endif /* CONFIG_TDLS_TESTING */
1130         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1131                                      sizeof(timeoutie), lifetime);
1132         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
1133                    lifetime);
1134
1135         /* compute MIC before sending */
1136         wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p,
1137                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
1138
1139 skip_ies:
1140         wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
1141                           rbuf, pos - rbuf);
1142         os_free(rbuf);
1143
1144         return 0;
1145 }
1146
1147
1148 static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
1149                                 const unsigned char *src_addr, u8 dtoken,
1150                                 struct wpa_tdls_lnkid *lnkid,
1151                                 const struct wpa_tdls_peer *peer)
1152 {
1153         u8 *rbuf, *pos;
1154         size_t buf_len;
1155         struct wpa_tdls_ftie *ftie;
1156         struct wpa_tdls_timeoutie timeoutie;
1157         u32 lifetime;
1158
1159         buf_len = 0;
1160         if (wpa_tdls_get_privacy(sm)) {
1161                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1162                  * Lifetime */
1163                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1164                         sizeof(struct wpa_tdls_timeoutie);
1165 #ifdef CONFIG_TDLS_TESTING
1166                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1167                         buf_len += 170;
1168 #endif /* CONFIG_TDLS_TESTING */
1169         }
1170
1171         rbuf = os_zalloc(buf_len + 1);
1172         if (rbuf == NULL)
1173                 return -1;
1174         pos = rbuf;
1175
1176         if (!wpa_tdls_get_privacy(sm))
1177                 goto skip_ies;
1178
1179         /* Peer RSN IE */
1180         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1181
1182         ftie = (struct wpa_tdls_ftie *) pos;
1183         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1184         /*TODO: ftie->mic_control to set 3-CONFIRM */
1185         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1186         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1187         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1188
1189         pos = (u8 *) (ftie + 1);
1190
1191 #ifdef CONFIG_TDLS_TESTING
1192         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1193                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1194                            "FTIE");
1195                 ftie->ie_len += 170;
1196                 *pos++ = 255; /* FTIE subelem */
1197                 *pos++ = 168; /* FTIE subelem length */
1198                 pos += 168;
1199         }
1200 #endif /* CONFIG_TDLS_TESTING */
1201
1202         /* Lifetime */
1203         lifetime = peer->lifetime;
1204 #ifdef CONFIG_TDLS_TESTING
1205         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
1206                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1207                            "lifetime in confirm");
1208                 lifetime++;
1209         }
1210 #endif /* CONFIG_TDLS_TESTING */
1211         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1212                                      sizeof(timeoutie), lifetime);
1213         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
1214                    lifetime);
1215
1216         /* compute MIC before sending */
1217         wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
1218                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
1219
1220 skip_ies:
1221         wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 0,
1222                           rbuf, pos - rbuf);
1223         os_free(rbuf);
1224
1225         return 0;
1226 }
1227
1228
1229 static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
1230                                             struct wpa_tdls_peer *peer,
1231                                             u8 dialog_token)
1232 {
1233         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
1234                    "(peer " MACSTR ")", MAC2STR(peer->addr));
1235
1236         return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
1237                                  dialog_token, 0, NULL, 0);
1238 }
1239
1240
1241 static int
1242 wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
1243                                    const u8 *buf, size_t len)
1244 {
1245         struct wpa_eapol_ie_parse kde;
1246         const struct wpa_tdls_lnkid *lnkid;
1247         struct wpa_tdls_peer *peer;
1248         size_t min_req_len = sizeof(struct wpa_tdls_frame) +
1249                 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
1250         u8 dialog_token;
1251
1252         wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
1253                    MAC2STR(addr));
1254
1255         if (len < min_req_len) {
1256                 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
1257                            "%d", (int) len);
1258                 return -1;
1259         }
1260
1261         dialog_token = buf[sizeof(struct wpa_tdls_frame)];
1262
1263         if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
1264                                      len - (sizeof(struct wpa_tdls_frame) + 1),
1265                                      &kde) < 0)
1266                 return -1;
1267
1268         if (!kde.lnkid) {
1269                 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
1270                            "Request");
1271                 return -1;
1272         }
1273
1274         lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
1275
1276         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1277                 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
1278                            " BSS " MACSTR, MAC2STR(lnkid->bssid));
1279                 return -1;
1280         }
1281
1282         peer = wpa_tdls_add_peer(sm, addr);
1283         if (peer == NULL)
1284                 return -1;
1285
1286         return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
1287 }
1288
1289
1290 int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
1291 {
1292         if (sm->tdls_disabled || !sm->tdls_supported)
1293                 return -1;
1294
1295         wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
1296                    MACSTR, MAC2STR(addr));
1297         return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
1298                                  1, 0, NULL, 0);
1299 }
1300
1301
1302 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
1303                                    const u8 *buf, size_t len)
1304 {
1305         struct wpa_tdls_peer *peer;
1306         struct wpa_eapol_ie_parse kde;
1307         struct wpa_ie_data ie;
1308         int cipher;
1309         const u8 *cpos;
1310         struct wpa_tdls_ftie *ftie = NULL;
1311         struct wpa_tdls_timeoutie *timeoutie;
1312         struct wpa_tdls_lnkid *lnkid;
1313         u32 lifetime = 0;
1314 #if 0
1315         struct rsn_ie_hdr *hdr;
1316         u8 *pos;
1317         u16 rsn_capab;
1318         u16 rsn_ver;
1319 #endif
1320         u8 dtoken;
1321         u16 ielen;
1322         u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1323         int tdls_prohibited = sm->tdls_prohibited;
1324
1325         if (len < 3 + 3)
1326                 return -1;
1327
1328         cpos = buf;
1329         cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1330
1331         /* driver had already verified the frame format */
1332         dtoken = *cpos++; /* dialog token */
1333
1334         wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
1335
1336         cpos += 2; /* capability information */
1337
1338         ielen = len - (cpos - buf); /* start of IE in buf */
1339         if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
1340                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1");
1341                 goto error;
1342         }
1343
1344         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1345                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1346                            "TPK M1");
1347                 goto error;
1348         }
1349         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
1350                     kde.lnkid, kde.lnkid_len);
1351         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1352         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1353                 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
1354                 status = WLAN_STATUS_NOT_IN_SAME_BSS;
1355                 goto error;
1356         }
1357
1358         wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
1359                    MAC2STR(src_addr));
1360
1361 #ifdef CONFIG_TDLS_TESTING
1362         if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
1363                 for (peer = sm->tdls; peer; peer = peer->next) {
1364                         if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1365                                 break;
1366                 }
1367                 if (peer == NULL) {
1368                         peer = os_zalloc(sizeof(*peer));
1369                         if (peer == NULL)
1370                                 goto error;
1371                         os_memcpy(peer->addr, src_addr, ETH_ALEN);
1372                         peer->next = sm->tdls;
1373                         sm->tdls = peer;
1374                 }
1375                 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
1376                            "TDLS setup - send own request");
1377                 peer->initiator = 1;
1378                 wpa_tdls_send_tpk_m1(sm, peer);
1379         }
1380
1381         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1382             tdls_prohibited) {
1383                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1384                            "on TDLS");
1385                 tdls_prohibited = 0;
1386         }
1387 #endif /* CONFIG_TDLS_TESTING */
1388
1389         if (tdls_prohibited) {
1390                 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
1391                 status = WLAN_STATUS_REQUEST_DECLINED;
1392                 goto error;
1393         }
1394
1395         if (!wpa_tdls_get_privacy(sm)) {
1396                 if (kde.rsn_ie) {
1397                         wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
1398                                    "security is disabled");
1399                         status = WLAN_STATUS_SECURITY_DISABLED;
1400                         goto error;
1401                 }
1402                 goto skip_rsn;
1403         }
1404
1405         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1406             kde.rsn_ie == NULL) {
1407                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
1408                 status = WLAN_STATUS_INVALID_PARAMETERS;
1409                 goto error;
1410         }
1411
1412         if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
1413                 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
1414                            "TPK M1");
1415                 status = WLAN_STATUS_INVALID_RSNIE;
1416                 goto error;
1417         }
1418
1419         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1420                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
1421                 status = WLAN_STATUS_INVALID_RSNIE;
1422                 goto error;
1423         }
1424
1425         cipher = ie.pairwise_cipher;
1426         if (cipher & WPA_CIPHER_CCMP) {
1427                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1428                 cipher = WPA_CIPHER_CCMP;
1429         } else {
1430                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
1431                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1432                 goto error;
1433         }
1434
1435         if ((ie.capabilities &
1436              (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
1437             WPA_CAPABILITY_PEERKEY_ENABLED) {
1438                 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
1439                            "TPK M1");
1440                 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
1441                 goto error;
1442         }
1443
1444         /* Lifetime */
1445         if (kde.key_lifetime == NULL) {
1446                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
1447                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1448                 goto error;
1449         }
1450         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1451         lifetime = WPA_GET_LE32(timeoutie->value);
1452         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
1453         if (lifetime < 300) {
1454                 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
1455                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1456                 goto error;
1457         }
1458
1459 skip_rsn:
1460         /* Find existing entry and if found, use that instead of adding
1461          * a new one; how to handle the case where both ends initiate at the
1462          * same time? */
1463         for (peer = sm->tdls; peer; peer = peer->next) {
1464                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1465                         break;
1466         }
1467
1468         if (peer == NULL) {
1469                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
1470                            "peer, creating one for " MACSTR,
1471                            MAC2STR(src_addr));
1472                 peer = os_malloc(sizeof(*peer));
1473                 if (peer == NULL)
1474                         goto error;
1475                 os_memset(peer, 0, sizeof(*peer));
1476                 os_memcpy(peer->addr, src_addr, ETH_ALEN);
1477                 peer->next = sm->tdls;
1478                 sm->tdls = peer;
1479         } else {
1480                 if (peer->tpk_success) {
1481                         wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
1482                                    "direct link is enabled - tear down the "
1483                                    "old link first");
1484 #if 0
1485                         /* TODO: Disabling the link would be more proper
1486                          * operation here, but it seems to trigger a race with
1487                          * some drivers handling the new request frame. */
1488                         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr);
1489 #else
1490                         wpa_tdls_del_key(sm, peer);
1491 #endif
1492                         wpa_tdls_peer_free(sm, peer);
1493                 }
1494
1495                 /*
1496                  * An entry is already present, so check if we already sent a
1497                  * TDLS Setup Request. If so, compare MAC addresses and let the
1498                  * STA with the lower MAC address continue as the initiator.
1499                  * The other negotiation is terminated.
1500                  */
1501                 if (peer->initiator) {
1502                         if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
1503                                 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
1504                                            "from peer with higher address "
1505                                            MACSTR, MAC2STR(src_addr));
1506                                 return -1;
1507                         } else {
1508                                 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
1509                                            "from peer with lower address "
1510                                            MACSTR " (terminate previously "
1511                                            "initiated negotiation",
1512                                            MAC2STR(src_addr));
1513                                 wpa_tdls_peer_free(sm, peer);
1514                         }
1515                 }
1516         }
1517
1518         peer->initiator = 0; /* Need to check */
1519         peer->dtoken = dtoken;
1520
1521         if (!wpa_tdls_get_privacy(sm)) {
1522                 peer->rsnie_i_len = 0;
1523                 peer->rsnie_p_len = 0;
1524                 peer->cipher = WPA_CIPHER_NONE;
1525                 goto skip_rsn_check;
1526         }
1527
1528         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1529         os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
1530         os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
1531         peer->rsnie_i_len = kde.rsn_ie_len;
1532         peer->cipher = cipher;
1533
1534         if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
1535                 wpa_msg(sm->ctx->ctx, MSG_WARNING,
1536                         "TDLS: Failed to get random data for responder nonce");
1537                 wpa_tdls_peer_free(sm, peer);
1538                 goto error;
1539         }
1540
1541 #if 0
1542         /* get version info from RSNIE received from Peer */
1543         hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
1544         rsn_ver = WPA_GET_LE16(hdr->version);
1545
1546         /* use min(peer's version, out version) */
1547         if (rsn_ver > RSN_VERSION)
1548                 rsn_ver = RSN_VERSION;
1549
1550         hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
1551
1552         hdr->elem_id = WLAN_EID_RSN;
1553         WPA_PUT_LE16(hdr->version, rsn_ver);
1554         pos = (u8 *) (hdr + 1);
1555
1556         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1557         pos += RSN_SELECTOR_LEN;
1558         /* Include only the selected cipher in pairwise cipher suite */
1559         WPA_PUT_LE16(pos, 1);
1560         pos += 2;
1561         if (cipher == WPA_CIPHER_CCMP)
1562                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1563         pos += RSN_SELECTOR_LEN;
1564
1565         WPA_PUT_LE16(pos, 1);
1566         pos += 2;
1567         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1568         pos += RSN_SELECTOR_LEN;
1569
1570         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1571         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1572         WPA_PUT_LE16(pos, rsn_capab);
1573         pos += 2;
1574
1575         hdr->len = (pos - peer->rsnie_p) - 2;
1576         peer->rsnie_p_len = pos - peer->rsnie_p;
1577 #endif
1578
1579         /* temp fix: validation of RSNIE later */
1580         os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
1581         peer->rsnie_p_len = peer->rsnie_i_len;
1582
1583         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
1584                     peer->rsnie_p, peer->rsnie_p_len);
1585
1586         peer->lifetime = lifetime;
1587
1588         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
1589
1590 skip_rsn_check:
1591         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
1592         wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer);
1593
1594         return 0;
1595
1596 error:
1597         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken,
1598                             status);
1599         return -1;
1600 }
1601
1602
1603 static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
1604 {
1605         peer->tpk_success = 1;
1606         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
1607         if (wpa_tdls_get_privacy(sm)) {
1608                 u32 lifetime = peer->lifetime;
1609                 /*
1610                  * Start the initiator process a bit earlier to avoid race
1611                  * condition with the responder sending teardown request.
1612                  */
1613                 if (lifetime > 3 && peer->initiator)
1614                         lifetime -= 3;
1615                 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
1616                                        sm, peer);
1617 #ifdef CONFIG_TDLS_TESTING
1618         if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
1619                 wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
1620                            "expiration");
1621                 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
1622         }
1623 #endif /* CONFIG_TDLS_TESTING */
1624         }
1625         wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
1626 }
1627
1628
1629 static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
1630                                    const u8 *buf, size_t len)
1631 {
1632         struct wpa_tdls_peer *peer;
1633         struct wpa_eapol_ie_parse kde;
1634         struct wpa_ie_data ie;
1635         int cipher;
1636         struct wpa_tdls_ftie *ftie;
1637         struct wpa_tdls_timeoutie *timeoutie;
1638         struct wpa_tdls_lnkid *lnkid;
1639         u32 lifetime;
1640         u8 dtoken;
1641         int ielen;
1642         u16 status;
1643         const u8 *pos;
1644
1645         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
1646                    "(Peer " MACSTR ")", MAC2STR(src_addr));
1647         for (peer = sm->tdls; peer; peer = peer->next) {
1648                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1649                         break;
1650         }
1651         if (peer == NULL) {
1652                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
1653                            "TPK M2: " MACSTR, MAC2STR(src_addr));
1654                 return -1;
1655         }
1656         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
1657
1658         if (len < 3 + 2 + 1)
1659                 return -1;
1660         pos = buf;
1661         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1662         status = WPA_GET_LE16(pos);
1663         pos += 2 /* status code */;
1664
1665         if (status != WLAN_STATUS_SUCCESS) {
1666                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
1667                            status);
1668                 return -1;
1669         }
1670
1671         status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1672
1673         /* TODO: need to verify dialog token matches here or in kernel */
1674         dtoken = *pos++; /* dialog token */
1675
1676         wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
1677
1678         if (len < 3 + 2 + 1 + 2)
1679                 return -1;
1680         pos += 2; /* capability information */
1681
1682         ielen = len - (pos - buf); /* start of IE in buf */
1683         if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
1684                 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2");
1685                 goto error;
1686         }
1687
1688 #ifdef CONFIG_TDLS_TESTING
1689         if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
1690                 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
1691                 status = WLAN_STATUS_REQUEST_DECLINED;
1692                 goto error;
1693         }
1694 #endif /* CONFIG_TDLS_TESTING */
1695
1696         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1697                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1698                            "TPK M2");
1699                 goto error;
1700         }
1701         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
1702                     kde.lnkid, kde.lnkid_len);
1703         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1704
1705         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1706                 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
1707                 status = WLAN_STATUS_NOT_IN_SAME_BSS;
1708                 goto error;
1709         }
1710
1711         if (!wpa_tdls_get_privacy(sm)) {
1712                 peer->rsnie_p_len = 0;
1713                 peer->cipher = WPA_CIPHER_NONE;
1714                 goto skip_rsn;
1715         }
1716
1717         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1718             kde.rsn_ie == NULL) {
1719                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
1720                 status = WLAN_STATUS_INVALID_PARAMETERS;
1721                 goto error;
1722         }
1723         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
1724                     kde.rsn_ie, kde.rsn_ie_len);
1725
1726         /*
1727          * FIX: bitwise comparison of RSN IE is not the correct way of
1728          * validation this. It can be different, but certain fields must
1729          * match. Since we list only a single pairwise cipher in TPK M1, the
1730          * memcmp is likely to work in most cases, though.
1731          */
1732         if (kde.rsn_ie_len != peer->rsnie_i_len ||
1733             os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
1734                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
1735                            "not match with RSN IE used in TPK M1");
1736                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
1737                             peer->rsnie_i, peer->rsnie_i_len);
1738                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
1739                             kde.rsn_ie, kde.rsn_ie_len);
1740                 status = WLAN_STATUS_INVALID_RSNIE;
1741                 goto error;
1742         }
1743
1744         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1745                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
1746                 status = WLAN_STATUS_INVALID_RSNIE;
1747                 goto error;
1748         }
1749
1750         cipher = ie.pairwise_cipher;
1751         if (cipher == WPA_CIPHER_CCMP) {
1752                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1753                 cipher = WPA_CIPHER_CCMP;
1754         } else {
1755                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
1756                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1757                 goto error;
1758         }
1759
1760         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
1761                     kde.ftie, sizeof(*ftie));
1762         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1763
1764         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
1765                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
1766                            "not match with FTIE SNonce used in TPK M1");
1767                 /* Silently discard the frame */
1768                 return -1;
1769         }
1770
1771         /* Responder Nonce and RSN IE */
1772         os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
1773         os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
1774         peer->rsnie_p_len = kde.rsn_ie_len;
1775         peer->cipher = cipher;
1776
1777         /* Lifetime */
1778         if (kde.key_lifetime == NULL) {
1779                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
1780                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1781                 goto error;
1782         }
1783         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1784         lifetime = WPA_GET_LE32(timeoutie->value);
1785         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
1786                    lifetime);
1787         if (lifetime != peer->lifetime) {
1788                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
1789                            "TPK M2 (expected %u)", lifetime, peer->lifetime);
1790                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1791                 goto error;
1792         }
1793
1794         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
1795
1796         /* Process MIC check to see if TPK M2 is right */
1797         if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid,
1798                                            (u8 *) timeoutie, ftie) < 0) {
1799                 /* Discard the frame */
1800                 wpa_tdls_del_key(sm, peer);
1801                 wpa_tdls_peer_free(sm, peer);
1802                 return -1;
1803         }
1804
1805         wpa_tdls_set_key(sm, peer);
1806
1807 skip_rsn:
1808         peer->dtoken = dtoken;
1809
1810         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
1811                    "TPK Handshake Message 3");
1812         wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer);
1813
1814         wpa_tdls_enable_link(sm, peer);
1815
1816         return 0;
1817
1818 error:
1819         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
1820                             status);
1821         return -1;
1822 }
1823
1824
1825 static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
1826                                    const u8 *buf, size_t len)
1827 {
1828         struct wpa_tdls_peer *peer;
1829         struct wpa_eapol_ie_parse kde;
1830         struct wpa_tdls_ftie *ftie;
1831         struct wpa_tdls_timeoutie *timeoutie;
1832         struct wpa_tdls_lnkid *lnkid;
1833         int ielen;
1834         u16 status;
1835         const u8 *pos;
1836         u32 lifetime;
1837
1838         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
1839                    "(Peer " MACSTR ")", MAC2STR(src_addr));
1840         for (peer = sm->tdls; peer; peer = peer->next) {
1841                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
1842                         break;
1843         }
1844         if (peer == NULL) {
1845                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
1846                            "TPK M3: " MACSTR, MAC2STR(src_addr));
1847                 return -1;
1848         }
1849         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
1850
1851         if (len < 3 + 3)
1852                 return -1;
1853         pos = buf;
1854         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1855
1856         status = WPA_GET_LE16(pos);
1857
1858         if (status != 0) {
1859                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
1860                            status);
1861                 return -1;
1862         }
1863         pos += 2 /* status code */ + 1 /* dialog token */;
1864
1865         ielen = len - (pos - buf); /* start of IE in buf */
1866         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
1867                 wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3");
1868                 return -1;
1869         }
1870
1871         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1872                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
1873                 return -1;
1874         }
1875         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
1876                     (u8 *) kde.lnkid, kde.lnkid_len);
1877         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1878
1879         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1880                 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
1881                 return -1;
1882         }
1883
1884         if (!wpa_tdls_get_privacy(sm))
1885                 goto skip_rsn;
1886
1887         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
1888                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
1889                 return -1;
1890         }
1891         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
1892                     kde.ftie, sizeof(*ftie));
1893         ftie = (struct wpa_tdls_ftie *) kde.ftie;
1894
1895         if (kde.rsn_ie == NULL) {
1896                 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
1897                 return -1;
1898         }
1899         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
1900                     kde.rsn_ie, kde.rsn_ie_len);
1901         if (kde.rsn_ie_len != peer->rsnie_p_len ||
1902             os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
1903                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
1904                            "with the one sent in TPK M2");
1905                 return -1;
1906         }
1907
1908         if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
1909                 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
1910                            "not match with FTIE ANonce used in TPK M2");
1911                 return -1;
1912         }
1913
1914         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
1915                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
1916                            "match with FTIE SNonce used in TPK M1");
1917                 return -1;
1918         }
1919
1920         if (kde.key_lifetime == NULL) {
1921                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
1922                 return -1;
1923         }
1924         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1925         wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
1926                     (u8 *) timeoutie, sizeof(*timeoutie));
1927         lifetime = WPA_GET_LE32(timeoutie->value);
1928         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
1929                    lifetime);
1930         if (lifetime != peer->lifetime) {
1931                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
1932                            "TPK M3 (expected %u)", lifetime, peer->lifetime);
1933                 return -1;
1934         }
1935
1936         if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid,
1937                                            (u8 *) timeoutie, ftie) < 0) {
1938                 wpa_tdls_del_key(sm, peer);
1939                 wpa_tdls_peer_free(sm, peer);
1940                 return -1;
1941         }
1942
1943         if (wpa_tdls_set_key(sm, peer) < 0)
1944                 return -1;
1945
1946 skip_rsn:
1947         wpa_tdls_enable_link(sm, peer);
1948
1949         return 0;
1950 }
1951
1952
1953 static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
1954 {
1955         struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
1956
1957         os_memset(lifetime, 0, ie_len);
1958         lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
1959         lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
1960         lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
1961         WPA_PUT_LE32(lifetime->value, tsecs);
1962         os_memcpy(pos, ie, ie_len);
1963         return pos + ie_len;
1964 }
1965
1966
1967 /**
1968  * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
1969  * @sm: Pointer to WPA state machine data from wpa_sm_init()
1970  * @peer: MAC address of the peer STA
1971  * Returns: 0 on success, or -1 on failure
1972  *
1973  * Send TPK Handshake Message 1 info to driver to start TDLS
1974  * handshake with the peer.
1975  */
1976 int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
1977 {
1978         struct wpa_tdls_peer *peer;
1979         int tdls_prohibited = sm->tdls_prohibited;
1980
1981         if (sm->tdls_disabled || !sm->tdls_supported)
1982                 return -1;
1983
1984 #ifdef CONFIG_TDLS_TESTING
1985         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1986             tdls_prohibited) {
1987                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1988                            "on TDLS");
1989                 tdls_prohibited = 0;
1990         }
1991 #endif /* CONFIG_TDLS_TESTING */
1992
1993         if (tdls_prohibited) {
1994                 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
1995                            "reject request to start setup");
1996                 return -1;
1997         }
1998
1999         /* Find existing entry and if found, use that instead of adding
2000          * a new one */
2001         for (peer = sm->tdls; peer; peer = peer->next) {
2002                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2003                         break;
2004         }
2005
2006         if (peer == NULL) {
2007                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
2008                            "peer, creating one for " MACSTR, MAC2STR(addr));
2009                 peer = os_malloc(sizeof(*peer));
2010                 if (peer == NULL)
2011                         return -1;
2012                 os_memset(peer, 0, sizeof(*peer));
2013                 os_memcpy(peer->addr, addr, ETH_ALEN);
2014                 peer->next = sm->tdls;
2015                 sm->tdls = peer;
2016         }
2017
2018         peer->initiator = 1;
2019
2020         return wpa_tdls_send_tpk_m1(sm, peer);
2021 }
2022
2023
2024 int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr)
2025 {
2026         struct wpa_tdls_peer *peer;
2027
2028         if (sm->tdls_disabled || !sm->tdls_supported)
2029                 return -1;
2030
2031         for (peer = sm->tdls; peer; peer = peer->next) {
2032                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2033                         break;
2034         }
2035
2036         if (peer == NULL || !peer->tpk_success)
2037                 return -1;
2038
2039         return wpa_tdls_start(sm, addr);
2040 }
2041
2042
2043 /**
2044  * wpa_supplicant_rx_tdls - Receive TDLS data frame
2045  *
2046  * This function is called to receive TDLS (ethertype = 0x890d) data frames.
2047  */
2048 static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
2049                                    const u8 *buf, size_t len)
2050 {
2051         struct wpa_sm *sm = ctx;
2052         struct wpa_tdls_frame *tf;
2053
2054         wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
2055                     buf, len);
2056
2057         if (sm->tdls_disabled || !sm->tdls_supported) {
2058                 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
2059                            "or unsupported by driver");
2060                 return;
2061         }
2062
2063         if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
2064                 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
2065                 return;
2066         }
2067
2068         if (len < sizeof(*tf)) {
2069                 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
2070                 return;
2071         }
2072
2073         /* Check to make sure its a valid encapsulated TDLS frame */
2074         tf = (struct wpa_tdls_frame *) buf;
2075         if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
2076             tf->category != WLAN_ACTION_TDLS) {
2077                 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
2078                            "category=%u action=%u",
2079                            tf->payloadtype, tf->category, tf->action);
2080                 return;
2081         }
2082
2083         switch (tf->action) {
2084         case WLAN_TDLS_SETUP_REQUEST:
2085                 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
2086                 break;
2087         case WLAN_TDLS_SETUP_RESPONSE:
2088                 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
2089                 break;
2090         case WLAN_TDLS_SETUP_CONFIRM:
2091                 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
2092                 break;
2093         case WLAN_TDLS_TEARDOWN:
2094                 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
2095                 break;
2096         case WLAN_TDLS_DISCOVERY_REQUEST:
2097                 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
2098                 break;
2099         default:
2100                 /* Kernel code will process remaining frames */
2101                 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
2102                            tf->action);
2103                 break;
2104         }
2105 }
2106
2107
2108 /**
2109  * wpa_tdls_init - Initialize driver interface parameters for TDLS
2110  * @wpa_s: Pointer to wpa_supplicant data
2111  * Returns: 0 on success, -1 on failure
2112  *
2113  * This function is called to initialize driver interface parameters for TDLS.
2114  * wpa_drv_init() must have been called before this function to initialize the
2115  * driver interface.
2116  */
2117 int wpa_tdls_init(struct wpa_sm *sm)
2118 {
2119         if (sm == NULL)
2120                 return -1;
2121
2122         sm->l2_tdls = l2_packet_init(sm->ifname, sm->own_addr,
2123                                      ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
2124                                      sm, 0);
2125         if (sm->l2_tdls == NULL) {
2126                 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
2127                            "connection");
2128                 return -1;
2129         }
2130
2131         /*
2132          * Drivers that support TDLS but don't implement the get_capa callback
2133          * are assumed to perform everything internally
2134          */
2135         if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
2136                                  &sm->tdls_external_setup) < 0) {
2137                 sm->tdls_supported = 1;
2138                 sm->tdls_external_setup = 0;
2139         }
2140
2141         wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
2142                    "driver", sm->tdls_supported ? "" : " not");
2143         wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
2144                    sm->tdls_external_setup ? "external" : "internal");
2145
2146         return 0;
2147 }
2148
2149
2150 static void wpa_tdls_remove_peers(struct wpa_sm *sm)
2151 {
2152         struct wpa_tdls_peer *peer, *tmp;
2153
2154         peer = sm->tdls;
2155         sm->tdls = NULL;
2156
2157         while (peer) {
2158                 int res;
2159                 tmp = peer->next;
2160                 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
2161                 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
2162                            MAC2STR(peer->addr), res);
2163                 wpa_tdls_peer_free(sm, peer);
2164                 os_free(peer);
2165                 peer = tmp;
2166         }
2167 }
2168
2169
2170 /**
2171  * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
2172  *
2173  * This function is called to recover driver interface parameters for TDLS
2174  * and frees resources allocated for it.
2175  */
2176 void wpa_tdls_deinit(struct wpa_sm *sm)
2177 {
2178         if (sm == NULL)
2179                 return;
2180
2181         if (sm->l2_tdls)
2182                 l2_packet_deinit(sm->l2_tdls);
2183         sm->l2_tdls = NULL;
2184
2185         wpa_tdls_remove_peers(sm);
2186 }
2187
2188
2189 void wpa_tdls_assoc(struct wpa_sm *sm)
2190 {
2191         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
2192         wpa_tdls_remove_peers(sm);
2193 }
2194
2195
2196 void wpa_tdls_disassoc(struct wpa_sm *sm)
2197 {
2198         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
2199         wpa_tdls_remove_peers(sm);
2200 }
2201
2202
2203 static int wpa_tdls_prohibited(const u8 *ies, size_t len)
2204 {
2205         struct wpa_eapol_ie_parse elems;
2206
2207         if (ies == NULL)
2208                 return 0;
2209
2210         if (wpa_supplicant_parse_ies(ies, len, &elems) < 0)
2211                 return 0;
2212
2213         if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
2214                 return 0;
2215
2216          /* bit 38 - TDLS Prohibited */
2217         return !!(elems.ext_capab[2 + 4] & 0x40);
2218 }
2219
2220
2221 void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2222 {
2223         sm->tdls_prohibited = wpa_tdls_prohibited(ies, len);
2224         wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
2225                    sm->tdls_prohibited ? "prohibited" : "allowed");
2226 }
2227
2228
2229 void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2230 {
2231         if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) {
2232                 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
2233                            "(Re)Association Response IEs");
2234                 sm->tdls_prohibited = 1;
2235         }
2236 }
2237
2238
2239 void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
2240 {
2241         wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
2242         sm->tdls_disabled = !enabled;
2243 }