p2p_supplicant_sd.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. /*
  2. * wpa_supplicant - P2P service discovery
  3. * Copyright (c) 2009-2010, Atheros Communications
  4. * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
  5. *
  6. * This software may be distributed under the terms of the BSD license.
  7. * See README for more details.
  8. */
  9. #include "utils/includes.h"
  10. #include "utils/common.h"
  11. #include "p2p/p2p.h"
  12. #include "wpa_supplicant_i.h"
  13. #include "notify.h"
  14. #include "p2p_supplicant.h"
  15. /*
  16. * DNS Header section is used only to calculate compression pointers, so the
  17. * contents of this data does not matter, but the length needs to be reserved
  18. * in the virtual packet.
  19. */
  20. #define DNS_HEADER_LEN 12
  21. /*
  22. * 27-octet in-memory packet from P2P specification containing two implied
  23. * queries for _tcp.lcoal. PTR IN and _udp.local. PTR IN
  24. */
  25. #define P2P_SD_IN_MEMORY_LEN 27
  26. static int p2p_sd_dns_uncompress_label(char **upos, char *uend, u8 *start,
  27. u8 **spos, const u8 *end)
  28. {
  29. while (*spos < end) {
  30. u8 val = ((*spos)[0] & 0xc0) >> 6;
  31. int len;
  32. if (val == 1 || val == 2) {
  33. /* These are reserved values in RFC 1035 */
  34. wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
  35. "sequence starting with 0x%x", val);
  36. return -1;
  37. }
  38. if (val == 3) {
  39. u16 offset;
  40. u8 *spos_tmp;
  41. /* Offset */
  42. if (end - *spos < 2) {
  43. wpa_printf(MSG_DEBUG, "P2P: No room for full "
  44. "DNS offset field");
  45. return -1;
  46. }
  47. offset = (((*spos)[0] & 0x3f) << 8) | (*spos)[1];
  48. if (offset >= *spos - start) {
  49. wpa_printf(MSG_DEBUG, "P2P: Invalid DNS "
  50. "pointer offset %u", offset);
  51. return -1;
  52. }
  53. (*spos) += 2;
  54. spos_tmp = start + offset;
  55. return p2p_sd_dns_uncompress_label(upos, uend, start,
  56. &spos_tmp,
  57. *spos - 2);
  58. }
  59. /* Label */
  60. len = (*spos)[0] & 0x3f;
  61. if (len == 0)
  62. return 0;
  63. (*spos)++;
  64. if (len > end - *spos) {
  65. wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
  66. "sequence - no room for label with length "
  67. "%u", len);
  68. return -1;
  69. }
  70. if (len + 2 > uend - *upos)
  71. return -2;
  72. os_memcpy(*upos, *spos, len);
  73. *spos += len;
  74. *upos += len;
  75. (*upos)[0] = '.';
  76. (*upos)++;
  77. (*upos)[0] = '\0';
  78. }
  79. return 0;
  80. }
  81. /* Uncompress domain names per RFC 1035 using the P2P SD in-memory packet.
  82. * Returns -1 on parsing error (invalid input sequence), -2 if output buffer is
  83. * not large enough */
  84. static int p2p_sd_dns_uncompress(char *buf, size_t buf_len, const u8 *msg,
  85. size_t msg_len, size_t offset)
  86. {
  87. /* 27-octet in-memory packet from P2P specification */
  88. const char *prefix = "\x04_tcp\x05local\x00\x00\x0C\x00\x01"
  89. "\x04_udp\xC0\x11\x00\x0C\x00\x01";
  90. u8 *tmp, *end, *spos;
  91. char *upos, *uend;
  92. int ret = 0;
  93. if (buf_len < 2)
  94. return -1;
  95. if (offset > msg_len)
  96. return -1;
  97. tmp = os_malloc(DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN + msg_len);
  98. if (tmp == NULL)
  99. return -1;
  100. spos = tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN;
  101. end = spos + msg_len;
  102. spos += offset;
  103. os_memset(tmp, 0, DNS_HEADER_LEN);
  104. os_memcpy(tmp + DNS_HEADER_LEN, prefix, P2P_SD_IN_MEMORY_LEN);
  105. os_memcpy(tmp + DNS_HEADER_LEN + P2P_SD_IN_MEMORY_LEN, msg, msg_len);
  106. upos = buf;
  107. uend = buf + buf_len;
  108. ret = p2p_sd_dns_uncompress_label(&upos, uend, tmp, &spos, end);
  109. if (ret) {
  110. os_free(tmp);
  111. return ret;
  112. }
  113. if (upos == buf) {
  114. upos[0] = '.';
  115. upos[1] = '\0';
  116. } else if (upos[-1] == '.')
  117. upos[-1] = '\0';
  118. os_free(tmp);
  119. return 0;
  120. }
  121. static struct p2p_srv_bonjour *
  122. wpas_p2p_service_get_bonjour(struct wpa_supplicant *wpa_s,
  123. const struct wpabuf *query)
  124. {
  125. struct p2p_srv_bonjour *bsrv;
  126. size_t len;
  127. len = wpabuf_len(query);
  128. dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
  129. struct p2p_srv_bonjour, list) {
  130. if (len == wpabuf_len(bsrv->query) &&
  131. os_memcmp(wpabuf_head(query), wpabuf_head(bsrv->query),
  132. len) == 0)
  133. return bsrv;
  134. }
  135. return NULL;
  136. }
  137. static struct p2p_srv_upnp *
  138. wpas_p2p_service_get_upnp(struct wpa_supplicant *wpa_s, u8 version,
  139. const char *service)
  140. {
  141. struct p2p_srv_upnp *usrv;
  142. dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
  143. struct p2p_srv_upnp, list) {
  144. if (version == usrv->version &&
  145. os_strcmp(service, usrv->service) == 0)
  146. return usrv;
  147. }
  148. return NULL;
  149. }
  150. static void wpas_sd_add_empty(struct wpabuf *resp, u8 srv_proto,
  151. u8 srv_trans_id, u8 status)
  152. {
  153. u8 *len_pos;
  154. if (wpabuf_tailroom(resp) < 5)
  155. return;
  156. /* Length (to be filled) */
  157. len_pos = wpabuf_put(resp, 2);
  158. wpabuf_put_u8(resp, srv_proto);
  159. wpabuf_put_u8(resp, srv_trans_id);
  160. /* Status Code */
  161. wpabuf_put_u8(resp, status);
  162. /* Response Data: empty */
  163. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
  164. }
  165. static void wpas_sd_add_proto_not_avail(struct wpabuf *resp, u8 srv_proto,
  166. u8 srv_trans_id)
  167. {
  168. wpas_sd_add_empty(resp, srv_proto, srv_trans_id,
  169. P2P_SD_PROTO_NOT_AVAILABLE);
  170. }
  171. static void wpas_sd_add_bad_request(struct wpabuf *resp, u8 srv_proto,
  172. u8 srv_trans_id)
  173. {
  174. wpas_sd_add_empty(resp, srv_proto, srv_trans_id, P2P_SD_BAD_REQUEST);
  175. }
  176. static void wpas_sd_add_not_found(struct wpabuf *resp, u8 srv_proto,
  177. u8 srv_trans_id)
  178. {
  179. wpas_sd_add_empty(resp, srv_proto, srv_trans_id,
  180. P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
  181. }
  182. static void wpas_sd_all_bonjour(struct wpa_supplicant *wpa_s,
  183. struct wpabuf *resp, u8 srv_trans_id)
  184. {
  185. struct p2p_srv_bonjour *bsrv;
  186. u8 *len_pos;
  187. wpa_printf(MSG_DEBUG, "P2P: SD Request for all Bonjour services");
  188. if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
  189. wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
  190. return;
  191. }
  192. dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
  193. struct p2p_srv_bonjour, list) {
  194. if (wpabuf_tailroom(resp) <
  195. 5 + wpabuf_len(bsrv->query) + wpabuf_len(bsrv->resp))
  196. return;
  197. /* Length (to be filled) */
  198. len_pos = wpabuf_put(resp, 2);
  199. wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
  200. wpabuf_put_u8(resp, srv_trans_id);
  201. /* Status Code */
  202. wpabuf_put_u8(resp, P2P_SD_SUCCESS);
  203. wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
  204. wpabuf_head(bsrv->resp),
  205. wpabuf_len(bsrv->resp));
  206. /* Response Data */
  207. wpabuf_put_buf(resp, bsrv->query); /* Key */
  208. wpabuf_put_buf(resp, bsrv->resp); /* Value */
  209. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
  210. 2);
  211. }
  212. }
  213. static int match_bonjour_query(struct p2p_srv_bonjour *bsrv, const u8 *query,
  214. size_t query_len)
  215. {
  216. char str_rx[256], str_srv[256];
  217. if (query_len < 3 || wpabuf_len(bsrv->query) < 3)
  218. return 0; /* Too short to include DNS Type and Version */
  219. if (os_memcmp(query + query_len - 3,
  220. wpabuf_head_u8(bsrv->query) + wpabuf_len(bsrv->query) - 3,
  221. 3) != 0)
  222. return 0; /* Mismatch in DNS Type or Version */
  223. if (query_len == wpabuf_len(bsrv->query) &&
  224. os_memcmp(query, wpabuf_head(bsrv->query), query_len - 3) == 0)
  225. return 1; /* Binary match */
  226. if (p2p_sd_dns_uncompress(str_rx, sizeof(str_rx), query, query_len - 3,
  227. 0))
  228. return 0; /* Failed to uncompress query */
  229. if (p2p_sd_dns_uncompress(str_srv, sizeof(str_srv),
  230. wpabuf_head(bsrv->query),
  231. wpabuf_len(bsrv->query) - 3, 0))
  232. return 0; /* Failed to uncompress service */
  233. return os_strcmp(str_rx, str_srv) == 0;
  234. }
  235. static void wpas_sd_req_bonjour(struct wpa_supplicant *wpa_s,
  236. struct wpabuf *resp, u8 srv_trans_id,
  237. const u8 *query, size_t query_len)
  238. {
  239. struct p2p_srv_bonjour *bsrv;
  240. u8 *len_pos;
  241. int matches = 0;
  242. wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for Bonjour",
  243. query, query_len);
  244. if (dl_list_empty(&wpa_s->global->p2p_srv_bonjour)) {
  245. wpa_printf(MSG_DEBUG, "P2P: Bonjour protocol not available");
  246. wpas_sd_add_proto_not_avail(resp, P2P_SERV_BONJOUR,
  247. srv_trans_id);
  248. return;
  249. }
  250. if (query_len == 0) {
  251. wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
  252. return;
  253. }
  254. dl_list_for_each(bsrv, &wpa_s->global->p2p_srv_bonjour,
  255. struct p2p_srv_bonjour, list) {
  256. if (!match_bonjour_query(bsrv, query, query_len))
  257. continue;
  258. if (wpabuf_tailroom(resp) <
  259. 5 + query_len + wpabuf_len(bsrv->resp))
  260. return;
  261. matches++;
  262. /* Length (to be filled) */
  263. len_pos = wpabuf_put(resp, 2);
  264. wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
  265. wpabuf_put_u8(resp, srv_trans_id);
  266. /* Status Code */
  267. wpabuf_put_u8(resp, P2P_SD_SUCCESS);
  268. wpa_hexdump_ascii(MSG_DEBUG, "P2P: Matching Bonjour service",
  269. wpabuf_head(bsrv->resp),
  270. wpabuf_len(bsrv->resp));
  271. /* Response Data */
  272. wpabuf_put_data(resp, query, query_len); /* Key */
  273. wpabuf_put_buf(resp, bsrv->resp); /* Value */
  274. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
  275. }
  276. if (matches == 0) {
  277. wpa_printf(MSG_DEBUG, "P2P: Requested Bonjour service not "
  278. "available");
  279. if (wpabuf_tailroom(resp) < 5)
  280. return;
  281. /* Length (to be filled) */
  282. len_pos = wpabuf_put(resp, 2);
  283. wpabuf_put_u8(resp, P2P_SERV_BONJOUR);
  284. wpabuf_put_u8(resp, srv_trans_id);
  285. /* Status Code */
  286. wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
  287. /* Response Data: empty */
  288. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
  289. 2);
  290. }
  291. }
  292. static void wpas_sd_all_upnp(struct wpa_supplicant *wpa_s,
  293. struct wpabuf *resp, u8 srv_trans_id)
  294. {
  295. struct p2p_srv_upnp *usrv;
  296. u8 *len_pos;
  297. wpa_printf(MSG_DEBUG, "P2P: SD Request for all UPnP services");
  298. if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
  299. wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
  300. return;
  301. }
  302. dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
  303. struct p2p_srv_upnp, list) {
  304. if (wpabuf_tailroom(resp) < 5 + 1 + os_strlen(usrv->service))
  305. return;
  306. /* Length (to be filled) */
  307. len_pos = wpabuf_put(resp, 2);
  308. wpabuf_put_u8(resp, P2P_SERV_UPNP);
  309. wpabuf_put_u8(resp, srv_trans_id);
  310. /* Status Code */
  311. wpabuf_put_u8(resp, P2P_SD_SUCCESS);
  312. /* Response Data */
  313. wpabuf_put_u8(resp, usrv->version);
  314. wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
  315. usrv->service);
  316. wpabuf_put_str(resp, usrv->service);
  317. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos -
  318. 2);
  319. }
  320. }
  321. static void wpas_sd_req_upnp(struct wpa_supplicant *wpa_s,
  322. struct wpabuf *resp, u8 srv_trans_id,
  323. const u8 *query, size_t query_len)
  324. {
  325. struct p2p_srv_upnp *usrv;
  326. u8 *len_pos;
  327. u8 version;
  328. char *str;
  329. int count = 0;
  330. wpa_hexdump_ascii(MSG_DEBUG, "P2P: SD Request for UPnP",
  331. query, query_len);
  332. if (dl_list_empty(&wpa_s->global->p2p_srv_upnp)) {
  333. wpa_printf(MSG_DEBUG, "P2P: UPnP protocol not available");
  334. wpas_sd_add_proto_not_avail(resp, P2P_SERV_UPNP,
  335. srv_trans_id);
  336. return;
  337. }
  338. if (query_len == 0) {
  339. wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
  340. return;
  341. }
  342. if (wpabuf_tailroom(resp) < 5)
  343. return;
  344. /* Length (to be filled) */
  345. len_pos = wpabuf_put(resp, 2);
  346. wpabuf_put_u8(resp, P2P_SERV_UPNP);
  347. wpabuf_put_u8(resp, srv_trans_id);
  348. version = query[0];
  349. str = os_malloc(query_len);
  350. if (str == NULL)
  351. return;
  352. os_memcpy(str, query + 1, query_len - 1);
  353. str[query_len - 1] = '\0';
  354. dl_list_for_each(usrv, &wpa_s->global->p2p_srv_upnp,
  355. struct p2p_srv_upnp, list) {
  356. if (version != usrv->version)
  357. continue;
  358. if (os_strcmp(str, "ssdp:all") != 0 &&
  359. os_strstr(usrv->service, str) == NULL)
  360. continue;
  361. if (wpabuf_tailroom(resp) < 2)
  362. break;
  363. if (count == 0) {
  364. /* Status Code */
  365. wpabuf_put_u8(resp, P2P_SD_SUCCESS);
  366. /* Response Data */
  367. wpabuf_put_u8(resp, version);
  368. } else
  369. wpabuf_put_u8(resp, ',');
  370. count++;
  371. wpa_printf(MSG_DEBUG, "P2P: Matching UPnP Service: %s",
  372. usrv->service);
  373. if (wpabuf_tailroom(resp) < os_strlen(usrv->service))
  374. break;
  375. wpabuf_put_str(resp, usrv->service);
  376. }
  377. os_free(str);
  378. if (count == 0) {
  379. wpa_printf(MSG_DEBUG, "P2P: Requested UPnP service not "
  380. "available");
  381. /* Status Code */
  382. wpabuf_put_u8(resp, P2P_SD_REQUESTED_INFO_NOT_AVAILABLE);
  383. /* Response Data: empty */
  384. }
  385. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
  386. }
  387. #ifdef CONFIG_WIFI_DISPLAY
  388. static void wpas_sd_req_wfd(struct wpa_supplicant *wpa_s,
  389. struct wpabuf *resp, u8 srv_trans_id,
  390. const u8 *query, size_t query_len)
  391. {
  392. const u8 *pos;
  393. u8 role;
  394. u8 *len_pos;
  395. wpa_hexdump(MSG_DEBUG, "P2P: SD Request for WFD", query, query_len);
  396. if (!wpa_s->global->wifi_display) {
  397. wpa_printf(MSG_DEBUG, "P2P: WFD protocol not available");
  398. wpas_sd_add_proto_not_avail(resp, P2P_SERV_WIFI_DISPLAY,
  399. srv_trans_id);
  400. return;
  401. }
  402. if (query_len < 1) {
  403. wpa_printf(MSG_DEBUG, "P2P: Missing WFD Requested Device "
  404. "Role");
  405. return;
  406. }
  407. if (wpabuf_tailroom(resp) < 5)
  408. return;
  409. pos = query;
  410. role = *pos++;
  411. wpa_printf(MSG_DEBUG, "P2P: WSD for device role 0x%x", role);
  412. /* TODO: role specific handling */
  413. /* Length (to be filled) */
  414. len_pos = wpabuf_put(resp, 2);
  415. wpabuf_put_u8(resp, P2P_SERV_WIFI_DISPLAY);
  416. wpabuf_put_u8(resp, srv_trans_id);
  417. wpabuf_put_u8(resp, P2P_SD_SUCCESS); /* Status Code */
  418. while (pos < query + query_len) {
  419. if (*pos < MAX_WFD_SUBELEMS &&
  420. wpa_s->global->wfd_subelem[*pos] &&
  421. wpabuf_tailroom(resp) >=
  422. wpabuf_len(wpa_s->global->wfd_subelem[*pos])) {
  423. wpa_printf(MSG_DEBUG, "P2P: Add WSD response "
  424. "subelement %u", *pos);
  425. wpabuf_put_buf(resp, wpa_s->global->wfd_subelem[*pos]);
  426. }
  427. pos++;
  428. }
  429. WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
  430. }
  431. #endif /* CONFIG_WIFI_DISPLAY */
  432. static int find_p2ps_substr(struct p2ps_advertisement *adv_data,
  433. const u8 *needle, size_t needle_len)
  434. {
  435. const u8 *haystack = (const u8 *) adv_data->svc_info;
  436. size_t haystack_len, i;
  437. /* Allow search term to be empty */
  438. if (!needle || !needle_len)
  439. return 1;
  440. if (!haystack)
  441. return 0;
  442. haystack_len = os_strlen(adv_data->svc_info);
  443. for (i = 0; i < haystack_len; i++) {
  444. if (haystack_len - i < needle_len)
  445. break;
  446. if (os_memcmp(haystack + i, needle, needle_len) == 0)
  447. return 1;
  448. }
  449. return 0;
  450. }
  451. static void wpas_sd_req_asp(struct wpa_supplicant *wpa_s,
  452. struct wpabuf *resp, u8 srv_trans_id,
  453. const u8 *query, size_t query_len)
  454. {
  455. struct p2ps_advertisement *adv_data;
  456. const u8 *svc = &query[1];
  457. const u8 *info = NULL;
  458. size_t svc_len = query[0];
  459. size_t info_len = 0;
  460. int prefix = 0;
  461. u8 *count_pos = NULL;
  462. u8 *len_pos = NULL;
  463. wpa_hexdump(MSG_DEBUG, "P2P: SD Request for ASP", query, query_len);
  464. if (!wpa_s->global->p2p) {
  465. wpa_printf(MSG_DEBUG, "P2P: ASP protocol not available");
  466. wpas_sd_add_proto_not_avail(resp, P2P_SERV_P2PS, srv_trans_id);
  467. return;
  468. }
  469. /* Info block is optional */
  470. if (svc_len + 1 < query_len) {
  471. info = &svc[svc_len];
  472. info_len = *info++;
  473. }
  474. /* Range check length of svc string and info block */
  475. if (svc_len + (info_len ? info_len + 2 : 1) > query_len) {
  476. wpa_printf(MSG_DEBUG, "P2P: ASP bad request");
  477. wpas_sd_add_bad_request(resp, P2P_SERV_P2PS, srv_trans_id);
  478. return;
  479. }
  480. /* Detect and correct for prefix search */
  481. if (svc_len && svc[svc_len - 1] == '*') {
  482. prefix = 1;
  483. svc_len--;
  484. }
  485. for (adv_data = p2p_get_p2ps_adv_list(wpa_s->global->p2p);
  486. adv_data; adv_data = adv_data->next) {
  487. /* If not a prefix match, reject length mismatches */
  488. if (!prefix && svc_len != os_strlen(adv_data->svc_name))
  489. continue;
  490. /* Search each service for request */
  491. if (os_memcmp(adv_data->svc_name, svc, svc_len) == 0 &&
  492. find_p2ps_substr(adv_data, info, info_len)) {
  493. size_t len = os_strlen(adv_data->svc_name);
  494. size_t svc_info_len = 0;
  495. if (adv_data->svc_info)
  496. svc_info_len = os_strlen(adv_data->svc_info);
  497. if (len > 0xff || svc_info_len > 0xffff)
  498. return;
  499. /* Length & Count to be filled as we go */
  500. if (!len_pos && !count_pos) {
  501. if (wpabuf_tailroom(resp) <
  502. len + svc_info_len + 16)
  503. return;
  504. len_pos = wpabuf_put(resp, 2);
  505. wpabuf_put_u8(resp, P2P_SERV_P2PS);
  506. wpabuf_put_u8(resp, srv_trans_id);
  507. /* Status Code */
  508. wpabuf_put_u8(resp, P2P_SD_SUCCESS);
  509. count_pos = wpabuf_put(resp, 1);
  510. *count_pos = 0;
  511. } else if (wpabuf_tailroom(resp) <
  512. len + svc_info_len + 10)
  513. return;
  514. if (svc_info_len) {
  515. wpa_printf(MSG_DEBUG,
  516. "P2P: Add Svc: %s info: %s",
  517. adv_data->svc_name,
  518. adv_data->svc_info);
  519. } else {
  520. wpa_printf(MSG_DEBUG, "P2P: Add Svc: %s",
  521. adv_data->svc_name);
  522. }
  523. /* Advertisement ID */
  524. wpabuf_put_le32(resp, adv_data->id);
  525. /* Config Methods */
  526. wpabuf_put_be16(resp, adv_data->config_methods);
  527. /* Service Name */
  528. wpabuf_put_u8(resp, (u8) len);
  529. wpabuf_put_data(resp, adv_data->svc_name, len);
  530. /* Service State */
  531. wpabuf_put_u8(resp, adv_data->state);
  532. /* Service Information */
  533. wpabuf_put_le16(resp, (u16) svc_info_len);
  534. wpabuf_put_data(resp, adv_data->svc_info, svc_info_len);
  535. /* Update length and count */
  536. (*count_pos)++;
  537. WPA_PUT_LE16(len_pos,
  538. (u8 *) wpabuf_put(resp, 0) - len_pos - 2);
  539. }
  540. }
  541. /* Return error if no matching svc found */
  542. if (count_pos == NULL) {
  543. wpa_printf(MSG_DEBUG, "P2P: ASP service not found");
  544. wpas_sd_add_not_found(resp, P2P_SERV_P2PS, srv_trans_id);
  545. }
  546. }
  547. static void wpas_sd_all_asp(struct wpa_supplicant *wpa_s,
  548. struct wpabuf *resp, u8 srv_trans_id)
  549. {
  550. /* Query data to add all P2PS advertisements:
  551. * - Service name length: 1
  552. * - Service name: '*'
  553. * - Service Information Request Length: 0
  554. */
  555. const u8 q[] = { 1, (const u8) '*', 0 };
  556. if (p2p_get_p2ps_adv_list(wpa_s->global->p2p))
  557. wpas_sd_req_asp(wpa_s, resp, srv_trans_id, q, sizeof(q));
  558. }
  559. void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
  560. u16 update_indic, const u8 *tlvs, size_t tlvs_len)
  561. {
  562. struct wpa_supplicant *wpa_s = ctx;
  563. const u8 *pos = tlvs;
  564. const u8 *end = tlvs + tlvs_len;
  565. const u8 *tlv_end;
  566. u16 slen;
  567. struct wpabuf *resp;
  568. u8 srv_proto, srv_trans_id;
  569. size_t buf_len;
  570. char *buf;
  571. wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Request TLVs",
  572. tlvs, tlvs_len);
  573. buf_len = 2 * tlvs_len + 1;
  574. buf = os_malloc(buf_len);
  575. if (buf) {
  576. wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
  577. wpa_msg_ctrl(wpa_s, MSG_INFO, P2P_EVENT_SERV_DISC_REQ "%d "
  578. MACSTR " %u %u %s",
  579. freq, MAC2STR(sa), dialog_token, update_indic,
  580. buf);
  581. os_free(buf);
  582. }
  583. if (wpa_s->p2p_sd_over_ctrl_iface) {
  584. wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
  585. update_indic, tlvs, tlvs_len);
  586. return; /* to be processed by an external program */
  587. }
  588. resp = wpabuf_alloc(10000);
  589. if (resp == NULL)
  590. return;
  591. while (end - pos > 1) {
  592. wpa_printf(MSG_DEBUG, "P2P: Service Request TLV");
  593. slen = WPA_GET_LE16(pos);
  594. pos += 2;
  595. if (slen > end - pos || slen < 2) {
  596. wpa_printf(MSG_DEBUG, "P2P: Unexpected Query Data "
  597. "length");
  598. wpabuf_free(resp);
  599. return;
  600. }
  601. tlv_end = pos + slen;
  602. srv_proto = *pos++;
  603. wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
  604. srv_proto);
  605. srv_trans_id = *pos++;
  606. wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
  607. srv_trans_id);
  608. wpa_hexdump(MSG_MSGDUMP, "P2P: Query Data",
  609. pos, tlv_end - pos);
  610. if (wpa_s->force_long_sd) {
  611. wpa_printf(MSG_DEBUG, "P2P: SD test - force long "
  612. "response");
  613. wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
  614. wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
  615. wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
  616. goto done;
  617. }
  618. switch (srv_proto) {
  619. case P2P_SERV_ALL_SERVICES:
  620. wpa_printf(MSG_DEBUG, "P2P: Service Discovery Request "
  621. "for all services");
  622. if (dl_list_empty(&wpa_s->global->p2p_srv_upnp) &&
  623. dl_list_empty(&wpa_s->global->p2p_srv_bonjour) &&
  624. !p2p_get_p2ps_adv_list(wpa_s->global->p2p)) {
  625. wpa_printf(MSG_DEBUG, "P2P: No service "
  626. "discovery protocols available");
  627. wpas_sd_add_proto_not_avail(
  628. resp, P2P_SERV_ALL_SERVICES,
  629. srv_trans_id);
  630. break;
  631. }
  632. wpas_sd_all_bonjour(wpa_s, resp, srv_trans_id);
  633. wpas_sd_all_upnp(wpa_s, resp, srv_trans_id);
  634. wpas_sd_all_asp(wpa_s, resp, srv_trans_id);
  635. break;
  636. case P2P_SERV_BONJOUR:
  637. wpas_sd_req_bonjour(wpa_s, resp, srv_trans_id,
  638. pos, tlv_end - pos);
  639. break;
  640. case P2P_SERV_UPNP:
  641. wpas_sd_req_upnp(wpa_s, resp, srv_trans_id,
  642. pos, tlv_end - pos);
  643. break;
  644. #ifdef CONFIG_WIFI_DISPLAY
  645. case P2P_SERV_WIFI_DISPLAY:
  646. wpas_sd_req_wfd(wpa_s, resp, srv_trans_id,
  647. pos, tlv_end - pos);
  648. break;
  649. #endif /* CONFIG_WIFI_DISPLAY */
  650. case P2P_SERV_P2PS:
  651. wpas_sd_req_asp(wpa_s, resp, srv_trans_id,
  652. pos, tlv_end - pos);
  653. break;
  654. default:
  655. wpa_printf(MSG_DEBUG, "P2P: Unavailable service "
  656. "protocol %u", srv_proto);
  657. wpas_sd_add_proto_not_avail(resp, srv_proto,
  658. srv_trans_id);
  659. break;
  660. }
  661. pos = tlv_end;
  662. }
  663. done:
  664. wpas_notify_p2p_sd_request(wpa_s, freq, sa, dialog_token,
  665. update_indic, tlvs, tlvs_len);
  666. wpas_p2p_sd_response(wpa_s, freq, sa, dialog_token, resp);
  667. wpabuf_free(resp);
  668. }
  669. static void wpas_sd_p2ps_serv_response(struct wpa_supplicant *wpa_s,
  670. const u8 *sa, u8 srv_trans_id,
  671. const u8 *pos, const u8 *tlv_end)
  672. {
  673. u8 left = *pos++;
  674. u32 adv_id;
  675. u8 svc_status;
  676. u16 config_methods;
  677. char svc_str[256];
  678. while (left-- && pos < tlv_end) {
  679. char *buf = NULL;
  680. size_t buf_len;
  681. u8 svc_len;
  682. /* Sanity check fixed length+svc_str */
  683. if (6 >= tlv_end - pos)
  684. break;
  685. svc_len = pos[6];
  686. if (svc_len + 10 > tlv_end - pos)
  687. break;
  688. /* Advertisement ID */
  689. adv_id = WPA_GET_LE32(pos);
  690. pos += sizeof(u32);
  691. /* Config Methods */
  692. config_methods = WPA_GET_BE16(pos);
  693. pos += sizeof(u16);
  694. /* Service Name */
  695. pos++; /* svc_len */
  696. os_memcpy(svc_str, pos, svc_len);
  697. svc_str[svc_len] = '\0';
  698. pos += svc_len;
  699. /* Service Status */
  700. svc_status = *pos++;
  701. /* Service Information Length */
  702. buf_len = WPA_GET_LE16(pos);
  703. pos += sizeof(u16);
  704. /* Sanity check buffer length */
  705. if (buf_len > (unsigned int) (tlv_end - pos))
  706. break;
  707. if (buf_len) {
  708. buf = os_zalloc(2 * buf_len + 1);
  709. if (buf) {
  710. utf8_escape((const char *) pos, buf_len, buf,
  711. 2 * buf_len + 1);
  712. }
  713. }
  714. pos += buf_len;
  715. if (buf) {
  716. wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_SERV_ASP_RESP
  717. MACSTR " %x %x %x %x %s '%s'",
  718. MAC2STR(sa), srv_trans_id, adv_id,
  719. svc_status, config_methods, svc_str,
  720. buf);
  721. os_free(buf);
  722. } else {
  723. wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_SERV_ASP_RESP
  724. MACSTR " %x %x %x %x %s",
  725. MAC2STR(sa), srv_trans_id, adv_id,
  726. svc_status, config_methods, svc_str);
  727. }
  728. }
  729. }
  730. void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
  731. const u8 *tlvs, size_t tlvs_len)
  732. {
  733. struct wpa_supplicant *wpa_s = ctx;
  734. const u8 *pos = tlvs;
  735. const u8 *end = tlvs + tlvs_len;
  736. const u8 *tlv_end;
  737. u16 slen;
  738. size_t buf_len;
  739. char *buf;
  740. wpa_hexdump(MSG_MSGDUMP, "P2P: Service Discovery Response TLVs",
  741. tlvs, tlvs_len);
  742. if (tlvs_len > 1500) {
  743. /* TODO: better way for handling this */
  744. wpa_msg_ctrl(wpa_s, MSG_INFO,
  745. P2P_EVENT_SERV_DISC_RESP MACSTR
  746. " %u <long response: %u bytes>",
  747. MAC2STR(sa), update_indic,
  748. (unsigned int) tlvs_len);
  749. } else {
  750. buf_len = 2 * tlvs_len + 1;
  751. buf = os_malloc(buf_len);
  752. if (buf) {
  753. wpa_snprintf_hex(buf, buf_len, tlvs, tlvs_len);
  754. wpa_msg_ctrl(wpa_s, MSG_INFO,
  755. P2P_EVENT_SERV_DISC_RESP MACSTR " %u %s",
  756. MAC2STR(sa), update_indic, buf);
  757. os_free(buf);
  758. }
  759. }
  760. while (end - pos >= 2) {
  761. u8 srv_proto, srv_trans_id, status;
  762. wpa_printf(MSG_DEBUG, "P2P: Service Response TLV");
  763. slen = WPA_GET_LE16(pos);
  764. pos += 2;
  765. if (slen > end - pos || slen < 3) {
  766. wpa_printf(MSG_DEBUG, "P2P: Unexpected Response Data "
  767. "length");
  768. return;
  769. }
  770. tlv_end = pos + slen;
  771. srv_proto = *pos++;
  772. wpa_printf(MSG_DEBUG, "P2P: Service Protocol Type %u",
  773. srv_proto);
  774. srv_trans_id = *pos++;
  775. wpa_printf(MSG_DEBUG, "P2P: Service Transaction ID %u",
  776. srv_trans_id);
  777. status = *pos++;
  778. wpa_printf(MSG_DEBUG, "P2P: Status Code ID %u",
  779. status);
  780. wpa_hexdump(MSG_MSGDUMP, "P2P: Response Data",
  781. pos, tlv_end - pos);
  782. if (srv_proto == P2P_SERV_P2PS && pos < tlv_end) {
  783. wpas_sd_p2ps_serv_response(wpa_s, sa, srv_trans_id,
  784. pos, tlv_end);
  785. }
  786. pos = tlv_end;
  787. }
  788. wpas_notify_p2p_sd_response(wpa_s, sa, update_indic, tlvs, tlvs_len);
  789. }
  790. u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
  791. const struct wpabuf *tlvs)
  792. {
  793. if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
  794. return 0;
  795. return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
  796. }
  797. u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
  798. u8 version, const char *query)
  799. {
  800. struct wpabuf *tlvs;
  801. u64 ret;
  802. tlvs = wpabuf_alloc(2 + 1 + 1 + 1 + os_strlen(query));
  803. if (tlvs == NULL)
  804. return 0;
  805. wpabuf_put_le16(tlvs, 1 + 1 + 1 + os_strlen(query));
  806. wpabuf_put_u8(tlvs, P2P_SERV_UPNP); /* Service Protocol Type */
  807. wpabuf_put_u8(tlvs, 1); /* Service Transaction ID */
  808. wpabuf_put_u8(tlvs, version);
  809. wpabuf_put_str(tlvs, query);
  810. ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
  811. wpabuf_free(tlvs);
  812. return ret;
  813. }
  814. u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id,
  815. const char *svc_str, const char *info_substr)
  816. {
  817. struct wpabuf *tlvs;
  818. size_t plen, svc_len, substr_len = 0;
  819. u64 ret;
  820. svc_len = os_strlen(svc_str);
  821. if (info_substr)
  822. substr_len = os_strlen(info_substr);
  823. if (svc_len > 0xff || substr_len > 0xff)
  824. return 0;
  825. plen = 1 + 1 + 1 + svc_len + 1 + substr_len;
  826. tlvs = wpabuf_alloc(2 + plen);
  827. if (tlvs == NULL)
  828. return 0;
  829. wpabuf_put_le16(tlvs, plen);
  830. wpabuf_put_u8(tlvs, P2P_SERV_P2PS);
  831. wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
  832. wpabuf_put_u8(tlvs, (u8) svc_len); /* Service String Length */
  833. wpabuf_put_data(tlvs, svc_str, svc_len);
  834. wpabuf_put_u8(tlvs, (u8) substr_len); /* Info Substring Length */
  835. wpabuf_put_data(tlvs, info_substr, substr_len);
  836. ret = wpas_p2p_sd_request(wpa_s, dst, tlvs);
  837. wpabuf_free(tlvs);
  838. return ret;
  839. }
  840. #ifdef CONFIG_WIFI_DISPLAY
  841. static u64 wpas_p2p_sd_request_wfd(struct wpa_supplicant *wpa_s, const u8 *dst,
  842. const struct wpabuf *tlvs)
  843. {
  844. if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
  845. return 0;
  846. return (uintptr_t) p2p_sd_request_wfd(wpa_s->global->p2p, dst, tlvs);
  847. }
  848. #define MAX_WFD_SD_SUBELEMS 20
  849. static void wfd_add_sd_req_role(struct wpabuf *tlvs, u8 id, u8 role,
  850. const char *subelems)
  851. {
  852. u8 *len;
  853. const char *pos;
  854. int val;
  855. int count = 0;
  856. len = wpabuf_put(tlvs, 2);
  857. wpabuf_put_u8(tlvs, P2P_SERV_WIFI_DISPLAY); /* Service Protocol Type */
  858. wpabuf_put_u8(tlvs, id); /* Service Transaction ID */
  859. wpabuf_put_u8(tlvs, role);
  860. pos = subelems;
  861. while (*pos) {
  862. val = atoi(pos);
  863. if (val >= 0 && val < 256) {
  864. wpabuf_put_u8(tlvs, val);
  865. count++;
  866. if (count == MAX_WFD_SD_SUBELEMS)
  867. break;
  868. }
  869. pos = os_strchr(pos + 1, ',');
  870. if (pos == NULL)
  871. break;
  872. pos++;
  873. }
  874. WPA_PUT_LE16(len, (u8 *) wpabuf_put(tlvs, 0) - len - 2);
  875. }
  876. u64 wpas_p2p_sd_request_wifi_display(struct wpa_supplicant *wpa_s,
  877. const u8 *dst, const char *role)
  878. {
  879. struct wpabuf *tlvs;
  880. u64 ret;
  881. const char *subelems;
  882. u8 id = 1;
  883. subelems = os_strchr(role, ' ');
  884. if (subelems == NULL)
  885. return 0;
  886. subelems++;
  887. tlvs = wpabuf_alloc(4 * (2 + 1 + 1 + 1 + MAX_WFD_SD_SUBELEMS));
  888. if (tlvs == NULL)
  889. return 0;
  890. if (os_strstr(role, "[source]"))
  891. wfd_add_sd_req_role(tlvs, id++, 0x00, subelems);
  892. if (os_strstr(role, "[pri-sink]"))
  893. wfd_add_sd_req_role(tlvs, id++, 0x01, subelems);
  894. if (os_strstr(role, "[sec-sink]"))
  895. wfd_add_sd_req_role(tlvs, id++, 0x02, subelems);
  896. if (os_strstr(role, "[source+sink]"))
  897. wfd_add_sd_req_role(tlvs, id++, 0x03, subelems);
  898. ret = wpas_p2p_sd_request_wfd(wpa_s, dst, tlvs);
  899. wpabuf_free(tlvs);
  900. return ret;
  901. }
  902. #endif /* CONFIG_WIFI_DISPLAY */
  903. int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req)
  904. {
  905. if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
  906. return -1;
  907. return p2p_sd_cancel_request(wpa_s->global->p2p,
  908. (void *) (uintptr_t) req);
  909. }
  910. void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq,
  911. const u8 *dst, u8 dialog_token,
  912. const struct wpabuf *resp_tlvs)
  913. {
  914. if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
  915. return;
  916. p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
  917. resp_tlvs);
  918. }
  919. void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
  920. {
  921. if (wpa_s->global->p2p)
  922. p2p_sd_service_update(wpa_s->global->p2p);
  923. }
  924. static void wpas_p2p_srv_bonjour_free(struct p2p_srv_bonjour *bsrv)
  925. {
  926. dl_list_del(&bsrv->list);
  927. wpabuf_free(bsrv->query);
  928. wpabuf_free(bsrv->resp);
  929. os_free(bsrv);
  930. }
  931. static void wpas_p2p_srv_upnp_free(struct p2p_srv_upnp *usrv)
  932. {
  933. dl_list_del(&usrv->list);
  934. os_free(usrv->service);
  935. os_free(usrv);
  936. }
  937. void wpas_p2p_service_flush(struct wpa_supplicant *wpa_s)
  938. {
  939. struct p2p_srv_bonjour *bsrv, *bn;
  940. struct p2p_srv_upnp *usrv, *un;
  941. dl_list_for_each_safe(bsrv, bn, &wpa_s->global->p2p_srv_bonjour,
  942. struct p2p_srv_bonjour, list)
  943. wpas_p2p_srv_bonjour_free(bsrv);
  944. dl_list_for_each_safe(usrv, un, &wpa_s->global->p2p_srv_upnp,
  945. struct p2p_srv_upnp, list)
  946. wpas_p2p_srv_upnp_free(usrv);
  947. wpas_p2p_service_flush_asp(wpa_s);
  948. wpas_p2p_sd_service_update(wpa_s);
  949. }
  950. int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id)
  951. {
  952. if (adv_id == 0)
  953. return 1;
  954. if (p2p_service_p2ps_id(wpa_s->global->p2p, adv_id))
  955. return 1;
  956. return 0;
  957. }
  958. int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id)
  959. {
  960. int ret;
  961. ret = p2p_service_del_asp(wpa_s->global->p2p, adv_id);
  962. if (ret == 0)
  963. wpas_p2p_sd_service_update(wpa_s);
  964. return ret;
  965. }
  966. int wpas_p2p_service_add_asp(struct wpa_supplicant *wpa_s,
  967. int auto_accept, u32 adv_id,
  968. const char *adv_str, u8 svc_state,
  969. u16 config_methods, const char *svc_info,
  970. const u8 *cpt_priority)
  971. {
  972. int ret;
  973. ret = p2p_service_add_asp(wpa_s->global->p2p, auto_accept, adv_id,
  974. adv_str, svc_state, config_methods,
  975. svc_info, cpt_priority);
  976. if (ret == 0)
  977. wpas_p2p_sd_service_update(wpa_s);
  978. return ret;
  979. }
  980. void wpas_p2p_service_flush_asp(struct wpa_supplicant *wpa_s)
  981. {
  982. p2p_service_flush_asp(wpa_s->global->p2p);
  983. }
  984. int wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s,
  985. struct wpabuf *query, struct wpabuf *resp)
  986. {
  987. struct p2p_srv_bonjour *bsrv;
  988. bsrv = os_zalloc(sizeof(*bsrv));
  989. if (bsrv == NULL)
  990. return -1;
  991. bsrv->query = query;
  992. bsrv->resp = resp;
  993. dl_list_add(&wpa_s->global->p2p_srv_bonjour, &bsrv->list);
  994. wpas_p2p_sd_service_update(wpa_s);
  995. return 0;
  996. }
  997. int wpas_p2p_service_del_bonjour(struct wpa_supplicant *wpa_s,
  998. const struct wpabuf *query)
  999. {
  1000. struct p2p_srv_bonjour *bsrv;
  1001. bsrv = wpas_p2p_service_get_bonjour(wpa_s, query);
  1002. if (bsrv == NULL)
  1003. return -1;
  1004. wpas_p2p_srv_bonjour_free(bsrv);
  1005. wpas_p2p_sd_service_update(wpa_s);
  1006. return 0;
  1007. }
  1008. int wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version,
  1009. const char *service)
  1010. {
  1011. struct p2p_srv_upnp *usrv;
  1012. if (wpas_p2p_service_get_upnp(wpa_s, version, service))
  1013. return 0; /* Already listed */
  1014. usrv = os_zalloc(sizeof(*usrv));
  1015. if (usrv == NULL)
  1016. return -1;
  1017. usrv->version = version;
  1018. usrv->service = os_strdup(service);
  1019. if (usrv->service == NULL) {
  1020. os_free(usrv);
  1021. return -1;
  1022. }
  1023. dl_list_add(&wpa_s->global->p2p_srv_upnp, &usrv->list);
  1024. wpas_p2p_sd_service_update(wpa_s);
  1025. return 0;
  1026. }
  1027. int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
  1028. const char *service)
  1029. {
  1030. struct p2p_srv_upnp *usrv;
  1031. usrv = wpas_p2p_service_get_upnp(wpa_s, version, service);
  1032. if (usrv == NULL)
  1033. return -1;
  1034. wpas_p2p_srv_upnp_free(usrv);
  1035. wpas_p2p_sd_service_update(wpa_s);
  1036. return 0;
  1037. }