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