bnep.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2011-2014 Intel Corporation
  7. * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
  8. *
  9. *
  10. */
  11. #ifdef HAVE_CONFIG_H
  12. #include <config.h>
  13. #endif
  14. #define _GNU_SOURCE
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <inttypes.h>
  20. #include "lib/bluetooth.h"
  21. #include "lib/uuid.h"
  22. #include "src/shared/util.h"
  23. #include "bt.h"
  24. #include "packet.h"
  25. #include "display.h"
  26. #include "l2cap.h"
  27. #include "keys.h"
  28. #include "sdp.h"
  29. #include "bnep.h"
  30. #define GET_PKT_TYPE(type) (type & 0x7f)
  31. #define GET_EXTENSION(type) (type & 0x80)
  32. /* BNEP Extension Type */
  33. #define BNEP_EXTENSION_CONTROL 0x00
  34. #define BNEP_CONTROL 0x01
  35. uint16_t proto = 0x0000;
  36. struct bnep_frame {
  37. uint8_t type;
  38. int extension;
  39. struct l2cap_frame l2cap_frame;
  40. };
  41. static bool get_macaddr(struct bnep_frame *bnep_frame, char *str)
  42. {
  43. uint8_t addr[6];
  44. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  45. int i;
  46. for (i = 0; i < 6; i++)
  47. if (!l2cap_frame_get_u8(frame, &addr[i]))
  48. return false;
  49. sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
  50. addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
  51. return true;
  52. }
  53. static bool bnep_general(struct bnep_frame *bnep_frame,
  54. uint8_t indent, int hdr_len)
  55. {
  56. struct l2cap_frame *frame;
  57. char src_addr[20], dest_addr[20];
  58. if (!get_macaddr(bnep_frame, dest_addr))
  59. return false;
  60. if (!get_macaddr(bnep_frame, src_addr))
  61. return false;
  62. frame = &bnep_frame->l2cap_frame;
  63. if (!l2cap_frame_get_be16(frame, &proto))
  64. return false;
  65. print_field("%*cdst %s src %s [proto 0x%04x] ", indent,
  66. ' ', dest_addr, src_addr, proto);
  67. return true;
  68. }
  69. static bool cmd_nt_understood(struct bnep_frame *bnep_frame, uint8_t indent)
  70. {
  71. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  72. uint8_t ptype;
  73. if (!l2cap_frame_get_u8(frame, &ptype))
  74. return false;
  75. print_field("%*cType: 0x%02x ", indent, ' ', ptype);
  76. return true;
  77. }
  78. static bool setup_conn_req(struct bnep_frame *bnep_frame, uint8_t indent)
  79. {
  80. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  81. uint8_t uuid_size;
  82. uint32_t src_uuid = 0, dst_uuid = 0;
  83. if (!l2cap_frame_get_u8(frame, &uuid_size))
  84. return false;
  85. print_field("%*cSize: 0x%02x ", indent, ' ', uuid_size);
  86. switch (uuid_size) {
  87. case 2:
  88. if (!l2cap_frame_get_be16(frame, (uint16_t *) &dst_uuid))
  89. return false;
  90. if (!l2cap_frame_get_be16(frame, (uint16_t *) &src_uuid))
  91. return false;
  92. break;
  93. case 4:
  94. if (!l2cap_frame_get_be32(frame, &dst_uuid))
  95. return false;
  96. if (!l2cap_frame_get_be32(frame, &src_uuid))
  97. return false;
  98. break;
  99. case 16:
  100. if (!l2cap_frame_get_be32(frame, &dst_uuid))
  101. return false;
  102. l2cap_frame_pull(frame, frame, 12);
  103. if (!l2cap_frame_get_be32(frame, &src_uuid))
  104. return false;
  105. l2cap_frame_pull(frame, frame, 12);
  106. break;
  107. default:
  108. l2cap_frame_pull(frame, frame, (uuid_size * 2));
  109. return true;
  110. }
  111. print_field("%*cDst: 0x%x(%s)", indent, ' ', dst_uuid,
  112. bt_uuid32_to_str(dst_uuid));
  113. print_field("%*cSrc: 0x%x(%s)", indent, ' ', src_uuid,
  114. bt_uuid32_to_str(src_uuid));
  115. return true;
  116. }
  117. static const char *value2str(uint16_t value)
  118. {
  119. switch (value) {
  120. case 0x00:
  121. return "Operation Successful";
  122. case 0x01:
  123. return "Operation Failed - Invalid Dst Srv UUID";
  124. case 0x02:
  125. return "Operation Failed - Invalid Src Srv UUID";
  126. case 0x03:
  127. return "Operation Failed - Invalid Srv UUID size";
  128. case 0x04:
  129. return "Operation Failed - Conn not allowed";
  130. default:
  131. return "Unknown";
  132. }
  133. }
  134. static bool print_rsp_msg(struct bnep_frame *bnep_frame, uint8_t indent)
  135. {
  136. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  137. uint16_t rsp_msg;
  138. if (!l2cap_frame_get_be16(frame, &rsp_msg))
  139. return false;
  140. print_field("%*cRsp msg: %s(0x%04x) ", indent, ' ',
  141. value2str(rsp_msg), rsp_msg);
  142. return true;
  143. }
  144. static bool filter_nettype_req(struct bnep_frame *bnep_frame, uint8_t indent)
  145. {
  146. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  147. uint16_t length, start_range, end_range;
  148. int i;
  149. if (!l2cap_frame_get_be16(frame, &length))
  150. return false;
  151. print_field("%*cLength: 0x%04x", indent, ' ', length);
  152. for (i = 0; i < length / 4; i++) {
  153. if (!l2cap_frame_get_be16(frame, &start_range))
  154. return false;
  155. if (!l2cap_frame_get_be16(frame, &end_range))
  156. return false;
  157. print_field("%*c0x%04x - 0x%04x", indent, ' ',
  158. start_range, end_range);
  159. }
  160. return true;
  161. }
  162. static bool filter_multaddr_req(struct bnep_frame *bnep_frame, uint8_t indent)
  163. {
  164. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  165. uint16_t length;
  166. char start_addr[20], end_addr[20];
  167. int i;
  168. if (!l2cap_frame_get_be16(frame, &length))
  169. return false;
  170. print_field("%*cLength: 0x%04x", indent, ' ', length);
  171. for (i = 0; i < length / 12; i++) {
  172. if (!get_macaddr(bnep_frame, start_addr))
  173. return false;
  174. if (!get_macaddr(bnep_frame, end_addr))
  175. return false;
  176. print_field("%*c%s - %s", indent, ' ', start_addr, end_addr);
  177. }
  178. return true;
  179. }
  180. struct bnep_control_data {
  181. uint8_t type;
  182. const char *str;
  183. bool (*func) (struct bnep_frame *frame, uint8_t indent);
  184. };
  185. static const struct bnep_control_data bnep_control_table[] = {
  186. { 0x00, "Command Not Understood", cmd_nt_understood },
  187. { 0x01, "Setup Conn Req", setup_conn_req },
  188. { 0x02, "Setup Conn Rsp", print_rsp_msg },
  189. { 0x03, "Filter NetType Set", filter_nettype_req },
  190. { 0x04, "Filter NetType Rsp", print_rsp_msg },
  191. { 0x05, "Filter MultAddr Set", filter_multaddr_req },
  192. { 0x06, "Filter MultAddr Rsp", print_rsp_msg },
  193. { }
  194. };
  195. static bool bnep_control(struct bnep_frame *bnep_frame,
  196. uint8_t indent, int hdr_len)
  197. {
  198. uint8_t ctype;
  199. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  200. const struct bnep_control_data *bnep_control_data = NULL;
  201. const char *type_str;
  202. int i;
  203. if (!l2cap_frame_get_u8(frame, &ctype))
  204. return false;
  205. for (i = 0; bnep_control_table[i].str; i++) {
  206. if (bnep_control_table[i].type == ctype) {
  207. bnep_control_data = &bnep_control_table[i];
  208. break;
  209. }
  210. }
  211. if (bnep_control_data)
  212. type_str = bnep_control_data->str;
  213. else
  214. type_str = "Unknown control type";
  215. print_field("%*c%s (0x%02x) ", indent, ' ', type_str, ctype);
  216. if (!bnep_control_data || !bnep_control_data->func) {
  217. packet_hexdump(frame->data, hdr_len - 1);
  218. l2cap_frame_pull(frame, frame, hdr_len - 1);
  219. goto done;
  220. }
  221. if (!bnep_control_data->func(bnep_frame, indent+2))
  222. return false;
  223. done:
  224. return true;
  225. }
  226. static bool bnep_compressed(struct bnep_frame *bnep_frame,
  227. uint8_t indent, int hdr_len)
  228. {
  229. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  230. if (!l2cap_frame_get_be16(frame, &proto))
  231. return false;
  232. print_field("%*c[proto 0x%04x] ", indent, ' ', proto);
  233. return true;
  234. }
  235. static bool bnep_src_only(struct bnep_frame *bnep_frame,
  236. uint8_t indent, int hdr_len)
  237. {
  238. struct l2cap_frame *frame;
  239. char src_addr[20];
  240. if (!get_macaddr(bnep_frame, src_addr))
  241. return false;
  242. frame = &bnep_frame->l2cap_frame;
  243. if (!l2cap_frame_get_be16(frame, &proto))
  244. return false;
  245. print_field("%*csrc %s [proto 0x%04x] ", indent,
  246. ' ', src_addr, proto);
  247. return true;
  248. }
  249. static bool bnep_dst_only(struct bnep_frame *bnep_frame,
  250. uint8_t indent, int hdr_len)
  251. {
  252. struct l2cap_frame *frame;
  253. char dest_addr[20];
  254. if (!get_macaddr(bnep_frame, dest_addr))
  255. return false;
  256. frame = &bnep_frame->l2cap_frame;
  257. if (!l2cap_frame_get_be16(frame, &proto))
  258. return false;
  259. print_field("%*cdst %s [proto 0x%04x] ", indent,
  260. ' ', dest_addr, proto);
  261. return true;
  262. }
  263. static bool bnep_eval_extension(struct bnep_frame *bnep_frame, uint8_t indent)
  264. {
  265. struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
  266. uint8_t type, length;
  267. int extension;
  268. if (!l2cap_frame_get_u8(frame, &type))
  269. return false;
  270. if (!l2cap_frame_get_u8(frame, &length))
  271. return false;
  272. extension = GET_EXTENSION(type);
  273. type = GET_PKT_TYPE(type);
  274. switch (type) {
  275. case BNEP_EXTENSION_CONTROL:
  276. print_field("%*cExt Control(0x%02x|%s) len 0x%02x", indent,
  277. ' ', type, extension ? "1" : "0", length);
  278. if (!bnep_control(bnep_frame, indent+2, length))
  279. return false;
  280. break;
  281. default:
  282. print_field("%*cExt Unknown(0x%02x|%s) len 0x%02x", indent,
  283. ' ', type, extension ? "1" : "0", length);
  284. packet_hexdump(frame->data, length);
  285. l2cap_frame_pull(frame, frame, length);
  286. }
  287. if (extension)
  288. if (!bnep_eval_extension(bnep_frame, indent))
  289. return false;
  290. return true;
  291. }
  292. struct bnep_data {
  293. uint8_t type;
  294. const char *str;
  295. bool (*func) (struct bnep_frame *frame, uint8_t indent, int hdr_len);
  296. };
  297. static const struct bnep_data bnep_table[] = {
  298. { 0x00, "General Ethernet", bnep_general },
  299. { 0x01, "Control", bnep_control },
  300. { 0x02, "Compressed Ethernet", bnep_compressed },
  301. { 0x03, "Compressed Ethernet SrcOnly", bnep_src_only },
  302. { 0x04, "Compressed Ethernet DestOnly", bnep_dst_only },
  303. { }
  304. };
  305. void bnep_packet(const struct l2cap_frame *frame)
  306. {
  307. uint8_t type, indent = 1;
  308. struct bnep_frame bnep_frame;
  309. struct l2cap_frame *l2cap_frame;
  310. const struct bnep_data *bnep_data = NULL;
  311. const char *pdu_color, *pdu_str;
  312. int i;
  313. l2cap_frame_pull(&bnep_frame.l2cap_frame, frame, 0);
  314. l2cap_frame = &bnep_frame.l2cap_frame;
  315. if (!l2cap_frame_get_u8(l2cap_frame, &type))
  316. goto fail;
  317. bnep_frame.extension = GET_EXTENSION(type);
  318. bnep_frame.type = GET_PKT_TYPE(type);
  319. for (i = 0; bnep_table[i].str; i++) {
  320. if (bnep_table[i].type == bnep_frame.type) {
  321. bnep_data = &bnep_table[i];
  322. break;
  323. }
  324. }
  325. if (bnep_data) {
  326. if (bnep_data->func) {
  327. if (frame->in)
  328. pdu_color = COLOR_MAGENTA;
  329. else
  330. pdu_color = COLOR_BLUE;
  331. } else
  332. pdu_color = COLOR_WHITE_BG;
  333. pdu_str = bnep_data->str;
  334. } else {
  335. pdu_color = COLOR_WHITE_BG;
  336. pdu_str = "Unknown packet type";
  337. }
  338. print_indent(6, pdu_color, "BNEP: ", pdu_str, COLOR_OFF,
  339. " (0x%02x|%s)", bnep_frame.type,
  340. bnep_frame.extension ? "1" : "0");
  341. if (!bnep_data || !bnep_data->func) {
  342. packet_hexdump(l2cap_frame->data, l2cap_frame->size);
  343. return;
  344. }
  345. if (!bnep_data->func(&bnep_frame, indent, -1))
  346. goto fail;
  347. /* Extension info */
  348. if (bnep_frame.extension)
  349. if (!bnep_eval_extension(&bnep_frame, indent+2))
  350. goto fail;
  351. /* Control packet => No payload info */
  352. if (bnep_frame.type == BNEP_CONTROL)
  353. return;
  354. /* TODO: Handle BNEP IP packet */
  355. packet_hexdump(l2cap_frame->data, l2cap_frame->size);
  356. return;
  357. fail:
  358. print_text(COLOR_ERROR, "frame too short");
  359. packet_hexdump(frame->data, frame->size);
  360. }