Home | History | Annotate | Download | only in plugins
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2010  Nokia Corporation
      6  *  Copyright (C) 2010  Marcel Holtmann <marcel (at) holtmann.org>
      7  *
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <errno.h>
     30 #include <unistd.h>
     31 #include <sys/socket.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <sys/wait.h>
     36 #include <fcntl.h>
     37 
     38 #include <bluetooth/bluetooth.h>
     39 #include <bluetooth/rfcomm.h>
     40 #include <bluetooth/sdp.h>
     41 #include <bluetooth/sdp_lib.h>
     42 
     43 #include <glib.h>
     44 
     45 #include <gdbus.h>
     46 
     47 #include "plugin.h"
     48 #include "sdpd.h"
     49 #include "btio.h"
     50 #include "adapter.h"
     51 #include "log.h"
     52 
     53 /* FIXME: This location should be build-time configurable */
     54 #define PNATD "/usr/bin/phonet-at"
     55 
     56 #define DUN_CHANNEL 1
     57 #define DUN_UUID "00001103-0000-1000-8000-00805F9B34FB"
     58 
     59 #define TTY_TIMEOUT 100
     60 #define TTY_TRIES 10
     61 
     62 struct dun_client {
     63 	bdaddr_t bda;
     64 
     65 	GIOChannel *io;	/* Client socket */
     66 	guint io_watch;	/* Client IO watch id */
     67 
     68 	guint tty_timer;
     69 	int tty_tries;
     70 	gboolean tty_open;
     71 	int tty_id;
     72 	char tty_name[PATH_MAX];
     73 
     74 	GPid pnatd_pid;
     75 };
     76 
     77 struct dun_server {
     78 	bdaddr_t bda;		/* Local adapter address */
     79 
     80 	uint32_t record_handle; /* Local SDP record handle */
     81 	GIOChannel *server;	/* Server socket */
     82 
     83 	int rfcomm_ctl;
     84 
     85 	struct dun_client client;
     86 };
     87 
     88 static GSList *servers = NULL;
     89 
     90 static void disconnect(struct dun_server *server)
     91 {
     92 	struct dun_client *client = &server->client;
     93 
     94 	if (!client->io)
     95 		return;
     96 
     97 	if (client->io_watch > 0) {
     98 		g_source_remove(client->io_watch);
     99 		client->io_watch = 0;
    100 	}
    101 
    102 	g_io_channel_shutdown(client->io, TRUE, NULL);
    103 	g_io_channel_unref(client->io);
    104 	client->io = NULL;
    105 
    106 	if (client->pnatd_pid > 0) {
    107 		kill(client->pnatd_pid, SIGTERM);
    108 		client->pnatd_pid = 0;
    109 	}
    110 
    111 	if (client->tty_timer > 0) {
    112 		g_source_remove(client->tty_timer);
    113 		client->tty_timer = 0;
    114 	}
    115 
    116 	if (client->tty_id >= 0) {
    117 		struct rfcomm_dev_req req;
    118 
    119 		memset(&req, 0, sizeof(req));
    120 		req.dev_id = client->tty_id;
    121 		req.flags = (1 << RFCOMM_HANGUP_NOW);
    122 		ioctl(server->rfcomm_ctl, RFCOMMRELEASEDEV, &req);
    123 
    124 		client->tty_name[0] = '\0';
    125 		client->tty_open = FALSE;
    126 		client->tty_id = -1;
    127 	}
    128 }
    129 
    130 static gboolean client_event(GIOChannel *chan,
    131 					GIOCondition cond, gpointer data)
    132 {
    133 	struct dun_server *server = data;
    134 	struct dun_client *client = &server->client;
    135 	char addr[18];
    136 
    137 	ba2str(&client->bda, addr);
    138 
    139 	DBG("Disconnected DUN from %s (%s)", addr, client->tty_name);
    140 
    141 	client->io_watch = 0;
    142 	disconnect(server);
    143 
    144 	return FALSE;
    145 }
    146 
    147 static void pnatd_exit(GPid pid, gint status, gpointer user_data)
    148 {
    149 	struct dun_server *server = user_data;
    150 	struct dun_client *client = &server->client;
    151 
    152         if (WIFEXITED(status))
    153                 DBG("pnatd (%d) exited with status %d", pid,
    154 							WEXITSTATUS(status));
    155         else
    156                 DBG("pnatd (%d) was killed by signal %d", pid,
    157 							WTERMSIG(status));
    158 	g_spawn_close_pid(pid);
    159 
    160 	if (pid != client->pnatd_pid)
    161 		return;
    162 
    163 	/* So disconnect() doesn't send SIGTERM to a non-existing process */
    164 	client->pnatd_pid = 0;
    165 
    166 	disconnect(server);
    167 }
    168 
    169 static gboolean start_pnatd(struct dun_server *server)
    170 {
    171 	struct dun_client *client = &server->client;
    172 	GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
    173 	char *argv[] = { PNATD, client->tty_name, NULL };
    174 	GError *err = NULL;
    175 	GPid pid;
    176 
    177 	g_spawn_async(NULL, argv, NULL, flags, NULL, NULL, &pid, &err);
    178 	if (err != NULL) {
    179 		error("Unable to spawn pnatd: %s", err->message);
    180 		g_error_free(err);
    181 		return FALSE;
    182 	}
    183 
    184 	DBG("pnatd started for %s with pid %d", client->tty_name, pid);
    185 
    186 	client->pnatd_pid = pid;
    187 
    188 	/* We do not store the GSource id since g_remove_source doesn't
    189 	 * make sense for a child watch. If the callback gets removed
    190 	 * waitpid won't be called and the child remains as a zombie)
    191 	 */
    192 	g_child_watch_add(pid, pnatd_exit, server);
    193 
    194 	return TRUE;
    195 }
    196 
    197 static gboolean tty_try_open(gpointer user_data)
    198 {
    199 	struct dun_server *server = user_data;
    200 	struct dun_client *client = &server->client;
    201 	int tty_fd;
    202 
    203 	tty_fd = open(client->tty_name, O_RDONLY | O_NOCTTY);
    204 	if (tty_fd < 0) {
    205 		if (errno == EACCES)
    206 			goto disconnect;
    207 
    208 		client->tty_tries--;
    209 
    210 		if (client->tty_tries <= 0)
    211 			goto disconnect;
    212 
    213 		return TRUE;
    214 	}
    215 
    216 	DBG("%s created for DUN", client->tty_name);
    217 
    218 	client->tty_open = TRUE;
    219 	client->tty_timer = 0;
    220 
    221 	g_io_channel_unref(client->io);
    222 	g_source_remove(client->io_watch);
    223 
    224 	client->io = g_io_channel_unix_new(tty_fd);
    225 	client->io_watch = g_io_add_watch(client->io,
    226 					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
    227 					client_event, server);
    228 
    229 	if (!start_pnatd(server))
    230 		goto disconnect;
    231 
    232 	return FALSE;
    233 
    234 disconnect:
    235 	client->tty_timer = 0;
    236 	disconnect(server);
    237 	return FALSE;
    238 }
    239 
    240 static gboolean create_tty(struct dun_server *server)
    241 {
    242 	struct dun_client *client = &server->client;
    243 	struct rfcomm_dev_req req;
    244 	int sk = g_io_channel_unix_get_fd(client->io);
    245 
    246 	memset(&req, 0, sizeof(req));
    247 	req.dev_id = -1;
    248 	req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
    249 
    250 	bacpy(&req.src, &server->bda);
    251 	bacpy(&req.dst, &client->bda);
    252 
    253 	bt_io_get(client->io, BT_IO_RFCOMM, NULL,
    254 			BT_IO_OPT_DEST_CHANNEL, &req.channel,
    255 			BT_IO_OPT_INVALID);
    256 
    257 	client->tty_id = ioctl(sk, RFCOMMCREATEDEV, &req);
    258 	if (client->tty_id < 0) {
    259 		error("Can't create RFCOMM TTY: %s", strerror(errno));
    260 		return FALSE;
    261 	}
    262 
    263 	snprintf(client->tty_name, PATH_MAX - 1, "/dev/rfcomm%d",
    264 							client->tty_id);
    265 
    266 	client->tty_tries = TTY_TRIES;
    267 
    268 	tty_try_open(server);
    269 	if (!client->tty_open && client->tty_tries > 0)
    270 		client->tty_timer = g_timeout_add(TTY_TIMEOUT,
    271 							tty_try_open, server);
    272 
    273 	return TRUE;
    274 }
    275 
    276 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
    277 {
    278 	struct dun_server *server = user_data;
    279 
    280 	if (err) {
    281 		error("Accepting DUN connection failed: %s", err->message);
    282 		disconnect(server);
    283 		return;
    284 	}
    285 
    286 	if (!create_tty(server)) {
    287 		error("Device creation failed");
    288 		disconnect(server);
    289 	}
    290 }
    291 
    292 static void auth_cb(DBusError *derr, void *user_data)
    293 {
    294 	struct dun_server *server = user_data;
    295 	struct dun_client *client = &server->client;
    296 	GError *err = NULL;
    297 
    298 	if (derr && dbus_error_is_set(derr)) {
    299 		error("DUN access denied: %s", derr->message);
    300 		goto drop;
    301 	}
    302 
    303 	if (!bt_io_accept(client->io, connect_cb, server, NULL, &err)) {
    304 		error("bt_io_accept: %s", err->message);
    305 		g_error_free(err);
    306 		goto drop;
    307 	}
    308 
    309 	return;
    310 
    311 drop:
    312 	disconnect(server);
    313 }
    314 
    315 static gboolean auth_watch(GIOChannel *chan, GIOCondition cond, gpointer data)
    316 {
    317 	struct dun_server *server = data;
    318 	struct dun_client *client = &server->client;
    319 
    320 	error("DUN client disconnected while waiting for authorization");
    321 
    322 	btd_cancel_authorization(&server->bda, &client->bda);
    323 
    324 	disconnect(server);
    325 
    326 	return FALSE;
    327 }
    328 
    329 static void confirm_cb(GIOChannel *io, gpointer user_data)
    330 {
    331 	struct dun_server *server = user_data;
    332 	struct dun_client *client = &server->client;
    333 	GError *err = NULL;
    334 
    335 	if (client->io) {
    336 		error("Rejecting DUN connection since one already exists");
    337 		return;
    338 	}
    339 
    340 	bt_io_get(io, BT_IO_RFCOMM, &err,
    341 			BT_IO_OPT_DEST_BDADDR, &client->bda,
    342 			BT_IO_OPT_INVALID);
    343 	if (err != NULL) {
    344 		error("Unable to get DUN source and dest address: %s",
    345 								err->message);
    346 		g_error_free(err);
    347 		return;
    348 	}
    349 
    350 	if (btd_request_authorization(&server->bda, &client->bda, DUN_UUID,
    351 						auth_cb, user_data) < 0) {
    352 		error("Requesting DUN authorization failed");
    353 		return;
    354 	}
    355 
    356 	client->io_watch = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
    357 						(GIOFunc) auth_watch, server);
    358 	client->io = g_io_channel_ref(io);
    359 }
    360 
    361 static sdp_record_t *dun_record(uint8_t ch)
    362 {
    363 	sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
    364 	uuid_t root_uuid, dun, gn, l2cap, rfcomm;
    365 	sdp_profile_desc_t profile;
    366 	sdp_list_t *proto[2];
    367 	sdp_record_t *record;
    368 	sdp_data_t *channel;
    369 
    370 	record = sdp_record_alloc();
    371 	if (!record)
    372 		return NULL;
    373 
    374 	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
    375 	root = sdp_list_append(NULL, &root_uuid);
    376 	sdp_set_browse_groups(record, root);
    377 
    378 	sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
    379 	svclass_id = sdp_list_append(NULL, &dun);
    380 	sdp_uuid16_create(&gn,  GENERIC_NETWORKING_SVCLASS_ID);
    381 	svclass_id = sdp_list_append(svclass_id, &gn);
    382 	sdp_set_service_classes(record, svclass_id);
    383 
    384 	sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
    385 	profile.version = 0x0100;
    386 	pfseq = sdp_list_append(NULL, &profile);
    387 	sdp_set_profile_descs(record, pfseq);
    388 
    389 	sdp_uuid16_create(&l2cap, L2CAP_UUID);
    390 	proto[0] = sdp_list_append(NULL, &l2cap);
    391 	apseq = sdp_list_append(NULL, proto[0]);
    392 
    393 	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
    394 	proto[1] = sdp_list_append(NULL, &rfcomm);
    395 	channel = sdp_data_alloc(SDP_UINT8, &ch);
    396 	proto[1] = sdp_list_append(proto[1], channel);
    397 	apseq = sdp_list_append(apseq, proto[1]);
    398 
    399 	aproto = sdp_list_append(0, apseq);
    400 	sdp_set_access_protos(record, aproto);
    401 
    402 	sdp_set_info_attr(record, "Dial-Up Networking", 0, 0);
    403 
    404 	sdp_data_free(channel);
    405 	sdp_list_free(root, NULL);
    406 	sdp_list_free(svclass_id, NULL);
    407 	sdp_list_free(proto[0], NULL);
    408 	sdp_list_free(proto[1], NULL);
    409 	sdp_list_free(pfseq, NULL);
    410 	sdp_list_free(apseq, NULL);
    411 	sdp_list_free(aproto, NULL);
    412 
    413 	return record;
    414 }
    415 
    416 static gint server_cmp(gconstpointer a, gconstpointer b)
    417 {
    418 	const struct dun_server *server = a;
    419 	const bdaddr_t *src = b;
    420 
    421 	return bacmp(src, &server->bda);
    422 }
    423 
    424 static int pnat_probe(struct btd_adapter *adapter)
    425 {
    426 	struct dun_server *server;
    427 	GIOChannel *io;
    428 	GError *err = NULL;
    429 	sdp_record_t *record;
    430 	bdaddr_t src;
    431 
    432 	adapter_get_address(adapter, &src);
    433 
    434 	server = g_new0(struct dun_server, 1);
    435 
    436 	io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_cb, server, NULL, &err,
    437 				BT_IO_OPT_SOURCE_BDADDR, &src,
    438 				BT_IO_OPT_CHANNEL, DUN_CHANNEL,
    439 				BT_IO_OPT_INVALID);
    440 	if (err != NULL) {
    441 		error("Failed to start DUN server: %s", err->message);
    442 		g_error_free(err);
    443 		goto fail;
    444 	}
    445 
    446 	record = dun_record(DUN_CHANNEL);
    447 	if (!record) {
    448 		error("Unable to allocate new service record");
    449 		goto fail;
    450 	}
    451 
    452 	if (add_record_to_server(&src, record) < 0) {
    453 		error("Unable to register DUN service record");
    454 		goto fail;
    455 	}
    456 
    457 	server->rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
    458 	if (server->rfcomm_ctl < 0) {
    459 		error("Unable to create RFCOMM control socket: %s (%d)",
    460 						strerror(errno), errno);
    461 		goto fail;
    462 	}
    463 
    464 	server->server = io;
    465 	server->record_handle = record->handle;
    466 	bacpy(&server->bda, &src);
    467 
    468 	servers = g_slist_append(servers, server);
    469 
    470 	return 0;
    471 
    472 fail:
    473 	if (io != NULL)
    474 		g_io_channel_unref(io);
    475 	g_free(server);
    476 	return -EIO;
    477 }
    478 
    479 static void pnat_remove(struct btd_adapter *adapter)
    480 {
    481 	struct dun_server *server;
    482 	GSList *match;
    483 	bdaddr_t src;
    484 
    485 	adapter_get_address(adapter, &src);
    486 
    487 	match = g_slist_find_custom(servers, &src, server_cmp);
    488 	if (match == NULL)
    489 		return;
    490 
    491 	server = match->data;
    492 
    493 	servers = g_slist_delete_link(servers, match);
    494 
    495 	disconnect(server);
    496 
    497 	remove_record_from_server(server->record_handle);
    498 	close(server->rfcomm_ctl);
    499 	g_io_channel_shutdown(server->server, TRUE, NULL);
    500 	g_io_channel_unref(server->server);
    501 	g_free(server);
    502 }
    503 
    504 static struct btd_adapter_driver pnat_server = {
    505 	.name	= "pnat-server",
    506 	.probe	= pnat_probe,
    507 	.remove	= pnat_remove,
    508 };
    509 
    510 static int pnat_init(void)
    511 {
    512 	DBG("Setup Phonet AT (DUN) plugin");
    513 
    514 	return btd_register_adapter_driver(&pnat_server);
    515 }
    516 
    517 static void pnat_exit(void)
    518 {
    519 	DBG("Cleanup Phonet AT (DUN) plugin");
    520 
    521 	btd_unregister_adapter_driver(&pnat_server);
    522 }
    523 
    524 BLUETOOTH_PLUGIN_DEFINE(pnat, VERSION,
    525 			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
    526 			pnat_init, pnat_exit)
    527