diff options
Diffstat (limited to 'dund/main.c')
-rw-r--r-- | dund/main.c | 635 |
1 files changed, 0 insertions, 635 deletions
diff --git a/dund/main.c b/dund/main.c deleted file mode 100644 index b14adce0..00000000 --- a/dund/main.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> - * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org> - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <signal.h> -#include <getopt.h> - -#include <sys/socket.h> - -#include <bluetooth/bluetooth.h> -#include <bluetooth/hci.h> -#include <bluetooth/hci_lib.h> -#include <bluetooth/rfcomm.h> - -#include "dund.h" -#include "lib.h" - -volatile sig_atomic_t __io_canceled; - -/* MS dialup networking support (i.e. CLIENT / CLIENTSERVER thing) */ -static int msdun = 0; - -static char *pppd = "/usr/sbin/pppd"; -static char *pppd_opts[DUN_MAX_PPP_OPTS] = - { - /* First 3 are reserved */ - "", "", "", - "noauth", - "noipdefault", - NULL - }; - -static int detach = 1; -static int persist; -static int use_sdp = 1; -static int auth; -static int encrypt; -static int secure; -static int master; -static int type = LANACCESS; -static int search_duration = 10; -static uint use_cache; - -static int channel; - -static struct { - uint valid; - char dst[40]; - bdaddr_t bdaddr; - int channel; -} cache; - -static bdaddr_t src_addr = *BDADDR_ANY; -static int src_dev = -1; - -volatile int terminate; - -enum { - NONE, - SHOW, - LISTEN, - CONNECT, - KILL -} modes; - -static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter); - -static int do_listen(void) -{ - struct sockaddr_rc sa; - int sk, lm; - - if (type == MROUTER) { - if (!cache.valid) - return -1; - - if (create_connection(cache.dst, &cache.bdaddr, type) < 0) { - syslog(LOG_ERR, "Cannot connect to mRouter device. %s(%d)", - strerror(errno), errno); - return -1; - } - } - - if (!channel) - channel = DUN_DEFAULT_CHANNEL; - - if (use_sdp) - dun_sdp_register(&src_addr, channel, type); - - if (type == MROUTER) - syslog(LOG_INFO, "Waiting for mRouter callback on channel %d", channel); - - /* Create RFCOMM socket */ - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) { - syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)", - strerror(errno), errno); - return -1; - } - - sa.rc_family = AF_BLUETOOTH; - sa.rc_channel = channel; - sa.rc_bdaddr = src_addr; - - if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) { - syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno); - return -1; - } - - /* Set link mode */ - lm = 0; - if (master) - lm |= RFCOMM_LM_MASTER; - if (auth) - lm |= RFCOMM_LM_AUTH; - if (encrypt) - lm |= RFCOMM_LM_ENCRYPT; - if (secure) - lm |= RFCOMM_LM_SECURE; - - if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { - syslog(LOG_ERR, "Failed to set link mode. %s(%d)", strerror(errno), errno); - return -1; - } - - listen(sk, 10); - - while (!terminate) { - socklen_t alen = sizeof(sa); - int nsk; - char ba[40]; - char ch[10]; - - nsk = accept(sk, (struct sockaddr *) &sa, &alen); - if (nsk < 0) { - syslog(LOG_ERR, "Accept failed. %s(%d)", strerror(errno), errno); - continue; - } - - switch (fork()) { - case 0: - break; - case -1: - syslog(LOG_ERR, "Fork failed. %s(%d)", strerror(errno), errno); - default: - close(nsk); - if (type == MROUTER) { - close(sk); - terminate = 1; - } - continue; - } - - close(sk); - - if (msdun && ms_dun(nsk, 1, msdun) < 0) { - syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno); - exit(0); - } - - ba2str(&sa.rc_bdaddr, ba); - sprintf(ch, "%d", channel); - - /* Setup environment */ - setenv("DUN_BDADDR", ba, 1); - setenv("DUN_CHANNEL", ch, 1); - - if (!dun_open_connection(nsk, pppd, pppd_opts, 0)) - syslog(LOG_INFO, "New connection from %s", ba); - - close(nsk); - exit(0); - } - - if (use_sdp) - dun_sdp_unregister(); - return 0; -} - -/* Connect and initiate RFCOMM session - * Returns: - * -1 - critical error (exit persist mode) - * 1 - non critical error - * 0 - success - */ -static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter) -{ - struct sockaddr_rc sa; - int sk, err = 0, ch; - - if (use_cache && cache.valid && cache.channel) { - /* Use cached channel */ - ch = cache.channel; - - } else if (!channel) { - syslog(LOG_INFO, "Searching for %s on %s", mrouter ? "SP" : "LAP", dst); - - if (dun_sdp_search(&src_addr, bdaddr, &ch, mrouter) <= 0) - return 0; - } else - ch = channel; - - syslog(LOG_INFO, "Connecting to %s channel %d", dst, ch); - - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) { - syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)", - strerror(errno), errno); - return -1; - } - - sa.rc_family = AF_BLUETOOTH; - sa.rc_channel = 0; - sa.rc_bdaddr = src_addr; - - if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) - syslog(LOG_ERR, "Bind failed. %s(%d)", - strerror(errno), errno); - - sa.rc_channel = ch; - sa.rc_bdaddr = *bdaddr; - - if (!connect(sk, (struct sockaddr *) &sa, sizeof(sa)) ) { - if (mrouter) { - sleep(1); - close(sk); - return 0; - } - - syslog(LOG_INFO, "Connection established"); - - if (msdun && ms_dun(sk, 0, msdun) < 0) { - syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno); - err = 1; - goto out; - } - - if (!dun_open_connection(sk, pppd, pppd_opts, (persist > 0))) - err = 0; - else - err = 1; - } else { - syslog(LOG_ERR, "Connect to %s failed. %s(%d)", - dst, strerror(errno), errno); - err = 1; - } - -out: - if (use_cache) { - if (!err) { - /* Succesesful connection, validate cache */ - strcpy(cache.dst, dst); - bacpy(&cache.bdaddr, bdaddr); - cache.channel = ch; - cache.valid = use_cache; - } else { - cache.channel = 0; - cache.valid--; - } - } - - close(sk); - return err; -} - -/* Search and connect - * Returns: - * -1 - critical error (exit persist mode) - * 1 - non critical error - * 0 - success - */ -static int do_connect(void) -{ - inquiry_info *ii; - int reconnect = 0; - int i, n, r = 0; - - do { - if (reconnect) - sleep(persist); - reconnect = 1; - - if (cache.valid) { - /* Use cached bdaddr */ - r = create_connection(cache.dst, &cache.bdaddr, 0); - if (r < 0) { - terminate = 1; - break; - } - continue; - } - - syslog(LOG_INFO, "Inquiring"); - - /* FIXME: Should we use non general LAP here ? */ - - ii = NULL; - n = hci_inquiry(src_dev, search_duration, 0, NULL, &ii, 0); - if (n < 0) { - syslog(LOG_ERR, "Inquiry failed. %s(%d)", strerror(errno), errno); - continue; - } - - for (i = 0; i < n; i++) { - char dst[40]; - ba2str(&ii[i].bdaddr, dst); - - r = create_connection(dst, &ii[i].bdaddr, 0); - if (r < 0) { - terminate = 1; - break; - } - } - bt_free(ii); - } while (!terminate && persist); - - return r; -} - -static void do_show(void) -{ - dun_show_connections(); -} - -static void do_kill(char *dst) -{ - if (dst) { - bdaddr_t ba; - str2ba(dst, &ba); - dun_kill_connection((void *) &ba); - } else - dun_kill_all_connections(); -} - -void sig_hup(int sig) -{ - return; -} - -void sig_term(int sig) -{ - io_cancel(); - terminate = 1; -} - -static struct option main_lopts[] = { - { "help", 0, 0, 'h' }, - { "listen", 0, 0, 's' }, - { "connect", 1, 0, 'c' }, - { "search", 2, 0, 'Q' }, - { "kill", 1, 0, 'k' }, - { "killall", 0, 0, 'K' }, - { "channel", 1, 0, 'P' }, - { "device", 1, 0, 'i' }, - { "nosdp", 0, 0, 'D' }, - { "list", 0, 0, 'l' }, - { "show", 0, 0, 'l' }, - { "nodetach", 0, 0, 'n' }, - { "persist", 2, 0, 'p' }, - { "auth", 0, 0, 'A' }, - { "encrypt", 0, 0, 'E' }, - { "secure", 0, 0, 'S' }, - { "master", 0, 0, 'M' }, - { "cache", 0, 0, 'C' }, - { "pppd", 1, 0, 'd' }, - { "msdun", 2, 0, 'X' }, - { "activesync", 0, 0, 'a' }, - { "mrouter", 1, 0, 'm' }, - { "dialup", 0, 0, 'u' }, - { 0, 0, 0, 0 } -}; - -static char main_sopts[] = "hsc:k:Kr:i:lnp::DQ::AESMP:C::P:Xam:u"; - -static char main_help[] = - "Bluetooth LAP (LAN Access over PPP) daemon version " VERSION " \n" - "Usage:\n" - "\tdund <options> [pppd options]\n" - "Options:\n" - "\t--show --list -l Show active LAP connections\n" - "\t--listen -s Listen for LAP connections\n" - "\t--dialup -u Pretend to be a dialup/telephone\n" - "\t--connect -c <bdaddr> Create LAP connection\n" - "\t--mrouter -m <bdaddr> Create mRouter connection\n" - "\t--search -Q[duration] Search and connect\n" - "\t--kill -k <bdaddr> Kill LAP connection\n" - "\t--killall -K Kill all LAP connections\n" - "\t--channel -P <channel> RFCOMM channel\n" - "\t--device -i <bdaddr> Source bdaddr\n" - "\t--nosdp -D Disable SDP\n" - "\t--auth -A Enable authentication\n" - "\t--encrypt -E Enable encryption\n" - "\t--secure -S Secure connection\n" - "\t--master -M Become the master of a piconet\n" - "\t--nodetach -n Do not become a daemon\n" - "\t--persist -p[interval] Persist mode\n" - "\t--pppd -d <pppd> Location of the PPP daemon (pppd)\n" - "\t--msdun -X[timeo] Enable Microsoft dialup networking support\n" - "\t--activesync -a Enable Microsoft ActiveSync networking\n" - "\t--cache -C[valid] Enable address cache\n"; - -int main(int argc, char *argv[]) -{ - char *dst = NULL, *src = NULL; - struct sigaction sa; - int mode = NONE; - int opt; - - while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) { - switch(opt) { - case 'l': - mode = SHOW; - detach = 0; - break; - - case 's': - mode = LISTEN; - type = LANACCESS; - break; - - case 'c': - mode = CONNECT; - dst = strdup(optarg); - break; - - case 'Q': - mode = CONNECT; - dst = NULL; - if (optarg) - search_duration = atoi(optarg); - break; - - case 'k': - mode = KILL; - detach = 0; - dst = strdup(optarg); - break; - - case 'K': - mode = KILL; - detach = 0; - dst = NULL; - break; - - case 'P': - channel = atoi(optarg); - break; - - case 'i': - src = strdup(optarg); - break; - - case 'D': - use_sdp = 0; - break; - - case 'A': - auth = 1; - break; - - case 'E': - encrypt = 1; - break; - - case 'S': - secure = 1; - break; - - case 'M': - master = 1; - break; - - case 'n': - detach = 0; - break; - - case 'p': - if (optarg) - persist = atoi(optarg); - else - persist = 5; - break; - - case 'C': - if (optarg) - use_cache = atoi(optarg); - else - use_cache = 2; - break; - - case 'd': - pppd = strdup(optarg); - break; - - case 'X': - if (optarg) - msdun = atoi(optarg); - else - msdun = 10; - break; - - case 'a': - msdun = 10; - type = ACTIVESYNC; - break; - - case 'm': - mode = LISTEN; - dst = strdup(optarg); - type = MROUTER; - break; - - case 'u': - mode = LISTEN; - type = DIALUP; - break; - - case 'h': - default: - printf(main_help); - exit(0); - } - } - - argc -= optind; - argv += optind; - - /* The rest is pppd options */ - if (argc > 0) { - for (opt = 3; argc && opt < DUN_MAX_PPP_OPTS; argc--, opt++) - pppd_opts[opt] = *argv++; - pppd_opts[opt] = NULL; - } - - io_init(); - - if (dun_init()) - return -1; - - /* Check non daemon modes first */ - switch (mode) { - case SHOW: - do_show(); - return 0; - - case KILL: - do_kill(dst); - return 0; - - case NONE: - printf(main_help); - return 0; - } - - /* Initialize signals */ - memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_NOCLDSTOP; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - - sa.sa_handler = sig_term; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - - sa.sa_handler = sig_hup; - sigaction(SIGHUP, &sa, NULL); - - if (detach && daemon(0, 0)) { - perror("Can't start daemon"); - exit(1); - } - - openlog("dund", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); - syslog(LOG_INFO, "Bluetooth DUN daemon version %s", VERSION); - - if (src) { - src_dev = hci_devid(src); - if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) { - syslog(LOG_ERR, "Invalid source. %s(%d)", strerror(errno), errno); - return -1; - } - } - - if (dst) { - strncpy(cache.dst, dst, sizeof(cache.dst) - 1); - str2ba(dst, &cache.bdaddr); - - /* Disable cache invalidation */ - use_cache = cache.valid = ~0; - } - - switch (mode) { - case CONNECT: - do_connect(); - break; - - case LISTEN: - do_listen(); - break; - } - - return 0; -} |