📄 adapter.c
字号:
} sk = g_io_channel_unix_get_fd(io); len = sizeof(ret); if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { error("Can't get socket error: %s (%d)", strerror(errno), errno); error_failed_errno(adapter->bonding->conn, adapter->bonding->rq, errno); goto failed; } if (ret != 0) { if (adapter->bonding->auth_active) reply_authentication_failure(adapter->bonding); else error_connection_attempt_failed(adapter->bonding->conn, adapter->bonding->rq, ret); goto failed; } len = sizeof(cinfo); if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) { error("Can't get connection info: %s (%d)", strerror(errno), errno); error_failed_errno(adapter->bonding->conn, adapter->bonding->rq, errno); goto failed; } dd = hci_open_dev(adapter->dev_id); if (dd < 0) { error_no_such_adapter(adapter->bonding->conn, adapter->bonding->rq); goto failed; } memset(&rp, 0, sizeof(rp)); memset(&cp, 0, sizeof(cp)); cp.handle = htobs(cinfo.hci_handle); memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_AUTH_REQUESTED; rq.cparam = &cp; rq.clen = AUTH_REQUESTED_CP_SIZE; rq.rparam = &rp; rq.rlen = EVT_CMD_STATUS_SIZE; rq.event = EVT_CMD_STATUS; if (hci_send_req(dd, &rq, 500) < 0) { error("Unable to send HCI request: %s (%d)", strerror(errno), errno); error_failed_errno(adapter->bonding->conn, adapter->bonding->rq, errno); hci_close_dev(dd); goto failed; } if (rp.status) { error("HCI_Authentication_Requested failed with status 0x%02x", rp.status); error_failed_errno(adapter->bonding->conn, adapter->bonding->rq, bt_error(rp.status)); hci_close_dev(dd); goto failed; } hci_close_dev(dd); adapter->bonding->auth_active = 1; adapter->bonding->io_id = g_io_add_watch(io, G_IO_NVAL | G_IO_HUP | G_IO_ERR, (GIOFunc) create_bonding_conn_complete, adapter); return FALSE;failed: g_io_channel_close(io);cleanup: name_listener_remove(adapter->bonding->conn, dbus_message_get_sender(adapter->bonding->rq), (name_cb_t) create_bond_req_exit, adapter); bonding_request_free(adapter->bonding); adapter->bonding = NULL; return FALSE;}static DBusHandlerResult adapter_create_bonding(DBusConnection *conn, DBusMessage *msg, void *data){ char filename[PATH_MAX + 1]; char *str, *peer_addr = NULL; struct adapter *adapter = data; bdaddr_t peer_bdaddr; int sk; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg, NULL); str2ba(peer_addr, &peer_bdaddr); /* check if there is a pending discover: requested by D-Bus/non clients */ if (adapter->discov_active || (adapter->pdiscov_active && !adapter->pinq_idle)) return error_discover_in_progress(conn, msg); pending_remote_name_cancel(adapter); if (adapter->bonding) return error_bonding_in_progress(conn, msg); if (g_slist_find_custom(adapter->pin_reqs, &peer_bdaddr, pin_req_cmp)) return error_bonding_in_progress(conn, msg); /* check if a link key already exists */ create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "linkkeys"); str = textfile_caseget(filename, peer_addr); if (str) { free(str); return error_bonding_already_exists(conn, msg); } sk = l2raw_connect(adapter->address, &peer_bdaddr); if (sk < 0) return error_connection_attempt_failed(conn, msg, 0); adapter->bonding = bonding_request_new(&peer_bdaddr, conn, msg); if (!adapter->bonding) { close(sk); return DBUS_HANDLER_RESULT_NEED_MEMORY; } adapter->bonding->io = g_io_channel_unix_new(sk); adapter->bonding->io_id = g_io_add_watch(adapter->bonding->io, G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR, (GIOFunc) create_bonding_conn_complete, adapter); name_listener_add(conn, dbus_message_get_sender(msg), (name_cb_t) create_bond_req_exit, adapter); return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult adapter_cancel_bonding(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; bdaddr_t peer_bdaddr; const char *peer_addr; GSList *l; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(peer_addr) < 0) return error_invalid_arguments(conn, msg, NULL); str2ba(peer_addr, &peer_bdaddr); if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, &peer_bdaddr)) return error_bonding_not_in_progress(conn, msg); if (strcmp(dbus_message_get_sender(adapter->bonding->rq), dbus_message_get_sender(msg))) return error_not_authorized(conn, msg); adapter->bonding->cancel = 1; l = g_slist_find_custom(adapter->pin_reqs, &peer_bdaddr, pin_req_cmp); if (l) { struct pending_pin_info *pin_req = l->data; if (pin_req->replied) { /* * If disconnect can't be applied and the PIN code * request was already replied it doesn't make sense * cancel the remote passkey: return not authorized. */ g_io_channel_close(adapter->bonding->io); return error_not_authorized(conn, msg); } else { int dd = hci_open_dev(adapter->dev_id); if (dd < 0) { error("Can't open hci%d: %s (%d)", adapter->dev_id, strerror(errno), errno); return DBUS_HANDLER_RESULT_HANDLED; } hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &peer_bdaddr); hci_close_dev(dd); } adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, pin_req); g_free(pin_req); } g_io_channel_close(adapter->bonding->io); reply = dbus_message_new_method_return(msg); send_message_and_unref(conn, reply); return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult adapter_remove_bonding(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; GSList *l; DBusMessage *reply; char filename[PATH_MAX + 1]; char *addr_ptr, *str; bdaddr_t bdaddr; int dd; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_ptr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg, NULL); dd = hci_open_dev(adapter->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "linkkeys"); /* textfile_del doesn't return an error when the key is not found */ str = textfile_caseget(filename, addr_ptr); if (!str) { hci_close_dev(dd); return error_bonding_does_not_exist(conn, msg); } free(str); /* Delete the link key from storage */ if (textfile_casedel(filename, addr_ptr) < 0) { int err = errno; hci_close_dev(dd); return error_failed_errno(conn, msg, err); } str2ba(addr_ptr, &bdaddr); /* Delete the link key from the Bluetooth chip */ hci_delete_stored_link_key(dd, &bdaddr, 0, 1000); /* find the connection */ l = g_slist_find_custom(adapter->active_conn, &bdaddr, active_conn_find_by_bdaddr); if (l) { struct active_conn_info *con = l->data; /* Send the HCI disconnect command */ if (hci_disconnect(dd, htobs(con->handle), HCI_OE_USER_ENDED_CONNECTION, 500) < 0) { int err = errno; error("Disconnect failed"); hci_close_dev(dd); return error_failed_errno(conn, msg, err); } } dbus_connection_emit_signal(conn, dbus_message_get_path(msg), ADAPTER_INTERFACE, "BondingRemoved", DBUS_TYPE_STRING, &addr_ptr, DBUS_TYPE_INVALID); reply = dbus_message_new_method_return(msg); hci_close_dev(dd); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_has_bonding(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; char filename[PATH_MAX + 1]; char *addr_ptr, *str; dbus_bool_t result; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_ptr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg, NULL); create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "linkkeys"); str = textfile_caseget(filename, addr_ptr); if (str) { result = TRUE; free(str); } else result = FALSE; reply = dbus_message_new_method_return(msg); dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static void list_bondings_do_append(char *key, char *value, void *data){ DBusMessageIter *iter = data; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);}static DBusHandlerResult adapter_list_bondings(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessageIter iter; DBusMessageIter array_iter; DBusMessage *reply; char filename[PATH_MAX + 1]; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "linkkeys"); reply = dbus_message_new_method_return(msg); dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array_iter); textfile_foreach(filename, list_bondings_do_append, &array_iter); dbus_message_iter_close_container(&iter, &array_iter); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_pin_code_length(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; bdaddr_t local, peer; char *addr_ptr; uint8_t length; int len; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_ptr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg, NULL); str2ba(adapter->address, &local); str2ba(addr_ptr, &peer); len = read_pin_length(&local, &peer); if (len < 0) return error_record_does_not_exist(conn, msg); reply = dbus_message_new_method_return(msg); length = len; dbus_message_append_args(reply, DBUS_TYPE_BYTE, &length, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_encryption_key_size(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; bdaddr_t bdaddr; char *addr_ptr; uint8_t size; int val; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr_ptr, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg, NULL); if (check_address(addr_ptr) < 0) return error_invalid_arguments(conn, msg, NULL); str2ba(addr_ptr, &bdaddr); val = get_encryption_key_size(adapter->dev_id, &bdaddr); if (val < 0) return error_failed_errno(conn, msg, -val); reply = dbus_message_new_method_return(msg); size = val; dbus_message_append_args(reply, DBUS_TYPE_BYTE, &size, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_start_periodic(DBusConnection *conn, DBusMessage *msg, void *data){ DBusMessage *reply; periodic_inquiry_cp cp; struct hci_request rq; struct adapter *adapter = data; uint8_t lap[3] = { 0x33, 0x8b, 0x9e }; uint8_t status; int dd; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return error_invalid_arguments(conn, msg, NULL); if (adapter->discov_active || adapter->pdiscov_active) return error_discover_in_progress(conn, msg); pending_remote_name_cancel(adapter); dd = hci_open_dev(adapter->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); memset(&cp, 0, sizeof(cp)); memcpy(&cp.lap, lap, 3); cp.max_period = htobs(24); cp.min_period = htobs(16); cp.length = 0x08; cp.num_rsp = 0x00; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_PERIODIC_INQUIRY; rq.cparam = &cp; rq.clen = PERIODIC_INQUIRY_CP_SIZE; rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, 1000) < 0) { int err = errno; error("Unable to start periodic inquiry: %s (%d)", strerror(errno), errno); hci_close_dev(dd); return error_failed_errno(conn, msg, err); } if (status) { error("HCI_Periodic_Inquiry_Mode failed with status 0x%02x", status); hci_close_dev(dd); return error_failed_errno(conn, msg, bt_error(status)); } adapter->pdiscov_requestor = g_strdup(dbus_message_get_sender(msg)); if (adapter->pdiscov_resolve_names) adapter->discov_type = PERIODIC_INQUIRY | RESOLVE_NAME; else adapter->discov_type = PERIODIC_INQUIRY; reply = dbus_message_new_method_return(msg); hci_close_dev(dd); /* track the request owner
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -