Home | History | Annotate | Download | only in network
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) holtmann.org>
      6  *
      7  *
      8  *  This program is free software; you can redistribute it and/or modify
      9  *  it under the terms of the GNU General Public License as published by
     10  *  the Free Software Foundation; either version 2 of the License, or
     11  *  (at your option) any later version.
     12  *
     13  *  This program is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *  GNU General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU General Public License
     19  *  along with this program; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <stdio.h>
     29 #include <unistd.h>
     30 #include <stdlib.h>
     31 #include <errno.h>
     32 
     33 #include <bluetooth/bluetooth.h>
     34 #include <bluetooth/hci.h>
     35 #include <bluetooth/bnep.h>
     36 #include <bluetooth/l2cap.h>
     37 #include <bluetooth/sdp.h>
     38 #include <bluetooth/sdp_lib.h>
     39 #include <netinet/in.h>
     40 
     41 #include <glib.h>
     42 #include <gdbus.h>
     43 
     44 #include "../src/dbus-common.h"
     45 #include "../src/adapter.h"
     46 
     47 #include "log.h"
     48 #include "error.h"
     49 #include "sdpd.h"
     50 #include "btio.h"
     51 #include "glib-helper.h"
     52 
     53 #include "common.h"
     54 #include "server.h"
     55 
     56 #define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer"
     57 #define SETUP_TIMEOUT		1
     58 
     59 /* Pending Authorization */
     60 struct network_session {
     61 	bdaddr_t	dst;		/* Remote Bluetooth Address */
     62 	GIOChannel	*io;		/* Pending connect channel */
     63 	guint		watch;		/* BNEP socket watch */
     64 };
     65 
     66 struct network_adapter {
     67 	struct btd_adapter *adapter;	/* Adapter pointer */
     68 	GIOChannel	*io;		/* Bnep socket */
     69 	struct network_session *setup;	/* Setup in progress */
     70 	GSList		*servers;	/* Server register to adapter */
     71 };
     72 
     73 /* Main server structure */
     74 struct network_server {
     75 	bdaddr_t	src;		/* Bluetooth Local Address */
     76 	char		*iface;		/* DBus interface */
     77 	char		*name;		/* Server service name */
     78 	char		*bridge;	/* Bridge name */
     79 	uint32_t	record_id;	/* Service record id */
     80 	uint16_t	id;		/* Service class identifier */
     81 	GSList		*sessions;	/* Active connections */
     82 	struct network_adapter *na;	/* Adapter reference */
     83 	guint		watch_id;	/* Client service watch */
     84 };
     85 
     86 static DBusConnection *connection = NULL;
     87 static GSList *adapters = NULL;
     88 static gboolean security = TRUE;
     89 
     90 static struct network_adapter *find_adapter(GSList *list,
     91 					struct btd_adapter *adapter)
     92 {
     93 	GSList *l;
     94 
     95 	for (l = list; l; l = l->next) {
     96 		struct network_adapter *na = l->data;
     97 
     98 		if (na->adapter == adapter)
     99 			return na;
    100 	}
    101 
    102 	return NULL;
    103 }
    104 
    105 static struct network_server *find_server(GSList *list, uint16_t id)
    106 {
    107 	GSList *l;
    108 
    109 	for (l = list; l; l = l->next) {
    110 		struct network_server *ns = l->data;
    111 
    112 		if (ns->id == id)
    113 			return ns;
    114 	}
    115 
    116 	return NULL;
    117 }
    118 
    119 static void add_lang_attr(sdp_record_t *r)
    120 {
    121 	sdp_lang_attr_t base_lang;
    122 	sdp_list_t *langs = 0;
    123 
    124 	/* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */
    125 	base_lang.code_ISO639 = (0x65 << 8) | 0x6e;
    126 	base_lang.encoding = 106;
    127 	base_lang.base_offset = SDP_PRIMARY_LANG_BASE;
    128 	langs = sdp_list_append(0, &base_lang);
    129 	sdp_set_lang_attr(r, langs);
    130 	sdp_list_free(langs, 0);
    131 }
    132 
    133 static sdp_record_t *server_record_new(const char *name, uint16_t id)
    134 {
    135 	sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
    136 	uuid_t root_uuid, pan, l2cap, bnep;
    137 	sdp_profile_desc_t profile[1];
    138 	sdp_list_t *proto[2];
    139 	sdp_data_t *v, *p;
    140 	uint16_t psm = BNEP_PSM, version = 0x0100;
    141 	uint16_t security_desc = (security ? 0x0001 : 0x0000);
    142 	uint16_t net_access_type = 0xfffe;
    143 	uint32_t max_net_access_rate = 0;
    144 	const char *desc = "Network service";
    145 	sdp_record_t *record;
    146 
    147 	record = sdp_record_alloc();
    148 	if (!record)
    149 		return NULL;
    150 
    151 	record->attrlist = NULL;
    152 	record->pattern = NULL;
    153 
    154 	switch (id) {
    155 	case BNEP_SVC_NAP:
    156 		sdp_uuid16_create(&pan, NAP_SVCLASS_ID);
    157 		svclass = sdp_list_append(NULL, &pan);
    158 		sdp_set_service_classes(record, svclass);
    159 
    160 		sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
    161 		profile[0].version = 0x0100;
    162 		pfseq = sdp_list_append(NULL, &profile[0]);
    163 		sdp_set_profile_descs(record, pfseq);
    164 
    165 		sdp_set_info_attr(record, name, NULL, desc);
    166 
    167 		sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE,
    168 					SDP_UINT16, &net_access_type);
    169 		sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE,
    170 					SDP_UINT32, &max_net_access_rate);
    171 		break;
    172 	case BNEP_SVC_GN:
    173 		sdp_uuid16_create(&pan, GN_SVCLASS_ID);
    174 		svclass = sdp_list_append(NULL, &pan);
    175 		sdp_set_service_classes(record, svclass);
    176 
    177 		sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
    178 		profile[0].version = 0x0100;
    179 		pfseq = sdp_list_append(NULL, &profile[0]);
    180 		sdp_set_profile_descs(record, pfseq);
    181 
    182 		sdp_set_info_attr(record, name, NULL, desc);
    183 		break;
    184 	case BNEP_SVC_PANU:
    185 		sdp_uuid16_create(&pan, PANU_SVCLASS_ID);
    186 		svclass = sdp_list_append(NULL, &pan);
    187 		sdp_set_service_classes(record, svclass);
    188 
    189 		sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
    190 		profile[0].version = 0x0100;
    191 		pfseq = sdp_list_append(NULL, &profile[0]);
    192 		sdp_set_profile_descs(record, pfseq);
    193 
    194 		sdp_set_info_attr(record, name, NULL, desc);
    195 		break;
    196 	default:
    197 		sdp_record_free(record);
    198 		return NULL;
    199 	}
    200 
    201 	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
    202 	root = sdp_list_append(NULL, &root_uuid);
    203 	sdp_set_browse_groups(record, root);
    204 
    205 	sdp_uuid16_create(&l2cap, L2CAP_UUID);
    206 	proto[0] = sdp_list_append(NULL, &l2cap);
    207 	p = sdp_data_alloc(SDP_UINT16, &psm);
    208 	proto[0] = sdp_list_append(proto[0], p);
    209 	apseq    = sdp_list_append(NULL, proto[0]);
    210 
    211 	sdp_uuid16_create(&bnep, BNEP_UUID);
    212 	proto[1] = sdp_list_append(NULL, &bnep);
    213 	v = sdp_data_alloc(SDP_UINT16, &version);
    214 	proto[1] = sdp_list_append(proto[1], v);
    215 
    216 	/* Supported protocols */
    217 	{
    218 		uint16_t ptype[] = {
    219 			0x0800,  /* IPv4 */
    220 			0x0806,  /* ARP */
    221 		};
    222 		sdp_data_t *head, *pseq;
    223 		int p;
    224 
    225 		for (p = 0, head = NULL; p < 2; p++) {
    226 			sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
    227 			if (head)
    228 				sdp_seq_append(head, data);
    229 			else
    230 				head = data;
    231 		}
    232 		pseq = sdp_data_alloc(SDP_SEQ16, head);
    233 		proto[1] = sdp_list_append(proto[1], pseq);
    234 	}
    235 
    236 	apseq = sdp_list_append(apseq, proto[1]);
    237 
    238 	aproto = sdp_list_append(NULL, apseq);
    239 	sdp_set_access_protos(record, aproto);
    240 
    241 	add_lang_attr(record);
    242 
    243 	sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC,
    244 				SDP_UINT16, &security_desc);
    245 
    246 	sdp_data_free(p);
    247 	sdp_data_free(v);
    248 	sdp_list_free(apseq, NULL);
    249 	sdp_list_free(root, NULL);
    250 	sdp_list_free(aproto, NULL);
    251 	sdp_list_free(proto[0], NULL);
    252 	sdp_list_free(proto[1], NULL);
    253 	sdp_list_free(svclass, NULL);
    254 	sdp_list_free(pfseq, NULL);
    255 
    256 	return record;
    257 }
    258 
    259 static ssize_t send_bnep_ctrl_rsp(int sk, uint16_t val)
    260 {
    261 	struct bnep_control_rsp rsp;
    262 
    263 	rsp.type = BNEP_CONTROL;
    264 	rsp.ctrl = BNEP_SETUP_CONN_RSP;
    265 	rsp.resp = htons(val);
    266 
    267 	return send(sk, &rsp, sizeof(rsp), 0);
    268 }
    269 
    270 static int server_connadd(struct network_server *ns,
    271 				struct network_session *session,
    272 				uint16_t dst_role)
    273 {
    274 	char devname[16];
    275 	int err, nsk;
    276 
    277 	memset(devname, 0, sizeof(devname));
    278 	strcpy(devname, "bnep%d");
    279 
    280 	nsk = g_io_channel_unix_get_fd(session->io);
    281 	err = bnep_connadd(nsk, dst_role, devname);
    282 	if (err < 0)
    283 		return err;
    284 
    285 	info("Added new connection: %s", devname);
    286 
    287 	if (bnep_add_to_bridge(devname, ns->bridge) < 0) {
    288 		error("Can't add %s to the bridge %s: %s(%d)",
    289 				devname, ns->bridge, strerror(errno), errno);
    290 		return -EPERM;
    291 	}
    292 
    293 	bnep_if_up(devname);
    294 
    295 	ns->sessions = g_slist_append(ns->sessions, session);
    296 
    297 	return 0;
    298 }
    299 
    300 static uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role)
    301 {
    302 	/* Allowed PAN Profile scenarios */
    303 	switch (dst_role) {
    304 	case BNEP_SVC_NAP:
    305 	case BNEP_SVC_GN:
    306 		if (src_role == BNEP_SVC_PANU)
    307 			return 0;
    308 		return BNEP_CONN_INVALID_SRC;
    309 	case BNEP_SVC_PANU:
    310 		if (src_role == BNEP_SVC_PANU ||
    311 				src_role == BNEP_SVC_GN ||
    312 				src_role == BNEP_SVC_NAP)
    313 			return 0;
    314 
    315 		return BNEP_CONN_INVALID_SRC;
    316 	}
    317 
    318 	return BNEP_CONN_INVALID_DST;
    319 }
    320 
    321 static uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req,
    322 				uint16_t *dst_role, uint16_t *src_role)
    323 {
    324 	uint8_t *dest, *source;
    325 
    326 	dest = req->service;
    327 	source = req->service + req->uuid_size;
    328 
    329 	switch (req->uuid_size) {
    330 	case 2: /* UUID16 */
    331 		*dst_role = ntohs(bt_get_unaligned((uint16_t *) dest));
    332 		*src_role = ntohs(bt_get_unaligned((uint16_t *) source));
    333 		break;
    334 	case 4: /* UUID32 */
    335 	case 16: /* UUID128 */
    336 		*dst_role = ntohl(bt_get_unaligned((uint32_t *) dest));
    337 		*src_role = ntohl(bt_get_unaligned((uint32_t *) source));
    338 		break;
    339 	default:
    340 		return BNEP_CONN_INVALID_SVC;
    341 	}
    342 
    343 	return 0;
    344 }
    345 
    346 static void session_free(void *data)
    347 {
    348 	struct network_session *session = data;
    349 
    350 	if (session->watch)
    351 		g_source_remove(session->watch);
    352 
    353 	if (session->io)
    354 		g_io_channel_unref(session->io);
    355 
    356 	g_free(session);
    357 }
    358 
    359 static void setup_destroy(void *user_data)
    360 {
    361 	struct network_adapter *na = user_data;
    362 	struct network_session *setup = na->setup;
    363 
    364 	if (!setup)
    365 		return;
    366 
    367 	na->setup = NULL;
    368 
    369 	session_free(setup);
    370 }
    371 
    372 static gboolean bnep_setup(GIOChannel *chan,
    373 			GIOCondition cond, gpointer user_data)
    374 {
    375 	struct network_adapter *na = user_data;
    376 	struct network_server *ns;
    377 	uint8_t packet[BNEP_MTU];
    378 	struct bnep_setup_conn_req *req = (void *) packet;
    379 	uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
    380 	int n, sk;
    381 
    382 	if (cond & G_IO_NVAL)
    383 		return FALSE;
    384 
    385 	if (cond & (G_IO_ERR | G_IO_HUP)) {
    386 		error("Hangup or error on BNEP socket");
    387 		return FALSE;
    388 	}
    389 
    390 	sk = g_io_channel_unix_get_fd(chan);
    391 
    392 	/* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
    393 	n = read(sk, packet, sizeof(packet));
    394 	if (n < 0) {
    395 		error("read(): %s(%d)", strerror(errno), errno);
    396 		return FALSE;
    397 	}
    398 
    399 	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
    400 		return FALSE;
    401 
    402 	rsp = bnep_setup_decode(req, &dst_role, &src_role);
    403 	if (rsp)
    404 		goto reply;
    405 
    406 	rsp = bnep_setup_chk(dst_role, src_role);
    407 	if (rsp)
    408 		goto reply;
    409 
    410 	ns = find_server(na->servers, dst_role);
    411 	if (!ns) {
    412 		error("Server unavailable: (0x%x)", dst_role);
    413 		goto reply;
    414 	}
    415 
    416 	if (!ns->record_id) {
    417 		error("Service record not available");
    418 		goto reply;
    419 	}
    420 
    421 	if (!ns->bridge) {
    422 		error("Bridge interface not configured");
    423 		goto reply;
    424 	}
    425 
    426 	if (server_connadd(ns, na->setup, dst_role) < 0)
    427 		goto reply;
    428 
    429 	na->setup = NULL;
    430 
    431 	rsp = BNEP_SUCCESS;
    432 
    433 reply:
    434 	send_bnep_ctrl_rsp(sk, rsp);
    435 
    436 	return FALSE;
    437 }
    438 
    439 static void connect_event(GIOChannel *chan, GError *err, gpointer user_data)
    440 {
    441 	struct network_adapter *na = user_data;
    442 
    443 	if (err) {
    444 		error("%s", err->message);
    445 		setup_destroy(na);
    446 		return;
    447 	}
    448 
    449 	g_io_channel_set_close_on_unref(chan, TRUE);
    450 
    451 	na->setup->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,
    452 				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
    453 				bnep_setup, na, setup_destroy);
    454 }
    455 
    456 static void auth_cb(DBusError *derr, void *user_data)
    457 {
    458 	struct network_adapter *na = user_data;
    459 	GError *err = NULL;
    460 
    461 	if (derr) {
    462 		error("Access denied: %s", derr->message);
    463 		goto reject;
    464 	}
    465 
    466 	if (!bt_io_accept(na->setup->io, connect_event, na, NULL,
    467 							&err)) {
    468 		error("bt_io_accept: %s", err->message);
    469 		g_error_free(err);
    470 		goto reject;
    471 	}
    472 
    473 	return;
    474 
    475 reject:
    476 	g_io_channel_shutdown(na->setup->io, TRUE, NULL);
    477 	setup_destroy(na);
    478 }
    479 
    480 static void confirm_event(GIOChannel *chan, gpointer user_data)
    481 {
    482 	struct network_adapter *na = user_data;
    483 	struct network_server *ns;
    484 	int perr;
    485 	bdaddr_t src, dst;
    486 	char address[18];
    487 	GError *err = NULL;
    488 
    489 	bt_io_get(chan, BT_IO_L2CAP, &err,
    490 			BT_IO_OPT_SOURCE_BDADDR, &src,
    491 			BT_IO_OPT_DEST_BDADDR, &dst,
    492 			BT_IO_OPT_DEST, address,
    493 			BT_IO_OPT_INVALID);
    494 	if (err) {
    495 		error("%s", err->message);
    496 		g_error_free(err);
    497 		goto drop;
    498 	}
    499 
    500 	DBG("BNEP: incoming connect from %s", address);
    501 
    502 	if (na->setup) {
    503 		error("Refusing connect from %s: setup in progress", address);
    504 		goto drop;
    505 	}
    506 
    507 	ns = find_server(na->servers, BNEP_SVC_NAP);
    508 	if (!ns)
    509 		goto drop;
    510 
    511 	if (!ns->record_id)
    512 		goto drop;
    513 
    514 	if (!ns->bridge)
    515 		goto drop;
    516 
    517 	na->setup = g_new0(struct network_session, 1);
    518 	bacpy(&na->setup->dst, &dst);
    519 	na->setup->io = g_io_channel_ref(chan);
    520 
    521 	perr = btd_request_authorization(&src, &dst, BNEP_SVC_UUID,
    522 					auth_cb, na);
    523 	if (perr < 0) {
    524 		error("Refusing connect from %s: %s (%d)", address,
    525 				strerror(-perr), -perr);
    526 		setup_destroy(na);
    527 		goto drop;
    528 	}
    529 
    530 	return;
    531 
    532 drop:
    533 	g_io_channel_shutdown(chan, TRUE, NULL);
    534 }
    535 
    536 int server_init(DBusConnection *conn, gboolean secure)
    537 {
    538 	security = secure;
    539 	connection = dbus_connection_ref(conn);
    540 
    541 	return 0;
    542 }
    543 
    544 void server_exit(void)
    545 {
    546 	dbus_connection_unref(connection);
    547 	connection = NULL;
    548 }
    549 
    550 static uint32_t register_server_record(struct network_server *ns)
    551 {
    552 	sdp_record_t *record;
    553 
    554 	record = server_record_new(ns->name, ns->id);
    555 	if (!record) {
    556 		error("Unable to allocate new service record");
    557 		return 0;
    558 	}
    559 
    560 	if (add_record_to_server(&ns->src, record) < 0) {
    561 		error("Failed to register service record");
    562 		sdp_record_free(record);
    563 		return 0;
    564 	}
    565 
    566 	DBG("got record id 0x%x", record->handle);
    567 
    568 	return record->handle;
    569 }
    570 
    571 
    572 static inline DBusMessage *failed(DBusMessage *msg, const char *description)
    573 {
    574 	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    575 				description);
    576 }
    577 
    578 static inline DBusMessage *invalid_arguments(DBusMessage *msg,
    579 					const char *description)
    580 {
    581 	return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",
    582 				description);
    583 }
    584 
    585 static void server_disconnect(DBusConnection *conn, void *user_data)
    586 {
    587 	struct network_server *ns = user_data;
    588 
    589 	ns->watch_id = 0;
    590 
    591 	if (ns->record_id) {
    592 		remove_record_from_server(ns->record_id);
    593 		ns->record_id = 0;
    594 	}
    595 
    596 	g_free(ns->bridge);
    597 	ns->bridge = NULL;
    598 }
    599 
    600 static DBusMessage *register_server(DBusConnection *conn,
    601 				DBusMessage *msg, void *data)
    602 {
    603 	struct network_server *ns = data;
    604 	DBusMessage *reply;
    605 	const char *uuid, *bridge;
    606 
    607 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
    608 				DBUS_TYPE_STRING, &bridge, DBUS_TYPE_INVALID))
    609 		return NULL;
    610 
    611 	if (g_strcmp0(uuid, "nap"))
    612 		return failed(msg, "Invalid UUID");
    613 
    614 	if (ns->record_id)
    615 		return failed(msg, "Already registered");
    616 
    617 	reply = dbus_message_new_method_return(msg);
    618 	if (!reply)
    619 		return NULL;
    620 
    621 	ns->record_id = register_server_record(ns);
    622 	if (!ns->record_id)
    623 		return failed(msg, "SDP record registration failed");
    624 
    625 	g_free(ns->bridge);
    626 	ns->bridge = g_strdup(bridge);
    627 
    628 	ns->watch_id = g_dbus_add_disconnect_watch(conn,
    629 					dbus_message_get_sender(msg),
    630 					server_disconnect, ns, NULL);
    631 
    632 	return reply;
    633 }
    634 
    635 static DBusMessage *unregister_server(DBusConnection *conn,
    636 					DBusMessage *msg, void *data)
    637 {
    638 	struct network_server *ns = data;
    639 	DBusMessage *reply;
    640 	const char *uuid;
    641 
    642 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
    643 							DBUS_TYPE_INVALID))
    644 		return NULL;
    645 
    646 	if (g_strcmp0(uuid, "nap"))
    647 		return failed(msg, "Invalid UUID");
    648 
    649 	reply = dbus_message_new_method_return(msg);
    650 	if (!reply)
    651 		return NULL;
    652 
    653 	g_dbus_remove_watch(conn, ns->watch_id);
    654 
    655 	server_disconnect(conn, ns);
    656 
    657 	return reply;
    658 }
    659 
    660 static void adapter_free(struct network_adapter *na)
    661 {
    662 	if (na->io != NULL) {
    663 		g_io_channel_shutdown(na->io, TRUE, NULL);
    664 		g_io_channel_unref(na->io);
    665 	}
    666 
    667 	setup_destroy(na);
    668 	btd_adapter_unref(na->adapter);
    669 	g_free(na);
    670 }
    671 
    672 static void server_free(struct network_server *ns)
    673 {
    674 	if (!ns)
    675 		return;
    676 
    677 	/* FIXME: Missing release/free all bnepX interfaces */
    678 	if (ns->record_id)
    679 		remove_record_from_server(ns->record_id);
    680 
    681 	g_free(ns->iface);
    682 	g_free(ns->name);
    683 	g_free(ns->bridge);
    684 
    685 	if (ns->sessions) {
    686 		g_slist_foreach(ns->sessions, (GFunc) session_free, NULL);
    687 		g_slist_free(ns->sessions);
    688 	}
    689 
    690 	g_free(ns);
    691 }
    692 
    693 static void path_unregister(void *data)
    694 {
    695 	struct network_server *ns = data;
    696 	struct network_adapter *na = ns->na;
    697 
    698 	DBG("Unregistered interface %s on path %s",
    699 		ns->iface, adapter_get_path(na->adapter));
    700 
    701 	na->servers = g_slist_remove(na->servers, ns);
    702 	server_free(ns);
    703 
    704 	if (na->servers)
    705 		return;
    706 
    707 	adapters = g_slist_remove(adapters, na);
    708 	adapter_free(na);
    709 }
    710 
    711 static GDBusMethodTable server_methods[] = {
    712 	{ "Register",	"ss",	"",	register_server		},
    713 	{ "Unregister",	"s",	"",	unregister_server	},
    714 	{ }
    715 };
    716 
    717 static struct network_adapter *create_adapter(struct btd_adapter *adapter)
    718 {
    719 	struct network_adapter *na;
    720 	GError *err = NULL;
    721 	bdaddr_t src;
    722 
    723 	na = g_new0(struct network_adapter, 1);
    724 	na->adapter = btd_adapter_ref(adapter);
    725 
    726 	adapter_get_address(adapter, &src);
    727 
    728 	na->io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, na,
    729 				NULL, &err,
    730 				BT_IO_OPT_SOURCE_BDADDR, &src,
    731 				BT_IO_OPT_PSM, BNEP_PSM,
    732 				BT_IO_OPT_OMTU, BNEP_MTU,
    733 				BT_IO_OPT_IMTU, BNEP_MTU,
    734 				BT_IO_OPT_SEC_LEVEL,
    735 				security ? BT_IO_SEC_MEDIUM : BT_IO_SEC_LOW,
    736 				BT_IO_OPT_INVALID);
    737 	if (!na->io) {
    738 		error("%s", err->message);
    739 		g_error_free(err);
    740 		adapter_free(na);
    741 		return NULL;
    742 	}
    743 
    744 	return na;
    745 }
    746 
    747 int server_register(struct btd_adapter *adapter)
    748 {
    749 	struct network_adapter *na;
    750 	struct network_server *ns;
    751 	const char *path;
    752 
    753 	na = find_adapter(adapters, adapter);
    754 	if (!na) {
    755 		na = create_adapter(adapter);
    756 		if (!na)
    757 			return -EINVAL;
    758 		adapters = g_slist_append(adapters, na);
    759 	}
    760 
    761 	ns = find_server(na->servers, BNEP_SVC_NAP);
    762 	if (ns)
    763 		return 0;
    764 
    765 	ns = g_new0(struct network_server, 1);
    766 
    767 	ns->iface = g_strdup(NETWORK_SERVER_INTERFACE);
    768 	ns->name = g_strdup("Network service");
    769 
    770 	path = adapter_get_path(adapter);
    771 
    772 	if (!g_dbus_register_interface(connection, path, ns->iface,
    773 					server_methods, NULL, NULL,
    774 					ns, path_unregister)) {
    775 		error("D-Bus failed to register %s interface",
    776 				ns->iface);
    777 		server_free(ns);
    778 		return -1;
    779 	}
    780 
    781 	adapter_get_address(adapter, &ns->src);
    782 	ns->id = BNEP_SVC_NAP;
    783 	ns->na = na;
    784 	ns->record_id = 0;
    785 	na->servers = g_slist_append(na->servers, ns);
    786 
    787 	DBG("Registered interface %s on path %s", ns->iface, path);
    788 
    789 	return 0;
    790 }
    791 
    792 int server_unregister(struct btd_adapter *adapter)
    793 {
    794 	struct network_adapter *na;
    795 	struct network_server *ns;
    796 	uint16_t id = BNEP_SVC_NAP;
    797 
    798 	na = find_adapter(adapters, adapter);
    799 	if (!na)
    800 		return -EINVAL;
    801 
    802 	ns = find_server(na->servers, id);
    803 	if (!ns)
    804 		return -EINVAL;
    805 
    806 	g_dbus_unregister_interface(connection, adapter_get_path(adapter),
    807 					ns->iface);
    808 
    809 	return 0;
    810 }
    811