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; -}  | 
