Path: blob/main/usr.sbin/bluetooth/l2control/l2cap.c
103554 views
/*-1* l2cap.c2*3* SPDX-License-Identifier: BSD-2-Clause4*5* Copyright (c) 2001-2002 Maksim Yevmenkin <[email protected]>6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*29* $Id: l2cap.c,v 1.5 2003/05/16 19:52:37 max Exp $30*/3132#include <sys/ioctl.h>33#define L2CAP_SOCKET_CHECKED34#include <bluetooth.h>35#include <errno.h>36#include <stdio.h>37#include <stdlib.h>38#include <string.h>39#include "l2control.h"4041#define SIZE(x) (sizeof((x))/sizeof((x)[0]))4243/* Print BDADDR */44static char *45bdaddrpr(bdaddr_t const *ba)46{47extern int numeric_bdaddr;48static char str[24];49struct hostent *he = NULL;5051if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {52str[0] = '*';53str[1] = 0;5455return (str);56}5758if (!numeric_bdaddr &&59(he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {60strlcpy(str, he->h_name, sizeof(str));6162return (str);63}6465bt_ntoa(ba, str);6667return (str);68} /* bdaddrpr */6970/* Send read_node_flags command to the node */71static int72l2cap_read_node_flags(int s, int argc, char **argv)73{74struct ng_btsocket_l2cap_raw_node_flags r;7576memset(&r, 0, sizeof(r));77if (ioctl(s, SIOC_L2CAP_NODE_GET_FLAGS, &r, sizeof(r)) < 0)78return (ERROR);7980fprintf(stdout, "Connectionless traffic flags:\n");81fprintf(stdout, "\tSDP: %s\n",82(r.flags & NG_L2CAP_CLT_SDP_DISABLED)? "disabled" : "enabled");83fprintf(stdout, "\tRFCOMM: %s\n",84(r.flags & NG_L2CAP_CLT_RFCOMM_DISABLED)? "disabled":"enabled");85fprintf(stdout, "\tTCP: %s\n",86(r.flags & NG_L2CAP_CLT_TCP_DISABLED)? "disabled" : "enabled");8788return (OK);89} /* l2cap_read_node_flags */9091/* Send read_debug_level command to the node */92static int93l2cap_read_debug_level(int s, int argc, char **argv)94{95struct ng_btsocket_l2cap_raw_node_debug r;9697memset(&r, 0, sizeof(r));98if (ioctl(s, SIOC_L2CAP_NODE_GET_DEBUG, &r, sizeof(r)) < 0)99return (ERROR);100101fprintf(stdout, "Debug level: %d\n", r.debug);102103return (OK);104} /* l2cap_read_debug_level */105106/* Send write_debug_level command to the node */107static int108l2cap_write_debug_level(int s, int argc, char **argv)109{110struct ng_btsocket_l2cap_raw_node_debug r;111112memset(&r, 0, sizeof(r));113switch (argc) {114case 1:115r.debug = atoi(argv[0]);116break;117118default:119return (USAGE);120}121122if (ioctl(s, SIOC_L2CAP_NODE_SET_DEBUG, &r, sizeof(r)) < 0)123return (ERROR);124125return (OK);126} /* l2cap_write_debug_level */127128/* Send read_connection_list command to the node */129static int130l2cap_read_connection_list(int s, int argc, char **argv)131{132static char const * const state[] = {133/* NG_L2CAP_CON_CLOSED */ "CLOSED",134/* NG_L2CAP_W4_LP_CON_CFM */ "W4_LP_CON_CFM",135/* NG_L2CAP_CON_OPEN */ "OPEN"136};137#define con_state2str(x) ((x) >= SIZE(state)? "UNKNOWN" : state[(x)])138139struct ng_btsocket_l2cap_raw_con_list r;140int n, error = OK;141142memset(&r, 0, sizeof(r));143r.num_connections = NG_L2CAP_MAX_CON_NUM;144r.connections = calloc(NG_L2CAP_MAX_CON_NUM,145sizeof(ng_l2cap_node_con_ep));146if (r.connections == NULL) {147errno = ENOMEM;148return (ERROR);149}150151if (ioctl(s, SIOC_L2CAP_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) {152error = ERROR;153goto out;154}155156fprintf(stdout, "L2CAP connections:\n");157fprintf(stdout,158"Remote BD_ADDR Handle Flags Pending State\n");159for (n = 0; n < r.num_connections; n++) {160fprintf(stdout,161"%-17.17s " \162"%6d " \163"%c%c%c%c%c " \164"%7d " \165"%s\n",166bdaddrpr(&r.connections[n].remote),167r.connections[n].con_handle,168((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'),169((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '),170((r.connections[n].flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)? 'D' : ' '),171((r.connections[n].flags & NG_L2CAP_CON_TX)? 'T' : ' '),172((r.connections[n].flags & NG_L2CAP_CON_RX)? 'R' : ' '),173r.connections[n].pending,174con_state2str(r.connections[n].state));175}176out:177free(r.connections);178179return (error);180} /* l2cap_read_connection_list */181182/* Send read_channel_list command to the node */183static int184l2cap_read_channel_list(int s, int argc, char **argv)185{186static char const * const state[] = {187/* NG_L2CAP_CLOSED */ "CLOSED",188/* NG_L2CAP_W4_L2CAP_CON_RSP */ "W4_L2CAP_CON_RSP",189/* NG_L2CAP_W4_L2CA_CON_RSP */ "W4_L2CA_CON_RSP",190/* NG_L2CAP_CONFIG */ "CONFIG",191/* NG_L2CAP_OPEN */ "OPEN",192/* NG_L2CAP_W4_L2CAP_DISCON_RSP */ "W4_L2CAP_DISCON_RSP",193/* NG_L2CAP_W4_L2CA_DISCON_RSP */ "W4_L2CA_DISCON_RSP"194};195#define ch_state2str(x) ((x) >= SIZE(state)? "UNKNOWN" : state[(x)])196197struct ng_btsocket_l2cap_raw_chan_list r;198int n, error = OK;199200memset(&r, 0, sizeof(r));201r.num_channels = NG_L2CAP_MAX_CHAN_NUM;202r.channels = calloc(NG_L2CAP_MAX_CHAN_NUM,203sizeof(ng_l2cap_node_chan_ep));204if (r.channels == NULL) {205errno = ENOMEM;206return (ERROR);207}208209if (ioctl(s, SIOC_L2CAP_NODE_GET_CHAN_LIST, &r, sizeof(r)) < 0) {210error = ERROR;211goto out;212}213214fprintf(stdout, "L2CAP channels:\n");215fprintf(stdout,216"Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n");217for (n = 0; n < r.num_channels; n++) {218fprintf(stdout,219"%-17.17s " \220"%5d/%5d %5d " \221"%5d/%5d " \222"%s\n",223bdaddrpr(&r.channels[n].remote),224r.channels[n].scid, r.channels[n].dcid,225r.channels[n].psm, r.channels[n].imtu,226r.channels[n].omtu,227ch_state2str(r.channels[n].state));228}229out:230free(r.channels);231232return (error);233} /* l2cap_read_channel_list */234235/* Send read_auto_disconnect_timeout command to the node */236static int237l2cap_read_auto_disconnect_timeout(int s, int argc, char **argv)238{239struct ng_btsocket_l2cap_raw_auto_discon_timo r;240241memset(&r, 0, sizeof(r));242if (ioctl(s, SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)243return (ERROR);244245if (r.timeout != 0)246fprintf(stdout, "Auto disconnect timeout: %d sec\n", r.timeout);247else248fprintf(stdout, "Auto disconnect disabled\n");249250return (OK);251} /* l2cap_read_auto_disconnect_timeout */252253/* Send write_auto_disconnect_timeout command to the node */254static int255l2cap_write_auto_disconnect_timeout(int s, int argc, char **argv)256{257struct ng_btsocket_l2cap_raw_auto_discon_timo r;258259memset(&r, 0, sizeof(r));260switch (argc) {261case 1:262r.timeout = atoi(argv[0]);263break;264265default:266return (USAGE);267}268269if (ioctl(s, SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)270return (ERROR);271272return (OK);273} /* l2cap_write_auto_disconnect_timeout */274275struct l2cap_command l2cap_commands[] = {276{277"read_node_flags",278"Get L2CAP node flags",279&l2cap_read_node_flags280},281{282"read_debug_level",283"Get L2CAP node debug level",284&l2cap_read_debug_level285},286{287"write_debug_level <level>",288"Set L2CAP node debug level",289&l2cap_write_debug_level290},291{292"read_connection_list",293"Read list of the L2CAP connections",294&l2cap_read_connection_list295},296{297"read_channel_list",298"Read list of the L2CAP channels",299&l2cap_read_channel_list300},301{302"read_auto_disconnect_timeout",303"Get L2CAP node auto disconnect timeout (in sec)",304&l2cap_read_auto_disconnect_timeout305},306{307"write_auto_disconnect_timeout <timeout>",308"Set L2CAP node auto disconnect timeout (in sec)",309&l2cap_write_auto_disconnect_timeout310},311{312NULL,313}};314315316317