⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 Bluezan implementation of the Bluetooth&#8482 wireless standards specifications for Linux. The code
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com> *  Copyright (C) 2002-2004  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 version 2 as *  published by the Free Software Foundation; * *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. *  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY *  CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *  ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,  *  COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS  *  SOFTWARE IS DISCLAIMED. * * *  $Id: main.c,v 1.8 2005/05/07 20:40:02 holtmann Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <syslog.h>#include <signal.h>#include <errno.h>#include <getopt.h>#include <sys/socket.h>#include <sys/poll.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  mrouter;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 (mrouter) {		if (!cache.valid)			return -1;		if (create_connection(cache.dst, &cache.bdaddr, mrouter) < 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(channel, mrouter);	if (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) {		int  alen = sizeof(sa), 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 (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;			}		}		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' },	{ "mrouter",  1, 0, 'm' },	{ 0, 0, 0, 0 }};static char main_sopts[] = "hsc:k:Kr:i:lnp::DQ::AESMP:C::P:X";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--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--cache -C[valid]         Enable addess 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;			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 'm':			mode = LISTEN;			dst  = strdup(optarg);			mrouter = 1;			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) {		int fd;		if (fork()) exit(0);		/* Direct stdin,stdout,stderr to '/dev/null' */		fd = open("/dev/null", O_RDWR);		dup2(fd, 0); dup2(fd, 1); dup2(fd, 2);		close(fd);				setsid();		chdir("/");	}	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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -