p2p_dev_disc.c 9.3 KB

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