wifi_monitor.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. // Module for interfacing with WIFI
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "lapi.h"
  5. #include "platform.h"
  6. #include "c_string.h"
  7. #include "c_stdlib.h"
  8. #include "ctype.h"
  9. #include "c_types.h"
  10. #include "user_interface.h"
  11. #include "wifi_common.h"
  12. #include "sys/network_80211.h"
  13. static int recv_cb;
  14. static uint8 mon_offset;
  15. static uint8 mon_value;
  16. static uint8 mon_mask;
  17. static task_handle_t tasknumber;
  18. #define SNIFFER_BUF2_BUF_SIZE 112
  19. #define BITFIELD(byte, start, len) 8 * (byte) + (start), (len)
  20. #define BYTEFIELD(byte, len) 8 * (byte), 8 * (len)
  21. #define IS_SIGNED 1
  22. #define IS_STRING 2
  23. #define IS_HEXSTRING 3
  24. #define IE_TABLE 4
  25. #define SINGLE_IE 5
  26. #define IS_HEADER 6
  27. #define ANY_FRAME 16
  28. #define IE(id) 0, (id), SINGLE_IE
  29. static void (*on_disconnected)(void);
  30. typedef struct {
  31. const char *key;
  32. uint8 frametype;
  33. } typekey_t;
  34. typedef struct {
  35. const char *name;
  36. unsigned int start : 12;
  37. unsigned int length : 12;
  38. unsigned int opts : 3;
  39. unsigned int frametype : 5; // 16 is *any*
  40. } field_t;
  41. // must be sorted alphabetically
  42. static const field_t fields[] = {
  43. { "aggregation", BITFIELD(7, 3, 1), 0, ANY_FRAME},
  44. { "ampdu_cnt", BITFIELD(9, 0, 8), 0, ANY_FRAME},
  45. { "association_id", BYTEFIELD(40, 2), 0, FRAME_SUBTYPE_ASSOC_RESPONSE},
  46. { "association_id", BYTEFIELD(40, 2), 0, FRAME_SUBTYPE_REASSOC_RESPONSE},
  47. { "authentication_algorithm", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_AUTHENTICATION},
  48. { "authentication_transaction", BYTEFIELD(38, 2), 0, FRAME_SUBTYPE_AUTHENTICATION},
  49. { "beacon_interval", BYTEFIELD(44, 2), 0, FRAME_SUBTYPE_PROBE_RESPONSE},
  50. { "beacon_interval", BYTEFIELD(44, 2), 0, FRAME_SUBTYPE_BEACON},
  51. { "bssid", BYTEFIELD(28, 6), IS_STRING, ANY_FRAME},
  52. { "bssid_hex", BYTEFIELD(28, 6), IS_HEXSTRING, ANY_FRAME},
  53. { "bssidmatch0", BITFIELD(3, 6, 1), 0, ANY_FRAME},
  54. { "bssidmatch1", BITFIELD(3, 7, 1), 0, ANY_FRAME},
  55. { "capability", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_ASSOC_REQUEST},
  56. { "capability", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_ASSOC_RESPONSE},
  57. { "capability", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_REASSOC_REQUEST},
  58. { "capability", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_REASSOC_RESPONSE},
  59. { "capability", BYTEFIELD(46, 2), 0, FRAME_SUBTYPE_PROBE_RESPONSE},
  60. { "capability", BYTEFIELD(46, 2), 0, FRAME_SUBTYPE_BEACON},
  61. { "channel", BITFIELD(10, 0, 4), 0, ANY_FRAME},
  62. { "current_ap", BYTEFIELD(40, 6), IS_STRING, FRAME_SUBTYPE_REASSOC_REQUEST},
  63. { "cwb", BITFIELD(4, 7, 1), 0, ANY_FRAME},
  64. { "dmatch0", BITFIELD(3, 4, 1), 0, ANY_FRAME},
  65. { "dmatch1", BITFIELD(3, 5, 1), 0, ANY_FRAME},
  66. { "dstmac", BYTEFIELD(22, 6), IS_STRING, ANY_FRAME},
  67. { "dstmac_hex", BYTEFIELD(22, 6), IS_HEXSTRING, ANY_FRAME},
  68. { "duration", BYTEFIELD(14, 2), 0, ANY_FRAME},
  69. { "fec_coding", BITFIELD(7, 6, 1), 0, ANY_FRAME},
  70. { "frame", BYTEFIELD(12, 112), IS_STRING, ANY_FRAME},
  71. { "frame_hex", BYTEFIELD(12, 112), IS_HEXSTRING, ANY_FRAME},
  72. { "fromds", BITFIELD(13, 1, 1), 0, ANY_FRAME},
  73. { "header", BYTEFIELD(12, 0), IS_HEADER, ANY_FRAME},
  74. { "ht_length", BITFIELD(5, 0, 16), 0, ANY_FRAME},
  75. { "ie_20_40_bss_coexistence", IE(72), ANY_FRAME},
  76. { "ie_20_40_bss_intolerant_channel_report", IE(73), ANY_FRAME},
  77. { "ie_advertisement_protocol", IE(108), ANY_FRAME},
  78. { "ie_aid", IE(197), ANY_FRAME},
  79. { "ie_antenna", IE(64), ANY_FRAME},
  80. { "ie_ap_channel_report", IE(51), ANY_FRAME},
  81. { "ie_authenticated_mesh_peering_exchange", IE(139), ANY_FRAME},
  82. { "ie_beacon_timing", IE(120), ANY_FRAME},
  83. { "ie_bss_ac_access_delay", IE(68), ANY_FRAME},
  84. { "ie_bss_available_admission_capacity", IE(67), ANY_FRAME},
  85. { "ie_bss_average_access_delay", IE(63), ANY_FRAME},
  86. { "ie_bss_load", IE(11), ANY_FRAME},
  87. { "ie_bss_max_idle_period", IE(90), ANY_FRAME},
  88. { "ie_cf_parameter_set", IE(4), ANY_FRAME},
  89. { "ie_challenge_text", IE(16), ANY_FRAME},
  90. { "ie_channel_switch_announcement", IE(37), ANY_FRAME},
  91. { "ie_channel_switch_timing", IE(104), ANY_FRAME},
  92. { "ie_channel_switch_wrapper", IE(196), ANY_FRAME},
  93. { "ie_channel_usage", IE(97), ANY_FRAME},
  94. { "ie_collocated_interference_report", IE(96), ANY_FRAME},
  95. { "ie_congestion_notification", IE(116), ANY_FRAME},
  96. { "ie_country", IE(7), ANY_FRAME},
  97. { "ie_destination_uri", IE(141), ANY_FRAME},
  98. { "ie_diagnostic_report", IE(81), ANY_FRAME},
  99. { "ie_diagnostic_request", IE(80), ANY_FRAME},
  100. { "ie_dms_request", IE(99), ANY_FRAME},
  101. { "ie_dms_response", IE(100), ANY_FRAME},
  102. { "ie_dse_registered_location", IE(58), ANY_FRAME},
  103. { "ie_dsss_parameter_set", IE(3), ANY_FRAME},
  104. { "ie_edca_parameter_set", IE(12), ANY_FRAME},
  105. { "ie_emergency_alart_identifier", IE(112), ANY_FRAME},
  106. { "ie_erp_information", IE(42), ANY_FRAME},
  107. { "ie_event_report", IE(79), ANY_FRAME},
  108. { "ie_event_request", IE(78), ANY_FRAME},
  109. { "ie_expedited_bandwidth_request", IE(109), ANY_FRAME},
  110. { "ie_extended_bss_load", IE(193), ANY_FRAME},
  111. { "ie_extended_capabilities", IE(127), ANY_FRAME},
  112. { "ie_extended_channel_switch_announcement", IE(60), ANY_FRAME},
  113. { "ie_extended_supported_rates", IE(50), ANY_FRAME},
  114. { "ie_fast_bss_transition", IE(55), ANY_FRAME},
  115. { "ie_fh_parameter_set", IE(2), ANY_FRAME},
  116. { "ie_fms_descriptor", IE(86), ANY_FRAME},
  117. { "ie_fms_request", IE(87), ANY_FRAME},
  118. { "ie_fms_response", IE(88), ANY_FRAME},
  119. { "ie_gann", IE(125), ANY_FRAME},
  120. { "ie_he_capabilities", IE(255), ANY_FRAME},
  121. { "ie_hopping_pattern_parameters", IE(8), ANY_FRAME},
  122. { "ie_hopping_pattern_table", IE(9), ANY_FRAME},
  123. { "ie_ht_capabilities", IE(45), ANY_FRAME},
  124. { "ie_ht_operation", IE(61), ANY_FRAME},
  125. { "ie_ibss_dfs", IE(41), ANY_FRAME},
  126. { "ie_ibss_parameter_set", IE(6), ANY_FRAME},
  127. { "ie_interworking", IE(107), ANY_FRAME},
  128. { "ie_link_identifier", IE(101), ANY_FRAME},
  129. { "ie_location_parameters", IE(82), ANY_FRAME},
  130. { "ie_management_mic", IE(76), ANY_FRAME},
  131. { "ie_mccaop", IE(124), ANY_FRAME},
  132. { "ie_mccaop_advertisement", IE(123), ANY_FRAME},
  133. { "ie_mccaop_advertisement_overview", IE(174), ANY_FRAME},
  134. { "ie_mccaop_setup_reply", IE(122), ANY_FRAME},
  135. { "ie_mccaop_setup_request", IE(121), ANY_FRAME},
  136. { "ie_measurement_pilot_transmission", IE(66), ANY_FRAME},
  137. { "ie_measurement_report", IE(39), ANY_FRAME},
  138. { "ie_measurement_request", IE(38), ANY_FRAME},
  139. { "ie_mesh_awake_window", IE(119), ANY_FRAME},
  140. { "ie_mesh_channel_switch_parameters", IE(118), ANY_FRAME},
  141. { "ie_mesh_configuration", IE(113), ANY_FRAME},
  142. { "ie_mesh_id", IE(114), ANY_FRAME},
  143. { "ie_mesh_link_metric_report", IE(115), ANY_FRAME},
  144. { "ie_mesh_peering_management", IE(117), ANY_FRAME},
  145. { "ie_mic", IE(140), ANY_FRAME},
  146. { "ie_mobility_domain", IE(54), ANY_FRAME},
  147. { "ie_multiple_bssid", IE(71), ANY_FRAME},
  148. { "ie_multiple_bssid_index", IE(85), ANY_FRAME},
  149. { "ie_neighbor_report", IE(52), ANY_FRAME},
  150. { "ie_nontransmitted_bssid_capability", IE(83), ANY_FRAME},
  151. { "ie_operating_mode_notification", IE(199), ANY_FRAME},
  152. { "ie_overlapping_bss_scan_parameters", IE(74), ANY_FRAME},
  153. { "ie_perr", IE(132), ANY_FRAME},
  154. { "ie_power_capability", IE(33), ANY_FRAME},
  155. { "ie_power_constraint", IE(32), ANY_FRAME},
  156. { "ie_prep", IE(131), ANY_FRAME},
  157. { "ie_preq", IE(130), ANY_FRAME},
  158. { "ie_proxy_update", IE(137), ANY_FRAME},
  159. { "ie_proxy_update_confirmation", IE(138), ANY_FRAME},
  160. { "ie_pti_control", IE(105), ANY_FRAME},
  161. { "ie_qos_capability", IE(46), ANY_FRAME},
  162. { "ie_qos_map_set", IE(110), ANY_FRAME},
  163. { "ie_qos_traffic_capability", IE(89), ANY_FRAME},
  164. { "ie_quiet", IE(40), ANY_FRAME},
  165. { "ie_quiet_channel", IE(198), ANY_FRAME},
  166. { "ie_rann", IE(126), ANY_FRAME},
  167. { "ie_rcpi", IE(53), ANY_FRAME},
  168. { "ie_request", IE(10), ANY_FRAME},
  169. { "ie_ric_data", IE(57), ANY_FRAME},
  170. { "ie_ric_descriptor", IE(75), ANY_FRAME},
  171. { "ie_rm_enabled_capacities", IE(70), ANY_FRAME},
  172. { "ie_roaming_consortium", IE(111), ANY_FRAME},
  173. { "ie_rsn", IE(48), ANY_FRAME},
  174. { "ie_rsni", IE(65), ANY_FRAME},
  175. { "ie_schedule", IE(15), ANY_FRAME},
  176. { "ie_secondary_channel_offset", IE(62), ANY_FRAME},
  177. { "ie_ssid", IE(0), ANY_FRAME},
  178. { "ie_ssid_list", IE(84), ANY_FRAME},
  179. { "ie_supported_channels", IE(36), ANY_FRAME},
  180. { "ie_supported_operating_classes", IE(59), ANY_FRAME},
  181. { "ie_supported_rates", IE(1), ANY_FRAME},
  182. { "ie_table", BITFIELD(0, 0, 0), IE_TABLE, ANY_FRAME},
  183. { "ie_tclas", IE(14), ANY_FRAME},
  184. { "ie_tclas_processing", IE(44), ANY_FRAME},
  185. { "ie_tfs_request", IE(91), ANY_FRAME},
  186. { "ie_tfs_response", IE(92), ANY_FRAME},
  187. { "ie_tim", IE(5), ANY_FRAME},
  188. { "ie_tim_broadcast_request", IE(94), ANY_FRAME},
  189. { "ie_tim_broadcast_response", IE(95), ANY_FRAME},
  190. { "ie_time_advertisement", IE(69), ANY_FRAME},
  191. { "ie_time_zone", IE(98), ANY_FRAME},
  192. { "ie_timeout_interval", IE(56), ANY_FRAME},
  193. { "ie_tpc_report", IE(35), ANY_FRAME},
  194. { "ie_tpc_request", IE(34), ANY_FRAME},
  195. { "ie_tpu_buffer_status", IE(106), ANY_FRAME},
  196. { "ie_ts_delay", IE(43), ANY_FRAME},
  197. { "ie_tspec", IE(13), ANY_FRAME},
  198. { "ie_uapsd_coexistence", IE(142), ANY_FRAME},
  199. { "ie_vendor_specific", IE(221), ANY_FRAME},
  200. { "ie_vht_capabilities", IE(191), ANY_FRAME},
  201. { "ie_vht_operation", IE(192), ANY_FRAME},
  202. { "ie_vht_transmit_power_envelope", IE(195), ANY_FRAME},
  203. { "ie_wakeup_schedule", IE(102), ANY_FRAME},
  204. { "ie_wide_bandwidth_channel_switch", IE(194), ANY_FRAME},
  205. { "ie_wnm_sleep_mode", IE(93), ANY_FRAME},
  206. { "is_group", BITFIELD(1, 4, 1), 0, ANY_FRAME},
  207. { "legacy_length", BITFIELD(2, 0, 12), 0, ANY_FRAME},
  208. { "listen_interval", BYTEFIELD(38, 2), 0, FRAME_SUBTYPE_ASSOC_REQUEST},
  209. { "listen_interval", BYTEFIELD(38, 2), 0, FRAME_SUBTYPE_REASSOC_REQUEST},
  210. { "mcs", BITFIELD(4, 0, 7), 0, ANY_FRAME},
  211. { "moredata", BITFIELD(13, 5, 1), 0, ANY_FRAME},
  212. { "moreflag", BITFIELD(13, 2, 1), 0, ANY_FRAME},
  213. { "not_counding", BITFIELD(7, 1, 1), 0, ANY_FRAME},
  214. { "number", BYTEFIELD(34, 2), 0, ANY_FRAME},
  215. { "order", BITFIELD(13, 7, 1), 0, ANY_FRAME},
  216. { "protectedframe", BITFIELD(13, 6, 1), 0, ANY_FRAME},
  217. { "protocol", BITFIELD(12, 0, 2), 0, ANY_FRAME},
  218. { "pwrmgmt", BITFIELD(13, 4, 1), 0, ANY_FRAME},
  219. { "radio", BYTEFIELD(0, 12), IS_STRING, ANY_FRAME},
  220. { "rate", BITFIELD(1, 0, 4), 0, ANY_FRAME},
  221. { "reason", BYTEFIELD(36, 2), 0, FRAME_SUBTYPE_DEAUTHENTICATION},
  222. { "retry", BITFIELD(13, 3, 1), 0, ANY_FRAME},
  223. { "rssi", BYTEFIELD(0, 1), IS_SIGNED, ANY_FRAME},
  224. { "rxend_state", BITFIELD(8, 0, 8), 0, ANY_FRAME},
  225. { "sgi", BITFIELD(7, 7, 1), 0, ANY_FRAME},
  226. { "sig_mode", BITFIELD(1, 6, 2), 0, ANY_FRAME},
  227. { "smoothing", BITFIELD(7, 0, 1), 0, ANY_FRAME},
  228. { "srcmac", BYTEFIELD(16, 6), IS_STRING, ANY_FRAME},
  229. { "srcmac_hex", BYTEFIELD(16, 6), IS_HEXSTRING, ANY_FRAME},
  230. { "status", BYTEFIELD(38, 2), 0, FRAME_SUBTYPE_ASSOC_RESPONSE},
  231. { "status", BYTEFIELD(38, 2), 0, FRAME_SUBTYPE_REASSOC_RESPONSE},
  232. { "status", BYTEFIELD(40, 2), 0, FRAME_SUBTYPE_AUTHENTICATION},
  233. { "stbc", BITFIELD(7, 4, 2), 0, ANY_FRAME},
  234. { "subtype", BITFIELD(12, 4, 4), 0, ANY_FRAME},
  235. { "timestamp", BYTEFIELD(36, 8), IS_STRING, FRAME_SUBTYPE_PROBE_RESPONSE},
  236. { "timestamp", BYTEFIELD(36, 8), IS_STRING, FRAME_SUBTYPE_BEACON},
  237. { "tods", BITFIELD(13, 0, 1), 0, ANY_FRAME},
  238. { "type", BITFIELD(12, 2, 2), 0, ANY_FRAME}
  239. };
  240. static int8 variable_start[16] = {
  241. 4, // assoc req
  242. 6, // assoc response
  243. 10, // reassoc req
  244. 6, // reassoc resp
  245. 0, // probe req
  246. 12, // probe resp
  247. -1,
  248. -1,
  249. 12, // beacon
  250. -1, // ATIM
  251. 2, // Disassociation
  252. 6, // authentication
  253. 2, // Deauthentication
  254. 2, // action
  255. -1,
  256. -1
  257. };
  258. typedef struct {
  259. uint16 len;
  260. uint8 buf[];
  261. } packet_t;
  262. static const LUA_REG_TYPE packet_function_map[];
  263. static void wifi_rx_cb(uint8 *buf, uint16 len) {
  264. if (len != sizeof(struct sniffer_buf2)) {
  265. return;
  266. }
  267. struct sniffer_buf2 *snb = (struct sniffer_buf2 *) buf;
  268. management_request_t *mgt = (management_request_t *) snb->buf;
  269. if (mon_offset > len) {
  270. return;
  271. }
  272. if ((buf[mon_offset] & mon_mask) != mon_value) {
  273. return;
  274. }
  275. packet_t *packet = (packet_t *) c_malloc(len + sizeof(packet_t));
  276. if (packet) {
  277. packet->len = len;
  278. memcpy(packet->buf, buf, len);
  279. if (!task_post_medium(tasknumber, (ETSParam) packet)) {
  280. c_free(packet);
  281. }
  282. }
  283. }
  284. static void monitor_task(os_param_t param, uint8_t prio)
  285. {
  286. packet_t *input = (packet_t *) param;
  287. (void) prio;
  288. lua_State *L = lua_getstate();
  289. if (recv_cb != LUA_NOREF) {
  290. lua_rawgeti(L, LUA_REGISTRYINDEX, recv_cb);
  291. packet_t *packet = (packet_t *) lua_newuserdata(L, input->len + sizeof(packet_t));
  292. packet->len = input->len;
  293. memcpy(packet->buf, input->buf, input->len);
  294. luaL_getmetatable(L, "wifi.packet");
  295. lua_setmetatable(L, -2);
  296. c_free(input);
  297. lua_call(L, 1, 0);
  298. } else {
  299. c_free(input);
  300. }
  301. }
  302. static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
  303. /* relative string position: negative means back from end */
  304. if (pos < 0) pos += (ptrdiff_t)len + 1;
  305. return (pos >= 0) ? pos : 0;
  306. }
  307. static int packet_sub(lua_State *L, int buf_offset, int buf_length) {
  308. packet_t *packet = luaL_checkudata(L, 1, "wifi.packet");
  309. ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), buf_length);
  310. ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), buf_length);
  311. if (start < 1) start = 1;
  312. if (end > buf_length) end = buf_length;
  313. if (start <= end) {
  314. lua_pushlstring(L, packet->buf+start-1 + buf_offset, end-start+1);
  315. } else {
  316. lua_pushliteral(L, "");
  317. }
  318. return 1;
  319. }
  320. static int packet_frame_sub(lua_State *L) {
  321. return packet_sub(L, sizeof(struct RxControl), SNIFFER_BUF2_BUF_SIZE);
  322. }
  323. static int packet_radio_sub(lua_State *L) {
  324. return packet_sub(L, 0, sizeof(struct RxControl));
  325. }
  326. static void push_hex_string(lua_State *L, const uint8 *buf, int len, char *sep) {
  327. luaL_Buffer b;
  328. luaL_buffinit(L, &b);
  329. int i;
  330. for (i = 0; i < len; i++) {
  331. if (i && sep && *sep) {
  332. luaL_addstring(&b, sep);
  333. }
  334. char hex[3];
  335. uint8 c = buf[i];
  336. hex[0] = "0123456789abcdef"[c >> 4];
  337. hex[1] = "0123456789abcdef"[c & 0xf];
  338. hex[2] = 0;
  339. luaL_addstring(&b, hex);
  340. }
  341. luaL_pushresult(&b);
  342. }
  343. static void push_hex_string_colon(lua_State *L, const uint8 *buf, int len) {
  344. push_hex_string(L, buf, len, ":");
  345. }
  346. static int comparator(const void *typekey, const void *obj) {
  347. field_t *f = (field_t *) obj;
  348. const char *name = f->name;
  349. const typekey_t *tk = (const typekey_t *) typekey;
  350. const char *key = tk->key;
  351. if (!((uint32)key & 3) && !((uint32)name & 3)) {
  352. // Since all strings are 3 characters or more, can do accelerated first comparison
  353. uint32 key32 = htonl(*(uint32 *) key);
  354. uint32 name32 = htonl(*(uint32 *) name);
  355. if (key32 < name32) {
  356. return -1;
  357. }
  358. if (key32 > name32) {
  359. return 1;
  360. }
  361. }
  362. int rc = strcmp((const char *) key, name);
  363. if (rc) {
  364. return rc;
  365. }
  366. if (f->frametype == ANY_FRAME) {
  367. return 0;
  368. }
  369. return tk->frametype - f->frametype;
  370. }
  371. static bool push_field_value_string(lua_State *L, const uint8 *pkt,
  372. const uint8 *packet_end, const char *field) {
  373. const struct RxControl *rxc = (struct RxControl *) pkt;
  374. const management_request_t *mgt = (management_request_t *) (rxc + 1);
  375. typekey_t tk;
  376. tk.key = field;
  377. tk.frametype = mgt->framectrl.Subtype;
  378. field_t *f = bsearch(&tk, fields, sizeof(fields) / sizeof(fields[0]), sizeof(fields[0]), comparator);
  379. if (f) {
  380. if (f->opts == SINGLE_IE) {
  381. int varstart = variable_start[mgt->framectrl.Subtype];
  382. if (varstart >= 0) {
  383. const uint8 *var = (uint8 *) (mgt + 1) + varstart;
  384. while (var + 2 <= packet_end && var + 2 + var[1] <= packet_end) {
  385. if (*var == f->length) {
  386. lua_pushlstring(L, var + 2, var[1]);
  387. return true;
  388. }
  389. var += 2 + var[1];
  390. }
  391. }
  392. lua_pushnil(L);
  393. return true;
  394. }
  395. if (f->opts == IE_TABLE) {
  396. lua_newtable(L);
  397. int varstart = variable_start[mgt->framectrl.Subtype];
  398. if (varstart >= 0) {
  399. const uint8 *var = (uint8 *) (mgt + 1) + varstart;
  400. while (var + 2 <= packet_end && var + 2 + var[1] <= packet_end) {
  401. lua_pushlstring(L, var + 2, var[1]);
  402. lua_rawseti(L, -2, *var);
  403. var += 2 + var[1];
  404. }
  405. }
  406. return true;
  407. }
  408. if (f->opts == IS_STRING) {
  409. int use = f->length >> 3;
  410. const uint8 *start = pkt + (f->start >> 3);
  411. if (start + use > packet_end) {
  412. use = packet_end - start;
  413. }
  414. lua_pushlstring(L, start, use);
  415. return true;
  416. }
  417. if (f->opts == IS_HEXSTRING) {
  418. int use = f->length >> 3;
  419. const uint8 *start = pkt + (f->start >> 3);
  420. if (start + use > packet_end) {
  421. use = packet_end - start;
  422. }
  423. push_hex_string_colon(L, start, use);
  424. return true;
  425. }
  426. if (f->opts == IS_HEADER) {
  427. int varstart = variable_start[mgt->framectrl.Subtype];
  428. if (varstart >= 0) {
  429. lua_pushlstring(L, (const uint8 *) (mgt + 1), varstart);
  430. } else {
  431. lua_pushnil(L);
  432. }
  433. return true;
  434. }
  435. if (f->opts == 0 || f->opts == IS_SIGNED) {
  436. // bits start from the bottom of the byte.
  437. int value = 0;
  438. int bits = 0;
  439. int bitoff = f->start & 7;
  440. int byteoff = f->start >> 3;
  441. while (bits < f->length) {
  442. uint8 b = pkt[byteoff];
  443. value |= (b >> bitoff) << bits;
  444. bits += (8 - bitoff);
  445. bitoff = 0;
  446. byteoff++;
  447. }
  448. // get rid of excess bits
  449. value &= (1 << f->length) - 1;
  450. if (f->opts & IS_SIGNED) {
  451. if (value & (1 << (f->length - 1))) {
  452. value |= - (1 << f->length);
  453. }
  454. }
  455. lua_pushinteger(L, value);
  456. return true;
  457. }
  458. }
  459. return false;
  460. }
  461. static bool push_field_value_int(lua_State *L, management_request_t *mgt,
  462. const uint8 *packet_end, int field) {
  463. int varstart = variable_start[mgt->framectrl.Subtype];
  464. if (varstart >= 0) {
  465. uint8 *var = (uint8 *) (mgt + 1) + varstart;
  466. while (var + 2 <= packet_end && var + 2 + var[1] <= packet_end) {
  467. if (*var == field) {
  468. lua_pushlstring(L, var + 2, var[1]);
  469. return true;
  470. }
  471. var += var[1] + 2;
  472. }
  473. }
  474. return false;
  475. }
  476. static int packet_map_lookup(lua_State *L) {
  477. packet_t *packet = luaL_checkudata(L, 1, "wifi.packet");
  478. struct RxControl *rxc = (struct RxControl *) packet->buf;
  479. management_request_t *mgt = (management_request_t *) (rxc + 1);
  480. const uint8 *packet_end = packet->buf + packet->len;
  481. if ((void *) (mgt + 1) > (void *) packet_end) {
  482. return 0;
  483. }
  484. if (mgt->framectrl.Type != FRAME_TYPE_MANAGEMENT) {
  485. return 0;
  486. }
  487. if (lua_type(L, 2) == LUA_TNUMBER) {
  488. int field = luaL_checkinteger(L, 2);
  489. if (push_field_value_int(L, mgt, packet_end, field)) {
  490. return 1;
  491. }
  492. } else {
  493. const char *field = luaL_checkstring(L, 2);
  494. if (push_field_value_string(L, packet->buf, packet_end, field)) {
  495. return 1;
  496. }
  497. // Now search the packet function map
  498. const TValue *res = luaR_findentry((void *) packet_function_map, field, 0, NULL);
  499. if (res) {
  500. luaA_pushobject(L, res);
  501. return 1;
  502. }
  503. }
  504. return 0;
  505. }
  506. static int packet_byte(lua_State *L, int buf_offset, int buf_length) {
  507. packet_t *packet = luaL_checkudata(L, 1, "wifi.packet");
  508. int offset = luaL_checkinteger(L, 2);
  509. if (offset < 1 || offset > buf_length) {
  510. return 0;
  511. }
  512. lua_pushinteger(L, packet->buf[offset - 1 + buf_offset]);
  513. return 1;
  514. }
  515. static int packet_frame_byte(lua_State *L) {
  516. return packet_byte(L, sizeof(struct RxControl), SNIFFER_BUF2_BUF_SIZE);
  517. }
  518. static int packet_radio_byte(lua_State *L) {
  519. return packet_byte(L, 0, sizeof(struct RxControl));
  520. }
  521. static int packet_subhex(lua_State *L, int buf_offset, int buf_length) {
  522. packet_t *packet = luaL_checkudata(L, 1, "wifi.packet");
  523. ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), buf_length);
  524. ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), buf_length);
  525. const char *sep = luaL_optstring(L, 4, "");
  526. if (start < 1) start = 1;
  527. if (end > buf_length) end = buf_length;
  528. if (start <= end) {
  529. luaL_Buffer b;
  530. luaL_buffinit(L, &b);
  531. int i;
  532. for (i = start - 1; i < end; i++) {
  533. char hex[3];
  534. if (i >= start) {
  535. luaL_addstring(&b, sep);
  536. }
  537. uint8 c = packet->buf[i + buf_offset];
  538. hex[0] = "0123456789abcdef"[c >> 4];
  539. hex[1] = "0123456789abcdef"[c & 0xf];
  540. hex[2] = 0;
  541. luaL_addstring(&b, hex);
  542. }
  543. luaL_pushresult(&b);
  544. } else {
  545. lua_pushliteral(L, "");
  546. }
  547. return 1;
  548. }
  549. static int packet_frame_subhex(lua_State *L) {
  550. return packet_subhex(L, sizeof(struct RxControl), SNIFFER_BUF2_BUF_SIZE);
  551. }
  552. static int packet_radio_subhex(lua_State *L) {
  553. return packet_subhex(L, 0, sizeof(struct RxControl));
  554. }
  555. static void start_actually_monitoring() {
  556. wifi_set_channel(1);
  557. wifi_promiscuous_enable(1);
  558. }
  559. static int wifi_event_monitor_handle_event_cb_hook(System_Event_t *evt)
  560. {
  561. if (evt->event == EVENT_STAMODE_DISCONNECTED) {
  562. if (on_disconnected) {
  563. on_disconnected();
  564. on_disconnected = NULL;
  565. return 1; // We did handle the event
  566. }
  567. }
  568. return 0; // We did not handle the event
  569. }
  570. // This is a bit ugly as we have to use a bit of the event monitor infrastructure
  571. #ifdef WIFI_SDK_EVENT_MONITOR_ENABLE
  572. extern void wifi_event_monitor_register_hook(int (*fn)(System_Event_t*));
  573. static void eventmon_setup() {
  574. wifi_event_monitor_register_hook(wifi_event_monitor_handle_event_cb_hook);
  575. }
  576. #else
  577. static void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
  578. {
  579. wifi_event_monitor_handle_event_cb_hook(evt);
  580. }
  581. static void eventmon_setup() {
  582. wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);
  583. }
  584. #endif
  585. static void eventmon_call_on_disconnected(void (*fn)(void)) {
  586. on_disconnected = fn;
  587. }
  588. static int wifi_monitor_start(lua_State *L) {
  589. int argno = 1;
  590. if (lua_type(L, argno) == LUA_TNUMBER) {
  591. int offset = luaL_checkinteger(L, argno);
  592. argno++;
  593. if (lua_type(L, argno) == LUA_TNUMBER) {
  594. int value = luaL_checkinteger(L, argno);
  595. int mask = 0xff;
  596. argno++;
  597. if (lua_type(L, argno) == LUA_TNUMBER) {
  598. mask = luaL_checkinteger(L, argno);
  599. argno++;
  600. }
  601. mon_offset = offset - 1;
  602. mon_value = value;
  603. mon_mask = mask;
  604. } else {
  605. return luaL_error(L, "Must supply offset and value");
  606. }
  607. } else {
  608. // Management frames by default
  609. mon_offset = 12;
  610. mon_value = 0x00;
  611. mon_mask = 0x0C;
  612. }
  613. if (lua_type(L, argno) == LUA_TFUNCTION || lua_type(L, argno) == LUA_TLIGHTFUNCTION)
  614. {
  615. lua_pushvalue(L, argno); // copy argument (func) to the top of stack
  616. recv_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  617. uint8 connect_status = wifi_station_get_connect_status();
  618. wifi_station_set_auto_connect(0);
  619. wifi_set_opmode_current(1);
  620. wifi_promiscuous_enable(0);
  621. wifi_station_disconnect();
  622. wifi_set_promiscuous_rx_cb(wifi_rx_cb);
  623. // Now we have to wait until we get the EVENT_STAMODE_DISCONNECTED event
  624. // before we can go further.
  625. if (connect_status == STATION_IDLE) {
  626. start_actually_monitoring();
  627. } else {
  628. eventmon_call_on_disconnected(start_actually_monitoring);
  629. }
  630. return 0;
  631. }
  632. return luaL_error(L, "Missing callback");
  633. }
  634. static int wifi_monitor_channel(lua_State *L) {
  635. lua_pushinteger(L, wifi_get_channel());
  636. if (lua_type(L, 1) == LUA_TNUMBER) {
  637. int channel = luaL_checkinteger(L, 1);
  638. if (channel < 1 || channel > 15) {
  639. return luaL_error(L, "Channel number (%d) is out of range", channel);
  640. }
  641. wifi_set_channel(channel);
  642. }
  643. return 1;
  644. }
  645. static int wifi_monitor_stop(lua_State *L) {
  646. wifi_promiscuous_enable(0);
  647. wifi_set_opmode_current(1);
  648. luaL_unref(L, LUA_REGISTRYINDEX, recv_cb);
  649. recv_cb = LUA_NOREF;
  650. return 0;
  651. }
  652. static const LUA_REG_TYPE packet_function_map[] = {
  653. { LSTRKEY( "radio_byte" ), LFUNCVAL( packet_radio_byte ) },
  654. { LSTRKEY( "frame_byte" ), LFUNCVAL( packet_frame_byte ) },
  655. { LSTRKEY( "radio_sub" ), LFUNCVAL( packet_radio_sub ) },
  656. { LSTRKEY( "frame_sub" ), LFUNCVAL( packet_frame_sub ) },
  657. { LSTRKEY( "radio_subhex" ), LFUNCVAL( packet_radio_subhex ) },
  658. { LSTRKEY( "frame_subhex" ), LFUNCVAL( packet_frame_subhex ) },
  659. { LNILKEY, LNILVAL }
  660. };
  661. static const LUA_REG_TYPE packet_map[] = {
  662. { LSTRKEY( "__index" ), LFUNCVAL( packet_map_lookup ) },
  663. { LNILKEY, LNILVAL }
  664. };
  665. // Module function map
  666. const LUA_REG_TYPE wifi_monitor_map[] = {
  667. { LSTRKEY( "start" ), LFUNCVAL( wifi_monitor_start ) },
  668. { LSTRKEY( "stop" ), LFUNCVAL( wifi_monitor_stop ) },
  669. { LSTRKEY( "channel" ), LFUNCVAL( wifi_monitor_channel ) },
  670. { LNILKEY, LNILVAL }
  671. };
  672. int wifi_monitor_init(lua_State *L)
  673. {
  674. luaL_rometatable(L, "wifi.packet", (void *)packet_map);
  675. tasknumber = task_get_id(monitor_task);
  676. eventmon_setup();
  677. #ifdef CHECK_TABLE_IN_ORDER
  678. // verify that the table is in order
  679. typekey_t tk;
  680. tk.key = "";
  681. tk.frametype = 0;
  682. int i;
  683. for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) {
  684. if (comparator(&tk, &fields[i]) >= 0) {
  685. dbg_printf("Wrong order: %s,%d should be after %s,%d\n", tk.key, tk.frametype, fields[i].name, fields[i].frametype);
  686. }
  687. tk.key = fields[i].name;
  688. tk.frametype = fields[i].frametype;
  689. }
  690. #endif
  691. return 0;
  692. }