📄 hci.c
字号:
/* * * Bluetooth packet analyzer - HCI parser * * Copyright (C) 2000-2002 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2003-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Id: hci.c,v 1.46 2005/05/08 13:05:42 holtmann Exp $ */#include <stdio.h>#include <errno.h>#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include "parser.h"#ifndef OCF_READ_SCAN_ENABLE#define OCF_READ_SCAN_ENABLE 0x0019#endifstatic uint16_t manufacturer = DEFAULT_COMPID;static inline uint16_t get_manufacturer(void){ return (manufacturer == DEFAULT_COMPID ? parser.defcompid : manufacturer);}static char *event_str[] = { "Unknown", "Inquiry Complete", "Inquiry Result", "Connect Complete", "Connect Request", "Disconn Complete", "Auth Complete", "Remote Name Req Complete", "Encrypt Change", "Change Connection Link Key Complete", "Master Link Key Complete", "Read Remote Supported Features", "Read Remote Ver Info Complete", "QoS Setup Complete", "Command Complete", "Command Status", "Hardware Error", "Flush Occurred", "Role Change", "Number of Completed Packets", "Mode Change", "Return Link Keys", "PIN Code Request", "Link Key Request", "Link Key Notification", "Loopback Command", "Data Buffer Overflow", "Max Slots Change", "Read Clock Offset Complete", "Connection Packet Type Changed", "QoS Violation", "Page Scan Mode Change", "Page Scan Repetition Mode Change", "Flow Specification Complete", "Inquiry Result with RSSI", "Read Remote Extended Features", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Synchronous Connect Complete", "Synchronous Connect Changed"};#define EVENT_NUM 43static char *cmd_linkctl_str[] = { "Unknown", "Inquiry", "Inquiry Cancel", "Periodic Inquiry Mode", "Exit Periodic Inquiry Mode", "Create Connection", "Disconnect", "Add SCO Connection", "Create Connection Cancel", "Accept Connection Request", "Reject Connection Request", "Link Key Request Reply", "Link Key Request Negative Reply", "PIN Code Request Reply", "PIN Code Request Negative Reply", "Change Connection Packet Type", "Unknown", "Authentication Requested", "Unknown", "Set Connection Encryption", "Unknown", "Change Connection Link Key", "Unknown", "Master Link Key", "Unknown", "Remote Name Request", "Remote Name Request Cancel", "Read Remote Supported Features", "Read Remote Extended Features", "Read Remote Version Information", "Unknown", "Read Clock Offset", "Read LMP Handle" "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Setup Synchronous Connection", "Accept Synchronous Connection", "Reject Synchronous Connection"};#define CMD_LINKCTL_NUM 42static char *cmd_linkpol_str[] = { "Unknown", "Hold Mode", "Unknown", "Sniff Mode", "Exit Sniff Mode", "Park State", "Exit Park State", "QoS Setup", "Unknown", "Role Discovery", "Unknown", "Switch Role", "Read Link Policy Settings", "Write Link Policy Settings", "Read Default Link Policy Settings", "Write Default Link Policy Settings", "Flow Specification"};#define CMD_LINKPOL_NUM 16static char *cmd_hostctl_str[] = { "Unknown", "Set Event Mask", "Unknown", "Reset", "Unknown", "Set Event Filter", "Unknown", "Unknown", "Flush", "Read PIN Type ", "Write PIN Type", "Create New Unit Key", "Unknown", "Read Stored Link Key", "Unknown", "Unknown", "Unknown", "Write Stored Link Key", "Delete Stored Link Key", "Write Local Name", "Read Local Name", "Read Connection Accept Timeout", "Write Connection Accept Timeout", "Read Page Timeout", "Write Page Timeout", "Read Scan Enable", "Write Scan Enable", "Read Page Scan Activity", "Write Page Scan Activity", "Read Inquiry Scan Activity", "Write Inquiry Scan Activity", "Read Authentication Enable", "Write Authentication Enable", "Read Encryption Mode", "Write Encryption Mode", "Read Class of Device", "Write Class of Device", "Read Voice Setting", "Write Voice Setting", "Read Automatic Flush Timeout", "Write Automatic Flush Timeout", "Read Num Broadcast Retransmissions", "Write Num Broadcast Retransmissions", "Read Hold Mode Activity ", "Write Hold Mode Activity", "Read Transmit Power Level", "Read Synchronous Flow Control Enable", "Write Synchronous Flow Control Enable", "Unknown", "Set Host Controller To Host Flow Control", "Unknown", "Host Buffer Size", "Unknown", "Host Number of Completed Packets", "Read Link Supervision Timeout", "Write Link Supervision Timeout", "Read Number of Supported IAC", "Read Current IAC LAP", "Write Current IAC LAP", "Read Page Scan Period Mode", "Write Page Scan Period Mode", "Read Page Scan Mode", "Write Page Scan Mode", "Set AFH Host Channel Classification", "Unknown", "Unknown", "Read Inquiry Scan Type", "Write Inquiry Scan Type", "Read Inquiry Mode", "Write Inquiry Mode", "Read Page Scan Type", "Write Page Scan Type", "Read AFH Channel Assessment Mode", "Write AFH Channel Assessment Mode"};#define CMD_HOSTCTL_NUM 73static char *cmd_info_str[] = { "Unknown", "Read Local Version Information", "Read Local Supported Commands", "Read Local Supported Features", "Read Local Extended Features", "Read Buffer Size", "Unknown", "Read Country Code", "Unknown", "Read BD ADDR"};#define CMD_INFO_NUM 9static char *cmd_status_str[] = { "Unknown", "Read Failed Contact Counter", "Reset Failed Contact Counter", "Read Link Quality", "Unknown", "Read RSSI", "Read AFH Channel Map", "Read Clock"};#define CMD_STATUS_NUM 7static char *error_code_str[] = { "Success", "Unknown HCI Command", "Unknown Connection Identifier", "Hardware Failure", "Page Timeout", "Authentication Failure", "PIN or Key Missing", "Memory Capacity Exceeded", "Connection Timeout", "Connection Limit Exceeded", "Synchronous Connection to a Device Exceeded", "ACL Connection Already Exists", "Command Disallowed", "Connection Rejected due to Limited Resources", "Connection Rejected due to Security Reasons", "Connection Rejected due to Unacceptable BD_ADDR", "Connection Accept Timeout Exceeded", "Unsupported Feature or Parameter Value", "Invalid HCI Command Parameters", "Remote User Terminated Connection", "Remote Device Terminated Connection due to Low Resources", "Remote Device Terminated Connection due to Power Off", "Connection Terminated by Local Host", "Repeated Attempts", "Pairing Not Allowed", "Unknown LMP PDU", "Unsupported Remote Feature / Unsupported LMP Feature", "SCO Offset Rejected", "SCO Interval Rejected", "SCO Air Mode Rejected", "Invalid LMP Parameters", "Unspecified Error", "Unsupported LMP Parameter Value", "Role Change Not Allowed", "LMP Response Timeout", "LMP Error Transaction Collision", "LMP PDU Not Allowed", "Encryption Mode Not Acceptable", "Link Key Can Not be Changed", "Requested QoS Not Supported", "Instant Passed", "Pairing with Unit Key Not Supported", "Different Transaction Collision", "Reserved", "QoS Unacceptable Parameter", "QoS Rejected", "Channel Classification Not Supported", "Insufficient Security", "Parameter out of Mandatory Range", "Reserved", "Role Switch Pending", "Reserved", "Reserved Slot Violation", "Role Switch Failed"};#define ERROR_CODE_NUM 53static char *status2str(uint8_t status){ char *str; if (status <= ERROR_CODE_NUM) str = error_code_str[status]; else str = "Unknown"; return str;}static char *opcode2str(uint16_t opcode){ uint16_t ogf = cmd_opcode_ogf(opcode); uint16_t ocf = cmd_opcode_ocf(opcode); char *cmd; switch (ogf) { case OGF_INFO_PARAM: if (ocf <= CMD_INFO_NUM) cmd = cmd_info_str[ocf]; else cmd = "Unknown"; break; case OGF_HOST_CTL: if (ocf <= CMD_HOSTCTL_NUM) cmd = cmd_hostctl_str[ocf]; else cmd = "Unknown"; break; case OGF_LINK_CTL: if (ocf <= CMD_LINKCTL_NUM) cmd = cmd_linkctl_str[ocf]; else cmd = "Unknown"; break; case OGF_LINK_POLICY: if (ocf <= CMD_LINKPOL_NUM) cmd = cmd_linkpol_str[ocf]; else cmd = "Unknown"; break; case OGF_STATUS_PARAM: if (ocf <= CMD_STATUS_NUM) cmd = cmd_status_str[ocf]; else cmd = "Unknown"; break; case OGF_TESTING_CMD: cmd = "Testing"; break; case OGF_VENDOR_CMD: cmd = "Vendor"; break; default: cmd = "Unknown"; break; } return cmd;}static char *role2str(uint8_t role){ switch (role) { case 0x00: return "Master"; case 0x01: return "Slave"; default: return "Unknown"; }}static char *mode2str(uint8_t mode){ switch (mode) { case 0x00: return "Active"; case 0x01: return "Hold"; case 0x02: return "Sniff"; case 0x03: return "Park"; default: return "Unknown"; }}static char *airmode2str(uint8_t mode){ switch (mode) { case 0x00: return "u-law log"; case 0x01: return "A-law log"; case 0x02: return "CVSD"; case 0x04: return "Transparent data"; default: return "Reserved"; }}static inline void generic_command_dump(int level, struct frame *frm){ uint16_t handle = btohs(htons(get_u16(frm))); p_indent(level, frm); printf("handle %d\n", handle); raw_dump(level, frm);}static inline void bdaddr_command_dump(int level, struct frame *frm){ bdaddr_t *bdaddr = frm->ptr; char addr[18]; frm->ptr += sizeof(bdaddr_t); frm->len -= sizeof(bdaddr_t); p_indent(level, frm); ba2str(bdaddr, addr); printf("bdaddr %s\n", addr); raw_dump(level, frm);}static inline void inquiry_dump(int level, struct frame *frm){ inquiry_cp *cp = frm->ptr; p_indent(level, frm); printf("lap 0x%2.2x%2.2x%2.2x len %d num %d\n", cp->lap[2], cp->lap[1], cp->lap[0], cp->length, cp->num_rsp);}static inline void periodic_inquiry_dump(int level, struct frame *frm){ periodic_inquiry_cp *cp = frm->ptr; p_indent(level, frm); printf("max %d min %d lap 0x%2.2x%2.2x%2.2x len %d num %d\n", btohs(cp->max_period), btohs(cp->min_period), cp->lap[2], cp->lap[1], cp->lap[0], cp->length, cp->num_rsp);}static inline void create_conn_dump(int level, struct frame *frm){ create_conn_cp *cp = frm->ptr; uint16_t ptype = btohs(cp->pkt_type); uint16_t clkoffset = btohs(cp->clock_offset); char addr[18], *str; p_indent(level, frm); ba2str(&cp->bdaddr, addr); printf("bdaddr %s ptype 0x%4.4x rswitch 0x%2.2x clkoffset 0x%4.4x%s\n", addr, ptype, cp->role_switch, clkoffset & 0x7fff, clkoffset & 0x8000 ? " (valid)" : ""); str = hci_ptypetostr(ptype); if (str) { p_indent(level, frm); printf("Packet type: %s\n", str); free(str); }}static inline void disconnect_dump(int level, struct frame *frm){ disconnect_cp *cp = frm->ptr; p_indent(level, frm); printf("handle %d reason 0x%2.2x\n", btohs(cp->handle), cp->reason); p_indent(level, frm); printf("Reason: %s\n", status2str(cp->reason));}static inline void add_sco_dump(int level, struct frame *frm){ add_sco_cp *cp = frm->ptr; uint16_t ptype = btohs(cp->pkt_type); char *str; p_indent(level, frm); printf("handle %d ptype 0x%4.4x\n", btohs(cp->handle), ptype); str = hci_ptypetostr(ptype); if (str) { p_indent(level, frm); printf("Packet type: %s\n", str); free(str); }}static inline void accept_conn_req_dump(int level, struct frame *frm){ accept_conn_req_cp *cp = frm->ptr; char addr[18]; p_indent(level, frm); ba2str(&cp->bdaddr, addr); printf("bdaddr %s role 0x%2.2x\n", addr, cp->role); p_indent(level, frm); printf("Role: %s\n", role2str(cp->role));}static inline void reject_conn_req_dump(int level, struct frame *frm){ reject_conn_req_cp *cp = frm->ptr; char addr[18]; p_indent(level, frm); ba2str(&cp->bdaddr, addr); printf("bdaddr %s reason 0x%2.2x\n", addr, cp->reason); p_indent(level, frm); printf("Reason: %s\n", status2str(cp->reason));}static inline void pin_code_reply_dump(int level, struct frame *frm){ pin_code_reply_cp *cp = frm->ptr; char addr[18], pin[17]; p_indent(level, frm); ba2str(&cp->bdaddr, addr); memset(pin, 0, sizeof(pin)); memcpy(pin, cp->pin_code, cp->pin_len); printf("bdaddr %s len %d pin \'%s\'\n", addr, cp->pin_len, pin);}static inline void link_key_reply_dump(int level, struct frame *frm){ link_key_reply_cp *cp = frm->ptr; char addr[18]; int i; p_indent(level, frm); ba2str(&cp->bdaddr, addr); printf("bdaddr %s key ", addr); for (i = 0; i < 16; i++) printf("%2.2X", cp->link_key[i]); printf("\n");}static inline void pin_code_neg_reply_dump(int level, struct frame *frm){ bdaddr_t *bdaddr = frm->ptr; char addr[18]; p_indent(level, frm); ba2str(bdaddr, addr); printf("bdaddr %s\n", addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -