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

📄 dbus-hci.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2006-2007  Nokia Corporation *  Copyright (C) 2004-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#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sdp.h>#include <glib.h>#include <dbus/dbus.h>#include <gdbus.h>#include "logging.h"#include "textfile.h"#include "hcid.h"#include "manager.h"#include "adapter.h"#include "device.h"#include "error.h"#include "glib-helper.h"#include "dbus-common.h"#include "agent.h"#include "storage.h"static DBusConnection *connection = NULL;const char *class_to_icon(uint32_t class){	switch ((class & 0x1f00) >> 8) {	case 0x01:		return "computer";	case 0x02:		switch ((class & 0xfc) >> 2) {		case 0x01:		case 0x02:		case 0x03:		case 0x05:			return "phone";		case 0x04:			return "modem";		}		break;	case 0x03:		return "network-wireless";	case 0x04:		switch ((class & 0xfc) >> 2) {		case 0x01:		case 0x02:			return "audio-card";	/* Headset */		case 0x06:			return "audio-card";	/* Headphone */		}		break;	case 0x05:		switch ((class & 0xc0) >> 6) {		case 0x00:			switch ((class & 0x1e) >> 2) {			case 0x01:			case 0x02:				return "input-gaming";			}			break;		case 0x01:			return "input-keyboard";		case 0x02:			switch ((class & 0x1e) >> 2) {			case 0x05:				return "input-tablet";			default:				return "input-mouse";			}		}		break;	case 0x06:		if (class & 0x80)			return "printer";		if (class & 0x20)			return "camera-photo";		break;	}	return NULL;}DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status){	switch (status) {	case 0x00: /* success */		return dbus_message_new_method_return(msg);	case 0x04: /* page timeout */	case 0x08: /* connection timeout */	case 0x10: /* connection accept timeout */	case 0x22: /* LMP response timeout */	case 0x28: /* instant passed - is this a timeout? */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationTimeout",					"Authentication Timeout");	case 0x17: /* too frequent pairing attempts */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".RepeatedAttempts",					"Repeated Attempts");	case 0x06:	case 0x18: /* pairing not allowed (e.g. gw rejected attempt) */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationRejected",					"Authentication Rejected");	case 0x07: /* memory capacity */	case 0x09: /* connection limit */	case 0x0a: /* synchronous connection limit */	case 0x0d: /* limited resources */	case 0x13: /* user ended the connection */	case 0x14: /* terminated due to low resources */		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationCanceled",					"Authentication Canceled");	case 0x05: /* authentication failure */	case 0x0E: /* rejected due to security reasons - is this auth failure? */	case 0x25: /* encryption mode not acceptable - is this auth failure? */	case 0x26: /* link key cannot be changed - is this auth failure? */	case 0x29: /* pairing with unit key unsupported - is this auth failure? */	case 0x2f: /* insufficient security - is this auth failure? */	default:		return dbus_message_new_error(msg,					ERROR_INTERFACE ".AuthenticationFailed",					"Authentication Failed");	}}/***************************************************************** * *  Section reserved to HCI commands confirmation handling and low *  level events(eg: device attached/dettached. * *****************************************************************/static void pincode_cb(struct agent *agent, DBusError *err, const char *pincode,			struct btd_device *device){	struct btd_adapter *adapter = device_get_adapter(device);	pin_code_reply_cp pr;	bdaddr_t sba, dba;	size_t len;	int dev;	struct pending_auth_info *auth;	uint16_t dev_id = adapter_get_dev_id(adapter);	struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);	/* No need to reply anything if the authentication already failed */	if (bonding && bonding->hci_status)		return;	dev = hci_open_dev(dev_id);	if (dev < 0) {		error("hci_open_dev(%d): %s (%d)", dev_id,				strerror(errno), errno);		return;	}	adapter_get_address(adapter, &sba);	device_get_address(device, &dba);	auth = adapter_find_auth_request(adapter, &dba);	if (err) {		hci_send_cmd(dev, OGF_LINK_CTL,				OCF_PIN_CODE_NEG_REPLY, 6, &dba);		goto done;	}	len = strlen(pincode);	set_pin_length(&sba, len);	memset(&pr, 0, sizeof(pr));	bacpy(&pr.bdaddr, &dba);	memcpy(pr.pin_code, pincode, len);	pr.pin_len = len;	hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr);done:	if (auth) {		auth->replied = TRUE;		auth->agent = NULL;	}	hci_close_dev(dev);}int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci){	char addr[18];	struct btd_adapter *adapter;	struct btd_device *device;	struct agent *agent = NULL;	int ret;	adapter = manager_find_adapter(sba);	if (!adapter) {		error("No matching adapter found");		return -1;	}	if (!adapter_pairing_initiator(adapter, &ci->bdaddr) &&			!adapter_is_pairable(adapter))		return -EPERM;	ba2str(&ci->bdaddr, addr);	device = adapter_find_device(adapter, addr);	if (device)		agent = device_get_agent(device);	if (!agent)		agent = adapter_get_agent(adapter);	if (!agent)		return -EPERM;	if (!device) {		device = adapter_create_device(connection, adapter, addr);		if (!device)			return -ENODEV;	}	ret = agent_request_pincode(agent, device,					(agent_pincode_cb) pincode_cb,					device);	if (ret == 0) {		struct pending_auth_info *auth;		auth = adapter_new_auth_request(adapter, &ci->bdaddr,						AUTH_TYPE_PINCODE);		auth->agent = agent;	}	return ret;}static void confirm_cb(struct agent *agent, DBusError *err, void *user_data){	struct btd_device *device = user_data;	struct btd_adapter *adapter = device_get_adapter(device);	user_confirm_reply_cp cp;	int dd;	struct pending_auth_info *auth;	uint16_t dev_id = adapter_get_dev_id(adapter);	struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);	/* No need to reply anything if the authentication already failed */	if (bonding && bonding->hci_status)		return;	dd = hci_open_dev(dev_id);	if (dd < 0) {		error("Unable to open hci%d", dev_id);		return;	}	memset(&cp, 0, sizeof(cp));	device_get_address(device, &cp.bdaddr);	auth = adapter_find_auth_request(adapter, &cp.bdaddr);	if (err)		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,					USER_CONFIRM_REPLY_CP_SIZE, &cp);	else		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY,					USER_CONFIRM_REPLY_CP_SIZE, &cp);	if (auth) {		auth->replied = TRUE;		auth->agent = FALSE;	}	hci_close_dev(dd);}static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,			void *user_data){	struct btd_device *device = user_data;	struct btd_adapter *adapter = device_get_adapter(device);	user_passkey_reply_cp cp;	bdaddr_t dba;	int dd;	struct pending_auth_info *auth;	uint16_t dev_id = adapter_get_dev_id(adapter);	struct bonding_request_info *bonding = adapter_get_bonding_info(adapter);	/* No need to reply anything if the authentication already failed */	if (bonding && bonding->hci_status)		return;	dd = hci_open_dev(dev_id);	if (dd < 0) {		error("Unable to open hci%d", dev_id);		return;	}	device_get_address(device, &dba);	memset(&cp, 0, sizeof(cp));	bacpy(&cp.bdaddr, &dba);	cp.passkey = passkey;	auth = adapter_find_auth_request(adapter, &dba);	if (err)		hci_send_cmd(dd, OGF_LINK_CTL,				OCF_USER_PASSKEY_NEG_REPLY, 6, &dba);	else		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_REPLY,					USER_PASSKEY_REPLY_CP_SIZE, &cp);	if (auth) {		auth->replied = TRUE;		auth->agent = NULL;	}	hci_close_dev(dd);}static int get_auth_requirements(bdaddr_t *local, bdaddr_t *remote,							uint8_t *auth){	struct hci_auth_info_req req;	char addr[18];	int err, dd, dev_id;	ba2str(local, addr);	dev_id = hci_devid(addr);	if (dev_id < 0)		return dev_id;	dd = hci_open_dev(dev_id);	if (dd < 0)		return dd;	memset(&req, 0, sizeof(req));	bacpy(&req.bdaddr, remote);	err = ioctl(dd, HCIGETAUTHINFO, (unsigned long) &req);	if (err < 0) {		debug("HCIGETAUTHINFO failed: %s (%d)",					strerror(errno), errno);		hci_close_dev(dd);		return err;	}	hci_close_dev(dd);	if (auth)		*auth = req.type;	return 0;}int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey){	struct btd_adapter *adapter;	struct btd_device *device;	struct agent *agent;	char addr[18];	uint8_t type;	struct pending_auth_info *auth;	uint16_t dev_id;	adapter = manager_find_adapter(sba);	if (!adapter) {		error("No matching adapter found");		return -1;	}	dev_id = adapter_get_dev_id(adapter);	if (get_auth_requirements(sba, dba, &type) < 0) {		int dd;		dd = hci_open_dev(dev_id);		if (dd < 0) {			error("Unable to open hci%d", dev_id);			return -1;		}		hci_send_cmd(dd, OGF_LINK_CTL,					OCF_USER_CONFIRM_NEG_REPLY, 6, dba);		hci_close_dev(dd);		return 0;	}	ba2str(dba, addr);	device = adapter_get_device(connection, adapter, addr);	if (!device) {		error("Device creation failed");		return -1;	}	/* If no MITM protection required, auto-accept */	if (!(device_get_auth(device) & 0x01) && !(type & 0x01)) {		int dd;		dd = hci_open_dev(dev_id);		if (dd < 0) {			error("Unable to open hci%d", dev_id);			return -1;		}		hci_send_cmd(dd, OGF_LINK_CTL,					OCF_USER_CONFIRM_REPLY, 6, dba);		hci_close_dev(dd);		auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM);		auth->replied = TRUE;		return 0;	}	agent = device_get_agent(device);	if (!agent)		agent = adapter_get_agent(adapter);	if (!agent) {		error("No agent available for user confirm request");		return -1;	}	if (agent_request_confirmation(agent, device, passkey,						confirm_cb, device) < 0) {		error("Requesting passkey failed");		return -1;	}	auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM);	auth->agent = agent;	return 0;}int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba){	struct btd_adapter *adapter;	struct btd_device *device;	struct agent *agent = NULL;	char addr[18];	struct pending_auth_info *auth;	adapter = manager_find_adapter(sba);	if (!adapter) {		error("No matching adapter found");		return -1;	}	ba2str(dba, addr);	device = adapter_get_device(connection, adapter, addr);	if (device)		agent = device_get_agent(device);	if (!agent)		agent = adapter_get_agent(adapter);	if (!agent) {		error("No agent available for user confirm request");		return -1;	}	if (agent_request_passkey(agent, device, passkey_cb, device) < 0) {		error("Requesting passkey failed");		return -1;	}	auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_PASSKEY);	auth->agent = agent;	return 0;}int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey){	struct btd_adapter *adapter;	struct btd_device *device;	struct agent *agent = NULL;	char addr[18];	struct pending_auth_info *auth;	adapter = manager_find_adapter(sba);	if (!adapter) {		error("No matching adapter found");		return -1;	}	ba2str(dba, addr);	device = adapter_get_device(connection, adapter, addr);	if (device)		agent = device_get_agent(device);	if (!agent)		agent = adapter_get_agent(adapter);	if (!agent) {		error("No agent available for user confirm request");		return -1;	}	if (agent_display_passkey(agent, device, passkey) < 0) {		error("Displaying passkey failed");		return -1;	}	auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_NOTIFY);	auth->agent = agent;	return 0;}void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,					uint8_t status){	struct btd_adapter *adapter;	char peer_addr[18];	DBusMessage *reply;

⌨️ 快捷键说明

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