Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/hcitools/monitor/control.c
Views: 3959
/*1*2* BlueZ - Bluetooth protocol stack for Linux3*4* Copyright (C) 2011-2012 Intel Corporation5* Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>6*7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* (at your option) any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA21*22*/2324#ifdef HAVE_CONFIG_H25#include <config.h>26#endif2728#include <stdio.h>29#include <stdbool.h>30#include <errno.h>31#include <unistd.h>32#include <stdlib.h>33#include <string.h>34#include <fcntl.h>35#include <sys/time.h>36#include <sys/socket.h>37#include <sys/un.h>3839#include <lib/bluetooth/bluetooth.h>40#include <lib/bluetooth/hci.h>41#include <lib/mgmt.h>4243#include "mainloop.h"44#include "display.h"45#include "packet.h"46#include "btsnoop.h"47#include "hcidump.h"48#include "control.h"4950static bool hcidump_fallback = false;5152#define MAX_PACKET_SIZE (1486 + 4)5354struct control_data {55uint16_t channel;56int fd;57unsigned char buf[MAX_PACKET_SIZE];58uint16_t offset;59};6061static void free_data(void *user_data)62{63struct control_data *data = user_data;6465close(data->fd);6667free(data);68}6970static void mgmt_index_added(uint16_t len, const void *buf)71{72printf("@ Index Added\n");7374packet_hexdump(buf, len);75}7677static void mgmt_index_removed(uint16_t len, const void *buf)78{79printf("@ Index Removed\n");8081packet_hexdump(buf, len);82}8384static void mgmt_controller_error(uint16_t len, const void *buf)85{86const struct mgmt_ev_controller_error *ev = buf;8788if (len < sizeof(*ev)) {89printf("* Malformed Controller Error control\n");90return;91}9293printf("@ Controller Error: 0x%2.2x\n", ev->error_code);9495buf += sizeof(*ev);96len -= sizeof(*ev);9798packet_hexdump(buf, len);99}100101#ifndef NELEM102#define NELEM(x) (sizeof(x) / sizeof((x)[0]))103#endif104105static const char *settings_str[] = {106"powered", "connectable", "fast-connectable", "discoverable",107"pairable", "link-security", "ssp", "br/edr", "hs", "le",108"advertising",109};110111static void mgmt_new_settings(uint16_t len, const void *buf)112{113uint32_t settings;114unsigned int i;115116if (len < 4) {117printf("* Malformed New Settings control\n");118return;119}120121settings = bt_get_le32(buf);122123printf("@ New Settings: 0x%4.4x\n", settings);124125printf("%-12c", ' ');126for (i = 0; i < NELEM(settings_str); i++) {127if (settings & (1 << i))128printf("%s ", settings_str[i]);129}130printf("\n");131132buf += 4;133len -= 4;134135packet_hexdump(buf, len);136}137138static void mgmt_class_of_dev_changed(uint16_t len, const void *buf)139{140const struct mgmt_ev_class_of_dev_changed *ev = buf;141142if (len < sizeof(*ev)) {143printf("* Malformed Class of Device Changed control\n");144return;145}146147printf("@ Class of Device Changed: 0x%2.2x%2.2x%2.2x\n",148ev->class_of_dev[2],149ev->class_of_dev[1],150ev->class_of_dev[0]);151152buf += sizeof(*ev);153len -= sizeof(*ev);154155packet_hexdump(buf, len);156}157158static void mgmt_local_name_changed(uint16_t len, const void *buf)159{160const struct mgmt_ev_local_name_changed *ev = buf;161162if (len < sizeof(*ev)) {163printf("* Malformed Local Name Changed control\n");164return;165}166167printf("@ Local Name Changed: %s (%s)\n", ev->name, ev->short_name);168169buf += sizeof(*ev);170len -= sizeof(*ev);171172packet_hexdump(buf, len);173}174175static void mgmt_new_link_key(uint16_t len, const void *buf)176{177const struct mgmt_ev_new_link_key *ev = buf;178char str[18];179180if (len < sizeof(*ev)) {181printf("* Malformed New Link Key control\n");182return;183}184185ba2str(&ev->key.addr.bdaddr, str);186187printf("@ New Link Key: %s (%d)\n", str, ev->key.addr.type);188189buf += sizeof(*ev);190len -= sizeof(*ev);191192packet_hexdump(buf, len);193}194195static void mgmt_new_long_term_key(uint16_t len, const void *buf)196{197const struct mgmt_ev_new_long_term_key *ev = buf;198char str[18];199200if (len < sizeof(*ev)) {201printf("* Malformed New Long Term Key control\n");202return;203}204205ba2str(&ev->key.addr.bdaddr, str);206207printf("@ New Long Term Key: %s (%d)\n", str, ev->key.addr.type);208209buf += sizeof(*ev);210len -= sizeof(*ev);211212packet_hexdump(buf, len);213}214215static void mgmt_device_connected(uint16_t len, const void *buf)216{217const struct mgmt_ev_device_connected *ev = buf;218uint32_t flags;219char str[18];220221if (len < sizeof(*ev)) {222printf("* Malformed Device Connected control\n");223return;224}225226flags = btohl(ev->flags);227ba2str(&ev->addr.bdaddr, str);228229printf("@ Device Connected: %s (%d) flags 0x%4.4x\n",230str, ev->addr.type, flags);231232buf += sizeof(*ev);233len -= sizeof(*ev);234235packet_hexdump(buf, len);236}237238static void mgmt_device_disconnected(uint16_t len, const void *buf)239{240const struct mgmt_ev_device_disconnected *ev = buf;241char str[18];242uint8_t reason;243uint16_t consumed_len;244245if (len < sizeof(struct mgmt_addr_info)) {246printf("* Malformed Device Disconnected control\n");247return;248}249250if (len < sizeof(*ev)) {251reason = MGMT_DEV_DISCONN_UNKNOWN;252consumed_len = len;253} else {254reason = ev->reason;255consumed_len = sizeof(*ev);256}257258ba2str(&ev->addr.bdaddr, str);259260printf("@ Device Disconnected: %s (%d) reason %u\n", str, ev->addr.type,261reason);262263buf += consumed_len;264len -= consumed_len;265266packet_hexdump(buf, len);267}268269static void mgmt_connect_failed(uint16_t len, const void *buf)270{271const struct mgmt_ev_connect_failed *ev = buf;272char str[18];273274if (len < sizeof(*ev)) {275printf("* Malformed Connect Failed control\n");276return;277}278279ba2str(&ev->addr.bdaddr, str);280281printf("@ Connect Failed: %s (%d) status 0x%2.2x\n",282str, ev->addr.type, ev->status);283284buf += sizeof(*ev);285len -= sizeof(*ev);286287packet_hexdump(buf, len);288}289290static void mgmt_pin_code_request(uint16_t len, const void *buf)291{292const struct mgmt_ev_pin_code_request *ev = buf;293char str[18];294295if (len < sizeof(*ev)) {296printf("* Malformed PIN Code Request control\n");297return;298}299300ba2str(&ev->addr.bdaddr, str);301302printf("@ PIN Code Request: %s (%d) secure 0x%2.2x\n",303str, ev->addr.type, ev->secure);304305buf += sizeof(*ev);306len -= sizeof(*ev);307308packet_hexdump(buf, len);309}310311static void mgmt_user_confirm_request(uint16_t len, const void *buf)312{313const struct mgmt_ev_user_confirm_request *ev = buf;314char str[18];315316if (len < sizeof(*ev)) {317printf("* Malformed User Confirmation Request control\n");318return;319}320321ba2str(&ev->addr.bdaddr, str);322323printf("@ User Confirmation Request: %s (%d) hint %d value %d\n",324str, ev->addr.type, ev->confirm_hint, ev->value);325326buf += sizeof(*ev);327len -= sizeof(*ev);328329packet_hexdump(buf, len);330}331332static void mgmt_user_passkey_request(uint16_t len, const void *buf)333{334const struct mgmt_ev_user_passkey_request *ev = buf;335char str[18];336337if (len < sizeof(*ev)) {338printf("* Malformed User Passkey Request control\n");339return;340}341342ba2str(&ev->addr.bdaddr, str);343344printf("@ PIN User Passkey Request: %s (%d)\n", str, ev->addr.type);345346buf += sizeof(*ev);347len -= sizeof(*ev);348349packet_hexdump(buf, len);350}351352static void mgmt_auth_failed(uint16_t len, const void *buf)353{354const struct mgmt_ev_auth_failed *ev = buf;355char str[18];356357if (len < sizeof(*ev)) {358printf("* Malformed Authentication Failed control\n");359return;360}361362ba2str(&ev->addr.bdaddr, str);363364printf("@ Authentication Failed: %s (%d) status 0x%2.2x\n",365str, ev->addr.type, ev->status);366367buf += sizeof(*ev);368len -= sizeof(*ev);369370packet_hexdump(buf, len);371}372373static void mgmt_device_found(uint16_t len, const void *buf)374{375const struct mgmt_ev_device_found *ev = buf;376uint32_t flags;377char str[18];378379if (len < sizeof(*ev)) {380printf("* Malformed Device Found control\n");381return;382}383384flags = btohl(ev->flags);385ba2str(&ev->addr.bdaddr, str);386387printf("@ Device Found: %s (%d) rssi %d flags 0x%4.4x\n",388str, ev->addr.type, ev->rssi, flags);389390buf += sizeof(*ev);391len -= sizeof(*ev);392393packet_hexdump(buf, len);394}395396static void mgmt_discovering(uint16_t len, const void *buf)397{398const struct mgmt_ev_discovering *ev = buf;399400if (len < sizeof(*ev)) {401printf("* Malformed Discovering control\n");402return;403}404405printf("@ Discovering: 0x%2.2x (%d)\n", ev->discovering, ev->type);406407buf += sizeof(*ev);408len -= sizeof(*ev);409410packet_hexdump(buf, len);411}412413static void mgmt_device_blocked(uint16_t len, const void *buf)414{415const struct mgmt_ev_device_blocked *ev = buf;416char str[18];417418if (len < sizeof(*ev)) {419printf("* Malformed Device Blocked control\n");420return;421}422423ba2str(&ev->addr.bdaddr, str);424425printf("@ Device Blocked: %s (%d)\n", str, ev->addr.type);426427buf += sizeof(*ev);428len -= sizeof(*ev);429430packet_hexdump(buf, len);431}432433static void mgmt_device_unblocked(uint16_t len, const void *buf)434{435const struct mgmt_ev_device_unblocked *ev = buf;436char str[18];437438if (len < sizeof(*ev)) {439printf("* Malformed Device Unblocked control\n");440return;441}442443ba2str(&ev->addr.bdaddr, str);444445printf("@ Device Unblocked: %s (%d)\n", str, ev->addr.type);446447buf += sizeof(*ev);448len -= sizeof(*ev);449450packet_hexdump(buf, len);451}452453static void mgmt_device_unpaired(uint16_t len, const void *buf)454{455const struct mgmt_ev_device_unpaired *ev = buf;456char str[18];457458if (len < sizeof(*ev)) {459printf("* Malformed Device Unpaired control\n");460return;461}462463ba2str(&ev->addr.bdaddr, str);464465printf("@ Device Unpaired: %s (%d)\n", str, ev->addr.type);466467buf += sizeof(*ev);468len -= sizeof(*ev);469470packet_hexdump(buf, len);471}472473static void mgmt_passkey_notify(uint16_t len, const void *buf)474{475const struct mgmt_ev_passkey_notify *ev = buf;476uint32_t passkey;477char str[18];478479if (len < sizeof(*ev)) {480printf("* Malformed Passkey Notify control\n");481return;482}483484ba2str(&ev->addr.bdaddr, str);485486passkey = btohl(ev->passkey);487488printf("@ Passkey Notify: %s (%d) passkey %06u entered %u\n",489str, ev->addr.type, passkey, ev->entered);490491buf += sizeof(*ev);492len -= sizeof(*ev);493494packet_hexdump(buf, len);495}496497void control_message(uint16_t opcode, const void *data, uint16_t size)498{499switch (opcode) {500case MGMT_EV_INDEX_ADDED:501mgmt_index_added(size, data);502break;503case MGMT_EV_INDEX_REMOVED:504mgmt_index_removed(size, data);505break;506case MGMT_EV_CONTROLLER_ERROR:507mgmt_controller_error(size, data);508break;509case MGMT_EV_NEW_SETTINGS:510mgmt_new_settings(size, data);511break;512case MGMT_EV_CLASS_OF_DEV_CHANGED:513mgmt_class_of_dev_changed(size, data);514break;515case MGMT_EV_LOCAL_NAME_CHANGED:516mgmt_local_name_changed(size, data);517break;518case MGMT_EV_NEW_LINK_KEY:519mgmt_new_link_key(size, data);520break;521case MGMT_EV_NEW_LONG_TERM_KEY:522mgmt_new_long_term_key(size, data);523break;524case MGMT_EV_DEVICE_CONNECTED:525mgmt_device_connected(size, data);526break;527case MGMT_EV_DEVICE_DISCONNECTED:528mgmt_device_disconnected(size, data);529break;530case MGMT_EV_CONNECT_FAILED:531mgmt_connect_failed(size, data);532break;533case MGMT_EV_PIN_CODE_REQUEST:534mgmt_pin_code_request(size, data);535break;536case MGMT_EV_USER_CONFIRM_REQUEST:537mgmt_user_confirm_request(size, data);538break;539case MGMT_EV_USER_PASSKEY_REQUEST:540mgmt_user_passkey_request(size, data);541break;542case MGMT_EV_AUTH_FAILED:543mgmt_auth_failed(size, data);544break;545case MGMT_EV_DEVICE_FOUND:546mgmt_device_found(size, data);547break;548case MGMT_EV_DISCOVERING:549mgmt_discovering(size, data);550break;551case MGMT_EV_DEVICE_BLOCKED:552mgmt_device_blocked(size, data);553break;554case MGMT_EV_DEVICE_UNBLOCKED:555mgmt_device_unblocked(size, data);556break;557case MGMT_EV_DEVICE_UNPAIRED:558mgmt_device_unpaired(size, data);559break;560case MGMT_EV_PASSKEY_NOTIFY:561mgmt_passkey_notify(size, data);562break;563default:564printf("* Unknown control (code %d len %d)\n", opcode, size);565packet_hexdump(data, size);566break;567}568}569570static void data_callback(int fd, uint32_t events, void *user_data)571{572struct control_data *data = user_data;573unsigned char control[32];574struct mgmt_hdr hdr;575struct msghdr msg;576struct iovec iov[2];577578if (events & (EPOLLERR | EPOLLHUP)) {579mainloop_remove_fd(data->fd);580return;581}582583iov[0].iov_base = &hdr;584iov[0].iov_len = MGMT_HDR_SIZE;585iov[1].iov_base = data->buf;586iov[1].iov_len = sizeof(data->buf);587588memset(&msg, 0, sizeof(msg));589msg.msg_iov = iov;590msg.msg_iovlen = 2;591msg.msg_control = control;592msg.msg_controllen = sizeof(control);593594while (1) {595struct cmsghdr *cmsg;596struct timeval *tv = NULL;597struct timeval ctv;598uint16_t opcode, index, pktlen;599ssize_t len;600601len = recvmsg(data->fd, &msg, MSG_DONTWAIT);602if (len < 0)603break;604605if (len < MGMT_HDR_SIZE)606break;607608for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;609cmsg = CMSG_NXTHDR(&msg, cmsg)) {610if (cmsg->cmsg_level != SOL_SOCKET)611continue;612613if (cmsg->cmsg_type == SCM_TIMESTAMP) {614memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));615tv = &ctv;616}617}618619opcode = btohs(hdr.opcode);620index = btohs(hdr.index);621pktlen = btohs(hdr.len);622623switch (data->channel) {624case HCI_CHANNEL_CONTROL:625packet_control(tv, index, opcode, data->buf, pktlen);626break;627case HCI_CHANNEL_MONITOR:628packet_monitor(tv, index, opcode, data->buf, pktlen);629btsnoop_write_hci(tv, index, opcode, data->buf, pktlen);630break;631}632}633}634635static int open_socket(uint16_t channel)636{637struct sockaddr_hci addr;638int fd, opt = 1;639640fd = socket(AF_BLUETOOTH, SOCK_RAW | O_CLOEXEC, BTPROTO_HCI);641if (fd < 0) {642perror("Failed to open channel");643return -1;644}645646memset(&addr, 0, sizeof(addr));647addr.hci_family = AF_BLUETOOTH;648addr.hci_dev = HCI_DEV_NONE;649addr.hci_channel = channel;650651if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {652if (errno == EINVAL) {653/* Fallback to hcidump support */654hcidump_fallback = true;655close(fd);656return -1;657}658perror("Failed to bind channel");659close(fd);660return -1;661}662663if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {664perror("Failed to enable timestamps");665close(fd);666return -1;667}668669return fd;670}671672static int open_channel(uint16_t channel)673{674struct control_data *data;675676data = malloc(sizeof(*data));677if (!data)678return -1;679680memset(data, 0, sizeof(*data));681data->channel = channel;682683data->fd = open_socket(channel);684if (data->fd < 0) {685free(data);686return -1;687}688689mainloop_add_fd(data->fd, EPOLLIN, data_callback, data, free_data);690691return 0;692}693694static void client_callback(int fd, uint32_t events, void *user_data)695{696struct control_data *data = user_data;697ssize_t len;698699if (events & (EPOLLERR | EPOLLHUP)) {700mainloop_remove_fd(data->fd);701return;702}703704len = recv(data->fd, data->buf + data->offset,705sizeof(data->buf) - data->offset, MSG_DONTWAIT);706if (len < 0)707return;708709data->offset += len;710711if (data->offset > MGMT_HDR_SIZE) {712struct mgmt_hdr *hdr = (struct mgmt_hdr *) data->buf;713uint16_t pktlen = btohs(hdr->len);714715if (data->offset > pktlen + MGMT_HDR_SIZE) {716uint16_t opcode = btohs(hdr->opcode);717uint16_t index = btohs(hdr->index);718719packet_monitor(NULL, index, opcode,720data->buf + MGMT_HDR_SIZE, pktlen);721722data->offset -= pktlen + MGMT_HDR_SIZE;723724if (data->offset > 0)725memmove(data->buf, data->buf +726MGMT_HDR_SIZE + pktlen, data->offset);727}728}729}730731static void server_accept_callback(int fd, uint32_t events, void *user_data)732{733struct control_data *data;734struct sockaddr_un addr;735socklen_t len;736int nfd;737738if (events & (EPOLLERR | EPOLLHUP)) {739mainloop_remove_fd(fd);740return;741}742743memset(&addr, 0, sizeof(addr));744len = sizeof(addr);745746nfd = accept(fd, (struct sockaddr *) &addr, &len);747if (nfd < 0) {748perror("Failed to accept client socket");749return;750}751752printf("--- New monitor connection ---\n");753754data = malloc(sizeof(*data));755if (!data) {756close(nfd);757return;758}759760memset(data, 0, sizeof(*data));761data->channel = HCI_CHANNEL_MONITOR;762data->fd = nfd;763764mainloop_add_fd(data->fd, EPOLLIN, client_callback, data, free_data);765}766767static int server_fd = -1;768769void control_server(const char *path)770{771struct sockaddr_un addr;772int fd;773774if (server_fd >= 0)775return;776777unlink(path);778779fd = socket(PF_UNIX, SOCK_STREAM | O_CLOEXEC, 0);780if (fd < 0) {781perror("Failed to open server socket");782return;783}784785memset(&addr, 0, sizeof(addr));786addr.sun_family = AF_UNIX;787strcpy(addr.sun_path, path);788789if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {790perror("Failed to bind server socket");791close(fd);792return;793}794795if (listen(fd, 5) < 0) {796perror("Failed to listen server socket");797close(fd);798return;799}800801if (mainloop_add_fd(fd, EPOLLIN, server_accept_callback,802NULL, NULL) < 0) {803close(fd);804return;805}806807server_fd = fd;808}809810void control_writer(const char *path)811{812btsnoop_create(path, BTSNOOP_TYPE_EXTENDED_HCI);813}814815void control_reader(const char *path)816{817unsigned char buf[MAX_PACKET_SIZE];818uint16_t pktlen;819uint32_t type;820struct timeval tv;821822if (btsnoop_open(path, &type) < 0)823return;824825switch (type) {826case BTSNOOP_TYPE_HCI:827case BTSNOOP_TYPE_UART:828case BTSNOOP_TYPE_EXTENDED_PHY:829packet_del_filter(PACKET_FILTER_SHOW_INDEX);830break;831832case BTSNOOP_TYPE_EXTENDED_HCI:833packet_add_filter(PACKET_FILTER_SHOW_INDEX);834break;835}836837open_pager();838839switch (type) {840case BTSNOOP_TYPE_HCI:841case BTSNOOP_TYPE_UART:842case BTSNOOP_TYPE_EXTENDED_HCI:843while (1) {844uint16_t index, opcode;845846if (btsnoop_read_hci(&tv, &index, &opcode,847buf, &pktlen) < 0)848break;849850packet_monitor(&tv, index, opcode, buf, pktlen);851}852break;853854case BTSNOOP_TYPE_EXTENDED_PHY:855while (1) {856uint16_t frequency;857858if (btsnoop_read_phy(&tv, &frequency,859buf, &pktlen) < 0)860break;861862packet_simulator(&tv, frequency, buf, pktlen);863}864break;865}866867close_pager();868869btsnoop_close();870}871872int control_tracing(void)873{874packet_add_filter(PACKET_FILTER_SHOW_INDEX);875876if (server_fd >= 0)877return 0;878879if (open_channel(HCI_CHANNEL_MONITOR) < 0) {880if (!hcidump_fallback)881return -1;882if (hcidump_tracing() < 0)883return -1;884return 0;885}886887open_channel(HCI_CHANNEL_CONTROL);888889return 0;890}891892893