proxy.c revision da446f5edd0c5e2b7d634fd9b833ad48e77a2dd5
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@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 <ctype.h> 29#include <dirent.h> 30#include <errno.h> 31#include <fcntl.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <termios.h> 36#include <unistd.h> 37#include <arpa/inet.h> 38#include <sys/param.h> 39#include <sys/ioctl.h> 40#include <sys/stat.h> 41#include <sys/types.h> 42#include <sys/un.h> 43 44#include <bluetooth/bluetooth.h> 45#include <bluetooth/hci.h> 46#include <bluetooth/hci_lib.h> 47#include <bluetooth/sdp.h> 48#include <bluetooth/sdp_lib.h> 49#include <bluetooth/rfcomm.h> 50 51#include <glib.h> 52#include <gdbus.h> 53 54#include "../src/dbus-common.h" 55#include "../src/adapter.h" 56 57#include "log.h" 58#include "textfile.h" 59 60#include "error.h" 61#include "sdpd.h" 62#include "glib-helper.h" 63#include "btio.h" 64#include "proxy.h" 65 66#define SERIAL_PROXY_INTERFACE "org.bluez.SerialProxy" 67#define SERIAL_MANAGER_INTERFACE "org.bluez.SerialProxyManager" 68#define BUF_SIZE 1024 69 70typedef enum { 71 TTY_PROXY, 72 UNIX_SOCKET_PROXY, 73 TCP_SOCKET_PROXY, 74 UNKNOWN_PROXY_TYPE = 0xFF 75} proxy_type_t; 76 77struct serial_adapter { 78 struct btd_adapter *btd_adapter; /* Adapter pointer */ 79 DBusConnection *conn; /* Adapter connection */ 80 GSList *proxies; /* Proxies list */ 81}; 82 83struct serial_proxy { 84 bdaddr_t src; /* Local address */ 85 bdaddr_t dst; /* Remote address */ 86 char *path; /* Proxy path */ 87 char *uuid128; /* UUID 128 */ 88 char *address; /* TTY or Unix socket name */ 89 char *owner; /* Application bus name */ 90 guint watch; /* Application watch */ 91 short int port; /* TCP port */ 92 proxy_type_t type; /* TTY or Unix socket */ 93 struct termios sys_ti; /* Default TTY setting */ 94 struct termios proxy_ti; /* Proxy TTY settings */ 95 uint8_t channel; /* RFCOMM channel */ 96 uint32_t record_id; /* Service record id */ 97 GIOChannel *io; /* Server listen */ 98 GIOChannel *rfcomm; /* Remote RFCOMM channel*/ 99 GIOChannel *local; /* Local channel: TTY or Unix socket */ 100 struct serial_adapter *adapter; /* Adapter pointer */ 101}; 102 103static GSList *adapters = NULL; 104static int sk_counter = 0; 105 106static void disable_proxy(struct serial_proxy *prx) 107{ 108 if (prx->rfcomm) { 109 g_io_channel_shutdown(prx->rfcomm, TRUE, NULL); 110 g_io_channel_unref(prx->rfcomm); 111 prx->rfcomm = NULL; 112 } 113 114 if (prx->local) { 115 g_io_channel_shutdown(prx->local, TRUE, NULL); 116 g_io_channel_unref(prx->local); 117 prx->local = NULL; 118 } 119 120 remove_record_from_server(prx->record_id); 121 prx->record_id = 0; 122 123 g_io_channel_unref(prx->io); 124 prx->io = NULL; 125} 126 127static void proxy_free(struct serial_proxy *prx) 128{ 129 g_free(prx->owner); 130 g_free(prx->path); 131 g_free(prx->address); 132 g_free(prx->uuid128); 133 g_free(prx); 134} 135 136static inline DBusMessage *does_not_exist(DBusMessage *msg, 137 const char *description) 138{ 139 return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", 140 "%s", description); 141} 142 143static inline DBusMessage *invalid_arguments(DBusMessage *msg, 144 const char *description) 145{ 146 return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments", 147 "%s", description); 148} 149 150static inline DBusMessage *failed(DBusMessage *msg, const char *description) 151{ 152 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", 153 "%s", description); 154} 155 156static void add_lang_attr(sdp_record_t *r) 157{ 158 sdp_lang_attr_t base_lang; 159 sdp_list_t *langs = 0; 160 161 /* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */ 162 base_lang.code_ISO639 = (0x65 << 8) | 0x6e; 163 base_lang.encoding = 106; 164 base_lang.base_offset = SDP_PRIMARY_LANG_BASE; 165 langs = sdp_list_append(0, &base_lang); 166 sdp_set_lang_attr(r, langs); 167 sdp_list_free(langs, 0); 168} 169 170static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel) 171{ 172 sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; 173 uuid_t uuid, root_uuid, l2cap, rfcomm; 174 sdp_profile_desc_t profile; 175 sdp_record_t *record; 176 sdp_data_t *ch; 177 178 record = sdp_record_alloc(); 179 if (!record) 180 return NULL; 181 182 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 183 root = sdp_list_append(NULL, &root_uuid); 184 sdp_set_browse_groups(record, root); 185 sdp_list_free(root, NULL); 186 187 bt_string2uuid(&uuid, uuid128); 188 sdp_uuid128_to_uuid(&uuid); 189 svclass_id = sdp_list_append(NULL, &uuid); 190 sdp_set_service_classes(record, svclass_id); 191 sdp_list_free(svclass_id, NULL); 192 193 sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); 194 profile.version = 0x0100; 195 profiles = sdp_list_append(NULL, &profile); 196 sdp_set_profile_descs(record, profiles); 197 sdp_list_free(profiles, NULL); 198 199 sdp_uuid16_create(&l2cap, L2CAP_UUID); 200 proto[0] = sdp_list_append(NULL, &l2cap); 201 apseq = sdp_list_append(NULL, proto[0]); 202 203 sdp_uuid16_create(&rfcomm, RFCOMM_UUID); 204 proto[1] = sdp_list_append(NULL, &rfcomm); 205 ch = sdp_data_alloc(SDP_UINT8, &channel); 206 proto[1] = sdp_list_append(proto[1], ch); 207 apseq = sdp_list_append(apseq, proto[1]); 208 209 aproto = sdp_list_append(NULL, apseq); 210 sdp_set_access_protos(record, aproto); 211 212 add_lang_attr(record); 213 214 sdp_set_info_attr(record, "Serial Proxy", NULL, "Serial Proxy"); 215 216 sdp_data_free(ch); 217 sdp_list_free(proto[0], NULL); 218 sdp_list_free(proto[1], NULL); 219 sdp_list_free(apseq, NULL); 220 sdp_list_free(aproto, NULL); 221 222 return record; 223} 224 225static GIOError channel_write(GIOChannel *chan, char *buf, size_t size) 226{ 227 GIOError err = G_IO_ERROR_NONE; 228 gsize wbytes, written; 229 230 wbytes = written = 0; 231 while (wbytes < size) { 232 err = g_io_channel_write(chan, 233 buf + wbytes, 234 size - wbytes, 235 &written); 236 237 if (err != G_IO_ERROR_NONE) 238 return err; 239 240 wbytes += written; 241 } 242 243 return err; 244} 245 246static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) 247{ 248 char buf[BUF_SIZE]; 249 struct serial_proxy *prx = data; 250 GIOChannel *dest; 251 GIOError err; 252 size_t rbytes; 253 254 if (cond & G_IO_NVAL) 255 return FALSE; 256 257 dest = (chan == prx->rfcomm) ? prx->local : prx->rfcomm; 258 259 if (cond & (G_IO_HUP | G_IO_ERR)) { 260 /* Try forward remaining data */ 261 do { 262 rbytes = 0; 263 err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); 264 if (err != G_IO_ERROR_NONE || rbytes == 0) 265 break; 266 267 err = channel_write(dest, buf, rbytes); 268 } while (err == G_IO_ERROR_NONE); 269 270 g_io_channel_shutdown(prx->local, TRUE, NULL); 271 g_io_channel_unref(prx->local); 272 prx->local = NULL; 273 274 g_io_channel_shutdown(prx->rfcomm, TRUE, NULL); 275 g_io_channel_unref(prx->rfcomm); 276 prx->rfcomm = NULL; 277 278 return FALSE; 279 } 280 281 rbytes = 0; 282 err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); 283 if (err != G_IO_ERROR_NONE) 284 return FALSE; 285 286 err = channel_write(dest, buf, rbytes); 287 if (err != G_IO_ERROR_NONE) 288 return FALSE; 289 290 return TRUE; 291} 292 293static inline int unix_socket_connect(const char *address) 294{ 295 struct sockaddr_un addr; 296 int err, sk; 297 298 memset(&addr, 0, sizeof(addr)); 299 addr.sun_family = PF_UNIX; 300 301 if (strncmp("x00", address, 3) == 0) { 302 /* 303 * Abstract namespace: first byte NULL, x00 304 * must be removed from the original address. 305 */ 306 strncpy(addr.sun_path + 1, address + 3, 307 sizeof(addr.sun_path) - 2); 308 } else { 309 /* Filesystem address */ 310 strncpy(addr.sun_path, address, sizeof(addr.sun_path) - 1); 311 } 312 313 /* Unix socket */ 314 sk = socket(AF_UNIX, SOCK_STREAM, 0); 315 if (sk < 0) { 316 err = errno; 317 error("Unix socket(%s) create failed: %s(%d)", 318 address, strerror(err), err); 319 return -err; 320 } 321 322 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 323 err = errno; 324 error("Unix socket(%s) connect failed: %s(%d)", 325 address, strerror(err), err); 326 close(sk); 327 errno = err; 328 return -err; 329 } 330 331 return sk; 332} 333 334static int tcp_socket_connect(const char *address) 335{ 336 struct sockaddr_in addr; 337 int err, sk; 338 unsigned short int port; 339 340 memset(&addr, 0, sizeof(addr)); 341 342 if (strncmp(address, "localhost", 9) != 0) { 343 error("Address should have the form localhost:port."); 344 return -1; 345 } 346 port = atoi(strchr(address, ':') + 1); 347 if (port <= 0) { 348 error("Invalid port '%d'.", port); 349 return -1; 350 } 351 addr.sin_family = AF_INET; 352 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 353 addr.sin_port = htons(port); 354 355 sk = socket(PF_INET, SOCK_STREAM, 0); 356 if (sk < 0) { 357 err = errno; 358 error("TCP socket(%s) create failed %s(%d)", address, 359 strerror(err), err); 360 return -err; 361 } 362 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 363 err = errno; 364 error("TCP socket(%s) connect failed: %s(%d)", 365 address, strerror(err), err); 366 close(sk); 367 errno = err; 368 return -err; 369 } 370 return sk; 371} 372 373static inline int tty_open(const char *tty, struct termios *ti) 374{ 375 int err, sk; 376 377 sk = open(tty, O_RDWR | O_NOCTTY); 378 if (sk < 0) { 379 err = errno; 380 error("Can't open TTY %s: %s(%d)", tty, strerror(err), err); 381 return -err; 382 } 383 384 if (ti && tcsetattr(sk, TCSANOW, ti) < 0) { 385 err = errno; 386 error("Can't change serial settings: %s(%d)", 387 strerror(err), err); 388 close(sk); 389 errno = err; 390 return -err; 391 } 392 393 return sk; 394} 395 396static void connect_event_cb(GIOChannel *chan, GError *conn_err, gpointer data) 397{ 398 struct serial_proxy *prx = data; 399 int sk; 400 401 if (conn_err) { 402 error("%s", conn_err->message); 403 goto drop; 404 } 405 406 /* Connect local */ 407 switch (prx->type) { 408 case UNIX_SOCKET_PROXY: 409 sk = unix_socket_connect(prx->address); 410 break; 411 case TTY_PROXY: 412 sk = tty_open(prx->address, &prx->proxy_ti); 413 break; 414 case TCP_SOCKET_PROXY: 415 sk = tcp_socket_connect(prx->address); 416 break; 417 default: 418 sk = -1; 419 } 420 421 if (sk < 0) 422 goto drop; 423 424 prx->local = g_io_channel_unix_new(sk); 425 426 g_io_add_watch(prx->rfcomm, 427 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, 428 forward_data, prx); 429 430 g_io_add_watch(prx->local, 431 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, 432 forward_data, prx); 433 434 return; 435 436drop: 437 g_io_channel_shutdown(prx->rfcomm, TRUE, NULL); 438 g_io_channel_unref(prx->rfcomm); 439 prx->rfcomm = NULL; 440} 441 442static void auth_cb(DBusError *derr, void *user_data) 443{ 444 struct serial_proxy *prx = user_data; 445 GError *err = NULL; 446 447 if (derr) { 448 error("Access denied: %s", derr->message); 449 goto reject; 450 } 451 452 if (!bt_io_accept(prx->rfcomm, connect_event_cb, prx, NULL, 453 &err)) { 454 error("bt_io_accept: %s", err->message); 455 g_error_free(err); 456 goto reject; 457 } 458 459 return; 460 461reject: 462 g_io_channel_shutdown(prx->rfcomm, TRUE, NULL); 463 g_io_channel_unref(prx->rfcomm); 464 prx->rfcomm = NULL; 465} 466 467static void confirm_event_cb(GIOChannel *chan, gpointer user_data) 468{ 469 struct serial_proxy *prx = user_data; 470 int perr; 471 char address[18]; 472 GError *err = NULL; 473 474 bt_io_get(chan, BT_IO_RFCOMM, &err, 475 BT_IO_OPT_DEST_BDADDR, &prx->dst, 476 BT_IO_OPT_DEST, address, 477 BT_IO_OPT_INVALID); 478 if (err) { 479 error("%s", err->message); 480 g_error_free(err); 481 goto drop; 482 } 483 484 if (prx->rfcomm) { 485 error("Refusing connect from %s: Proxy already in use", 486 address); 487 goto drop; 488 } 489 490 DBG("Serial Proxy: incoming connect from %s", address); 491 492 prx->rfcomm = g_io_channel_ref(chan); 493 494 perr = btd_request_authorization(&prx->src, &prx->dst, 495 prx->uuid128, auth_cb, prx); 496 if (perr < 0) { 497 error("Refusing connect from %s: %s (%d)", address, 498 strerror(-perr), -perr); 499 g_io_channel_unref(prx->rfcomm); 500 prx->rfcomm = NULL; 501 goto drop; 502 } 503 504 return; 505 506drop: 507 g_io_channel_shutdown(chan, TRUE, NULL); 508} 509 510static int enable_proxy(struct serial_proxy *prx) 511{ 512 sdp_record_t *record; 513 GError *gerr = NULL; 514 int err; 515 516 if (prx->io) 517 return -EALREADY; 518 519 /* Listen */ 520 prx->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event_cb, prx, 521 NULL, &gerr, 522 BT_IO_OPT_SOURCE_BDADDR, &prx->src, 523 BT_IO_OPT_INVALID); 524 if (!prx->io) 525 goto failed; 526 527 bt_io_get(prx->io, BT_IO_RFCOMM, &gerr, 528 BT_IO_OPT_CHANNEL, &prx->channel, 529 BT_IO_OPT_INVALID); 530 if (gerr) { 531 g_io_channel_unref(prx->io); 532 prx->io = NULL; 533 goto failed; 534 } 535 536 DBG("Allocated channel %d", prx->channel); 537 538 g_io_channel_set_close_on_unref(prx->io, TRUE); 539 540 record = proxy_record_new(prx->uuid128, prx->channel); 541 if (!record) { 542 g_io_channel_unref(prx->io); 543 return -ENOMEM; 544 } 545 546 err = add_record_to_server(&prx->src, record); 547 if (err < 0) { 548 sdp_record_free(record); 549 g_io_channel_unref(prx->io); 550 return err; 551 } 552 553 prx->record_id = record->handle; 554 555 return 0; 556 557failed: 558 error("%s", gerr->message); 559 g_error_free(gerr); 560 return -EIO; 561 562} 563static DBusMessage *proxy_enable(DBusConnection *conn, 564 DBusMessage *msg, void *data) 565{ 566 struct serial_proxy *prx = data; 567 int err; 568 569 err = enable_proxy(prx); 570 if (err == -EALREADY) 571 return failed(msg, "Already enabled"); 572 else if (err == -ENOMEM) 573 return failed(msg, "Unable to allocate new service record"); 574 else if (err < 0) 575 return g_dbus_create_error(msg, ERROR_INTERFACE "Failed", 576 "Proxy enable failed (%s)", strerror(-err)); 577 578 return dbus_message_new_method_return(msg); 579} 580 581static DBusMessage *proxy_disable(DBusConnection *conn, 582 DBusMessage *msg, void *data) 583{ 584 struct serial_proxy *prx = data; 585 586 if (!prx->io) 587 return failed(msg, "Not enabled"); 588 589 /* Remove the watches and unregister the record */ 590 disable_proxy(prx); 591 592 return dbus_message_new_method_return(msg); 593} 594 595static DBusMessage *proxy_get_info(DBusConnection *conn, 596 DBusMessage *msg, void *data) 597{ 598 struct serial_proxy *prx = data; 599 DBusMessage *reply; 600 DBusMessageIter iter, dict; 601 dbus_bool_t boolean; 602 603 reply = dbus_message_new_method_return(msg); 604 if (!reply) 605 return NULL; 606 607 dbus_message_iter_init_append(reply, &iter); 608 609 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 610 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 611 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 612 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 613 614 dict_append_entry(&dict, "uuid", DBUS_TYPE_STRING, &prx->uuid128); 615 616 dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &prx->address); 617 618 if (prx->channel) 619 dict_append_entry(&dict, "channel", 620 DBUS_TYPE_BYTE, &prx->channel); 621 622 boolean = (prx->io ? TRUE : FALSE); 623 dict_append_entry(&dict, "enabled", DBUS_TYPE_BOOLEAN, &boolean); 624 625 boolean = (prx->rfcomm ? TRUE : FALSE); 626 dict_append_entry(&dict, "connected", DBUS_TYPE_BOOLEAN, &boolean); 627 628 /* If connected: append the remote address */ 629 if (boolean) { 630 char bda[18]; 631 const char *pstr = bda; 632 633 ba2str(&prx->dst, bda); 634 dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &pstr); 635 } 636 637 dbus_message_iter_close_container(&iter, &dict); 638 639 return reply; 640} 641 642static struct { 643 const char *str; 644 speed_t speed; 645} supported_speed[] = { 646 {"50", B50 }, 647 {"300", B300 }, 648 {"600", B600 }, 649 {"1200", B1200 }, 650 {"1800", B1800 }, 651 {"2400", B2400 }, 652 {"4800", B4800 }, 653 {"9600", B9600 }, 654 {"19200", B19200 }, 655 {"38400", B38400 }, 656 {"57600", B57600 }, 657 {"115200", B115200 }, 658 { NULL, B0 } 659}; 660 661static speed_t str2speed(const char *str, speed_t *speed) 662{ 663 int i; 664 665 for (i = 0; supported_speed[i].str; i++) { 666 if (strcmp(supported_speed[i].str, str) != 0) 667 continue; 668 669 if (speed) 670 *speed = supported_speed[i].speed; 671 672 return supported_speed[i].speed; 673 } 674 675 return B0; 676} 677 678static int set_parity(const char *str, tcflag_t *ctrl) 679{ 680 if (strcasecmp("even", str) == 0) { 681 *ctrl |= PARENB; 682 *ctrl &= ~PARODD; 683 } else if (strcasecmp("odd", str) == 0) { 684 *ctrl |= PARENB; 685 *ctrl |= PARODD; 686 } else if (strcasecmp("mark", str) == 0) 687 *ctrl |= PARENB; 688 else if ((strcasecmp("none", str) == 0) || 689 (strcasecmp("space", str) == 0)) 690 *ctrl &= ~PARENB; 691 else 692 return -1; 693 694 return 0; 695} 696 697static int set_databits(uint8_t databits, tcflag_t *ctrl) 698{ 699 if (databits < 5 || databits > 8) 700 return -EINVAL; 701 702 *ctrl &= ~CSIZE; 703 switch (databits) { 704 case 5: 705 *ctrl |= CS5; 706 break; 707 case 6: 708 *ctrl |= CS6; 709 break; 710 case 7: 711 *ctrl |= CS7; 712 break; 713 case 8: 714 *ctrl |= CS8; 715 break; 716 } 717 718 return 0; 719} 720 721static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl) 722{ 723 /* 1.5 will not be allowed */ 724 switch (stopbits) { 725 case 1: 726 *ctrl &= ~CSTOPB; 727 return 0; 728 case 2: 729 *ctrl |= CSTOPB; 730 return 0; 731 } 732 733 return -EINVAL; 734} 735 736static DBusMessage *proxy_set_serial_params(DBusConnection *conn, 737 DBusMessage *msg, void *data) 738{ 739 struct serial_proxy *prx = data; 740 const char *ratestr, *paritystr; 741 uint8_t databits, stopbits; 742 tcflag_t ctrl; /* Control mode flags */ 743 speed_t speed = B0; /* In/Out speed */ 744 745 /* Don't allow change TTY settings if it is open */ 746 if (prx->local) 747 return failed(msg, "Not allowed"); 748 749 if (!dbus_message_get_args(msg, NULL, 750 DBUS_TYPE_STRING, &ratestr, 751 DBUS_TYPE_BYTE, &databits, 752 DBUS_TYPE_BYTE, &stopbits, 753 DBUS_TYPE_STRING, &paritystr, 754 DBUS_TYPE_INVALID)) 755 return NULL; 756 757 if (str2speed(ratestr, &speed) == B0) 758 return invalid_arguments(msg, "Invalid baud rate"); 759 760 ctrl = prx->proxy_ti.c_cflag; 761 if (set_databits(databits, &ctrl) < 0) 762 return invalid_arguments(msg, "Invalid data bits"); 763 764 if (set_stopbits(stopbits, &ctrl) < 0) 765 return invalid_arguments(msg, "Invalid stop bits"); 766 767 if (set_parity(paritystr, &ctrl) < 0) 768 return invalid_arguments(msg, "Invalid parity"); 769 770 prx->proxy_ti.c_cflag = ctrl; 771 prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); 772 cfsetispeed(&prx->proxy_ti, speed); 773 cfsetospeed(&prx->proxy_ti, speed); 774 775 return dbus_message_new_method_return(msg); 776} 777 778static GDBusMethodTable proxy_methods[] = { 779 { "Enable", "", "", proxy_enable }, 780 { "Disable", "", "", proxy_disable }, 781 { "GetInfo", "", "a{sv}",proxy_get_info }, 782 { "SetSerialParameters", "syys", "", proxy_set_serial_params }, 783 { }, 784}; 785 786static void proxy_path_unregister(gpointer data) 787{ 788 struct serial_proxy *prx = data; 789 int sk; 790 791 DBG("Unregistered proxy: %s", prx->address); 792 793 if (prx->type != TTY_PROXY) 794 goto done; 795 796 /* Restore the initial TTY configuration */ 797 sk = open(prx->address, O_RDWR | O_NOCTTY); 798 if (sk >= 0) { 799 tcsetattr(sk, TCSAFLUSH, &prx->sys_ti); 800 close(sk); 801 } 802done: 803 804 proxy_free(prx); 805} 806 807static int register_proxy_object(struct serial_proxy *prx) 808{ 809 struct serial_adapter *adapter = prx->adapter; 810 char path[MAX_PATH_LENGTH + 1]; 811 812 snprintf(path, MAX_PATH_LENGTH, "%s/proxy%d", 813 adapter_get_path(adapter->btd_adapter), sk_counter++); 814 815 if (!g_dbus_register_interface(adapter->conn, path, 816 SERIAL_PROXY_INTERFACE, 817 proxy_methods, NULL, NULL, 818 prx, proxy_path_unregister)) { 819 error("D-Bus failed to register %s path", path); 820 return -1; 821 } 822 823 prx->path = g_strdup(path); 824 adapter->proxies = g_slist_append(adapter->proxies, prx); 825 826 DBG("Registered proxy: %s", path); 827 828 return 0; 829} 830 831static int proxy_tty_register(struct serial_adapter *adapter, 832 const char *uuid128, const char *address, 833 struct termios *ti, 834 struct serial_proxy **proxy) 835{ 836 struct termios sys_ti; 837 struct serial_proxy *prx; 838 int sk, ret; 839 840 sk = open(address, O_RDONLY | O_NOCTTY); 841 if (sk < 0) { 842 error("Cant open TTY: %s(%d)", strerror(errno), errno); 843 return -EINVAL; 844 } 845 846 prx = g_new0(struct serial_proxy, 1); 847 prx->address = g_strdup(address); 848 prx->uuid128 = g_strdup(uuid128); 849 prx->type = TTY_PROXY; 850 adapter_get_address(adapter->btd_adapter, &prx->src); 851 prx->adapter = adapter; 852 853 /* Current TTY settings */ 854 memset(&sys_ti, 0, sizeof(sys_ti)); 855 tcgetattr(sk, &sys_ti); 856 memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti)); 857 close(sk); 858 859 if (!ti) { 860 /* Use current settings */ 861 memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti)); 862 } else { 863 /* New TTY settings: user provided */ 864 memcpy(&prx->proxy_ti, ti, sizeof(*ti)); 865 } 866 867 ret = register_proxy_object(prx); 868 if (ret < 0) { 869 proxy_free(prx); 870 return ret; 871 } 872 873 *proxy = prx; 874 875 return ret; 876} 877 878static int proxy_socket_register(struct serial_adapter *adapter, 879 const char *uuid128, const char *address, 880 struct serial_proxy **proxy) 881{ 882 struct serial_proxy *prx; 883 int ret; 884 885 prx = g_new0(struct serial_proxy, 1); 886 prx->address = g_strdup(address); 887 prx->uuid128 = g_strdup(uuid128); 888 prx->type = UNIX_SOCKET_PROXY; 889 adapter_get_address(adapter->btd_adapter, &prx->src); 890 prx->adapter = adapter; 891 892 ret = register_proxy_object(prx); 893 if (ret < 0) { 894 proxy_free(prx); 895 return ret; 896 } 897 898 *proxy = prx; 899 900 return ret; 901} 902 903static int proxy_tcp_register(struct serial_adapter *adapter, 904 const char *uuid128, const char *address, 905 struct serial_proxy **proxy) 906{ 907 struct serial_proxy *prx; 908 int ret; 909 910 prx = g_new0(struct serial_proxy, 1); 911 prx->address = g_strdup(address); 912 prx->uuid128 = g_strdup(uuid128); 913 prx->type = TCP_SOCKET_PROXY; 914 adapter_get_address(adapter->btd_adapter, &prx->src); 915 prx->adapter = adapter; 916 917 ret = register_proxy_object(prx); 918 if (ret < 0) { 919 proxy_free(prx); 920 return ret; 921 } 922 923 *proxy = prx; 924 925 return ret; 926} 927 928static proxy_type_t addr2type(const char *address) 929{ 930 struct stat st; 931 932 if (stat(address, &st) < 0) { 933 /* 934 * Unix socket: if the sun_path starts with null byte 935 * it refers to abstract namespace. 'x00' will be used 936 * to represent the null byte. 937 */ 938 if (strncmp("localhost:", address, 10) == 0) 939 return TCP_SOCKET_PROXY; 940 if (strncmp("x00", address, 3) != 0) 941 return UNKNOWN_PROXY_TYPE; 942 else 943 return UNIX_SOCKET_PROXY; 944 } else { 945 /* Filesystem: char device or unix socket */ 946 if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0) 947 return TTY_PROXY; 948 else if (S_ISSOCK(st.st_mode)) 949 return UNIX_SOCKET_PROXY; 950 else 951 return UNKNOWN_PROXY_TYPE; 952 } 953} 954 955static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr) 956{ 957 const struct serial_proxy *prx = proxy; 958 const char *address = addr; 959 960 return strcmp(prx->address, address); 961} 962 963static int proxy_pathcmp(gconstpointer proxy, gconstpointer p) 964{ 965 const struct serial_proxy *prx = proxy; 966 const char *path = p; 967 968 return strcmp(prx->path, path); 969} 970 971static int register_proxy(struct serial_adapter *adapter, 972 const char *uuid_str, const char *address, 973 struct serial_proxy **proxy) 974{ 975 proxy_type_t type; 976 int err; 977 978 type = addr2type(address); 979 if (type == UNKNOWN_PROXY_TYPE) 980 return -EINVAL; 981 982 /* Only one proxy per address(TTY or unix socket) is allowed */ 983 if (g_slist_find_custom(adapter->proxies, address, proxy_addrcmp)) 984 return -EALREADY; 985 986 switch (type) { 987 case UNIX_SOCKET_PROXY: 988 err = proxy_socket_register(adapter, uuid_str, address, proxy); 989 break; 990 case TTY_PROXY: 991 err = proxy_tty_register(adapter, uuid_str, address, NULL, 992 proxy); 993 break; 994 case TCP_SOCKET_PROXY: 995 err = proxy_tcp_register(adapter, uuid_str, address, proxy); 996 break; 997 default: 998 err = -EINVAL; 999 } 1000 1001 if (err < 0) 1002 return err; 1003 1004 g_dbus_emit_signal(adapter->conn, 1005 adapter_get_path(adapter->btd_adapter), 1006 SERIAL_MANAGER_INTERFACE, "ProxyCreated", 1007 DBUS_TYPE_STRING, &(*proxy)->path, 1008 DBUS_TYPE_INVALID); 1009 1010 return 0; 1011} 1012 1013static void unregister_proxy(struct serial_proxy *proxy) 1014{ 1015 struct serial_adapter *adapter = proxy->adapter; 1016 char *path = g_strdup(proxy->path); 1017 1018 if (proxy->watch > 0) 1019 g_dbus_remove_watch(adapter->conn, proxy->watch); 1020 1021 g_dbus_emit_signal(adapter->conn, 1022 adapter_get_path(adapter->btd_adapter), 1023 SERIAL_MANAGER_INTERFACE, "ProxyRemoved", 1024 DBUS_TYPE_STRING, &path, 1025 DBUS_TYPE_INVALID); 1026 1027 adapter->proxies = g_slist_remove(adapter->proxies, proxy); 1028 1029 g_dbus_unregister_interface(adapter->conn, path, 1030 SERIAL_PROXY_INTERFACE); 1031 1032 g_free(path); 1033} 1034 1035static void watch_proxy(DBusConnection *connection, void *user_data) 1036{ 1037 struct serial_proxy *proxy = user_data; 1038 1039 proxy->watch = 0; 1040 unregister_proxy(proxy); 1041} 1042 1043static DBusMessage *create_proxy(DBusConnection *conn, 1044 DBusMessage *msg, void *data) 1045{ 1046 struct serial_adapter *adapter = data; 1047 struct serial_proxy *proxy; 1048 const char *pattern, *address; 1049 char *uuid_str; 1050 int err; 1051 1052 if (!dbus_message_get_args(msg, NULL, 1053 DBUS_TYPE_STRING, &pattern, 1054 DBUS_TYPE_STRING, &address, 1055 DBUS_TYPE_INVALID)) 1056 return NULL; 1057 1058 uuid_str = bt_name2string(pattern); 1059 if (!uuid_str) 1060 return invalid_arguments(msg, "Invalid UUID"); 1061 1062 err = register_proxy(adapter, uuid_str, address, &proxy); 1063 g_free(uuid_str); 1064 1065 if (err == -EINVAL) 1066 return invalid_arguments(msg, "Invalid address"); 1067 else if (err == -EALREADY) 1068 return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExist", 1069 "Proxy already exists"); 1070 else if (err < 0) 1071 return g_dbus_create_error(msg, ERROR_INTERFACE "Failed", 1072 "Proxy creation failed (%s)", strerror(-err)); 1073 1074 proxy->owner = g_strdup(dbus_message_get_sender(msg)); 1075 proxy->watch = g_dbus_add_disconnect_watch(conn, proxy->owner, 1076 watch_proxy, 1077 proxy, NULL); 1078 1079 return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &proxy->path, 1080 DBUS_TYPE_INVALID); 1081} 1082 1083static DBusMessage *list_proxies(DBusConnection *conn, 1084 DBusMessage *msg, void *data) 1085{ 1086 struct serial_adapter *adapter = data; 1087 const GSList *l; 1088 DBusMessage *reply; 1089 DBusMessageIter iter, iter_array; 1090 1091 reply = dbus_message_new_method_return(msg); 1092 if (!reply) 1093 return NULL; 1094 1095 dbus_message_iter_init_append(reply, &iter); 1096 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 1097 DBUS_TYPE_STRING_AS_STRING, &iter_array); 1098 1099 for (l = adapter->proxies; l; l = l->next) { 1100 struct serial_proxy *prx = l->data; 1101 1102 dbus_message_iter_append_basic(&iter_array, 1103 DBUS_TYPE_STRING, &prx->path); 1104 } 1105 1106 dbus_message_iter_close_container(&iter, &iter_array); 1107 1108 return reply; 1109} 1110 1111static DBusMessage *remove_proxy(DBusConnection *conn, 1112 DBusMessage *msg, void *data) 1113{ 1114 struct serial_adapter *adapter = data; 1115 struct serial_proxy *prx; 1116 const char *path, *sender; 1117 GSList *l; 1118 1119 if (!dbus_message_get_args(msg, NULL, 1120 DBUS_TYPE_STRING, &path, 1121 DBUS_TYPE_INVALID)) 1122 return NULL; 1123 1124 l = g_slist_find_custom(adapter->proxies, path, proxy_pathcmp); 1125 if (!l) 1126 return does_not_exist(msg, "Invalid proxy path"); 1127 1128 prx = l->data; 1129 1130 sender = dbus_message_get_sender(msg); 1131 if (g_strcmp0(prx->owner, sender) != 0) 1132 return failed(msg, "Permission denied"); 1133 1134 unregister_proxy(prx); 1135 1136 return dbus_message_new_method_return(msg); 1137} 1138 1139static void manager_path_unregister(void *data) 1140{ 1141 struct serial_adapter *adapter = data; 1142 GSList *l; 1143 1144 /* Remove proxy objects */ 1145 for (l = adapter->proxies; l; l = l->next) { 1146 struct serial_proxy *prx = l->data; 1147 char *path = g_strdup(prx->path); 1148 1149 g_dbus_unregister_interface(adapter->conn, path, 1150 SERIAL_PROXY_INTERFACE); 1151 g_free(path); 1152 } 1153 1154 if (adapter->conn) 1155 dbus_connection_unref(adapter->conn); 1156 1157 adapters = g_slist_remove(adapters, adapter); 1158 g_slist_free(adapter->proxies); 1159 btd_adapter_unref(adapter->btd_adapter); 1160 g_free(adapter); 1161} 1162 1163static GDBusMethodTable manager_methods[] = { 1164 { "CreateProxy", "ss", "s", create_proxy }, 1165 { "ListProxies", "", "as", list_proxies }, 1166 { "RemoveProxy", "s", "", remove_proxy }, 1167 { }, 1168}; 1169 1170static GDBusSignalTable manager_signals[] = { 1171 { "ProxyCreated", "s" }, 1172 { "ProxyRemoved", "s" }, 1173 { } 1174}; 1175 1176static struct serial_adapter *find_adapter(GSList *list, 1177 struct btd_adapter *btd_adapter) 1178{ 1179 GSList *l; 1180 1181 for (l = list; l; l = l->next) { 1182 struct serial_adapter *adapter = l->data; 1183 1184 if (adapter->btd_adapter == btd_adapter) 1185 return adapter; 1186 } 1187 1188 return NULL; 1189} 1190 1191static void serial_proxy_init(struct serial_adapter *adapter) 1192{ 1193 GKeyFile *config; 1194 GError *gerr = NULL; 1195 const char *file = CONFIGDIR "/serial.conf"; 1196 char **group_list; 1197 int i; 1198 1199 config = g_key_file_new(); 1200 1201 if (!g_key_file_load_from_file(config, file, 0, &gerr)) { 1202 error("Parsing %s failed: %s", file, gerr->message); 1203 g_error_free(gerr); 1204 g_key_file_free(config); 1205 return; 1206 } 1207 1208 group_list = g_key_file_get_groups(config, NULL); 1209 1210 for (i = 0; group_list[i] != NULL; i++) { 1211 char *group_str = group_list[i], *uuid_str, *address; 1212 int err; 1213 struct serial_proxy *prx; 1214 1215 /* string length of "Proxy" is 5 */ 1216 if (strlen(group_str) < 5 || strncmp(group_str, "Proxy", 5)) 1217 continue; 1218 1219 uuid_str = g_key_file_get_string(config, group_str, "UUID", 1220 &gerr); 1221 if (gerr) { 1222 DBG("%s: %s", file, gerr->message); 1223 g_error_free(gerr); 1224 g_key_file_free(config); 1225 g_strfreev(group_list); 1226 return; 1227 } 1228 1229 address = g_key_file_get_string(config, group_str, "Address", 1230 &gerr); 1231 if (gerr) { 1232 DBG("%s: %s", file, gerr->message); 1233 g_error_free(gerr); 1234 g_key_file_free(config); 1235 g_free(uuid_str); 1236 g_strfreev(group_list); 1237 return; 1238 } 1239 1240 err = register_proxy(adapter, uuid_str, address, &prx); 1241 if (err == -EINVAL) 1242 error("Invalid address."); 1243 else if (err == -EALREADY) 1244 DBG("Proxy already exists."); 1245 else if (err < 0) 1246 error("Proxy creation failed (%s)", strerror(-err)); 1247 else { 1248 err = enable_proxy(prx); 1249 if (err < 0) 1250 error("Proxy enable failed (%s)", 1251 strerror(-err)); 1252 } 1253 1254 g_free(uuid_str); 1255 g_free(address); 1256 } 1257 1258 g_strfreev(group_list); 1259 g_key_file_free(config); 1260} 1261 1262int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter) 1263{ 1264 struct serial_adapter *adapter; 1265 const char *path; 1266 1267 adapter = find_adapter(adapters, btd_adapter); 1268 if (adapter) 1269 return -EINVAL; 1270 1271 adapter = g_new0(struct serial_adapter, 1); 1272 adapter->conn = dbus_connection_ref(conn); 1273 adapter->btd_adapter = btd_adapter_ref(btd_adapter); 1274 1275 path = adapter_get_path(btd_adapter); 1276 1277 if (!g_dbus_register_interface(conn, path, 1278 SERIAL_MANAGER_INTERFACE, 1279 manager_methods, manager_signals, NULL, 1280 adapter, manager_path_unregister)) { 1281 error("Failed to register %s interface to %s", 1282 SERIAL_MANAGER_INTERFACE, path); 1283 return -1; 1284 } 1285 1286 adapters = g_slist_append(adapters, adapter); 1287 1288 DBG("Registered interface %s on path %s", 1289 SERIAL_MANAGER_INTERFACE, path); 1290 1291 serial_proxy_init(adapter); 1292 1293 return 0; 1294} 1295 1296void proxy_unregister(struct btd_adapter *btd_adapter) 1297{ 1298 struct serial_adapter *adapter; 1299 1300 adapter = find_adapter(adapters, btd_adapter); 1301 if (!adapter) 1302 return; 1303 1304 g_dbus_unregister_interface(adapter->conn, 1305 adapter_get_path(btd_adapter), 1306 SERIAL_MANAGER_INTERFACE); 1307} 1308