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