cn_did_wifi.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /*
  2. Copyright (C) 2020 Simon Wunderlich, Marek Sobe
  3. Copyright (C) 2020 Doodle Labs
  4. SPDX-License-Identifier: Apache-2.0
  5. Open Drone ID C Library
  6. Maintainer:
  7. Simon Wunderlich
  8. sw@simonwunderlich.de
  9. */
  10. /*该文件是对开源wifi修改适配国产标准*/
  11. #if defined(ARDUINO_ARCH_ESP32)
  12. #include <Arduino.h>
  13. int clock_gettime(clockid_t, struct timespec *);
  14. #else
  15. #include <string.h>
  16. #include <stddef.h>
  17. #include <stdio.h>
  18. #endif
  19. #include <errno.h>
  20. #include <time.h>
  21. #include "cn_did_wifi.h"
  22. #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  23. #define cpu_to_le16(x) (x)
  24. #define cpu_to_le64(x) (x)
  25. #else
  26. #define cpu_to_le16(x) (bswap_16(x))
  27. #define cpu_to_le64(x) (bswap_64(x))
  28. #endif
  29. #define IEEE80211_FCTL_FTYPE 0x000c
  30. #define IEEE80211_FCTL_STYPE 0x00f0
  31. #define IEEE80211_FTYPE_MGMT 0x0000
  32. #define IEEE80211_STYPE_ACTION 0x00D0
  33. #define IEEE80211_STYPE_BEACON 0x0080
  34. /* IEEE 802.11-2016 capability info */
  35. #define IEEE80211_CAPINFO_ESS 0x0001
  36. #define IEEE80211_CAPINFO_IBSS 0x0002
  37. #define IEEE80211_CAPINFO_CF_POLLABLE 0x0004
  38. #define IEEE80211_CAPINFO_CF_POLLREQ 0x0008
  39. #define IEEE80211_CAPINFO_PRIVACY 0x0010
  40. #define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020
  41. /* bits 6-7 reserved */
  42. #define IEEE80211_CAPINFO_SPECTRUM_MGMT 0x0100
  43. #define IEEE80211_CAPINFO_QOS 0x0200
  44. #define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400
  45. #define IEEE80211_CAPINFO_APSD 0x0800
  46. #define IEEE80211_CAPINFO_RADIOMEAS 0x1000
  47. /* bit 13 reserved */
  48. #define IEEE80211_CAPINFO_DEL_BLOCK_ACK 0x4000
  49. #define IEEE80211_CAPINFO_IMM_BLOCK_ACK 0x8000
  50. /* IEEE 802.11 Element IDs */
  51. #define IEEE80211_ELEMID_SSID 0x00
  52. #define IEEE80211_ELEMID_RATES 0x01
  53. #define IEEE80211_ELEMID_VENDOR 0xDD
  54. /* 《邻居感知网络规范》v3.1第2.8.2节
  55. * NAN集群ID是一个MAC地址,其取值范围为50-6F-9A-01-00-00至50-6F-9A-01-FF-FF,
  56. * 承载于部分NAN帧的A3字段中。NAN集群ID由发起NAN集群的设备随机选择。
  57. * 然而,《ASTM远程ID规范》v1.1规定,NAN集群ID必须固定为50-6F-9A-01-00-FF这一值。
  58. */
  59. static const uint8_t *get_nan_cluster_id(void)
  60. {
  61. static const uint8_t cluster_id[6] = { 0x50, 0x6F, 0x9A, 0x01, 0x00, 0xFF };
  62. return cluster_id;
  63. }
  64. static int buf_fill_ieee80211_mgmt(uint8_t *buf, size_t *len, size_t buf_size,
  65. const uint16_t subtype,
  66. const uint8_t *dst_addr,
  67. const uint8_t *src_addr,
  68. const uint8_t *bssid)
  69. {
  70. if (*len + sizeof(struct ieee80211_mgmt) > buf_size)
  71. return -ENOMEM;
  72. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)(buf + *len);
  73. mgmt->frame_control = (uint16_t) cpu_to_le16(IEEE80211_FTYPE_MGMT | subtype);
  74. mgmt->duration = cpu_to_le16(0x0000);
  75. memcpy(mgmt->da, dst_addr, sizeof(mgmt->da));
  76. memcpy(mgmt->sa, src_addr, sizeof(mgmt->sa));
  77. memcpy(mgmt->bssid, bssid, sizeof(mgmt->bssid));
  78. mgmt->seq_ctrl = cpu_to_le16(0x0000);
  79. *len += sizeof(*mgmt);
  80. return 0;
  81. }
  82. static int buf_fill_ieee80211_beacon(uint8_t *buf, size_t *len, size_t buf_size, uint16_t interval_tu)
  83. {
  84. if (*len + sizeof(struct ieee80211_beacon) > buf_size)
  85. return -ENOMEM;
  86. struct ieee80211_beacon *beacon = (struct ieee80211_beacon *)(buf + *len);
  87. struct timespec ts;
  88. uint64_t mono_us = 0;
  89. #if defined(CLOCK_MONOTONIC)
  90. clock_gettime(CLOCK_MONOTONIC, &ts);
  91. mono_us = (uint64_t)((double) ts.tv_sec * 1e6 + (double) ts.tv_nsec * 1e-3);
  92. #elif defined(CLOCK_REALTIME)
  93. clock_gettime(CLOCK_REALTIME, &ts);
  94. mono_us = (uint64_t)((double) ts.tv_sec * 1e6 + (double) ts.tv_nsec * 1e-3);
  95. #elif defined(ARDUINO)
  96. #warning "No REALTIME or MONOTONIC clock, using micros()."
  97. mono_us = micros();
  98. #else
  99. #warning "Unable to set wifi timestamp."
  100. #endif
  101. beacon->timestamp = cpu_to_le64(mono_us);
  102. beacon->beacon_interval = cpu_to_le16(interval_tu);
  103. beacon->capability = cpu_to_le16(IEEE80211_CAPINFO_SHORT_SLOTTIME | IEEE80211_CAPINFO_SHORT_PREAMBLE);
  104. *len += sizeof(*beacon);
  105. return 0;
  106. }
  107. /* void* 不能用 可能是编译器版本的问题 改成uint8_t* 了*/
  108. int cndid_message_build_pack(CNDID_UAS_Data *UAS_Data, uint8_t *pack, size_t buflen)
  109. {
  110. CNDID_MessagePack_data msg_pack;
  111. CNDID_MessagePack_encoded *msg_pack_enc;
  112. size_t len;
  113. /* create a complete message pack 不知道这里为什么不允许void* 都改成对应的指针类别了*/
  114. msg_pack.SingleMessageSize = CNDID_MESSAGE_SIZE;
  115. msg_pack.MsgPackSize = 0;
  116. for (int i = 0; i < CNDID_BASIC_ID_MAX_MESSAGES; i++) {
  117. if (UAS_Data->BasicIDValid[i]) {
  118. if (msg_pack.MsgPackSize >= CNDID_PACK_MAX_MESSAGES)
  119. return -EINVAL;
  120. if (encodeCNBasicIDMessage((CNDID_BasicID_encoded*)(&msg_pack.Messages[msg_pack.MsgPackSize]), &UAS_Data->BasicID[i]) == CNDID_SUCCESS)
  121. msg_pack.MsgPackSize++;
  122. }
  123. }
  124. if (UAS_Data->LocationValid) {
  125. if (msg_pack.MsgPackSize >= CNDID_PACK_MAX_MESSAGES)
  126. return -EINVAL;
  127. if (encodeCNLocationMessage((CNDID_Location_encoded*)(&msg_pack.Messages[msg_pack.MsgPackSize]), &UAS_Data->Location) == CNDID_SUCCESS)
  128. msg_pack.MsgPackSize++;
  129. }
  130. if (UAS_Data->SelfIDValid) {
  131. if (msg_pack.MsgPackSize >= CNDID_PACK_MAX_MESSAGES)
  132. return -EINVAL;
  133. if (encodeCNSelfIDMessage((CNDID_SelfID_encoded*)(&msg_pack.Messages[msg_pack.MsgPackSize]), &UAS_Data->SelfID) == CNDID_SUCCESS)
  134. msg_pack.MsgPackSize++;
  135. }
  136. if (UAS_Data->SystemValid) {
  137. if (msg_pack.MsgPackSize >= CNDID_PACK_MAX_MESSAGES)
  138. return -EINVAL;
  139. if (encodeCNSystemMessage((CNDID_System_encoded*)(&msg_pack.Messages[msg_pack.MsgPackSize]), &UAS_Data->System) == CNDID_SUCCESS)
  140. msg_pack.MsgPackSize++;
  141. }
  142. /* check that there is at least one message to send. */
  143. if (msg_pack.MsgPackSize == 0)
  144. return -EINVAL;
  145. /* calculate the exact encoded message pack size. */
  146. len = sizeof(*msg_pack_enc) - (CNDID_PACK_MAX_MESSAGES - msg_pack.MsgPackSize) * CNDID_MESSAGE_SIZE;
  147. /* check if there is enough space for the message pack. */
  148. if (len > buflen)
  149. return -ENOMEM;
  150. msg_pack_enc = (CNDID_MessagePack_encoded *) pack;
  151. if (encodeCNMessagePack(msg_pack_enc, &msg_pack) != CNDID_SUCCESS)
  152. return -1;
  153. return (int) len;
  154. }
  155. // 里面的服务id可能后面要改 还有一些指向 open droneid的
  156. int cndid_wifi_build_nan_sync_beacon_frame(char *mac, uint8_t *buf, size_t buf_size)
  157. {
  158. /* Broadcast address */
  159. uint8_t target_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  160. uint8_t wifi_alliance_oui[3] = { 0x50, 0x6F, 0x9A };
  161. /* "org.opendroneid.remoteid" hash */
  162. uint8_t service_id[6] = { 0x88, 0x69, 0x19, 0x9D, 0x92, 0x09 };
  163. const uint8_t *cluster_id = get_nan_cluster_id();
  164. struct ieee80211_vendor_specific *vendor;
  165. struct nan_master_indication_attribute *master_indication_attr;
  166. struct nan_cluster_attribute *cluster_attr;
  167. struct nan_service_id_list_attribute *nsila;
  168. int ret;
  169. size_t len = 0;
  170. /* IEEE 802.11 Management Header */
  171. ret = buf_fill_ieee80211_mgmt(buf, &len, buf_size, IEEE80211_STYPE_BEACON, target_addr, (uint8_t *)mac, cluster_id);
  172. if (ret <0)
  173. return ret;
  174. /* Beacon */
  175. ret = buf_fill_ieee80211_beacon(buf, &len, buf_size, 0x0200);
  176. if (ret <0)
  177. return ret;
  178. /* Vendor Specific */
  179. if (len + sizeof(*vendor) > buf_size)
  180. return -ENOMEM;
  181. vendor = (struct ieee80211_vendor_specific *)(buf + len);
  182. memset(vendor, 0, sizeof(*vendor));
  183. vendor->element_id = IEEE80211_ELEMID_VENDOR;
  184. vendor->length = 0x22;
  185. memcpy(vendor->oui, wifi_alliance_oui, sizeof(vendor->oui));
  186. vendor->oui_type = 0x13;
  187. len += sizeof(*vendor);
  188. /* NAN Master Indication attribute */
  189. if (len + sizeof(*master_indication_attr) > buf_size)
  190. return -ENOMEM;
  191. master_indication_attr = (struct nan_master_indication_attribute *)(buf + len);
  192. memset(master_indication_attr, 0, sizeof(*master_indication_attr));
  193. master_indication_attr->header.attribute_id = 0x00;
  194. master_indication_attr->header.length = cpu_to_le16(0x0002);
  195. /* Information that is used to indicate a NAN Device’s preference to serve
  196. * as the role of Master, with a larger value indicating a higher
  197. * preference. Values 1 and 255 are used for testing purposes only.
  198. */
  199. master_indication_attr->master_preference = 0xFE;
  200. /* Random factor value 0xEA is recommended by the European Standard */
  201. master_indication_attr->random_factor = 0xEA;
  202. len += sizeof(*master_indication_attr);
  203. /* NAN Cluster attribute */
  204. if (len + sizeof(*cluster_attr) > buf_size)
  205. return -ENOMEM;
  206. cluster_attr = (struct nan_cluster_attribute *)(buf + len);
  207. memset(cluster_attr, 0, sizeof(*cluster_attr));
  208. cluster_attr->header.attribute_id = 0x1;
  209. cluster_attr->header.length = cpu_to_le16(0x000D);
  210. memcpy(cluster_attr->device_mac, mac, sizeof(cluster_attr->device_mac));
  211. cluster_attr->random_factor = 0xEA;
  212. cluster_attr->master_preference = 0xFE;
  213. cluster_attr->hop_count_to_anchor_master = 0x00;
  214. memset(cluster_attr->anchor_master_beacon_transmission_time, 0, sizeof(cluster_attr->anchor_master_beacon_transmission_time));
  215. len += sizeof(*cluster_attr);
  216. /* NAN attributes */
  217. if (len + sizeof(*nsila) > buf_size)
  218. return -ENOMEM;
  219. nsila = (struct nan_service_id_list_attribute *)(buf + len);
  220. memset(nsila, 0, sizeof(*nsila));
  221. nsila->header.attribute_id = 0x02;
  222. nsila->header.length = cpu_to_le16(0x0006);
  223. memcpy(nsila->service_id, service_id, sizeof(service_id));
  224. len += sizeof(*nsila);
  225. return (int) len;
  226. }
  227. int cndid_wifi_build_message_pack_nan_action_frame(CNDID_UAS_Data *UAS_Data, char *mac,
  228. uint8_t send_counter,
  229. uint8_t *buf, size_t buf_size)
  230. {
  231. /* Neighbor Awareness Networking Specification v3.0 in section 2.8.1
  232. * NAN网络ID要求目标MAC地址为51-6F-9A-01-00-00*/
  233. uint8_t target_addr[6] = { 0x51, 0x6F, 0x9A, 0x01, 0x00, 0x00 };
  234. /* "org.opendroneid.remoteid 哈希值 国际通用的*/
  235. uint8_t service_id[6] = { 0x88, 0x69, 0x19, 0x9D, 0x92, 0x09 };
  236. uint8_t wifi_alliance_oui[3] = { 0x50, 0x6F, 0x9A };
  237. const uint8_t *cluster_id = get_nan_cluster_id();
  238. struct nan_service_discovery *nsd;
  239. struct nan_service_descriptor_attribute *nsda;
  240. struct nan_service_descriptor_extension_attribute *nsdea;
  241. struct CNDID_service_info *si;
  242. int ret;
  243. size_t len = 0;
  244. /* IEEE 802.11 Management Header */
  245. ret = buf_fill_ieee80211_mgmt(buf, &len, buf_size, IEEE80211_STYPE_ACTION, target_addr, (uint8_t *)mac, cluster_id);
  246. if (ret <0)
  247. return ret;
  248. /* NAN Service Discovery header */
  249. if (len + sizeof(*nsd) > buf_size)
  250. return -ENOMEM;
  251. nsd = (struct nan_service_discovery *)(buf + len);
  252. memset(nsd, 0, sizeof(*nsd));
  253. nsd->category = 0x04; /* IEEE 802.11 Public Action frame */
  254. nsd->action_code = 0x09; /* IEEE 802.11 Public Action frame Vendor Specific*/
  255. memcpy(nsd->oui, wifi_alliance_oui, sizeof(nsd->oui));
  256. nsd->oui_type = 0x13; /* Identify Type and version of the NAN */
  257. len += sizeof(*nsd);
  258. /* NAN Attribute for Service Descriptor header */
  259. if (len + sizeof(*nsda) > buf_size)
  260. return -ENOMEM;
  261. nsda = (struct nan_service_descriptor_attribute *)(buf + len);
  262. nsda->header.attribute_id = 0x3; /* Service Descriptor Attribute type */
  263. memcpy(nsda->service_id, service_id, sizeof(service_id));
  264. /* always 1 */
  265. nsda->instance_id = 0x01; /* always 1 */
  266. nsda->requestor_instance_id = 0x00; /* from triggering frame */
  267. nsda->service_control = 0x10; /* follow up */
  268. len += sizeof(*nsda);
  269. /* CNDID Service Info Attribute header */
  270. if (len + sizeof(*si) > buf_size)
  271. return -ENOMEM;
  272. si = (struct CNDID_service_info *)(buf + len);
  273. memset(si, 0, sizeof(*si));
  274. si->message_counter = send_counter;
  275. len += sizeof(*si);
  276. ret = cndid_message_build_pack(UAS_Data, buf + len, buf_size - len);
  277. if (ret < 0)
  278. return ret;
  279. len += ret;
  280. /* set the lengths according to the message pack lengths */
  281. nsda->service_info_length = sizeof(*si) + ret;
  282. nsda->header.length = cpu_to_le16(sizeof(*nsda) - sizeof(struct nan_attribute_header) + nsda->service_info_length);
  283. /* NAN Attribute for Service Descriptor extension header */
  284. if (len + sizeof(*nsdea) > buf_size)
  285. return -ENOMEM;
  286. nsdea = (struct nan_service_descriptor_extension_attribute *)(buf + len);
  287. nsdea->header.attribute_id = 0xE;
  288. nsdea->header.length = cpu_to_le16(0x0004);
  289. nsdea->instance_id = 0x01;
  290. nsdea->control = cpu_to_le16(0x0200);
  291. nsdea->service_update_indicator = send_counter;
  292. len += sizeof(*nsdea);
  293. return (int) len;
  294. }
  295. int cndid_wifi_build_message_pack_beacon_frame(CNDID_UAS_Data *UAS_Data, char *mac,
  296. const char *SSID, size_t SSID_len,
  297. uint16_t interval_tu, uint8_t send_counter,
  298. uint8_t *buf, size_t buf_size)
  299. {
  300. /* Broadcast address */
  301. uint8_t target_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  302. uint8_t asd_stan_oui[3] = { 0xFA, 0x0B, 0xBC }; // 国标也是0xFA0BBC
  303. /* Mgmt Beacon frame mandatory fields + IE 221 */
  304. struct ieee80211_ssid *ssid_s;
  305. struct ieee80211_supported_rates *rates;
  306. struct ieee80211_vendor_specific *vendor;
  307. /* Message Pack */
  308. struct CNDID_service_info *si;
  309. int ret;
  310. size_t len = 0;
  311. /* IEEE 802.11 Management Header */
  312. ret = buf_fill_ieee80211_mgmt(buf, &len, buf_size, IEEE80211_STYPE_BEACON, target_addr, (uint8_t *)mac, (uint8_t *)mac);
  313. if (ret <0)
  314. return ret;
  315. /* Mandatory Beacon as of 802.11-2016 Part 11 */
  316. ret = buf_fill_ieee80211_beacon(buf, &len, buf_size, interval_tu);
  317. if (ret <0)
  318. return ret;
  319. /* SSID: 1-32 bytes */
  320. if (len + sizeof(*ssid_s) > buf_size)
  321. return -ENOMEM;
  322. ssid_s = (struct ieee80211_ssid *)(buf + len);
  323. if(!SSID || (SSID_len ==0) || (SSID_len > 32))
  324. return -EINVAL;
  325. ssid_s->element_id = IEEE80211_ELEMID_SSID;
  326. ssid_s->length = (uint8_t) SSID_len;
  327. memcpy(ssid_s->ssid, SSID, ssid_s->length);
  328. len += sizeof(*ssid_s) + SSID_len;
  329. /* Supported Rates: 1 record at minimum */
  330. if (len + sizeof(*rates) > buf_size)
  331. return -ENOMEM;
  332. rates = (struct ieee80211_supported_rates *)(buf + len);
  333. rates->element_id = IEEE80211_ELEMID_RATES;
  334. rates->length = 1; // One rate only
  335. rates->supported_rates = 0x8C; // 6 Mbps
  336. len += sizeof(*rates);
  337. /* Vendor Specific Information Element (IE 221) */
  338. if (len + sizeof(*vendor) > buf_size)
  339. return -ENOMEM;
  340. vendor = (struct ieee80211_vendor_specific *)(buf + len);
  341. vendor->element_id = IEEE80211_ELEMID_VENDOR;
  342. vendor->length = 0x00; // Length updated at end of function
  343. memcpy(vendor->oui, asd_stan_oui, sizeof(vendor->oui));
  344. vendor->oui_type = 0x0D;
  345. len += sizeof(*vendor);
  346. /* CNDID Service Info Attribute header */
  347. if (len + sizeof(*si) > buf_size)
  348. return -ENOMEM;
  349. si = (struct CNDID_service_info *)(buf + len);
  350. memset(si, 0, sizeof(*si));
  351. si->message_counter = send_counter;
  352. len += sizeof(*si);
  353. ret = cndid_message_build_pack(UAS_Data, buf + len, buf_size - len);
  354. if (ret < 0)
  355. return ret;
  356. len += ret;
  357. /* set the lengths according to the message pack lengths */
  358. vendor->length = sizeof(vendor->oui) + sizeof(vendor->oui_type) + sizeof(*si) + ret;
  359. return (int) len;
  360. }
  361. int cndid_message_process_pack(CNDID_UAS_Data *UAS_Data, uint8_t *pack, size_t buflen)
  362. {
  363. CNDID_MessagePack_encoded *msg_pack_enc = (CNDID_MessagePack_encoded *) pack;
  364. size_t size = sizeof(*msg_pack_enc) - CNDID_MESSAGE_SIZE * (CNDID_PACK_MAX_MESSAGES - msg_pack_enc->MsgPackSize);
  365. if (size > buflen)
  366. return -ENOMEM;
  367. cndid_initUasData(UAS_Data);
  368. if (decodeCNMessagePack(UAS_Data, msg_pack_enc) != CNDID_SUCCESS)
  369. return -1;
  370. return (int) size;
  371. }
  372. int cndid_wifi_receive_message_pack_nan_action_frame(CNDID_UAS_Data *UAS_Data,
  373. char *mac, uint8_t *buf, size_t buf_size)
  374. {
  375. struct ieee80211_mgmt *mgmt; // 802.11管理帧头
  376. struct nan_service_discovery *nsd; // NAN服务发现帧头
  377. struct nan_service_descriptor_attribute *nsda; // NAN服务描述符属性
  378. struct nan_service_descriptor_extension_attribute *nsdea; // NAN服务描述符扩展属性
  379. struct CNDID_service_info *si; // 中国远程ID服务信息
  380. uint8_t target_addr[6] = { 0x51, 0x6F, 0x9A, 0x01, 0x00, 0x00 }; // 远程ID(Remote ID)分配的专用组播地址
  381. uint8_t wifi_alliance_oui[3] = { 0x50, 0x6F, 0x9A }; // Wi-Fi联盟OUI
  382. uint8_t service_id[6] = { 0x88, 0x69, 0x19, 0x9D, 0x92, 0x09 }; // 远程ID服务ID 国际通用的 不需要改
  383. int ret;
  384. size_t len = 0;
  385. /* IEEE 802.11 Management Header */
  386. if (len + sizeof(*mgmt) > buf_size) // 检查缓冲区是否足够容纳一个管理帧头
  387. return -EINVAL;
  388. mgmt = (struct ieee80211_mgmt *)(buf + len);
  389. if ((mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
  390. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION))
  391. return -EINVAL;
  392. if (memcmp(mgmt->da, target_addr, sizeof(mgmt->da)) != 0)
  393. return -EINVAL;
  394. memcpy(mac, mgmt->sa, sizeof(mgmt->sa));
  395. len += sizeof(*mgmt);
  396. /* NAN Service Discovery header */
  397. if (len + sizeof(*nsd) > buf_size)
  398. return -EINVAL;
  399. nsd = (struct nan_service_discovery *)(buf + len);
  400. if (nsd->category != 0x04)
  401. return -EINVAL;
  402. if (nsd->action_code != 0x09)
  403. return -EINVAL;
  404. if (memcmp(nsd->oui, wifi_alliance_oui, sizeof(wifi_alliance_oui)) != 0)
  405. return -EINVAL;
  406. if (nsd->oui_type != 0x13)
  407. return -EINVAL;
  408. len += sizeof(*nsd);
  409. /* NAN Attribute for Service Descriptor header */
  410. if (len + sizeof(*nsda) > buf_size)
  411. return -EINVAL;
  412. nsda = (struct nan_service_descriptor_attribute *)(buf + len);
  413. if (nsda->header.attribute_id != 0x3)
  414. return -EINVAL;
  415. if (memcmp(nsda->service_id, service_id, sizeof(service_id)) != 0)
  416. return -EINVAL;
  417. if (nsda->instance_id != 0x01)
  418. return -EINVAL;
  419. if (nsda->service_control != 0x10)
  420. return -EINVAL;
  421. len += sizeof(*nsda);
  422. si = (struct CNDID_service_info *)(buf + len);
  423. ret = cndid_message_process_pack(UAS_Data, buf + len + sizeof(*si), buf_size - len - sizeof(*nsdea));
  424. if (ret < 0)
  425. return -EINVAL;
  426. if (nsda->service_info_length != (sizeof(*si) + ret))
  427. return -EINVAL;
  428. if (nsda->header.length != (cpu_to_le16(sizeof(*nsda) - sizeof(struct nan_attribute_header) + nsda->service_info_length)))
  429. return -EINVAL;
  430. len += sizeof(*si) + ret;
  431. /* NAN Attribute for Service Descriptor extension header */
  432. if (len + sizeof(*nsdea) > buf_size)
  433. return -ENOMEM;
  434. nsdea = (struct nan_service_descriptor_extension_attribute *)(buf + len);
  435. if (nsdea->header.attribute_id != 0xE)
  436. return -EINVAL;
  437. if (nsdea->header.length != cpu_to_le16(0x0004))
  438. return -EINVAL;
  439. if (nsdea->instance_id != 0x01)
  440. return -EINVAL;
  441. if (nsdea->control != cpu_to_le16(0x0200))
  442. return -EINVAL;
  443. return 0;
  444. }