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

📄 btsrv.c

📁 Affix - Bluetooth Protocol Stack for Linux has been developed at Nokia Research Center in Helsinki
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Affix - Bluetooth Protocol Stack for Linux   Copyright (C) 2001,2002 Nokia Corporation   Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>   Original Author: Imre Deak <ext-imre.deak@nokia.com>   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.,   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*//*    $Id: btsrv.c,v 1.13 2004/02/13 17:16:03 kassatki Exp $   User space daemon for making local services accessable to remote devices      Fixes:   		Imre Deak <ext-imre.deak@nokia.com>		Dmitry Kasatkin <dmitry.kasatkin@nokia.com>*/#include <affix/config.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/errno.h>#include <fcntl.h>#include <unistd.h>#include <syslog.h>#include <signal.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <getopt.h>#include <string.h>#include <sys/mman.h>/* bluetooth stuff */#include <affix/bluetooth.h>#include <affix/btcore.h>#include "btsrv.h"#define DEF_CONFIG_FILE		"/etc/affix/btsrv.conf"service_t	services[MAX_SERVICE_NUM];device_t	devices[MAX_DEVICE_NUM];btdev_list	btdevs;		// device cachechar		*config_file = NULL;char		*config_expr = NULL;int		initdev = 0;int		startsvc = 0;int		managepin = 0;int		managekey = 0;/* local */int 		svcnums;int		devnums;int		efd, mfd;char		confdir[80];int		_daemon = 0;service_info_t profiles[] = {        {		"SerialPort", 		SDP_UUID_SERIAL_PORT, 		0x0000,		SDP_UUID_SERIAL_PORT,		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"DialupNetworking", 		SDP_UUID_DUN, 		SDP_UUID_GENERIC_NETWORKING,		SDP_UUID_DUN, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},	{		"LANAccess", 		SDP_UUID_LAN, 		SDP_UUID_GENERIC_NETWORKING,		SDP_UUID_LAN, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"OBEXFiletransfer", 		SDP_UUID_OBEX_FTP, 		0x0000, 		SDP_UUID_OBEX_FTP, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},	{		"OBEXObjectPush", 		SDP_UUID_OBEX_PUSH, 		0x0000, 		SDP_UUID_OBEX_PUSH, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},	{		"PANPanu", 		SDP_UUID_PANU, 		0x0000, 		SDP_UUID_PANU, 		BTPROTO_L2CAP, 		sdpreg_pan	},	{		"PANGn", 		SDP_UUID_GN, 		0x0000, 		SDP_UUID_GN, 		BTPROTO_L2CAP, 		sdpreg_pan	},	{		"PANNap", 		SDP_UUID_NAP, 		0x0000, 		SDP_UUID_NAP, 		BTPROTO_L2CAP, 		sdpreg_pan	},        {		"FAX", 		SDP_UUID_FAX, 		SDP_UUID_GENERIC_TELEPHONY, 		SDP_UUID_FAX, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"HandsFree", 		SDP_UUID_HANDSFREE, 		SDP_UUID_GENERIC_AUDIO, 		SDP_UUID_HANDSFREE, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"HandsFreeAG", 		SDP_UUID_HANDSFREE_AG, 		SDP_UUID_GENERIC_AUDIO, 		SDP_UUID_HANDSFREE, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"Headset", 		SDP_UUID_HEADSET, 		SDP_UUID_GENERIC_AUDIO, 		SDP_UUID_HEADSET, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},        {		"HeadsetAG", 		SDP_UUID_HEADSET_AG, 		SDP_UUID_GENERIC_AUDIO, 		SDP_UUID_HEADSET, 		BTPROTO_RFCOMM, 		sdpreg_rfcomm	},	{NULL,}};int btsrv_devconf(int fd);void printusage(void){	printf("usage: btsrv "			"[-d] "			"[-v] "			"[--config config_file | -C config_file] "			"[--expression config_expr | -e config_expr] "			"[--initdev | -i] "			"[--noinitdev] "			"[--startsvc | -s] "			"[--nostartsvc] "			"[--managepin | -p] "			"[--nomanagepin] "			"[--managekey | -k]"			"[--nomanagekey] "			"\n"	      );}int start_service(service_t *svc){	struct sockaddr_affix	saddr;	int		err, fd;	socklen_t	len = sizeof(saddr);	svc->srv_fd = -1;	if (!(svc->flags & SRV_FLAG_SOCKET))		goto skip_socket;	if (svc->info->proto == BTPROTO_RFCOMM) {		fd = socket(PF_AFFIX, SOCK_STREAM, BTPROTO_RFCOMM);		if (fd < 0) {			BTERROR("Unable to create RFCOMM socket");			return -1;		}		if (svc->flags & SRV_FLAG_RFCOMM_TTY) {			err = rfcomm_set_type(fd, RFCOMM_TYPE_BTY);			if (err < 0) {				BTERROR("Unable to set RFCOMM interface type to tty");				return -1;			}		}	} else {		fd = socket(PF_AFFIX, SOCK_SEQPACKET, BTPROTO_L2CAP);		if (fd < 0) {			BTERROR("Unable to create L2CAP socket");			return -1;		}	}	if (fcntl(fd, F_SETFL, O_NONBLOCK) != 0) {		BTERROR("Unable to set non blocking mode for RFCOMM socket");		return -1;	}	saddr.family = AF_AFFIX;	saddr.devnum = HCIDEV_ANY;	saddr.port = svc->port;	/* if 0 - dynamically allocated */	saddr.bda = BDADDR_ANY;	err = bind(fd, (struct sockaddr*)&saddr, sizeof(saddr));	if (err < 0) {		BTERROR("Unable to bind address");		return -1;	}	setsockopt(fd, SOL_AFFIX, BTSO_SECURITY, &svc->security, sizeof(int));	err = getsockname(fd, (struct sockaddr*)&saddr, &len);	if (err < 0) {		BTERROR("Unable to get address info");		return -1;	}	BTINFO("Bound service %s to port %d", svc->name, saddr.port);	err = listen(fd, 5);	if (err < 0) {		BTERROR("Unable to listen for connection requests");		return -1;	}	svc->srv_fd = fd;	svc->port = saddr.port;skip_socket:#if defined(CONFIG_AFFIX_SDP)	if (sdpreg_register(svc) < 0 )		return -1;#endif		svc->running = 1;	return 0;}void stop_service(service_t *svc){	if (!svc->running)		return;#if defined(CONFIG_AFFIX_SDP)	sdpreg_unregister(svc);#endif	if (svc->srv_fd != -1)		close(svc->srv_fd);}int start_all_services(void){	int	i, j;	if (!startsvc)		return 0;	for (i = 0; i < svcnums; i++)		if (services[i].active && start_service(&services[i]) < 0)			goto fail;	return 0;fail:	for (j = 0; j < i; j++)		stop_service(&services[i]);	return -1;}void stop_all_services(void){	int	i;	for (i = 0; i < svcnums; i++)		stop_service(&services[i]);}char *btsrv_format_cmd(const char *cmd, int conid, int line, BD_ADDR *bda, int port){        char    *formatted_cmd;	int	i, j, res;         formatted_cmd = (char *)malloc(MAX_CMD_LEN + 1);        if (formatted_cmd == NULL)                return NULL;        i = j = 0;        while (cmd[i]) {                switch (cmd[i]) {                case '%':                        switch(cmd[i + 1])                        {                        case 'a':                                res = snprintf(&formatted_cmd[j], MAX_CMD_LEN - j, "%s", bda2str(bda));                                break;                        case 'l':                                res = snprintf(&formatted_cmd[j],					      MAX_CMD_LEN - j, "%d", line);                                break;			case 'i':                                res = snprintf(&formatted_cmd[j],					      MAX_CMD_LEN - j, "%d", conid);                                break;                        case 'c':                                res = snprintf(&formatted_cmd[j],					       MAX_CMD_LEN - j, "%d", port);                                break;                        case '%':                                formatted_cmd[j] = '%';				res = j < MAX_CMD_LEN ? 1 : -1;                                break;			default:				res = -1;                        }                        i++;	/* skip % sign */                        break;                default:                        formatted_cmd[j] = cmd[i];			res = j < MAX_CMD_LEN ? 1 : -1;                }		if (res == -1) {			free(formatted_cmd);			return NULL;		}		j += res;                i++;        }        formatted_cmd[j] = '\0';        return formatted_cmd;}int execute_cmd(char *cmd, int sock_fd, int port, BD_ADDR *bd_addr, int flags){	char *formatted_cmd;	int  line;	int  fd = -1;	int  conid;	conid = sock_fd;	if (flags & SRV_FLAG_RFCOMM_TTY) {		char dev[10];		line = rfcomm_open_tty(sock_fd, RFCOMM_BTY_ANY);		close(sock_fd);		if (line < 0) {			BTERROR("Unable to bind a socket to virtual port device");			return -1;		}		sprintf(dev, "/dev/bty%d", line);		BTINFO("Socket bound to virtual port device %s", dev);		if (flags & SRV_FLAG_STD) {			fd = open(dev, O_RDWR);			if (fd < 0) {				BTERROR("Unable to open port device %s", dev);				return -1;			}		}	} else {		fd = sock_fd;		line = -1;	}	if (flags & SRV_FLAG_STD) {		BTINFO("Socket multiplexed to stdin/stdout");		if (fd != 0){			close(0);			if (dup2(fd, 0) < 0) {				BTERROR("Unable to duplicate socket descriptor to stdin\n");				return -1;			}		}		if (fd != 1) {			close(1);			if (dup2(fd, 1) < 0) {				BTERROR("Unable to duplicate socket descriptor to stdout\n");				return -1;			}		}		if (fd != 0 && fd != 1)			close(fd);		close(2);		if (open("/dev/null", O_RDWR) != 2) {			BTERROR("Cannot open /dev/null to stderr");			return -1;		}	}	formatted_cmd = btsrv_format_cmd(cmd, conid, line, bd_addr, port);	if (formatted_cmd) {		BTINFO("Execute %s", formatted_cmd);		/*  the following does not return normally  */		execl("/bin/sh", "sh", "-c", formatted_cmd, NULL);		BTERROR("Exec error");		return -1;	}	BTERROR("Parse error in the command line");	return -1;}/* * Event processing block */int event_pin_code_request(struct PIN_Code_Request_Event *evt, int devnum){	int		fd, err, flags;	FILE		*fp;	char		pin[32], cmdline[100];	char		name[248];	if (!managepin)		return 0;	err = hci_get_flags_id(devnum, &flags);	if (err)		return 0;	fd = hci_open_id(devnum);	if (fd < 0)		return fd;#if 0	{		/* get device name first */		INQUIRY_ITEM	dev;		dev.bda = evt->bda;		dev.PS_Repetition_Mode = 0x00;		dev.PS_Mode = 0x00;		dev.Clock_Offset = 0x00;		err = HCI_RemoteNameRequest(fd, &dev, name);		if (err) {			close(fd);			BTERROR("Name request failed");			return err;		}	}#else	name[0] = '\0';#endif	if (!(flags & HCI_SECURITY_PAIRABLE))		goto err;	sprintf(cmdline, "/etc/affix/btsrv-gui pin %s \"%s\"", bda2str(&evt->bda), name);	DBPRT("cmdline: [%s]", cmdline);	fp = popen(cmdline, "r");	if (!fp) {		BTERROR("popen() failed");		goto err;	}	err = fscanf(fp, "%s", pin);	if (err == EOF) {		BTERROR("fscanf() failed");		pclose(fp);		goto err;	}	DBPRT("Got PIN code from pipe: %s, len: %d", pin, strlen(pin));	pclose(fp);	err = HCI_PINCodeRequestReply(fd, &evt->bda, strlen(pin), pin);	if (err) {		BTERROR("unable to set pin code: %d", err);	}	close(fd);	return 0;err:	err = HCI_PINCodeRequestNegativeReply(fd, &evt->bda);	close(fd);	return 0;}int event_link_key_request(struct Link_Key_Request_Event *evt, int devnum){	int		fd, err, ok = 0;	btdev_struct	*btdev;	fd = hci_open_id(devnum);	if (fd < 0)		return fd;	btdev_cache_reload(&btdevs);	btdev = btdev_cache_lookup(&btdevs, &evt->bda);	if (btdev && (btdev->flags & BTDEV_KEY))		ok = 1;	if (ok) {

⌨️ 快捷键说明

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