server.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <errno.h>
  18. #include <netinet/in.h>
  19. #include <glib.h>
  20. #include "lib/bluetooth.h"
  21. #include "lib/bnep.h"
  22. #include "lib/sdp.h"
  23. #include "lib/sdp_lib.h"
  24. #include "lib/uuid.h"
  25. #include "gdbus/gdbus.h"
  26. #include "btio/btio.h"
  27. #include "src/dbus-common.h"
  28. #include "src/adapter.h"
  29. #include "src/log.h"
  30. #include "src/error.h"
  31. #include "src/sdpd.h"
  32. #include "src/shared/util.h"
  33. #include "bnep.h"
  34. #include "server.h"
  35. #define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1"
  36. #define BNEP_INTERFACE "bnep%d"
  37. #define SETUP_TIMEOUT 1
  38. /* Pending Authorization */
  39. struct network_session {
  40. bdaddr_t dst; /* Remote Bluetooth Address */
  41. char dev[16]; /* Interface name */
  42. GIOChannel *io; /* Pending connect channel */
  43. guint watch; /* BNEP socket watch */
  44. };
  45. struct network_adapter {
  46. struct btd_adapter *adapter; /* Adapter pointer */
  47. GIOChannel *io; /* Bnep socket */
  48. struct network_session *setup; /* Setup in progress */
  49. GSList *servers; /* Server register to adapter */
  50. };
  51. /* Main server structure */
  52. struct network_server {
  53. bdaddr_t src; /* Bluetooth Local Address */
  54. char *name; /* Server service name */
  55. char *bridge; /* Bridge name */
  56. uint32_t record_id; /* Service record id */
  57. uint16_t id; /* Service class identifier */
  58. GSList *sessions; /* Active connections */
  59. struct network_adapter *na; /* Adapter reference */
  60. guint watch_id; /* Client service watch */
  61. };
  62. static GSList *adapters = NULL;
  63. static gboolean security = TRUE;
  64. static struct network_adapter *find_adapter(GSList *list,
  65. struct btd_adapter *adapter)
  66. {
  67. for (; list; list = list->next) {
  68. struct network_adapter *na = list->data;
  69. if (na->adapter == adapter)
  70. return na;
  71. }
  72. return NULL;
  73. }
  74. static struct network_server *find_server(GSList *list, uint16_t id)
  75. {
  76. for (; list; list = list->next) {
  77. struct network_server *ns = list->data;
  78. if (ns->id == id)
  79. return ns;
  80. }
  81. return NULL;
  82. }
  83. static struct network_server *find_server_by_uuid(GSList *list,
  84. const char *uuid)
  85. {
  86. bt_uuid_t srv_uuid, bnep_uuid;
  87. if (!bt_string_to_uuid(&srv_uuid, uuid)) {
  88. for (; list; list = list->next) {
  89. struct network_server *ns = list->data;
  90. bt_uuid16_create(&bnep_uuid, ns->id);
  91. /* UUID value compare */
  92. if (!bt_uuid_cmp(&srv_uuid, &bnep_uuid))
  93. return ns;
  94. }
  95. } else {
  96. for (; list; list = list->next) {
  97. struct network_server *ns = list->data;
  98. /* String value compare */
  99. switch (ns->id) {
  100. case BNEP_SVC_PANU:
  101. if (!strcasecmp(uuid, "panu"))
  102. return ns;
  103. break;
  104. case BNEP_SVC_NAP:
  105. if (!strcasecmp(uuid, "nap"))
  106. return ns;
  107. break;
  108. case BNEP_SVC_GN:
  109. if (!strcasecmp(uuid, "gn"))
  110. return ns;
  111. break;
  112. }
  113. }
  114. }
  115. return NULL;
  116. }
  117. static sdp_record_t *server_record_new(const char *name, uint16_t id)
  118. {
  119. sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
  120. uuid_t root_uuid, pan, l2cap, bnep;
  121. sdp_profile_desc_t profile[1];
  122. sdp_list_t *proto[2];
  123. sdp_data_t *v, *p;
  124. uint16_t psm = BNEP_PSM, version = 0x0100;
  125. uint16_t security_desc = (security ? 0x0001 : 0x0000);
  126. uint16_t net_access_type = 0xfffe;
  127. uint32_t max_net_access_rate = 0;
  128. const char *desc = "Network service";
  129. sdp_record_t *record;
  130. record = sdp_record_alloc();
  131. if (!record)
  132. return NULL;
  133. record->attrlist = NULL;
  134. record->pattern = NULL;
  135. switch (id) {
  136. case BNEP_SVC_NAP:
  137. sdp_uuid16_create(&pan, NAP_SVCLASS_ID);
  138. svclass = sdp_list_append(NULL, &pan);
  139. sdp_set_service_classes(record, svclass);
  140. sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
  141. profile[0].version = 0x0100;
  142. pfseq = sdp_list_append(NULL, &profile[0]);
  143. sdp_set_profile_descs(record, pfseq);
  144. sdp_set_info_attr(record, name, NULL, desc);
  145. sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE,
  146. SDP_UINT16, &net_access_type);
  147. sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE,
  148. SDP_UINT32, &max_net_access_rate);
  149. break;
  150. case BNEP_SVC_GN:
  151. sdp_uuid16_create(&pan, GN_SVCLASS_ID);
  152. svclass = sdp_list_append(NULL, &pan);
  153. sdp_set_service_classes(record, svclass);
  154. sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
  155. profile[0].version = 0x0100;
  156. pfseq = sdp_list_append(NULL, &profile[0]);
  157. sdp_set_profile_descs(record, pfseq);
  158. sdp_set_info_attr(record, name, NULL, desc);
  159. break;
  160. case BNEP_SVC_PANU:
  161. sdp_uuid16_create(&pan, PANU_SVCLASS_ID);
  162. svclass = sdp_list_append(NULL, &pan);
  163. sdp_set_service_classes(record, svclass);
  164. sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
  165. profile[0].version = 0x0100;
  166. pfseq = sdp_list_append(NULL, &profile[0]);
  167. sdp_set_profile_descs(record, pfseq);
  168. sdp_set_info_attr(record, name, NULL, desc);
  169. break;
  170. default:
  171. sdp_record_free(record);
  172. return NULL;
  173. }
  174. sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
  175. root = sdp_list_append(NULL, &root_uuid);
  176. sdp_set_browse_groups(record, root);
  177. sdp_uuid16_create(&l2cap, L2CAP_UUID);
  178. proto[0] = sdp_list_append(NULL, &l2cap);
  179. p = sdp_data_alloc(SDP_UINT16, &psm);
  180. proto[0] = sdp_list_append(proto[0], p);
  181. apseq = sdp_list_append(NULL, proto[0]);
  182. sdp_uuid16_create(&bnep, BNEP_UUID);
  183. proto[1] = sdp_list_append(NULL, &bnep);
  184. v = sdp_data_alloc(SDP_UINT16, &version);
  185. proto[1] = sdp_list_append(proto[1], v);
  186. /* Supported protocols */
  187. {
  188. uint16_t ptype[] = {
  189. 0x0800, /* IPv4 */
  190. 0x0806, /* ARP */
  191. };
  192. sdp_data_t *head, *pseq;
  193. int p;
  194. for (p = 0, head = NULL; p < 2; p++) {
  195. sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
  196. if (head)
  197. sdp_seq_append(head, data);
  198. else
  199. head = data;
  200. }
  201. pseq = sdp_data_alloc(SDP_SEQ16, head);
  202. proto[1] = sdp_list_append(proto[1], pseq);
  203. }
  204. apseq = sdp_list_append(apseq, proto[1]);
  205. aproto = sdp_list_append(NULL, apseq);
  206. sdp_set_access_protos(record, aproto);
  207. sdp_add_lang_attr(record);
  208. sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC,
  209. SDP_UINT16, &security_desc);
  210. sdp_data_free(p);
  211. sdp_data_free(v);
  212. sdp_list_free(apseq, NULL);
  213. sdp_list_free(root, NULL);
  214. sdp_list_free(aproto, NULL);
  215. sdp_list_free(proto[0], NULL);
  216. sdp_list_free(proto[1], NULL);
  217. sdp_list_free(svclass, NULL);
  218. sdp_list_free(pfseq, NULL);
  219. return record;
  220. }
  221. static void session_free(void *data)
  222. {
  223. struct network_session *session = data;
  224. if (session->watch)
  225. g_source_remove(session->watch);
  226. if (session->io)
  227. g_io_channel_unref(session->io);
  228. g_free(session);
  229. }
  230. static void setup_destroy(void *user_data)
  231. {
  232. struct network_adapter *na = user_data;
  233. struct network_session *setup = na->setup;
  234. if (!setup)
  235. return;
  236. na->setup = NULL;
  237. session_free(setup);
  238. }
  239. static gboolean bnep_setup(GIOChannel *chan,
  240. GIOCondition cond, gpointer user_data)
  241. {
  242. const uint8_t bt_base[] = { 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
  243. 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
  244. struct network_adapter *na = user_data;
  245. struct network_server *ns;
  246. uint8_t packet[BNEP_MTU];
  247. struct bnep_setup_conn_req *req = (void *) packet;
  248. uint16_t dst_role = 0;
  249. uint32_t val;
  250. int n, sk;
  251. char *bridge = NULL;
  252. if (cond & G_IO_NVAL)
  253. return FALSE;
  254. if (cond & (G_IO_ERR | G_IO_HUP)) {
  255. error("Hangup or error on BNEP socket");
  256. return FALSE;
  257. }
  258. sk = g_io_channel_unix_get_fd(chan);
  259. /*
  260. * BNEP_SETUP_CONNECTION_REQUEST_MSG should be read and left in case
  261. * of kernel setup connection msg handling.
  262. */
  263. n = recv(sk, packet, sizeof(packet), MSG_PEEK);
  264. if (n < 0) {
  265. error("read(): %s(%d)", strerror(errno), errno);
  266. return FALSE;
  267. }
  268. /*
  269. * Initial received data packet is BNEP_SETUP_CONNECTION_REQUEST_MSG
  270. * minimal size of this frame is 3 octets: 1 byte of BNEP Type +
  271. * 1 byte of BNEP Control Type + 1 byte of BNEP services UUID size.
  272. */
  273. if (n < 3) {
  274. error("To few setup connection request data received");
  275. return FALSE;
  276. }
  277. switch (req->uuid_size) {
  278. case 2:
  279. dst_role = get_be16(req->service);
  280. break;
  281. case 16:
  282. if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0)
  283. break;
  284. /* fall through */
  285. case 4:
  286. val = get_be32(req->service);
  287. if (val > 0xffff)
  288. break;
  289. dst_role = val;
  290. break;
  291. default:
  292. break;
  293. }
  294. ns = find_server(na->servers, dst_role);
  295. if (!ns || !ns->record_id || !ns->bridge)
  296. error("Server error, bridge not initialized: (0x%x)", dst_role);
  297. else
  298. bridge = ns->bridge;
  299. strncpy(na->setup->dev, BNEP_INTERFACE, 16);
  300. na->setup->dev[15] = '\0';
  301. if (bnep_server_add(sk, bridge, na->setup->dev, &na->setup->dst,
  302. packet, n) < 0)
  303. error("BNEP server cannot be added");
  304. na->setup = NULL;
  305. return FALSE;
  306. }
  307. static void connect_event(GIOChannel *chan, GError *err, gpointer user_data)
  308. {
  309. struct network_adapter *na = user_data;
  310. if (err) {
  311. error("%s", err->message);
  312. setup_destroy(na);
  313. return;
  314. }
  315. g_io_channel_set_close_on_unref(chan, TRUE);
  316. na->setup->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,
  317. G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  318. bnep_setup, na, setup_destroy);
  319. }
  320. static void auth_cb(DBusError *derr, void *user_data)
  321. {
  322. struct network_adapter *na = user_data;
  323. GError *err = NULL;
  324. if (derr) {
  325. error("Access denied: %s", derr->message);
  326. goto reject;
  327. }
  328. if (!bt_io_accept(na->setup->io, connect_event, na, NULL,
  329. &err)) {
  330. error("bt_io_accept: %s", err->message);
  331. g_error_free(err);
  332. goto reject;
  333. }
  334. return;
  335. reject:
  336. g_io_channel_shutdown(na->setup->io, TRUE, NULL);
  337. setup_destroy(na);
  338. }
  339. static void confirm_event(GIOChannel *chan, gpointer user_data)
  340. {
  341. struct network_adapter *na = user_data;
  342. bdaddr_t src, dst;
  343. char address[18];
  344. GError *err = NULL;
  345. guint ret;
  346. bt_io_get(chan, &err,
  347. BT_IO_OPT_SOURCE_BDADDR, &src,
  348. BT_IO_OPT_DEST_BDADDR, &dst,
  349. BT_IO_OPT_DEST, address,
  350. BT_IO_OPT_INVALID);
  351. if (err) {
  352. error("%s", err->message);
  353. g_error_free(err);
  354. goto drop;
  355. }
  356. DBG("BNEP: incoming connect from %s", address);
  357. if (na->setup) {
  358. error("Refusing connect from %s: setup in progress", address);
  359. goto drop;
  360. }
  361. if (!na->servers)
  362. goto drop;
  363. na->setup = g_new0(struct network_session, 1);
  364. bacpy(&na->setup->dst, &dst);
  365. na->setup->io = g_io_channel_ref(chan);
  366. ret = btd_request_authorization(&src, &dst, BNEP_SVC_UUID,
  367. auth_cb, na);
  368. if (ret == 0) {
  369. error("Refusing connect from %s", address);
  370. setup_destroy(na);
  371. goto drop;
  372. }
  373. return;
  374. drop:
  375. g_io_channel_shutdown(chan, TRUE, NULL);
  376. }
  377. int server_init(gboolean secure)
  378. {
  379. security = secure;
  380. return 0;
  381. }
  382. static uint32_t register_server_record(struct network_server *ns)
  383. {
  384. sdp_record_t *record;
  385. record = server_record_new(ns->name, ns->id);
  386. if (!record) {
  387. error("Unable to allocate new service record");
  388. return 0;
  389. }
  390. if (adapter_service_add(ns->na->adapter, record) < 0) {
  391. error("Failed to register service record");
  392. sdp_record_free(record);
  393. return 0;
  394. }
  395. DBG("got record id 0x%x", record->handle);
  396. return record->handle;
  397. }
  398. static void server_remove_sessions(struct network_server *ns)
  399. {
  400. GSList *list;
  401. for (list = ns->sessions; list; list = list->next) {
  402. struct network_session *session = list->data;
  403. if (*session->dev == '\0')
  404. continue;
  405. bnep_server_delete(ns->bridge, session->dev, &session->dst);
  406. }
  407. g_slist_free_full(ns->sessions, session_free);
  408. ns->sessions = NULL;
  409. }
  410. static void server_disconnect(DBusConnection *conn, void *user_data)
  411. {
  412. struct network_server *ns = user_data;
  413. server_remove_sessions(ns);
  414. ns->watch_id = 0;
  415. if (ns->record_id) {
  416. adapter_service_remove(ns->na->adapter, ns->record_id);
  417. ns->record_id = 0;
  418. }
  419. g_free(ns->bridge);
  420. ns->bridge = NULL;
  421. }
  422. static DBusMessage *register_server(DBusConnection *conn,
  423. DBusMessage *msg, void *data)
  424. {
  425. struct network_adapter *na = data;
  426. struct network_server *ns;
  427. DBusMessage *reply;
  428. const char *uuid, *bridge;
  429. if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
  430. DBUS_TYPE_STRING, &bridge, DBUS_TYPE_INVALID))
  431. return btd_error_invalid_args(msg);
  432. ns = find_server_by_uuid(na->servers, uuid);
  433. if (ns == NULL)
  434. return btd_error_failed(msg, "Invalid UUID");
  435. if (ns->record_id)
  436. return btd_error_already_exists(msg);
  437. reply = dbus_message_new_method_return(msg);
  438. if (!reply)
  439. return NULL;
  440. ns->record_id = register_server_record(ns);
  441. if (!ns->record_id)
  442. return btd_error_failed(msg, "SDP record registration failed");
  443. g_free(ns->bridge);
  444. ns->bridge = g_strdup(bridge);
  445. ns->watch_id = g_dbus_add_disconnect_watch(conn,
  446. dbus_message_get_sender(msg),
  447. server_disconnect, ns, NULL);
  448. return reply;
  449. }
  450. static DBusMessage *unregister_server(DBusConnection *conn,
  451. DBusMessage *msg, void *data)
  452. {
  453. struct network_adapter *na = data;
  454. struct network_server *ns;
  455. DBusMessage *reply;
  456. const char *uuid;
  457. if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
  458. DBUS_TYPE_INVALID))
  459. return btd_error_invalid_args(msg);
  460. ns = find_server_by_uuid(na->servers, uuid);
  461. if (!ns)
  462. return btd_error_failed(msg, "Invalid UUID");
  463. reply = dbus_message_new_method_return(msg);
  464. if (!reply)
  465. return NULL;
  466. g_dbus_remove_watch(conn, ns->watch_id);
  467. server_disconnect(conn, ns);
  468. return reply;
  469. }
  470. static void adapter_free(struct network_adapter *na)
  471. {
  472. if (na->io != NULL) {
  473. g_io_channel_shutdown(na->io, TRUE, NULL);
  474. g_io_channel_unref(na->io);
  475. }
  476. setup_destroy(na);
  477. btd_adapter_unref(na->adapter);
  478. g_free(na);
  479. }
  480. static void server_free(void *data)
  481. {
  482. struct network_server *ns = data;
  483. if (!ns)
  484. return;
  485. server_remove_sessions(ns);
  486. if (ns->record_id)
  487. adapter_service_remove(ns->na->adapter, ns->record_id);
  488. g_dbus_remove_watch(btd_get_dbus_connection(), ns->watch_id);
  489. g_free(ns->name);
  490. g_free(ns->bridge);
  491. g_free(ns);
  492. }
  493. static void path_unregister(void *data)
  494. {
  495. struct network_adapter *na = data;
  496. DBG("Unregistered interface %s on path %s",
  497. NETWORK_SERVER_INTERFACE, adapter_get_path(na->adapter));
  498. g_slist_free_full(na->servers, server_free);
  499. adapters = g_slist_remove(adapters, na);
  500. adapter_free(na);
  501. }
  502. static const GDBusMethodTable server_methods[] = {
  503. { GDBUS_METHOD("Register",
  504. GDBUS_ARGS({ "uuid", "s" }, { "bridge", "s" }), NULL,
  505. register_server) },
  506. { GDBUS_METHOD("Unregister",
  507. GDBUS_ARGS({ "uuid", "s" }), NULL,
  508. unregister_server) },
  509. { }
  510. };
  511. static struct network_adapter *create_adapter(struct btd_adapter *adapter)
  512. {
  513. struct network_adapter *na;
  514. GError *err = NULL;
  515. na = g_new0(struct network_adapter, 1);
  516. na->adapter = btd_adapter_ref(adapter);
  517. na->io = bt_io_listen(NULL, confirm_event, na, NULL, &err,
  518. BT_IO_OPT_SOURCE_BDADDR,
  519. btd_adapter_get_address(adapter),
  520. BT_IO_OPT_PSM, BNEP_PSM,
  521. BT_IO_OPT_OMTU, BNEP_MTU,
  522. BT_IO_OPT_IMTU, BNEP_MTU,
  523. BT_IO_OPT_SEC_LEVEL,
  524. security ? BT_IO_SEC_MEDIUM : BT_IO_SEC_LOW,
  525. BT_IO_OPT_INVALID);
  526. if (!na->io) {
  527. error("%s", err->message);
  528. g_error_free(err);
  529. adapter_free(na);
  530. return NULL;
  531. }
  532. return na;
  533. }
  534. int server_register(struct btd_adapter *adapter, uint16_t id)
  535. {
  536. struct network_adapter *na;
  537. struct network_server *ns;
  538. const char *path;
  539. na = find_adapter(adapters, adapter);
  540. if (!na) {
  541. na = create_adapter(adapter);
  542. if (!na)
  543. return -EINVAL;
  544. adapters = g_slist_append(adapters, na);
  545. }
  546. ns = find_server(na->servers, id);
  547. if (ns)
  548. return 0;
  549. ns = g_new0(struct network_server, 1);
  550. ns->name = g_strdup("Network service");
  551. path = adapter_get_path(adapter);
  552. if (g_slist_length(na->servers) > 0)
  553. goto done;
  554. if (!g_dbus_register_interface(btd_get_dbus_connection(), path,
  555. NETWORK_SERVER_INTERFACE,
  556. server_methods, NULL, NULL, na,
  557. path_unregister)) {
  558. error("D-Bus failed to register %s interface",
  559. NETWORK_SERVER_INTERFACE);
  560. server_free(ns);
  561. return -1;
  562. }
  563. DBG("Registered interface %s on path %s", NETWORK_SERVER_INTERFACE,
  564. path);
  565. done:
  566. bacpy(&ns->src, btd_adapter_get_address(adapter));
  567. ns->id = id;
  568. ns->na = na;
  569. ns->record_id = 0;
  570. na->servers = g_slist_append(na->servers, ns);
  571. return 0;
  572. }
  573. int server_unregister(struct btd_adapter *adapter, uint16_t id)
  574. {
  575. struct network_adapter *na;
  576. struct network_server *ns;
  577. na = find_adapter(adapters, adapter);
  578. if (!na)
  579. return -EINVAL;
  580. ns = find_server(na->servers, id);
  581. if (!ns)
  582. return -EINVAL;
  583. na->servers = g_slist_remove(na->servers, ns);
  584. server_free(ns);
  585. if (g_slist_length(na->servers) > 0)
  586. return 0;
  587. g_dbus_unregister_interface(btd_get_dbus_connection(),
  588. adapter_get_path(adapter),
  589. NETWORK_SERVER_INTERFACE);
  590. return 0;
  591. }