1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk (at) qualcomm.com> 6 * Copyright (C) 2002-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 #define _GNU_SOURCE 30 #include <stdio.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <syslog.h> 37 #include <signal.h> 38 #include <getopt.h> 39 #include <sys/poll.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 44 #include <bluetooth/bluetooth.h> 45 #include <bluetooth/hci.h> 46 #include <bluetooth/hci_lib.h> 47 #include <bluetooth/l2cap.h> 48 #include <bluetooth/bnep.h> 49 #include <bluetooth/hidp.h> 50 51 #include "sdp.h" 52 #include "pand.h" 53 54 #ifdef __ANDROID__ 55 #include <android/log.h> 56 #define syslog android_log 57 #endif 58 59 #ifdef NEED_PPOLL 60 #include "ppoll.h" 61 #endif 62 63 static uint16_t role = BNEP_SVC_PANU; /* Local role (ie service) */ 64 static uint16_t service = BNEP_SVC_NAP; /* Remote service */ 65 66 static int detach = 1; 67 static int persist; 68 static int use_sdp = 1; 69 static int use_cache; 70 static int link_mode = 0; 71 static int cleanup; 72 static int search_duration = 10; 73 74 static struct { 75 int valid; 76 char dst[40]; 77 bdaddr_t bdaddr; 78 } cache; 79 80 static char netdev[16] = "bnep%d"; 81 static char *pidfile = NULL; 82 static char *devupcmd = NULL; 83 static char *devdowncmd = NULL; 84 85 static bdaddr_t src_addr = *BDADDR_ANY; 86 static int src_dev = -1; 87 88 static volatile int terminate; 89 90 static void do_kill(char *dst); 91 92 enum { 93 NONE, 94 SHOW, 95 LISTEN, 96 CONNECT, 97 KILL 98 } modes; 99 100 struct script_arg { 101 char dev[20]; 102 char dst[20]; 103 int sk; 104 int nsk; 105 }; 106 107 #ifdef __ANDROID__ 108 static void android_log(int priority, const char *format, ...) 109 { 110 va_list ap; 111 int alog_lvl; 112 113 if (priority <= LOG_ERR) 114 alog_lvl = ANDROID_LOG_ERROR; 115 else if (priority == LOG_WARNING) 116 alog_lvl = ANDROID_LOG_WARN; 117 else if (priority <= LOG_INFO) 118 alog_lvl = ANDROID_LOG_INFO; 119 else 120 alog_lvl = ANDROID_LOG_DEBUG; 121 va_start(ap, format); 122 __android_log_vprint(alog_lvl, "pand", format, ap); 123 va_end(ap); 124 } 125 #endif 126 static void run_script(char *script, char *dev, char *dst, int sk, int nsk) 127 { 128 char *argv[4]; 129 struct sigaction sa; 130 131 if (!script) 132 return; 133 134 if (access(script, R_OK | X_OK)) 135 return; 136 137 if (fork()) 138 return; 139 140 if (sk >= 0) 141 close(sk); 142 143 if (nsk >= 0) 144 close(nsk); 145 146 memset(&sa, 0, sizeof(sa)); 147 sa.sa_handler = SIG_DFL; 148 sigaction(SIGCHLD, &sa, NULL); 149 sigaction(SIGPIPE, &sa, NULL); 150 151 argv[0] = script; 152 argv[1] = dev; 153 argv[2] = dst; 154 argv[3] = NULL; 155 156 execv(script, argv); 157 158 exit(1); 159 } 160 161 /* Wait for disconnect or error condition on the socket */ 162 static int w4_hup(int sk, struct script_arg *down_cmd) 163 { 164 struct pollfd pf; 165 sigset_t sigs; 166 int n; 167 168 sigfillset(&sigs); 169 sigdelset(&sigs, SIGCHLD); 170 sigdelset(&sigs, SIGPIPE); 171 sigdelset(&sigs, SIGTERM); 172 sigdelset(&sigs, SIGINT); 173 sigdelset(&sigs, SIGHUP); 174 175 while (!terminate) { 176 pf.fd = sk; 177 pf.events = POLLERR | POLLHUP; 178 179 n = ppoll(&pf, 1, NULL, &sigs); 180 181 if (n < 0) { 182 if (errno == EINTR || errno == EAGAIN) 183 continue; 184 185 syslog(LOG_ERR, "Poll failed. %s(%d)", 186 strerror(errno), errno); 187 188 return 1; 189 } 190 191 if (n) { 192 int err = 0; 193 socklen_t olen = sizeof(err); 194 195 getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &olen); 196 197 syslog(LOG_INFO, "%s disconnected%s%s", netdev, 198 err ? " : " : "", err ? strerror(err) : ""); 199 200 if (down_cmd) 201 run_script(devdowncmd, 202 down_cmd->dev, down_cmd->dst, 203 down_cmd->sk, down_cmd->nsk); 204 205 close(sk); 206 207 return 0; 208 } 209 } 210 211 return 0; 212 } 213 214 static int do_listen(void) 215 { 216 struct l2cap_options l2o; 217 struct sockaddr_l2 l2a; 218 socklen_t olen; 219 int sk, lm; 220 221 if (use_sdp) 222 bnep_sdp_register(&src_addr, role); 223 224 /* Create L2CAP socket and bind it to PSM BNEP */ 225 sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 226 if (sk < 0) { 227 syslog(LOG_ERR, "Cannot create L2CAP socket. %s(%d)", 228 strerror(errno), errno); 229 return -1; 230 } 231 232 memset(&l2a, 0, sizeof(l2a)); 233 l2a.l2_family = AF_BLUETOOTH; 234 bacpy(&l2a.l2_bdaddr, &src_addr); 235 l2a.l2_psm = htobs(BNEP_PSM); 236 237 if (bind(sk, (struct sockaddr *) &l2a, sizeof(l2a))) { 238 syslog(LOG_ERR, "Bind failed. %s(%d)", 239 strerror(errno), errno); 240 return -1; 241 } 242 243 /* Setup L2CAP options according to BNEP spec */ 244 memset(&l2o, 0, sizeof(l2o)); 245 olen = sizeof(l2o); 246 if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen) < 0) { 247 syslog(LOG_ERR, "Failed to get L2CAP options. %s(%d)", 248 strerror(errno), errno); 249 return -1; 250 } 251 252 l2o.imtu = l2o.omtu = BNEP_MTU; 253 if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)) < 0) { 254 syslog(LOG_ERR, "Failed to set L2CAP options. %s(%d)", 255 strerror(errno), errno); 256 return -1; 257 } 258 259 /* Set link mode */ 260 lm = link_mode; 261 if (lm && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0) { 262 syslog(LOG_ERR, "Failed to set link mode. %s(%d)", 263 strerror(errno), errno); 264 return -1; 265 } 266 267 listen(sk, 10); 268 269 while (!terminate) { 270 socklen_t alen = sizeof(l2a); 271 char devname[16]; 272 int nsk; 273 274 nsk = accept(sk, (struct sockaddr *) &l2a, &alen); 275 if (nsk < 0) { 276 syslog(LOG_ERR, "Accept failed. %s(%d)", 277 strerror(errno), errno); 278 continue; 279 } 280 281 switch (fork()) { 282 case 0: 283 break; 284 case -1: 285 syslog(LOG_ERR, "Fork failed. %s(%d)", 286 strerror(errno), errno); 287 default: 288 close(nsk); 289 continue; 290 } 291 292 strncpy(devname, netdev, 16); 293 devname[15] = '\0'; 294 295 if (!bnep_accept_connection(nsk, role, devname)) { 296 char str[40]; 297 struct script_arg down_cmd; 298 299 ba2str(&l2a.l2_bdaddr, str); 300 301 syslog(LOG_INFO, "New connection from %s at %s", 302 str, devname); 303 304 run_script(devupcmd, devname, str, sk, nsk); 305 306 memset(&down_cmd, 0, sizeof(struct script_arg)); 307 strncpy(down_cmd.dev, devname, strlen(devname) + 1); 308 strncpy(down_cmd.dst, str, strlen(str) + 1); 309 down_cmd.sk = sk; 310 down_cmd.nsk = nsk; 311 w4_hup(nsk, &down_cmd); 312 } else { 313 syslog(LOG_ERR, "Connection failed. %s(%d)", 314 strerror(errno), errno); 315 } 316 317 close(nsk); 318 exit(0); 319 } 320 321 if (use_sdp) 322 bnep_sdp_unregister(); 323 324 return 0; 325 } 326 327 /* Connect and initiate BNEP session 328 * Returns: 329 * -1 - critical error (exit persist mode) 330 * 1 - non critical error 331 * 0 - success 332 */ 333 static int create_connection(char *dst, bdaddr_t *bdaddr) 334 { 335 struct l2cap_options l2o; 336 struct sockaddr_l2 l2a; 337 socklen_t olen; 338 int sk, r = 0; 339 struct script_arg down_cmd; 340 341 syslog(LOG_INFO, "Connecting to %s", dst); 342 343 sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 344 if (sk < 0) { 345 syslog(LOG_ERR, "Cannot create L2CAP socket. %s(%d)", 346 strerror(errno), errno); 347 return -1; 348 } 349 350 /* Setup L2CAP options according to BNEP spec */ 351 memset(&l2o, 0, sizeof(l2o)); 352 olen = sizeof(l2o); 353 getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); 354 l2o.imtu = l2o.omtu = BNEP_MTU; 355 setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); 356 357 memset(&l2a, 0, sizeof(l2a)); 358 l2a.l2_family = AF_BLUETOOTH; 359 bacpy(&l2a.l2_bdaddr, &src_addr); 360 361 if (bind(sk, (struct sockaddr *) &l2a, sizeof(l2a))) 362 syslog(LOG_ERR, "Bind failed. %s(%d)", 363 strerror(errno), errno); 364 365 memset(&l2a, 0, sizeof(l2a)); 366 l2a.l2_family = AF_BLUETOOTH; 367 bacpy(&l2a.l2_bdaddr, bdaddr); 368 l2a.l2_psm = htobs(BNEP_PSM); 369 370 if (!connect(sk, (struct sockaddr *) &l2a, sizeof(l2a)) && 371 !bnep_create_connection(sk, role, service, netdev)) { 372 373 syslog(LOG_INFO, "%s connected", netdev); 374 375 run_script(devupcmd, netdev, dst, sk, -1); 376 377 if (persist || devdowncmd) { 378 memset(&down_cmd, 0, sizeof(struct script_arg)); 379 strncpy(down_cmd.dev, netdev, strlen(netdev) + 1); 380 strncpy(down_cmd.dst, dst, strlen(dst) + 1); 381 down_cmd.sk = sk; 382 down_cmd.nsk = -1; 383 w4_hup(sk, &down_cmd); 384 385 if (terminate && cleanup) { 386 syslog(LOG_INFO, "Disconnecting from %s.", dst); 387 do_kill(dst); 388 } 389 } 390 391 r = 0; 392 } else { 393 syslog(LOG_ERR, "Connect to %s failed. %s(%d)", 394 dst, strerror(errno), errno); 395 r = 1; 396 } 397 398 close(sk); 399 400 if (use_cache) { 401 if (!r) { 402 /* Succesesful connection, validate cache */ 403 strcpy(cache.dst, dst); 404 bacpy(&cache.bdaddr, bdaddr); 405 cache.valid = use_cache; 406 } else 407 cache.valid--; 408 } 409 410 return r; 411 } 412 413 /* Search and connect 414 * Returns: 415 * -1 - critical error (exit persist mode) 416 * 1 - non critical error 417 * 0 - success 418 */ 419 static int do_connect(void) 420 { 421 inquiry_info *ii; 422 int reconnect = 0; 423 int i, n, r = 0; 424 425 do { 426 if (reconnect) 427 sleep(persist); 428 reconnect = 1; 429 430 if (cache.valid > 0) { 431 /* Use cached bdaddr */ 432 r = create_connection(cache.dst, &cache.bdaddr); 433 if (r < 0) { 434 terminate = 1; 435 break; 436 } 437 continue; 438 } 439 440 syslog(LOG_INFO, "Inquiring"); 441 442 /* FIXME: Should we use non general LAP here ? */ 443 444 ii = NULL; 445 n = hci_inquiry(src_dev, search_duration, 0, NULL, &ii, 0); 446 if (n < 0) { 447 syslog(LOG_ERR, "Inquiry failed. %s(%d)", 448 strerror(errno), errno); 449 continue; 450 } 451 452 for (i = 0; i < n; i++) { 453 char dst[40]; 454 ba2str(&ii[i].bdaddr, dst); 455 456 if (use_sdp) { 457 syslog(LOG_INFO, "Searching for %s on %s", 458 bnep_svc2str(service), dst); 459 460 if (bnep_sdp_search(&src_addr, &ii[i].bdaddr, service) <= 0) 461 continue; 462 } 463 464 r = create_connection(dst, &ii[i].bdaddr); 465 if (r < 0) { 466 terminate = 1; 467 break; 468 } 469 } 470 bt_free(ii); 471 } while (!terminate && persist); 472 473 return r; 474 } 475 476 static void do_show(void) 477 { 478 bnep_show_connections(); 479 } 480 481 static void do_kill(char *dst) 482 { 483 if (dst) { 484 bdaddr_t *ba = strtoba(dst); 485 bnep_kill_connection((void *) ba); 486 free(ba); 487 } else { 488 bnep_kill_all_connections(); 489 } 490 } 491 492 static void sig_hup(int sig) 493 { 494 return; 495 } 496 497 static void sig_term(int sig) 498 { 499 terminate = 1; 500 } 501 502 static int write_pidfile(void) 503 { 504 int fd; 505 FILE *f; 506 pid_t pid; 507 508 do { 509 fd = open(pidfile, O_WRONLY|O_TRUNC|O_CREAT|O_EXCL, 0644); 510 if (fd == -1) { 511 /* Try to open the file for read. */ 512 fd = open(pidfile, O_RDONLY); 513 if (fd < 0) { 514 syslog(LOG_ERR, "Could not read old pidfile: %s(%d)", 515 strerror(errno), errno); 516 return -1; 517 } 518 519 /* We're already running; send a SIGHUP (we presume that they 520 * are calling ifup for a reason, so they probably want to 521 * rescan) and then exit cleanly and let things go on in the 522 * background. Muck with the filename so that we don't go 523 * deleting the pid file for the already-running instance. 524 */ 525 f = fdopen(fd, "r"); 526 if (!f) { 527 syslog(LOG_ERR, "Could not fdopen old pidfile: %s(%d)", 528 strerror(errno), errno); 529 close(fd); 530 return -1; 531 } 532 533 pid = 0; 534 if (fscanf(f, "%d", &pid) != 1) 535 pid = 0; 536 fclose(f); 537 538 if (pid) { 539 /* Try to kill it. */ 540 if (kill(pid, SIGHUP) == -1) { 541 /* No such pid; remove the bogus pid file. */ 542 syslog(LOG_INFO, "Removing stale pidfile"); 543 unlink(pidfile); 544 fd = -1; 545 } else { 546 /* Got it. Don't mess with the pid file on 547 * our way out. */ 548 syslog(LOG_INFO, "Signalling existing process %d and exiting\n", pid); 549 pidfile = NULL; 550 return -1; 551 } 552 } 553 } 554 } while(fd == -1); 555 556 f = fdopen(fd, "w"); 557 if (!f) { 558 syslog(LOG_ERR, "Could not fdopen new pidfile: %s(%d)", 559 strerror(errno), errno); 560 close(fd); 561 unlink(pidfile); 562 return -1; 563 } 564 565 fprintf(f, "%d\n", getpid()); 566 fclose(f); 567 568 return 0; 569 } 570 571 static struct option main_lopts[] = { 572 { "help", 0, 0, 'h' }, 573 { "listen", 0, 0, 's' }, 574 { "connect", 1, 0, 'c' }, 575 { "search", 2, 0, 'Q' }, 576 { "kill", 1, 0, 'k' }, 577 { "killall", 0, 0, 'K' }, 578 { "role", 1, 0, 'r' }, 579 { "service", 1, 0, 'd' }, 580 { "ethernet", 1, 0, 'e' }, 581 { "device", 1, 0, 'i' }, 582 { "nosdp", 0, 0, 'D' }, 583 { "list", 0, 0, 'l' }, 584 { "show", 0, 0, 'l' }, 585 { "nodetach", 0, 0, 'n' }, 586 { "persist", 2, 0, 'p' }, 587 { "auth", 0, 0, 'A' }, 588 { "encrypt", 0, 0, 'E' }, 589 { "secure", 0, 0, 'S' }, 590 { "master", 0, 0, 'M' }, 591 { "cache", 0, 0, 'C' }, 592 { "pidfile", 1, 0, 'P' }, 593 { "devup", 1, 0, 'u' }, 594 { "devdown", 1, 0, 'o' }, 595 { "autozap", 0, 0, 'z' }, 596 { 0, 0, 0, 0 } 597 }; 598 599 static const char *main_sopts = "hsc:k:Kr:d:e:i:lnp::DQ::AESMC::P:u:o:z"; 600 601 static const char *main_help = 602 "Bluetooth PAN daemon version %s\n" 603 "Usage:\n" 604 "\tpand <options>\n" 605 "Options:\n" 606 "\t--show --list -l Show active PAN connections\n" 607 "\t--listen -s Listen for PAN connections\n" 608 "\t--connect -c <bdaddr> Create PAN connection\n" 609 "\t--autozap -z Disconnect automatically on exit\n" 610 "\t--search -Q[duration] Search and connect\n" 611 "\t--kill -k <bdaddr> Kill PAN connection\n" 612 "\t--killall -K Kill all PAN connections\n" 613 "\t--role -r <role> Local PAN role (PANU, NAP, GN)\n" 614 "\t--service -d <role> Remote PAN service (PANU, NAP, GN)\n" 615 "\t--ethernet -e <name> Network interface name\n" 616 "\t--device -i <bdaddr> Source bdaddr\n" 617 "\t--nosdp -D Disable SDP\n" 618 "\t--auth -A Enable authentication\n" 619 "\t--encrypt -E Enable encryption\n" 620 "\t--secure -S Secure connection\n" 621 "\t--master -M Become the master of a piconet\n" 622 "\t--nodetach -n Do not become a daemon\n" 623 "\t--persist -p[interval] Persist mode\n" 624 "\t--cache -C[valid] Cache addresses\n" 625 "\t--pidfile -P <pidfile> Create PID file\n" 626 "\t--devup -u <script> Script to run when interface comes up\n" 627 "\t--devdown -o <script> Script to run when interface comes down\n"; 628 629 int main(int argc, char *argv[]) 630 { 631 char *dst = NULL, *src = NULL; 632 struct sigaction sa; 633 int mode = NONE; 634 int opt; 635 636 while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) { 637 switch(opt) { 638 case 'l': 639 mode = SHOW; 640 detach = 0; 641 break; 642 643 case 's': 644 mode = LISTEN; 645 break; 646 647 case 'c': 648 mode = CONNECT; 649 dst = strdup(optarg); 650 break; 651 652 case 'Q': 653 mode = CONNECT; 654 if (optarg) 655 search_duration = atoi(optarg); 656 break; 657 658 case 'k': 659 mode = KILL; 660 detach = 0; 661 dst = strdup(optarg); 662 break; 663 664 case 'K': 665 mode = KILL; 666 detach = 0; 667 break; 668 669 case 'i': 670 src = strdup(optarg); 671 break; 672 673 case 'r': 674 bnep_str2svc(optarg, &role); 675 break; 676 677 case 'd': 678 bnep_str2svc(optarg, &service); 679 break; 680 681 case 'D': 682 use_sdp = 0; 683 break; 684 685 case 'A': 686 link_mode |= L2CAP_LM_AUTH; 687 break; 688 689 case 'E': 690 link_mode |= L2CAP_LM_ENCRYPT; 691 break; 692 693 case 'S': 694 link_mode |= L2CAP_LM_SECURE; 695 break; 696 697 case 'M': 698 link_mode |= L2CAP_LM_MASTER; 699 break; 700 701 case 'e': 702 strncpy(netdev, optarg, 16); 703 netdev[15] = '\0'; 704 break; 705 706 case 'n': 707 detach = 0; 708 break; 709 710 case 'p': 711 if (optarg) 712 persist = atoi(optarg); 713 else 714 persist = 5; 715 break; 716 717 case 'C': 718 if (optarg) 719 use_cache = atoi(optarg); 720 else 721 use_cache = 2; 722 break; 723 724 case 'P': 725 pidfile = strdup(optarg); 726 break; 727 728 case 'u': 729 devupcmd = strdup(optarg); 730 break; 731 732 case 'o': 733 devdowncmd = strdup(optarg); 734 break; 735 736 case 'z': 737 cleanup = 1; 738 break; 739 740 case 'h': 741 default: 742 printf(main_help, VERSION); 743 exit(0); 744 } 745 } 746 747 argc -= optind; 748 argv += optind; 749 optind = 0; 750 751 if (bnep_init()) { 752 free(dst); 753 return -1; 754 } 755 756 /* Check non daemon modes first */ 757 switch (mode) { 758 case SHOW: 759 do_show(); 760 free(dst); 761 return 0; 762 763 case KILL: 764 do_kill(dst); 765 free(dst); 766 return 0; 767 768 case NONE: 769 printf(main_help, VERSION); 770 free(dst); 771 return 0; 772 } 773 774 /* Initialize signals */ 775 memset(&sa, 0, sizeof(sa)); 776 sa.sa_flags = SA_NOCLDSTOP; 777 sa.sa_handler = SIG_IGN; 778 sigaction(SIGCHLD, &sa, NULL); 779 sigaction(SIGPIPE, &sa, NULL); 780 781 sa.sa_handler = sig_hup; 782 sigaction(SIGHUP, &sa, NULL); 783 784 sa.sa_handler = sig_term; 785 sigaction(SIGTERM, &sa, NULL); 786 sigaction(SIGINT, &sa, NULL); 787 788 if (detach && daemon(0, 0)) { 789 perror("Can't start daemon"); 790 exit(1); 791 } 792 793 openlog("pand", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); 794 syslog(LOG_INFO, "Bluetooth PAN daemon version %s", VERSION); 795 796 if (src) { 797 src_dev = hci_devid(src); 798 if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) { 799 syslog(LOG_ERR, "Invalid source. %s(%d)", 800 strerror(errno), errno); 801 free(dst); 802 return -1; 803 } 804 } 805 806 if (pidfile && write_pidfile()) { 807 free(dst); 808 return -1; 809 } 810 811 if (dst) { 812 /* Disable cache invalidation */ 813 use_cache = 0; 814 815 strncpy(cache.dst, dst, sizeof(cache.dst) - 1); 816 str2ba(dst, &cache.bdaddr); 817 cache.valid = 1; 818 free(dst); 819 } 820 821 switch (mode) { 822 case CONNECT: 823 do_connect(); 824 break; 825 826 case LISTEN: 827 do_listen(); 828 break; 829 } 830 831 if (pidfile) 832 unlink(pidfile); 833 834 return 0; 835 } 836