1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2000-2001 Qualcomm Incorporated 6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk (at) qualcomm.com> 7 * Copyright (C) 2002-2010 Marcel Holtmann <marcel (at) holtmann.org> 8 * 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 */ 25 26 #ifdef HAVE_CONFIG_H 27 #include <config.h> 28 #endif 29 30 #include <errno.h> 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <signal.h> 36 #include <sys/stat.h> 37 #include <sys/ioctl.h> 38 #include <sys/socket.h> 39 #include <sys/types.h> 40 41 #include <bluetooth/bluetooth.h> 42 #include <bluetooth/hci.h> 43 #include <bluetooth/hci_lib.h> 44 45 #include <glib.h> 46 47 #ifdef ANDROID_EXPAND_NAME 48 #include <cutils/properties.h> 49 #endif 50 51 #include <dbus/dbus.h> 52 53 #include "log.h" 54 55 #include "hcid.h" 56 #include "sdpd.h" 57 #include "adapter.h" 58 #include "dbus-hci.h" 59 #include "dbus-common.h" 60 #include "agent.h" 61 #include "manager.h" 62 63 #ifdef HAVE_CAPNG 64 #include <cap-ng.h> 65 #endif 66 67 #define LAST_ADAPTER_EXIT_TIMEOUT 30 68 69 struct main_opts main_opts; 70 71 static GKeyFile *load_config(const char *file) 72 { 73 GError *err = NULL; 74 GKeyFile *keyfile; 75 76 keyfile = g_key_file_new(); 77 78 g_key_file_set_list_separator(keyfile, ','); 79 80 if (!g_key_file_load_from_file(keyfile, file, 0, &err)) { 81 error("Parsing %s failed: %s", file, err->message); 82 g_error_free(err); 83 g_key_file_free(keyfile); 84 return NULL; 85 } 86 87 return keyfile; 88 } 89 90 static void parse_config(GKeyFile *config) 91 { 92 GError *err = NULL; 93 char *str; 94 int val; 95 gboolean boolean; 96 97 if (!config) 98 return; 99 100 DBG("parsing main.conf"); 101 102 val = g_key_file_get_integer(config, "General", 103 "DiscoverableTimeout", &err); 104 if (err) { 105 DBG("%s", err->message); 106 g_clear_error(&err); 107 } else { 108 DBG("discovto=%d", val); 109 main_opts.discovto = val; 110 main_opts.flags |= 1 << HCID_SET_DISCOVTO; 111 } 112 113 val = g_key_file_get_integer(config, "General", 114 "PairableTimeout", &err); 115 if (err) { 116 DBG("%s", err->message); 117 g_clear_error(&err); 118 } else { 119 DBG("pairto=%d", val); 120 main_opts.pairto = val; 121 } 122 123 val = g_key_file_get_integer(config, "General", "PageTimeout", &err); 124 if (err) { 125 DBG("%s", err->message); 126 g_clear_error(&err); 127 } else { 128 DBG("pageto=%d", val); 129 main_opts.pageto = val; 130 main_opts.flags |= 1 << HCID_SET_PAGETO; 131 } 132 133 str = g_key_file_get_string(config, "General", "Name", &err); 134 if (err) { 135 DBG("%s", err->message); 136 g_clear_error(&err); 137 } else { 138 DBG("name=%s", str); 139 g_free(main_opts.name); 140 main_opts.name = g_strdup(str); 141 main_opts.flags |= 1 << HCID_SET_NAME; 142 g_free(str); 143 } 144 145 str = g_key_file_get_string(config, "General", "Class", &err); 146 if (err) { 147 DBG("%s", err->message); 148 g_clear_error(&err); 149 } else { 150 DBG("class=%s", str); 151 main_opts.class = strtol(str, NULL, 16); 152 main_opts.flags |= 1 << HCID_SET_CLASS; 153 g_free(str); 154 } 155 156 val = g_key_file_get_integer(config, "General", 157 "DiscoverSchedulerInterval", &err); 158 if (err) { 159 DBG("%s", err->message); 160 g_clear_error(&err); 161 } else { 162 DBG("discov_interval=%d", val); 163 main_opts.discov_interval = val; 164 } 165 166 boolean = g_key_file_get_boolean(config, "General", 167 "InitiallyPowered", &err); 168 if (err) { 169 DBG("%s", err->message); 170 g_clear_error(&err); 171 } else if (boolean == FALSE) 172 main_opts.mode = MODE_OFF; 173 174 boolean = g_key_file_get_boolean(config, "General", 175 "RememberPowered", &err); 176 if (err) { 177 DBG("%s", err->message); 178 g_clear_error(&err); 179 } else 180 main_opts.remember_powered = boolean; 181 182 str = g_key_file_get_string(config, "General", "DeviceID", &err); 183 if (err) { 184 DBG("%s", err->message); 185 g_clear_error(&err); 186 } else { 187 DBG("deviceid=%s", str); 188 strncpy(main_opts.deviceid, str, 189 sizeof(main_opts.deviceid) - 1); 190 g_free(str); 191 } 192 193 boolean = g_key_file_get_boolean(config, "General", 194 "ReverseServiceDiscovery", &err); 195 if (err) { 196 DBG("%s", err->message); 197 g_clear_error(&err); 198 } else 199 main_opts.reverse_sdp = boolean; 200 201 boolean = g_key_file_get_boolean(config, "General", 202 "NameResolving", &err); 203 if (err) 204 g_clear_error(&err); 205 else 206 main_opts.name_resolv = boolean; 207 208 boolean = g_key_file_get_boolean(config, "General", 209 "DebugKeys", &err); 210 if (err) 211 g_clear_error(&err); 212 else 213 main_opts.debug_keys = boolean; 214 215 main_opts.link_mode = HCI_LM_ACCEPT; 216 217 main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF | 218 HCI_LP_HOLD | HCI_LP_PARK; 219 str = g_key_file_get_string(config, "General", 220 "DefaultLinkPolicy", &err); 221 if (err) 222 g_clear_error(&err); 223 else { 224 DBG("default_link_policy=%s", str); 225 main_opts.link_policy &= strtol(str, NULL, 16); 226 } 227 } 228 229 /* 230 * Device name expansion 231 * %d - device id 232 */ 233 char *expand_name(char *dst, int size, char *str, int dev_id) 234 { 235 register int sp, np, olen; 236 char *opt, buf[10]; 237 238 #ifdef ANDROID_EXPAND_NAME 239 char value[PROPERTY_VALUE_MAX]; 240 #endif 241 242 if (!str || !dst) 243 return NULL; 244 245 sp = np = 0; 246 while (np < size - 1 && str[sp]) { 247 switch (str[sp]) { 248 case '%': 249 opt = NULL; 250 251 switch (str[sp+1]) { 252 case 'd': 253 sprintf(buf, "%d", dev_id); 254 opt = buf; 255 break; 256 257 case 'h': 258 opt = main_opts.host_name; 259 break; 260 261 #ifdef ANDROID_EXPAND_NAME 262 case 'b': 263 property_get("ro.product.brand", value, ""); 264 opt = value; 265 break; 266 267 case 'm': 268 property_get("ro.product.model", value, ""); 269 opt = value; 270 break; 271 272 case 'n': 273 property_get("ro.product.name", value, ""); 274 opt = value; 275 break; 276 #endif 277 278 case '%': 279 dst[np++] = str[sp++]; 280 /* fall through */ 281 default: 282 sp++; 283 continue; 284 } 285 286 if (opt) { 287 /* substitute */ 288 olen = strlen(opt); 289 if (np + olen < size - 1) 290 memcpy(dst + np, opt, olen); 291 np += olen; 292 } 293 sp += 2; 294 continue; 295 296 case '\\': 297 sp++; 298 /* fall through */ 299 default: 300 dst[np++] = str[sp++]; 301 break; 302 } 303 } 304 dst[np] = '\0'; 305 return dst; 306 } 307 308 static void init_defaults(void) 309 { 310 /* Default HCId settings */ 311 memset(&main_opts, 0, sizeof(main_opts)); 312 main_opts.scan = SCAN_PAGE; 313 main_opts.mode = MODE_CONNECTABLE; 314 main_opts.name = g_strdup("BlueZ"); 315 main_opts.discovto = HCID_DEFAULT_DISCOVERABLE_TIMEOUT; 316 main_opts.remember_powered = TRUE; 317 main_opts.reverse_sdp = TRUE; 318 main_opts.name_resolv = TRUE; 319 main_opts.link_mode = HCI_LM_ACCEPT; 320 main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF | 321 HCI_LP_HOLD | HCI_LP_PARK; 322 323 if (gethostname(main_opts.host_name, sizeof(main_opts.host_name) - 1) < 0) 324 strcpy(main_opts.host_name, "noname"); 325 } 326 327 static GMainLoop *event_loop; 328 329 static void sig_term(int sig) 330 { 331 g_main_loop_quit(event_loop); 332 } 333 334 static void sig_debug(int sig) 335 { 336 __btd_toggle_debug(); 337 } 338 339 static gchar *option_debug = NULL; 340 static gboolean option_detach = TRUE; 341 static gboolean option_version = FALSE; 342 static gboolean option_udev = FALSE; 343 344 static guint last_adapter_timeout = 0; 345 346 static gboolean exit_timeout(gpointer data) 347 { 348 g_main_loop_quit(event_loop); 349 last_adapter_timeout = 0; 350 return FALSE; 351 } 352 353 void btd_start_exit_timer(void) 354 { 355 if (option_udev == FALSE) 356 return; 357 358 if (last_adapter_timeout > 0) 359 g_source_remove(last_adapter_timeout); 360 361 last_adapter_timeout = g_timeout_add_seconds(LAST_ADAPTER_EXIT_TIMEOUT, 362 exit_timeout, NULL); 363 } 364 365 void btd_stop_exit_timer(void) 366 { 367 if (last_adapter_timeout == 0) 368 return; 369 370 g_source_remove(last_adapter_timeout); 371 last_adapter_timeout = 0; 372 } 373 374 static gboolean parse_debug(const char *key, const char *value, 375 gpointer user_data, GError **error) 376 { 377 if (value) 378 option_debug = g_strdup(value); 379 else 380 option_debug = g_strdup("*"); 381 382 return TRUE; 383 } 384 385 static GOptionEntry options[] = { 386 { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG, 387 G_OPTION_ARG_CALLBACK, parse_debug, 388 "Specify debug options to enable", "DEBUG" }, 389 { "nodetach", 'n', G_OPTION_FLAG_REVERSE, 390 G_OPTION_ARG_NONE, &option_detach, 391 "Don't run as daemon in background" }, 392 { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version, 393 "Show version information and exit" }, 394 { "udev", 'u', 0, G_OPTION_ARG_NONE, &option_udev, 395 "Run from udev mode of operation" }, 396 { NULL }, 397 }; 398 399 int main(int argc, char *argv[]) 400 { 401 GOptionContext *context; 402 GError *err = NULL; 403 struct sigaction sa; 404 uint16_t mtu = 0; 405 GKeyFile *config; 406 407 #ifdef ANDROID_SET_AID_AND_CAP 408 /* Unfortunately Android's init.rc does not yet support applying 409 * capabilities. So we must do it in-process. */ 410 void *android_set_aid_and_cap(void); 411 android_set_aid_and_cap(); 412 #endif 413 414 init_defaults(); 415 416 #ifdef HAVE_CAPNG 417 /* Drop capabilities */ 418 capng_clear(CAPNG_SELECT_BOTH); 419 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, 420 CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, 421 CAP_NET_RAW, CAP_IPC_LOCK, -1); 422 capng_apply(CAPNG_SELECT_BOTH); 423 #endif 424 425 context = g_option_context_new(NULL); 426 g_option_context_add_main_entries(context, options, NULL); 427 428 if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) { 429 if (err != NULL) { 430 g_printerr("%s\n", err->message); 431 g_error_free(err); 432 } else 433 g_printerr("An unknown error occurred\n"); 434 exit(1); 435 } 436 437 g_option_context_free(context); 438 439 if (option_version == TRUE) { 440 printf("%s\n", VERSION); 441 exit(0); 442 } 443 444 if (option_udev == TRUE) { 445 int err; 446 447 option_detach = TRUE; 448 err = hcid_dbus_init(); 449 if (err < 0) { 450 if (err == -EALREADY) 451 exit(0); 452 exit(1); 453 } 454 } 455 456 if (option_detach == TRUE && option_udev == FALSE) { 457 if (daemon(0, 0)) { 458 perror("Can't start daemon"); 459 exit(1); 460 } 461 } 462 463 umask(0077); 464 465 __btd_log_init(option_debug, option_detach); 466 467 memset(&sa, 0, sizeof(sa)); 468 sa.sa_flags = SA_NOCLDSTOP; 469 sa.sa_handler = sig_term; 470 sigaction(SIGTERM, &sa, NULL); 471 sigaction(SIGINT, &sa, NULL); 472 473 sa.sa_handler = sig_debug; 474 sigaction(SIGUSR2, &sa, NULL); 475 476 sa.sa_handler = SIG_IGN; 477 sigaction(SIGPIPE, &sa, NULL); 478 479 config = load_config(CONFIGDIR "/main.conf"); 480 481 parse_config(config); 482 483 agent_init(); 484 485 if (option_udev == FALSE) { 486 if (hcid_dbus_init() < 0) { 487 error("Unable to get on D-Bus"); 488 exit(1); 489 } 490 } else { 491 if (daemon(0, 0)) { 492 perror("Can't start daemon"); 493 exit(1); 494 } 495 } 496 497 start_sdp_server(mtu, main_opts.deviceid, SDP_SERVER_COMPAT); 498 499 /* Loading plugins has to be done after D-Bus has been setup since 500 * the plugins might wanna expose some paths on the bus. However the 501 * best order of how to init various subsystems of the Bluetooth 502 * daemon needs to be re-worked. */ 503 plugin_init(config); 504 505 event_loop = g_main_loop_new(NULL, FALSE); 506 507 if (adapter_ops_setup() < 0) { 508 error("adapter_ops_setup failed"); 509 exit(1); 510 } 511 512 rfkill_init(); 513 514 DBG("Entering main loop"); 515 516 g_main_loop_run(event_loop); 517 518 hcid_dbus_unregister(); 519 520 hcid_dbus_exit(); 521 522 rfkill_exit(); 523 524 plugin_cleanup(); 525 526 stop_sdp_server(); 527 528 agent_exit(); 529 530 g_main_loop_unref(event_loop); 531 532 if (config) 533 g_key_file_free(config); 534 535 info("Exit"); 536 537 __btd_log_cleanup(); 538 539 return 0; 540 } 541