pan.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <errno.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <glib.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/socket.h>
  22. #include <sys/wait.h>
  23. #include <sys/types.h>
  24. #include <net/if.h>
  25. #include <linux/sockios.h>
  26. #include <netinet/in.h>
  27. #include <netinet/ip6.h>
  28. #include <linux/if_bridge.h>
  29. #include "btio/btio.h"
  30. #include "lib/bluetooth.h"
  31. #include "lib/bnep.h"
  32. #include "lib/sdp.h"
  33. #include "lib/sdp_lib.h"
  34. #include "src/uuid-helper.h"
  35. #include "profiles/network/bnep.h"
  36. #include "src/log.h"
  37. #include "hal-msg.h"
  38. #include "ipc-common.h"
  39. #include "ipc.h"
  40. #include "utils.h"
  41. #include "bluetooth.h"
  42. #include "pan.h"
  43. #define SVC_HINT_NETWORKING 0x02
  44. #define BNEP_BRIDGE "bt-pan"
  45. #define BNEP_PANU_INTERFACE "bt-pan"
  46. #define BNEP_NAP_INTERFACE "bt-pan%d"
  47. struct pan_device {
  48. char iface[16];
  49. bdaddr_t dst;
  50. uint8_t conn_state;
  51. uint8_t role;
  52. GIOChannel *io;
  53. struct bnep *session;
  54. guint watch;
  55. };
  56. static bdaddr_t adapter_addr;
  57. static GSList *devices = NULL;
  58. static uint8_t local_role = HAL_PAN_ROLE_NONE;
  59. static uint32_t nap_rec_id = 0;
  60. static uint32_t panu_rec_id = 0;
  61. static GIOChannel *nap_io = NULL;
  62. static bool nap_bridge_mode = false;
  63. static struct ipc *hal_ipc = NULL;
  64. static int set_forward_delay(int sk)
  65. {
  66. unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0 , 0, 0 };
  67. struct ifreq ifr;
  68. memset(&ifr, 0, sizeof(ifr));
  69. strncpy(ifr.ifr_name, BNEP_BRIDGE, IFNAMSIZ - 1);
  70. ifr.ifr_data = (char *) args;
  71. if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
  72. error("pan: setting forward delay failed: %d (%s)",
  73. errno, strerror(errno));
  74. return -1;
  75. }
  76. return 0;
  77. }
  78. static int nap_create_bridge(void)
  79. {
  80. int sk, err;
  81. DBG("%s", BNEP_BRIDGE);
  82. if (nap_bridge_mode)
  83. return 0;
  84. sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
  85. if (sk < 0)
  86. return -EOPNOTSUPP;
  87. if (ioctl(sk, SIOCBRADDBR, BNEP_BRIDGE) < 0) {
  88. err = -errno;
  89. if (err != -EEXIST) {
  90. close(sk);
  91. return -EOPNOTSUPP;
  92. }
  93. }
  94. err = set_forward_delay(sk);
  95. if (err < 0)
  96. ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
  97. close(sk);
  98. nap_bridge_mode = err == 0;
  99. return err;
  100. }
  101. static int bridge_if_down(void)
  102. {
  103. struct ifreq ifr;
  104. int sk, err;
  105. sk = socket(AF_INET, SOCK_DGRAM, 0);
  106. memset(&ifr, 0, sizeof(ifr));
  107. strncpy(ifr.ifr_name, BNEP_BRIDGE, IF_NAMESIZE - 1);
  108. ifr.ifr_flags &= ~IFF_UP;
  109. /* Bring down the interface */
  110. err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
  111. close(sk);
  112. if (err < 0) {
  113. error("pan: Could not bring down %s", BNEP_BRIDGE);
  114. return err;
  115. }
  116. return 0;
  117. }
  118. static int nap_remove_bridge(void)
  119. {
  120. int sk, err;
  121. DBG("%s", BNEP_BRIDGE);
  122. if (!nap_bridge_mode)
  123. return 0;
  124. bridge_if_down();
  125. sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
  126. if (sk < 0)
  127. return -EOPNOTSUPP;
  128. err = ioctl(sk, SIOCBRDELBR, BNEP_BRIDGE);
  129. if (err < 0)
  130. err = -errno;
  131. close(sk);
  132. if (err < 0)
  133. return err;
  134. nap_bridge_mode = false;
  135. return 0;
  136. }
  137. static int device_cmp(gconstpointer s, gconstpointer user_data)
  138. {
  139. const struct pan_device *dev = s;
  140. const bdaddr_t *dst = user_data;
  141. return bacmp(&dev->dst, dst);
  142. }
  143. static void pan_device_free(void *data)
  144. {
  145. struct pan_device *dev = data;
  146. if (dev->watch > 0) {
  147. bnep_server_delete(BNEP_BRIDGE, dev->iface, &dev->dst);
  148. g_source_remove(dev->watch);
  149. }
  150. if (dev->io) {
  151. g_io_channel_shutdown(dev->io, FALSE, NULL);
  152. g_io_channel_unref(dev->io);
  153. }
  154. if (dev->session)
  155. bnep_free(dev->session);
  156. g_free(dev);
  157. }
  158. static void pan_device_remove(struct pan_device *dev)
  159. {
  160. devices = g_slist_remove(devices, dev);
  161. if (g_slist_length(devices) == 0) {
  162. local_role = HAL_PAN_ROLE_NONE;
  163. nap_remove_bridge();
  164. }
  165. pan_device_free(dev);
  166. }
  167. static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
  168. {
  169. struct hal_ev_pan_conn_state ev;
  170. char addr[18];
  171. if (dev->conn_state == state)
  172. return;
  173. dev->conn_state = state;
  174. ba2str(&dev->dst, addr);
  175. DBG("device %s state %u", addr, state);
  176. bdaddr2android(&dev->dst, ev.bdaddr);
  177. ev.state = state;
  178. ev.local_role = local_role;
  179. ev.remote_role = dev->role;
  180. ev.status = HAL_STATUS_SUCCESS;
  181. ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE,
  182. sizeof(ev), &ev);
  183. if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED)
  184. pan_device_remove(dev);
  185. }
  186. static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state,
  187. uint8_t status)
  188. {
  189. struct hal_ev_pan_ctrl_state ev;
  190. DBG("");
  191. ev.state = state;
  192. ev.local_role = local_role;
  193. ev.status = status;
  194. memset(ev.name, 0, sizeof(ev.name));
  195. if (local_role == HAL_PAN_ROLE_NAP)
  196. memcpy(ev.name, BNEP_BRIDGE, sizeof(BNEP_BRIDGE));
  197. else if (local_role == HAL_PAN_ROLE_PANU)
  198. memcpy(ev.name, dev->iface, sizeof(dev->iface));
  199. ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE,
  200. sizeof(ev), &ev);
  201. }
  202. static void bnep_disconn_cb(void *data)
  203. {
  204. struct pan_device *dev = data;
  205. DBG("%s disconnected", dev->iface);
  206. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  207. }
  208. static void bnep_conn_cb(char *iface, int err, void *data)
  209. {
  210. struct pan_device *dev = data;
  211. DBG("");
  212. if (err < 0) {
  213. error("bnep connect req failed: %s", strerror(-err));
  214. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  215. return;
  216. }
  217. memcpy(dev->iface, iface, sizeof(dev->iface));
  218. DBG("%s connected", dev->iface);
  219. bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED, HAL_STATUS_SUCCESS);
  220. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
  221. }
  222. static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
  223. {
  224. struct pan_device *dev = data;
  225. uint16_t l_role, r_role;
  226. int perr, sk;
  227. DBG("");
  228. if (err) {
  229. error("%s", err->message);
  230. goto fail;
  231. }
  232. l_role = (local_role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP :
  233. BNEP_SVC_PANU;
  234. r_role = (dev->role == HAL_PAN_ROLE_NAP) ? BNEP_SVC_NAP : BNEP_SVC_PANU;
  235. sk = g_io_channel_unix_get_fd(dev->io);
  236. dev->session = bnep_new(sk, l_role, r_role, BNEP_PANU_INTERFACE);
  237. if (!dev->session)
  238. goto fail;
  239. perr = bnep_connect(dev->session, bnep_conn_cb, bnep_disconn_cb, dev,
  240. dev);
  241. if (perr < 0) {
  242. error("bnep connect req failed: %s", strerror(-perr));
  243. goto fail;
  244. }
  245. if (dev->io) {
  246. g_io_channel_unref(dev->io);
  247. dev->io = NULL;
  248. }
  249. return;
  250. fail:
  251. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  252. }
  253. static void bt_pan_connect(const void *buf, uint16_t len)
  254. {
  255. const struct hal_cmd_pan_connect *cmd = buf;
  256. struct pan_device *dev;
  257. uint8_t status;
  258. bdaddr_t dst;
  259. char addr[18];
  260. GSList *l;
  261. GError *gerr = NULL;
  262. DBG("");
  263. switch (cmd->local_role) {
  264. case HAL_PAN_ROLE_NAP:
  265. if (cmd->remote_role != HAL_PAN_ROLE_PANU) {
  266. status = HAL_STATUS_UNSUPPORTED;
  267. goto failed;
  268. }
  269. break;
  270. case HAL_PAN_ROLE_PANU:
  271. if (cmd->remote_role != HAL_PAN_ROLE_NAP &&
  272. cmd->remote_role != HAL_PAN_ROLE_PANU) {
  273. status = HAL_STATUS_UNSUPPORTED;
  274. goto failed;
  275. }
  276. break;
  277. default:
  278. status = HAL_STATUS_UNSUPPORTED;
  279. goto failed;
  280. }
  281. android2bdaddr(&cmd->bdaddr, &dst);
  282. l = g_slist_find_custom(devices, &dst, device_cmp);
  283. if (l) {
  284. status = HAL_STATUS_FAILED;
  285. goto failed;
  286. }
  287. dev = g_new0(struct pan_device, 1);
  288. bacpy(&dev->dst, &dst);
  289. local_role = cmd->local_role;
  290. dev->role = cmd->remote_role;
  291. ba2str(&dev->dst, addr);
  292. DBG("connecting to %s %s", addr, dev->iface);
  293. dev->io = bt_io_connect(connect_cb, dev, NULL, &gerr,
  294. BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
  295. BT_IO_OPT_DEST_BDADDR, &dev->dst,
  296. BT_IO_OPT_PSM, BNEP_PSM,
  297. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
  298. BT_IO_OPT_OMTU, BNEP_MTU,
  299. BT_IO_OPT_IMTU, BNEP_MTU,
  300. BT_IO_OPT_INVALID);
  301. if (!dev->io) {
  302. error("%s", gerr->message);
  303. g_error_free(gerr);
  304. g_free(dev);
  305. status = HAL_STATUS_FAILED;
  306. goto failed;
  307. }
  308. devices = g_slist_append(devices, dev);
  309. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
  310. status = HAL_STATUS_SUCCESS;
  311. failed:
  312. ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status);
  313. }
  314. static void bt_pan_disconnect(const void *buf, uint16_t len)
  315. {
  316. const struct hal_cmd_pan_disconnect *cmd = buf;
  317. struct pan_device *dev;
  318. uint8_t status;
  319. GSList *l;
  320. bdaddr_t dst;
  321. DBG("");
  322. android2bdaddr(&cmd->bdaddr, &dst);
  323. l = g_slist_find_custom(devices, &dst, device_cmp);
  324. if (!l) {
  325. status = HAL_STATUS_FAILED;
  326. goto failed;
  327. }
  328. dev = l->data;
  329. if (dev->conn_state == HAL_PAN_STATE_CONNECTED && dev->session)
  330. bnep_disconnect(dev->session);
  331. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  332. status = HAL_STATUS_SUCCESS;
  333. failed:
  334. ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
  335. status);
  336. }
  337. static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
  338. gpointer user_data)
  339. {
  340. struct pan_device *dev = user_data;
  341. DBG("disconnected");
  342. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  343. return FALSE;
  344. }
  345. static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
  346. gpointer user_data)
  347. {
  348. struct pan_device *dev = user_data;
  349. uint8_t packet[BNEP_MTU];
  350. int sk, n, err;
  351. if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
  352. error("Hangup or error or inval on BNEP socket");
  353. return FALSE;
  354. }
  355. sk = g_io_channel_unix_get_fd(chan);
  356. /*
  357. * BNEP_SETUP_CONNECTION_REQUEST_MSG should be read and left in case
  358. * of kernel setup connection msg handling.
  359. */
  360. n = recv(sk, packet, sizeof(packet), MSG_PEEK);
  361. if (n < 0) {
  362. error("read(): %s(%d)", strerror(errno), errno);
  363. goto failed;
  364. }
  365. if (n < 3) {
  366. error("pan: to few setup connection request data received");
  367. goto failed;
  368. }
  369. err = nap_create_bridge();
  370. if (err < 0)
  371. error("pan: Failed to create bridge: %s (%d)", strerror(-err),
  372. -err);
  373. if (bnep_server_add(sk, (err < 0) ? NULL : BNEP_BRIDGE, dev->iface,
  374. &dev->dst, packet, n) < 0) {
  375. error("pan: server_connadd failed");
  376. goto failed;
  377. }
  378. dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  379. nap_watchdog_cb, dev);
  380. g_io_channel_unref(dev->io);
  381. dev->io = NULL;
  382. bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED, HAL_STATUS_SUCCESS);
  383. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);
  384. return FALSE;
  385. failed:
  386. pan_device_remove(dev);
  387. return FALSE;
  388. }
  389. static void nap_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
  390. {
  391. struct pan_device *dev = user_data;
  392. DBG("");
  393. if (err) {
  394. error("%s", err->message);
  395. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  396. return;
  397. }
  398. g_io_channel_set_close_on_unref(chan, TRUE);
  399. dev->watch = g_io_add_watch(chan,
  400. G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  401. nap_setup_cb, dev);
  402. }
  403. static void nap_confirm_cb(GIOChannel *chan, gpointer data)
  404. {
  405. struct pan_device *dev;
  406. bdaddr_t dst;
  407. char address[18];
  408. GError *err = NULL;
  409. DBG("");
  410. bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
  411. BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
  412. if (err) {
  413. error("%s", err->message);
  414. g_error_free(err);
  415. return;
  416. }
  417. DBG("incoming connect request from %s", address);
  418. dev = g_new0(struct pan_device, 1);
  419. bacpy(&dev->dst, &dst);
  420. local_role = HAL_PAN_ROLE_NAP;
  421. dev->role = HAL_PAN_ROLE_PANU;
  422. strncpy(dev->iface, BNEP_NAP_INTERFACE, 16);
  423. dev->iface[15] = '\0';
  424. dev->io = g_io_channel_ref(chan);
  425. g_io_channel_set_close_on_unref(dev->io, TRUE);
  426. if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
  427. error("bt_io_accept: %s", err->message);
  428. g_error_free(err);
  429. goto failed;
  430. }
  431. devices = g_slist_append(devices, dev);
  432. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);
  433. return;
  434. failed:
  435. bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
  436. }
  437. static void destroy_nap_device(void)
  438. {
  439. DBG("");
  440. nap_remove_bridge();
  441. if (nap_io) {
  442. g_io_channel_shutdown(nap_io, FALSE, NULL);
  443. g_io_channel_unref(nap_io);
  444. nap_io = NULL;
  445. }
  446. }
  447. static int register_nap_server(void)
  448. {
  449. GError *gerr = NULL;
  450. DBG("");
  451. nap_io = bt_io_listen(NULL, nap_confirm_cb, NULL, NULL, &gerr,
  452. BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
  453. BT_IO_OPT_PSM, BNEP_PSM,
  454. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
  455. BT_IO_OPT_OMTU, BNEP_MTU,
  456. BT_IO_OPT_IMTU, BNEP_MTU,
  457. BT_IO_OPT_INVALID);
  458. if (!nap_io) {
  459. destroy_nap_device();
  460. error("%s", gerr->message);
  461. g_error_free(gerr);
  462. return -EIO;
  463. }
  464. return 0;
  465. }
  466. static void bt_pan_enable(const void *buf, uint16_t len)
  467. {
  468. const struct hal_cmd_pan_enable *cmd = buf;
  469. uint8_t status, state;
  470. int err;
  471. DBG("");
  472. if (local_role == cmd->local_role) {
  473. status = HAL_STATUS_SUCCESS;
  474. goto reply;
  475. }
  476. /* destroy existing server */
  477. destroy_nap_device();
  478. switch (cmd->local_role) {
  479. case HAL_PAN_ROLE_NAP:
  480. break;
  481. case HAL_PAN_ROLE_NONE:
  482. local_role = HAL_PAN_ROLE_NONE;
  483. status = HAL_STATUS_SUCCESS;
  484. state = HAL_PAN_CTRL_DISABLED;
  485. goto notify;
  486. default:
  487. status = HAL_STATUS_UNSUPPORTED;
  488. goto reply;
  489. }
  490. local_role = cmd->local_role;
  491. err = register_nap_server();
  492. if (err < 0) {
  493. status = HAL_STATUS_FAILED;
  494. destroy_nap_device();
  495. goto reply;
  496. }
  497. status = HAL_STATUS_SUCCESS;
  498. state = HAL_PAN_CTRL_ENABLED;
  499. notify:
  500. bt_pan_notify_ctrl_state(NULL, state, status);
  501. reply:
  502. ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
  503. }
  504. static void bt_pan_get_role(const void *buf, uint16_t len)
  505. {
  506. struct hal_rsp_pan_get_role rsp;
  507. DBG("");
  508. rsp.local_role = local_role;
  509. ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE,
  510. sizeof(rsp), &rsp, -1);
  511. }
  512. static const struct ipc_handler cmd_handlers[] = {
  513. /* HAL_OP_PAN_ENABLE */
  514. { bt_pan_enable, false, sizeof(struct hal_cmd_pan_enable) },
  515. /* HAL_OP_PAN_GET_ROLE */
  516. { bt_pan_get_role, false, 0 },
  517. /* HAL_OP_PAN_CONNECT */
  518. { bt_pan_connect, false, sizeof(struct hal_cmd_pan_connect) },
  519. /* HAL_OP_PAN_DISCONNECT */
  520. { bt_pan_disconnect, false, sizeof(struct hal_cmd_pan_disconnect) },
  521. };
  522. static sdp_record_t *nap_record(void)
  523. {
  524. sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
  525. uuid_t root_uuid, nap, l2cap, bnep;
  526. sdp_profile_desc_t profile[1];
  527. sdp_list_t *proto[2];
  528. sdp_data_t *v, *p;
  529. uint16_t psm = BNEP_PSM, version = 0x0100;
  530. uint16_t security = 0x0001, type = 0xfffe;
  531. uint32_t rate = 0;
  532. const char *desc = "Network Access Point", *name = "Network Service";
  533. sdp_record_t *record;
  534. uint16_t ptype[] = { 0x0800, /* IPv4 */ 0x0806, /* ARP */ };
  535. sdp_data_t *head, *pseq, *data;
  536. record = sdp_record_alloc();
  537. if (!record)
  538. return NULL;
  539. record->attrlist = NULL;
  540. record->pattern = NULL;
  541. sdp_uuid16_create(&nap, NAP_SVCLASS_ID);
  542. svclass = sdp_list_append(NULL, &nap);
  543. sdp_set_service_classes(record, svclass);
  544. sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
  545. profile[0].version = 0x0100;
  546. pfseq = sdp_list_append(NULL, &profile[0]);
  547. sdp_set_profile_descs(record, pfseq);
  548. sdp_set_info_attr(record, name, NULL, desc);
  549. sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE, SDP_UINT16, &type);
  550. sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE,
  551. SDP_UINT32, &rate);
  552. sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
  553. root = sdp_list_append(NULL, &root_uuid);
  554. sdp_set_browse_groups(record, root);
  555. sdp_uuid16_create(&l2cap, L2CAP_UUID);
  556. proto[0] = sdp_list_append(NULL, &l2cap);
  557. p = sdp_data_alloc(SDP_UINT16, &psm);
  558. proto[0] = sdp_list_append(proto[0], p);
  559. apseq = sdp_list_append(NULL, proto[0]);
  560. sdp_uuid16_create(&bnep, BNEP_UUID);
  561. proto[1] = sdp_list_append(NULL, &bnep);
  562. v = sdp_data_alloc(SDP_UINT16, &version);
  563. proto[1] = sdp_list_append(proto[1], v);
  564. head = sdp_data_alloc(SDP_UINT16, &ptype[0]);
  565. data = sdp_data_alloc(SDP_UINT16, &ptype[1]);
  566. sdp_seq_append(head, data);
  567. pseq = sdp_data_alloc(SDP_SEQ16, head);
  568. proto[1] = sdp_list_append(proto[1], pseq);
  569. apseq = sdp_list_append(apseq, proto[1]);
  570. aproto = sdp_list_append(NULL, apseq);
  571. sdp_set_access_protos(record, aproto);
  572. sdp_add_lang_attr(record);
  573. sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC, SDP_UINT16, &security);
  574. sdp_data_free(p);
  575. sdp_data_free(v);
  576. sdp_list_free(apseq, NULL);
  577. sdp_list_free(root, NULL);
  578. sdp_list_free(aproto, NULL);
  579. sdp_list_free(proto[0], NULL);
  580. sdp_list_free(proto[1], NULL);
  581. sdp_list_free(svclass, NULL);
  582. sdp_list_free(pfseq, NULL);
  583. return record;
  584. }
  585. static sdp_record_t *panu_record(void)
  586. {
  587. sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
  588. uuid_t root_uuid, panu, l2cap, bnep;
  589. sdp_profile_desc_t profile[1];
  590. sdp_list_t *proto[2];
  591. sdp_data_t *v, *p;
  592. uint16_t psm = BNEP_PSM, version = 0x0100;
  593. uint16_t security = 0x0001, type = 0xfffe;
  594. uint32_t rate = 0;
  595. const char *desc = "PAN User", *name = "Network Service";
  596. sdp_record_t *record;
  597. uint16_t ptype[] = { 0x0800, /* IPv4 */ 0x0806, /* ARP */ };
  598. sdp_data_t *head, *pseq, *data;
  599. record = sdp_record_alloc();
  600. if (!record)
  601. return NULL;
  602. record->attrlist = NULL;
  603. record->pattern = NULL;
  604. sdp_uuid16_create(&panu, PANU_SVCLASS_ID);
  605. svclass = sdp_list_append(NULL, &panu);
  606. sdp_set_service_classes(record, svclass);
  607. sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
  608. profile[0].version = 0x0100;
  609. pfseq = sdp_list_append(NULL, &profile[0]);
  610. sdp_set_profile_descs(record, pfseq);
  611. sdp_set_info_attr(record, name, NULL, desc);
  612. sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE, SDP_UINT16, &type);
  613. sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE,
  614. SDP_UINT32, &rate);
  615. sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
  616. root = sdp_list_append(NULL, &root_uuid);
  617. sdp_set_browse_groups(record, root);
  618. sdp_uuid16_create(&l2cap, L2CAP_UUID);
  619. proto[0] = sdp_list_append(NULL, &l2cap);
  620. p = sdp_data_alloc(SDP_UINT16, &psm);
  621. proto[0] = sdp_list_append(proto[0], p);
  622. apseq = sdp_list_append(NULL, proto[0]);
  623. sdp_uuid16_create(&bnep, BNEP_UUID);
  624. proto[1] = sdp_list_append(NULL, &bnep);
  625. v = sdp_data_alloc(SDP_UINT16, &version);
  626. proto[1] = sdp_list_append(proto[1], v);
  627. head = sdp_data_alloc(SDP_UINT16, &ptype[0]);
  628. data = sdp_data_alloc(SDP_UINT16, &ptype[1]);
  629. sdp_seq_append(head, data);
  630. pseq = sdp_data_alloc(SDP_SEQ16, head);
  631. proto[1] = sdp_list_append(proto[1], pseq);
  632. apseq = sdp_list_append(apseq, proto[1]);
  633. aproto = sdp_list_append(NULL, apseq);
  634. sdp_set_access_protos(record, aproto);
  635. sdp_add_lang_attr(record);
  636. sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC, SDP_UINT16, &security);
  637. sdp_data_free(p);
  638. sdp_data_free(v);
  639. sdp_list_free(apseq, NULL);
  640. sdp_list_free(root, NULL);
  641. sdp_list_free(aproto, NULL);
  642. sdp_list_free(proto[0], NULL);
  643. sdp_list_free(proto[1], NULL);
  644. sdp_list_free(svclass, NULL);
  645. sdp_list_free(pfseq, NULL);
  646. return record;
  647. }
  648. bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
  649. {
  650. sdp_record_t *nap_rec, *panu_rec;
  651. int err;
  652. DBG("");
  653. bacpy(&adapter_addr, addr);
  654. nap_rec = nap_record();
  655. if (bt_adapter_add_record(nap_rec, SVC_HINT_NETWORKING) < 0) {
  656. sdp_record_free(nap_rec);
  657. error("Failed to allocate PAN-NAP sdp record");
  658. return false;
  659. }
  660. panu_rec = panu_record();
  661. if (bt_adapter_add_record(panu_rec, SVC_HINT_NETWORKING) < 0) {
  662. sdp_record_free(nap_rec);
  663. sdp_record_free(panu_rec);
  664. error("Failed to allocate PAN-PANU sdp record");
  665. return false;
  666. }
  667. err = bnep_init();
  668. if (err < 0) {
  669. error("Failed to init BNEP");
  670. bt_adapter_remove_record(nap_rec->handle);
  671. bt_adapter_remove_record(panu_rec->handle);
  672. return false;
  673. }
  674. err = register_nap_server();
  675. if (err < 0) {
  676. error("Failed to register NAP server");
  677. bt_adapter_remove_record(nap_rec->handle);
  678. bt_adapter_remove_record(panu_rec->handle);
  679. bnep_cleanup();
  680. return false;
  681. }
  682. nap_rec_id = nap_rec->handle;
  683. panu_rec_id = panu_rec->handle;
  684. hal_ipc = ipc;
  685. ipc_register(hal_ipc, HAL_SERVICE_ID_PAN, cmd_handlers,
  686. G_N_ELEMENTS(cmd_handlers));
  687. return true;
  688. }
  689. void bt_pan_unregister(void)
  690. {
  691. DBG("");
  692. g_slist_free_full(devices, pan_device_free);
  693. devices = NULL;
  694. local_role = HAL_PAN_ROLE_NONE;
  695. bnep_cleanup();
  696. ipc_unregister(hal_ipc, HAL_SERVICE_ID_PAN);
  697. hal_ipc = NULL;
  698. bt_adapter_remove_record(nap_rec_id);
  699. nap_rec_id = 0;
  700. bt_adapter_remove_record(panu_rec_id);
  701. panu_rec_id = 0;
  702. destroy_nap_device();
  703. }