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 #include <stdio.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <unistd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <syslog.h> 36 #include <signal.h> 37 #include <getopt.h> 38 39 #include <sys/socket.h> 40 41 #include <bluetooth/bluetooth.h> 42 #include <bluetooth/hci.h> 43 #include <bluetooth/hci_lib.h> 44 #include <bluetooth/rfcomm.h> 45 #include <bluetooth/hidp.h> 46 47 #include "sdp.h" 48 #include "dund.h" 49 #include "lib.h" 50 51 volatile sig_atomic_t __io_canceled; 52 53 /* MS dialup networking support (i.e. CLIENT / CLIENTSERVER thing) */ 54 static int msdun = 0; 55 56 static char *pppd = "/usr/sbin/pppd"; 57 static char *pppd_opts[DUN_MAX_PPP_OPTS] = 58 { 59 /* First 3 are reserved */ 60 "", "", "", 61 "noauth", 62 "noipdefault", 63 NULL 64 }; 65 66 static int detach = 1; 67 static int persist; 68 static int use_sdp = 1; 69 static int auth; 70 static int encrypt; 71 static int secure; 72 static int master; 73 static int type = LANACCESS; 74 static int search_duration = 10; 75 static uint use_cache; 76 77 static int channel; 78 79 static struct { 80 uint valid; 81 char dst[40]; 82 bdaddr_t bdaddr; 83 int channel; 84 } cache; 85 86 static bdaddr_t src_addr = *BDADDR_ANY; 87 static int src_dev = -1; 88 89 volatile int terminate; 90 91 enum { 92 NONE, 93 SHOW, 94 LISTEN, 95 CONNECT, 96 KILL 97 } modes; 98 99 static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter); 100 101 static int do_listen(void) 102 { 103 struct sockaddr_rc sa; 104 int sk, lm; 105 106 if (type == MROUTER) { 107 if (!cache.valid) 108 return -1; 109 110 if (create_connection(cache.dst, &cache.bdaddr, type) < 0) { 111 syslog(LOG_ERR, "Cannot connect to mRouter device. %s(%d)", 112 strerror(errno), errno); 113 return -1; 114 } 115 } 116 117 if (!channel) 118 channel = DUN_DEFAULT_CHANNEL; 119 120 if (use_sdp) 121 dun_sdp_register(&src_addr, channel, type); 122 123 if (type == MROUTER) 124 syslog(LOG_INFO, "Waiting for mRouter callback on channel %d", channel); 125 126 /* Create RFCOMM socket */ 127 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 128 if (sk < 0) { 129 syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)", 130 strerror(errno), errno); 131 return -1; 132 } 133 134 sa.rc_family = AF_BLUETOOTH; 135 sa.rc_channel = channel; 136 sa.rc_bdaddr = src_addr; 137 138 if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) { 139 syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno); 140 return -1; 141 } 142 143 /* Set link mode */ 144 lm = 0; 145 if (master) 146 lm |= RFCOMM_LM_MASTER; 147 if (auth) 148 lm |= RFCOMM_LM_AUTH; 149 if (encrypt) 150 lm |= RFCOMM_LM_ENCRYPT; 151 if (secure) 152 lm |= RFCOMM_LM_SECURE; 153 154 if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { 155 syslog(LOG_ERR, "Failed to set link mode. %s(%d)", strerror(errno), errno); 156 return -1; 157 } 158 159 listen(sk, 10); 160 161 while (!terminate) { 162 socklen_t alen = sizeof(sa); 163 int nsk; 164 char ba[40]; 165 char ch[10]; 166 167 nsk = accept(sk, (struct sockaddr *) &sa, &alen); 168 if (nsk < 0) { 169 syslog(LOG_ERR, "Accept failed. %s(%d)", strerror(errno), errno); 170 continue; 171 } 172 173 switch (fork()) { 174 case 0: 175 break; 176 case -1: 177 syslog(LOG_ERR, "Fork failed. %s(%d)", strerror(errno), errno); 178 default: 179 close(nsk); 180 if (type == MROUTER) { 181 close(sk); 182 terminate = 1; 183 } 184 continue; 185 } 186 187 close(sk); 188 189 if (msdun && ms_dun(nsk, 1, msdun) < 0) { 190 syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno); 191 exit(0); 192 } 193 194 ba2str(&sa.rc_bdaddr, ba); 195 snprintf(ch, sizeof(ch), "%d", channel); 196 197 /* Setup environment */ 198 setenv("DUN_BDADDR", ba, 1); 199 setenv("DUN_CHANNEL", ch, 1); 200 201 if (!dun_open_connection(nsk, pppd, pppd_opts, 0)) 202 syslog(LOG_INFO, "New connection from %s", ba); 203 204 close(nsk); 205 exit(0); 206 } 207 208 if (use_sdp) 209 dun_sdp_unregister(); 210 return 0; 211 } 212 213 /* Connect and initiate RFCOMM session 214 * Returns: 215 * -1 - critical error (exit persist mode) 216 * 1 - non critical error 217 * 0 - success 218 */ 219 static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter) 220 { 221 struct sockaddr_rc sa; 222 int sk, err = 0, ch; 223 224 if (use_cache && cache.valid && cache.channel) { 225 /* Use cached channel */ 226 ch = cache.channel; 227 228 } else if (!channel) { 229 syslog(LOG_INFO, "Searching for %s on %s", mrouter ? "SP" : "LAP", dst); 230 231 if (dun_sdp_search(&src_addr, bdaddr, &ch, mrouter) <= 0) 232 return 0; 233 } else 234 ch = channel; 235 236 syslog(LOG_INFO, "Connecting to %s channel %d", dst, ch); 237 238 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 239 if (sk < 0) { 240 syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)", 241 strerror(errno), errno); 242 return -1; 243 } 244 245 sa.rc_family = AF_BLUETOOTH; 246 sa.rc_channel = 0; 247 sa.rc_bdaddr = src_addr; 248 249 if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) 250 syslog(LOG_ERR, "Bind failed. %s(%d)", 251 strerror(errno), errno); 252 253 sa.rc_channel = ch; 254 sa.rc_bdaddr = *bdaddr; 255 256 if (!connect(sk, (struct sockaddr *) &sa, sizeof(sa)) ) { 257 if (mrouter) { 258 sleep(1); 259 close(sk); 260 return 0; 261 } 262 263 syslog(LOG_INFO, "Connection established"); 264 265 if (msdun && ms_dun(sk, 0, msdun) < 0) { 266 syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno); 267 err = 1; 268 goto out; 269 } 270 271 if (!dun_open_connection(sk, pppd, pppd_opts, (persist > 0))) 272 err = 0; 273 else 274 err = 1; 275 } else { 276 syslog(LOG_ERR, "Connect to %s failed. %s(%d)", 277 dst, strerror(errno), errno); 278 err = 1; 279 } 280 281 out: 282 if (use_cache) { 283 if (!err) { 284 /* Succesesful connection, validate cache */ 285 strcpy(cache.dst, dst); 286 bacpy(&cache.bdaddr, bdaddr); 287 cache.channel = ch; 288 cache.valid = use_cache; 289 } else { 290 cache.channel = 0; 291 cache.valid--; 292 } 293 } 294 295 close(sk); 296 return err; 297 } 298 299 /* Search and connect 300 * Returns: 301 * -1 - critical error (exit persist mode) 302 * 1 - non critical error 303 * 0 - success 304 */ 305 static int do_connect(void) 306 { 307 inquiry_info *ii; 308 int reconnect = 0; 309 int i, n, r = 0; 310 311 do { 312 if (reconnect) 313 sleep(persist); 314 reconnect = 1; 315 316 if (cache.valid) { 317 /* Use cached bdaddr */ 318 r = create_connection(cache.dst, &cache.bdaddr, 0); 319 if (r < 0) { 320 terminate = 1; 321 break; 322 } 323 continue; 324 } 325 326 syslog(LOG_INFO, "Inquiring"); 327 328 /* FIXME: Should we use non general LAP here ? */ 329 330 ii = NULL; 331 n = hci_inquiry(src_dev, search_duration, 0, NULL, &ii, 0); 332 if (n < 0) { 333 syslog(LOG_ERR, "Inquiry failed. %s(%d)", strerror(errno), errno); 334 continue; 335 } 336 337 for (i = 0; i < n; i++) { 338 char dst[40]; 339 ba2str(&ii[i].bdaddr, dst); 340 341 r = create_connection(dst, &ii[i].bdaddr, 0); 342 if (r < 0) { 343 terminate = 1; 344 break; 345 } 346 } 347 bt_free(ii); 348 } while (!terminate && persist); 349 350 return r; 351 } 352 353 static void do_show(void) 354 { 355 dun_show_connections(); 356 } 357 358 static void do_kill(char *dst) 359 { 360 if (dst) { 361 bdaddr_t ba; 362 str2ba(dst, &ba); 363 dun_kill_connection((void *) &ba); 364 } else 365 dun_kill_all_connections(); 366 } 367 368 static void sig_hup(int sig) 369 { 370 return; 371 } 372 373 static void sig_term(int sig) 374 { 375 io_cancel(); 376 terminate = 1; 377 } 378 379 static struct option main_lopts[] = { 380 { "help", 0, 0, 'h' }, 381 { "listen", 0, 0, 's' }, 382 { "connect", 1, 0, 'c' }, 383 { "search", 2, 0, 'Q' }, 384 { "kill", 1, 0, 'k' }, 385 { "killall", 0, 0, 'K' }, 386 { "channel", 1, 0, 'P' }, 387 { "device", 1, 0, 'i' }, 388 { "nosdp", 0, 0, 'D' }, 389 { "list", 0, 0, 'l' }, 390 { "show", 0, 0, 'l' }, 391 { "nodetach", 0, 0, 'n' }, 392 { "persist", 2, 0, 'p' }, 393 { "auth", 0, 0, 'A' }, 394 { "encrypt", 0, 0, 'E' }, 395 { "secure", 0, 0, 'S' }, 396 { "master", 0, 0, 'M' }, 397 { "cache", 0, 0, 'C' }, 398 { "pppd", 1, 0, 'd' }, 399 { "msdun", 2, 0, 'X' }, 400 { "activesync", 0, 0, 'a' }, 401 { "mrouter", 1, 0, 'm' }, 402 { "dialup", 0, 0, 'u' }, 403 { 0, 0, 0, 0 } 404 }; 405 406 static const char *main_sopts = "hsc:k:Kr:i:lnp::DQ::AESMP:C::P:Xam:u"; 407 408 static const char *main_help = 409 "Bluetooth LAP (LAN Access over PPP) daemon version %s\n" 410 "Usage:\n" 411 "\tdund <options> [pppd options]\n" 412 "Options:\n" 413 "\t--show --list -l Show active LAP connections\n" 414 "\t--listen -s Listen for LAP connections\n" 415 "\t--dialup -u Pretend to be a dialup/telephone\n" 416 "\t--connect -c <bdaddr> Create LAP connection\n" 417 "\t--mrouter -m <bdaddr> Create mRouter connection\n" 418 "\t--search -Q[duration] Search and connect\n" 419 "\t--kill -k <bdaddr> Kill LAP connection\n" 420 "\t--killall -K Kill all LAP connections\n" 421 "\t--channel -P <channel> RFCOMM channel\n" 422 "\t--device -i <bdaddr> Source bdaddr\n" 423 "\t--nosdp -D Disable SDP\n" 424 "\t--auth -A Enable authentication\n" 425 "\t--encrypt -E Enable encryption\n" 426 "\t--secure -S Secure connection\n" 427 "\t--master -M Become the master of a piconet\n" 428 "\t--nodetach -n Do not become a daemon\n" 429 "\t--persist -p[interval] Persist mode\n" 430 "\t--pppd -d <pppd> Location of the PPP daemon (pppd)\n" 431 "\t--msdun -X[timeo] Enable Microsoft dialup networking support\n" 432 "\t--activesync -a Enable Microsoft ActiveSync networking\n" 433 "\t--cache -C[valid] Enable address cache\n"; 434 435 int main(int argc, char *argv[]) 436 { 437 char *dst = NULL, *src = NULL; 438 struct sigaction sa; 439 int mode = NONE; 440 int opt; 441 442 while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) { 443 switch(opt) { 444 case 'l': 445 mode = SHOW; 446 detach = 0; 447 break; 448 449 case 's': 450 mode = LISTEN; 451 type = LANACCESS; 452 break; 453 454 case 'c': 455 mode = CONNECT; 456 dst = strdup(optarg); 457 break; 458 459 case 'Q': 460 mode = CONNECT; 461 dst = NULL; 462 if (optarg) 463 search_duration = atoi(optarg); 464 break; 465 466 case 'k': 467 mode = KILL; 468 detach = 0; 469 dst = strdup(optarg); 470 break; 471 472 case 'K': 473 mode = KILL; 474 detach = 0; 475 dst = NULL; 476 break; 477 478 case 'P': 479 channel = atoi(optarg); 480 break; 481 482 case 'i': 483 src = strdup(optarg); 484 break; 485 486 case 'D': 487 use_sdp = 0; 488 break; 489 490 case 'A': 491 auth = 1; 492 break; 493 494 case 'E': 495 encrypt = 1; 496 break; 497 498 case 'S': 499 secure = 1; 500 break; 501 502 case 'M': 503 master = 1; 504 break; 505 506 case 'n': 507 detach = 0; 508 break; 509 510 case 'p': 511 if (optarg) 512 persist = atoi(optarg); 513 else 514 persist = 5; 515 break; 516 517 case 'C': 518 if (optarg) 519 use_cache = atoi(optarg); 520 else 521 use_cache = 2; 522 break; 523 524 case 'd': 525 pppd = strdup(optarg); 526 break; 527 528 case 'X': 529 if (optarg) 530 msdun = atoi(optarg); 531 else 532 msdun = 10; 533 break; 534 535 case 'a': 536 msdun = 10; 537 type = ACTIVESYNC; 538 break; 539 540 case 'm': 541 mode = LISTEN; 542 dst = strdup(optarg); 543 type = MROUTER; 544 break; 545 546 case 'u': 547 mode = LISTEN; 548 type = DIALUP; 549 break; 550 551 case 'h': 552 default: 553 printf(main_help, VERSION); 554 exit(0); 555 } 556 } 557 558 argc -= optind; 559 argv += optind; 560 561 /* The rest is pppd options */ 562 if (argc > 0) { 563 for (opt = 3; argc && opt < DUN_MAX_PPP_OPTS - 1; 564 argc--, opt++) 565 pppd_opts[opt] = *argv++; 566 pppd_opts[opt] = NULL; 567 } 568 569 io_init(); 570 571 if (dun_init()) { 572 free(dst); 573 return -1; 574 } 575 576 /* Check non daemon modes first */ 577 switch (mode) { 578 case SHOW: 579 do_show(); 580 free(dst); 581 return 0; 582 583 case KILL: 584 do_kill(dst); 585 free(dst); 586 return 0; 587 588 case NONE: 589 printf(main_help, VERSION); 590 free(dst); 591 return 0; 592 } 593 594 /* Initialize signals */ 595 memset(&sa, 0, sizeof(sa)); 596 sa.sa_flags = SA_NOCLDSTOP; 597 sa.sa_handler = SIG_IGN; 598 sigaction(SIGCHLD, &sa, NULL); 599 sigaction(SIGPIPE, &sa, NULL); 600 601 sa.sa_handler = sig_term; 602 sigaction(SIGTERM, &sa, NULL); 603 sigaction(SIGINT, &sa, NULL); 604 605 sa.sa_handler = sig_hup; 606 sigaction(SIGHUP, &sa, NULL); 607 608 if (detach && daemon(0, 0)) { 609 perror("Can't start daemon"); 610 exit(1); 611 } 612 613 openlog("dund", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); 614 syslog(LOG_INFO, "Bluetooth DUN daemon version %s", VERSION); 615 616 if (src) { 617 src_dev = hci_devid(src); 618 if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) { 619 syslog(LOG_ERR, "Invalid source. %s(%d)", strerror(errno), errno); 620 free(dst); 621 return -1; 622 } 623 } 624 625 if (dst) { 626 strncpy(cache.dst, dst, sizeof(cache.dst) - 1); 627 str2ba(dst, &cache.bdaddr); 628 629 /* Disable cache invalidation */ 630 use_cache = cache.valid = ~0; 631 } 632 633 switch (mode) { 634 case CONNECT: 635 do_connect(); 636 break; 637 638 case LISTEN: 639 do_listen(); 640 break; 641 } 642 643 free(dst); 644 return 0; 645 } 646