1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4107120Sjulian * btsockstat.c 5107120Sjulian * 6107120Sjulian * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7107120Sjulian * All rights reserved. 8107120Sjulian * 9107120Sjulian * Redistribution and use in source and binary forms, with or without 10107120Sjulian * modification, are permitted provided that the following conditions 11107120Sjulian * are met: 12107120Sjulian * 1. Redistributions of source code must retain the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer. 14107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 15107120Sjulian * notice, this list of conditions and the following disclaimer in the 16107120Sjulian * documentation and/or other materials provided with the distribution. 17107120Sjulian * 18107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28107120Sjulian * SUCH DAMAGE. 29107120Sjulian * 30121054Semax * $Id: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $ 31107120Sjulian * $FreeBSD: stable/11/usr.bin/bluetooth/btsockstat/btsockstat.c 330449 2018-03-05 07:26:05Z eadler $ 32107120Sjulian */ 33107120Sjulian 34107120Sjulian#include <sys/types.h> 35107120Sjulian#include <sys/callout.h> 36107120Sjulian#include <sys/param.h> 37180964Semax#include <sys/protosw.h> 38107120Sjulian#include <sys/queue.h> 39107120Sjulian#include <sys/socket.h> 40107120Sjulian#include <sys/socketvar.h> 41107120Sjulian 42107120Sjulian#include <net/if.h> 43107120Sjulian 44281210Stakawata#define L2CAP_SOCKET_CHECKED 45121054Semax#include <bluetooth.h> 46107120Sjulian#include <err.h> 47107120Sjulian#include <fcntl.h> 48107120Sjulian#include <kvm.h> 49107120Sjulian#include <limits.h> 50121064Sbde#include <nlist.h> 51107120Sjulian 52121054Semax#include <netgraph/bluetooth/include/ng_bluetooth.h> 53121054Semax#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h> 54121054Semax#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h> 55121054Semax#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h> 56107120Sjulian 57107120Sjulian#include <stdio.h> 58107120Sjulian#include <stdlib.h> 59107120Sjulian#include <string.h> 60107120Sjulian#include <unistd.h> 61107120Sjulian 62107120Sjulianstatic void hcirawpr (kvm_t *kvmd, u_long addr); 63107120Sjulianstatic void l2caprawpr (kvm_t *kvmd, u_long addr); 64107120Sjulianstatic void l2cappr (kvm_t *kvmd, u_long addr); 65107120Sjulianstatic void l2caprtpr (kvm_t *kvmd, u_long addr); 66114878Sjulianstatic void rfcommpr (kvm_t *kvmd, u_long addr); 67114878Sjulianstatic void rfcommpr_s (kvm_t *kvmd, u_long addr); 68107120Sjulian 69121054Semaxstatic char * bdaddrpr (bdaddr_p const ba, char *str, int len); 70121054Semax 71107120Sjulianstatic kvm_t * kopen (char const *memf); 72107120Sjulianstatic int kread (kvm_t *kvmd, u_long addr, char *buffer, int size); 73107120Sjulian 74107120Sjulianstatic void usage (void); 75107120Sjulian 76107120Sjulian/* 77107120Sjulian * List of symbols 78107120Sjulian */ 79107120Sjulian 80107120Sjulianstatic struct nlist nl[] = { 81107120Sjulian#define N_HCI_RAW 0 82107120Sjulian { "_ng_btsocket_hci_raw_sockets" }, 83107120Sjulian#define N_L2CAP_RAW 1 84107120Sjulian { "_ng_btsocket_l2cap_raw_sockets" }, 85107120Sjulian#define N_L2CAP 2 86107120Sjulian { "_ng_btsocket_l2cap_sockets" }, 87107120Sjulian#define N_L2CAP_RAW_RT 3 88107120Sjulian { "_ng_btsocket_l2cap_raw_rt" }, 89107120Sjulian#define N_L2CAP_RT 4 90107120Sjulian { "_ng_btsocket_l2cap_rt" }, 91114878Sjulian#define N_RFCOMM 5 92114878Sjulian { "_ng_btsocket_rfcomm_sockets" }, 93114878Sjulian#define N_RFCOMM_S 6 94114878Sjulian { "_ng_btsocket_rfcomm_sessions" }, 95107120Sjulian { "" }, 96107120Sjulian}; 97107120Sjulian 98114878Sjulian#define state2str(x) \ 99114878Sjulian (((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)]) 100114878Sjulian 101107120Sjulian/* 102107120Sjulian * Main 103107120Sjulian */ 104107120Sjulian 105121054Semaxstatic int numeric_bdaddr = 0; 106121054Semax 107107120Sjulianint 108107120Sjulianmain(int argc, char *argv[]) 109107120Sjulian{ 110107120Sjulian int opt, proto = -1, route = 0; 111107120Sjulian kvm_t *kvmd = NULL; 112107120Sjulian char *memf = NULL; 113107120Sjulian 114121054Semax while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) { 115107120Sjulian switch (opt) { 116121054Semax case 'n': 117121054Semax numeric_bdaddr = 1; 118121054Semax break; 119121054Semax 120107120Sjulian case 'M': 121107120Sjulian memf = optarg; 122107120Sjulian break; 123107120Sjulian 124107120Sjulian case 'p': 125107120Sjulian if (strcasecmp(optarg, "hci_raw") == 0) 126107120Sjulian proto = N_HCI_RAW; 127107120Sjulian else if (strcasecmp(optarg, "l2cap_raw") == 0) 128107120Sjulian proto = N_L2CAP_RAW; 129107120Sjulian else if (strcasecmp(optarg, "l2cap") == 0) 130107120Sjulian proto = N_L2CAP; 131114878Sjulian else if (strcasecmp(optarg, "rfcomm") == 0) 132114878Sjulian proto = N_RFCOMM; 133114878Sjulian else if (strcasecmp(optarg, "rfcomm_s") == 0) 134114878Sjulian proto = N_RFCOMM_S; 135107120Sjulian else 136107120Sjulian usage(); 137107120Sjulian /* NOT REACHED */ 138107120Sjulian break; 139107120Sjulian 140107120Sjulian case 'r': 141107120Sjulian route = 1; 142107120Sjulian break; 143107120Sjulian 144107120Sjulian case 'h': 145107120Sjulian default: 146107120Sjulian usage(); 147107120Sjulian /* NOT REACHED */ 148107120Sjulian } 149107120Sjulian } 150107120Sjulian 151114878Sjulian if ((proto == N_HCI_RAW || proto == N_RFCOMM || proto == N_RFCOMM_S) && route) 152107120Sjulian usage(); 153107120Sjulian /* NOT REACHED */ 154107120Sjulian 155114878Sjulian /* 156114878Sjulian * Discard setgid privileges if not the running kernel so that 157114878Sjulian * bad guys can't print interesting stuff from kernel memory. 158114878Sjulian */ 159114878Sjulian if (memf != NULL) 160287345Sdelphij if (setgid(getgid()) != 0) 161287345Sdelphij err(1, "setgid"); 162114878Sjulian 163107120Sjulian kvmd = kopen(memf); 164107120Sjulian if (kvmd == NULL) 165107120Sjulian return (1); 166107120Sjulian 167107120Sjulian switch (proto) { 168107120Sjulian case N_HCI_RAW: 169107120Sjulian hcirawpr(kvmd, nl[N_HCI_RAW].n_value); 170107120Sjulian break; 171107120Sjulian 172107120Sjulian case N_L2CAP_RAW: 173107120Sjulian if (route) 174107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value); 175107120Sjulian else 176107120Sjulian l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value); 177107120Sjulian break; 178107120Sjulian 179107120Sjulian case N_L2CAP: 180107120Sjulian if (route) 181107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value); 182107120Sjulian else 183107120Sjulian l2cappr(kvmd, nl[N_L2CAP].n_value); 184107120Sjulian break; 185107120Sjulian 186114878Sjulian case N_RFCOMM: 187114878Sjulian rfcommpr(kvmd, nl[N_RFCOMM].n_value); 188114878Sjulian break; 189114878Sjulian 190114878Sjulian case N_RFCOMM_S: 191114878Sjulian rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value); 192114878Sjulian break; 193114878Sjulian 194107120Sjulian default: 195107120Sjulian if (route) { 196107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value); 197107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value); 198107120Sjulian } else { 199107120Sjulian hcirawpr(kvmd, nl[N_HCI_RAW].n_value); 200107120Sjulian l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value); 201107120Sjulian l2cappr(kvmd, nl[N_L2CAP].n_value); 202114878Sjulian rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value); 203114878Sjulian rfcommpr(kvmd, nl[N_RFCOMM].n_value); 204107120Sjulian } 205107120Sjulian break; 206107120Sjulian } 207107120Sjulian 208107120Sjulian return (kvm_close(kvmd)); 209107120Sjulian} /* main */ 210107120Sjulian 211107120Sjulian/* 212107120Sjulian * Print raw HCI sockets 213107120Sjulian */ 214107120Sjulian 215107120Sjulianstatic void 216107120Sjulianhcirawpr(kvm_t *kvmd, u_long addr) 217107120Sjulian{ 218107120Sjulian ng_btsocket_hci_raw_pcb_p this = NULL, next = NULL; 219107120Sjulian ng_btsocket_hci_raw_pcb_t pcb; 220107120Sjulian struct socket so; 221107120Sjulian int first = 1; 222107120Sjulian 223107120Sjulian if (addr == 0) 224107120Sjulian return; 225107120Sjulian 226107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 227107120Sjulian return; 228107120Sjulian 229107120Sjulian for ( ; this != NULL; this = next) { 230107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 231107120Sjulian return; 232107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 233107120Sjulian return; 234107120Sjulian 235107120Sjulian next = LIST_NEXT(&pcb, next); 236107120Sjulian 237107120Sjulian if (first) { 238107120Sjulian first = 0; 239107120Sjulian fprintf(stdout, 240107120Sjulian"Active raw HCI sockets\n" \ 241107120Sjulian"%-8.8s %-8.8s %-6.6s %-6.6s %-6.6s %-16.16s\n", 242107120Sjulian "Socket", 243107120Sjulian "PCB", 244107120Sjulian "Flags", 245107120Sjulian "Recv-Q", 246107120Sjulian "Send-Q", 247107120Sjulian "Local address"); 248107120Sjulian } 249107120Sjulian 250107120Sjulian if (pcb.addr.hci_node[0] == 0) { 251107120Sjulian pcb.addr.hci_node[0] = '*'; 252107120Sjulian pcb.addr.hci_node[1] = 0; 253107120Sjulian } 254107120Sjulian 255107120Sjulian fprintf(stdout, 256128076Semax"%-8lx %-8lx %-6.6x %6d %6d %-16.16s\n", 257128076Semax (unsigned long) pcb.so, 258128076Semax (unsigned long) this, 259107120Sjulian pcb.flags, 260275326Sglebius so.so_rcv.sb_ccc, 261275326Sglebius so.so_snd.sb_ccc, 262107120Sjulian pcb.addr.hci_node); 263107120Sjulian } 264107120Sjulian} /* hcirawpr */ 265107120Sjulian 266107120Sjulian/* 267107120Sjulian * Print raw L2CAP sockets 268107120Sjulian */ 269107120Sjulian 270107120Sjulianstatic void 271107120Sjulianl2caprawpr(kvm_t *kvmd, u_long addr) 272107120Sjulian{ 273107120Sjulian ng_btsocket_l2cap_raw_pcb_p this = NULL, next = NULL; 274107120Sjulian ng_btsocket_l2cap_raw_pcb_t pcb; 275107120Sjulian struct socket so; 276107120Sjulian int first = 1; 277107120Sjulian 278107120Sjulian if (addr == 0) 279107120Sjulian return; 280107120Sjulian 281107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 282107120Sjulian return; 283107120Sjulian 284107120Sjulian for ( ; this != NULL; this = next) { 285107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 286107120Sjulian return; 287107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 288107120Sjulian return; 289107120Sjulian 290107120Sjulian next = LIST_NEXT(&pcb, next); 291107120Sjulian 292107120Sjulian if (first) { 293107120Sjulian first = 0; 294107120Sjulian fprintf(stdout, 295107120Sjulian"Active raw L2CAP sockets\n" \ 296114878Sjulian"%-8.8s %-8.8s %-6.6s %-6.6s %-17.17s\n", 297107120Sjulian "Socket", 298107120Sjulian "PCB", 299107120Sjulian "Recv-Q", 300107120Sjulian "Send-Q", 301107120Sjulian "Local address"); 302107120Sjulian } 303107120Sjulian 304107120Sjulian fprintf(stdout, 305128076Semax"%-8lx %-8lx %6d %6d %-17.17s\n", 306128076Semax (unsigned long) pcb.so, 307128076Semax (unsigned long) this, 308275326Sglebius so.so_rcv.sb_ccc, 309275326Sglebius so.so_snd.sb_ccc, 310121054Semax bdaddrpr(&pcb.src, NULL, 0)); 311107120Sjulian } 312107120Sjulian} /* l2caprawpr */ 313107120Sjulian 314107120Sjulian/* 315107120Sjulian * Print L2CAP sockets 316107120Sjulian */ 317107120Sjulian 318107120Sjulianstatic void 319107120Sjulianl2cappr(kvm_t *kvmd, u_long addr) 320107120Sjulian{ 321107120Sjulian static char const * const states[] = { 322107120Sjulian /* NG_BTSOCKET_L2CAP_CLOSED */ "CLOSED", 323107120Sjulian /* NG_BTSOCKET_L2CAP_CONNECTING */ "CON", 324107120Sjulian /* NG_BTSOCKET_L2CAP_CONFIGURING */ "CONFIG", 325107120Sjulian /* NG_BTSOCKET_L2CAP_OPEN */ "OPEN", 326107120Sjulian /* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON" 327107120Sjulian }; 328107120Sjulian 329107120Sjulian ng_btsocket_l2cap_pcb_p this = NULL, next = NULL; 330107120Sjulian ng_btsocket_l2cap_pcb_t pcb; 331107120Sjulian struct socket so; 332107120Sjulian int first = 1; 333121054Semax char local[24], remote[24]; 334107120Sjulian 335107120Sjulian if (addr == 0) 336107120Sjulian return; 337107120Sjulian 338107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 339107120Sjulian return; 340107120Sjulian 341107120Sjulian for ( ; this != NULL; this = next) { 342107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 343107120Sjulian return; 344107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 345107120Sjulian return; 346107120Sjulian 347107120Sjulian next = LIST_NEXT(&pcb, next); 348107120Sjulian 349107120Sjulian if (first) { 350107120Sjulian first = 0; 351107120Sjulian fprintf(stdout, 352107120Sjulian"Active L2CAP sockets\n" \ 353114878Sjulian"%-8.8s %-6.6s %-6.6s %-23.23s %-17.17s %-5.5s %s\n", 354107120Sjulian "PCB", 355107120Sjulian "Recv-Q", 356107120Sjulian "Send-Q", 357107120Sjulian "Local address/PSM", 358107120Sjulian "Foreign address", 359107120Sjulian "CID", 360107120Sjulian "State"); 361107120Sjulian } 362107120Sjulian 363107120Sjulian fprintf(stdout, 364128076Semax"%-8lx %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n", 365128076Semax (unsigned long) this, 366275326Sglebius so.so_rcv.sb_ccc, 367275326Sglebius so.so_snd.sb_ccc, 368121054Semax bdaddrpr(&pcb.src, local, sizeof(local)), 369121054Semax pcb.psm, 370121054Semax bdaddrpr(&pcb.dst, remote, sizeof(remote)), 371107120Sjulian pcb.cid, 372107120Sjulian (so.so_options & SO_ACCEPTCONN)? 373107120Sjulian "LISTEN" : state2str(pcb.state)); 374107120Sjulian } 375107120Sjulian} /* l2cappr */ 376107120Sjulian 377107120Sjulian/* 378107120Sjulian * Print L2CAP routing table 379107120Sjulian */ 380107120Sjulian 381107120Sjulianstatic void 382107120Sjulianl2caprtpr(kvm_t *kvmd, u_long addr) 383107120Sjulian{ 384107120Sjulian ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL; 385107120Sjulian ng_btsocket_l2cap_rtentry_t rt; 386107120Sjulian int first = 1; 387107120Sjulian 388107120Sjulian if (addr == 0) 389107120Sjulian return; 390107120Sjulian 391107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 392107120Sjulian return; 393107120Sjulian 394107120Sjulian for ( ; this != NULL; this = next) { 395107120Sjulian if (kread(kvmd, (u_long) this, (char *) &rt, sizeof(rt)) < 0) 396107120Sjulian return; 397107120Sjulian 398107120Sjulian next = LIST_NEXT(&rt, next); 399107120Sjulian 400107120Sjulian if (first) { 401107120Sjulian first = 0; 402107120Sjulian fprintf(stdout, 403107120Sjulian"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : ""); 404107120Sjulian fprintf(stdout, 405114878Sjulian"%-8.8s %-8.8s %-17.17s\n", "RTentry", 406107120Sjulian "Hook", 407107120Sjulian "BD_ADDR"); 408107120Sjulian } 409107120Sjulian 410107120Sjulian fprintf(stdout, 411128076Semax"%-8lx %-8lx %-17.17s\n", 412128076Semax (unsigned long) this, 413128076Semax (unsigned long) rt.hook, 414121054Semax bdaddrpr(&rt.src, NULL, 0)); 415107120Sjulian } 416107120Sjulian} /* l2caprtpr */ 417107120Sjulian 418107120Sjulian/* 419114878Sjulian * Print RFCOMM sockets 420114878Sjulian */ 421114878Sjulian 422114878Sjulianstatic void 423114878Sjulianrfcommpr(kvm_t *kvmd, u_long addr) 424114878Sjulian{ 425114878Sjulian static char const * const states[] = { 426114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CLOSED */ "CLOSED", 427114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT */ "W4CON", 428114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONFIGURING */ "CONFIG", 429114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONNECTING */ "CONN", 430114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONNECTED */ "OPEN", 431114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING */ "DISCON" 432114878Sjulian }; 433114878Sjulian 434114878Sjulian ng_btsocket_rfcomm_pcb_p this = NULL, next = NULL; 435114878Sjulian ng_btsocket_rfcomm_pcb_t pcb; 436114878Sjulian struct socket so; 437114878Sjulian int first = 1; 438121054Semax char local[24], remote[24]; 439114878Sjulian 440114878Sjulian if (addr == 0) 441114878Sjulian return; 442114878Sjulian 443114878Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 444114878Sjulian return; 445114878Sjulian 446114878Sjulian for ( ; this != NULL; this = next) { 447114878Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 448114878Sjulian return; 449114878Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 450114878Sjulian return; 451114878Sjulian 452114878Sjulian next = LIST_NEXT(&pcb, next); 453114878Sjulian 454114878Sjulian if (first) { 455114878Sjulian first = 0; 456114878Sjulian fprintf(stdout, 457114878Sjulian"Active RFCOMM sockets\n" \ 458114878Sjulian"%-8.8s %-6.6s %-6.6s %-17.17s %-17.17s %-4.4s %-4.4s %s\n", 459114878Sjulian "PCB", 460114878Sjulian "Recv-Q", 461114878Sjulian "Send-Q", 462114878Sjulian "Local address", 463114878Sjulian "Foreign address", 464114878Sjulian "Chan", 465114878Sjulian "DLCI", 466114878Sjulian "State"); 467114878Sjulian } 468114878Sjulian 469114878Sjulian fprintf(stdout, 470128076Semax"%-8lx %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n", 471128076Semax (unsigned long) this, 472275326Sglebius so.so_rcv.sb_ccc, 473275326Sglebius so.so_snd.sb_ccc, 474121054Semax bdaddrpr(&pcb.src, local, sizeof(local)), 475121054Semax bdaddrpr(&pcb.dst, remote, sizeof(remote)), 476114878Sjulian pcb.channel, 477114878Sjulian pcb.dlci, 478114878Sjulian (so.so_options & SO_ACCEPTCONN)? 479114878Sjulian "LISTEN" : state2str(pcb.state)); 480114878Sjulian } 481114878Sjulian} /* rfcommpr */ 482114878Sjulian 483114878Sjulian/* 484114878Sjulian * Print RFCOMM sessions 485114878Sjulian */ 486114878Sjulian 487114878Sjulianstatic void 488114878Sjulianrfcommpr_s(kvm_t *kvmd, u_long addr) 489114878Sjulian{ 490114878Sjulian static char const * const states[] = { 491114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CLOSED */ "CLOSED", 492114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_LISTENING */ "LISTEN", 493114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTING */ "CONNECTING", 494114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTED */ "CONNECTED", 495114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_OPEN */ "OPEN", 496114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING */ "DISCONNECTING" 497114878Sjulian }; 498114878Sjulian 499114878Sjulian ng_btsocket_rfcomm_session_p this = NULL, next = NULL; 500114878Sjulian ng_btsocket_rfcomm_session_t s; 501114878Sjulian struct socket so; 502114878Sjulian int first = 1; 503114878Sjulian 504114878Sjulian if (addr == 0) 505114878Sjulian return; 506114878Sjulian 507114878Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 508114878Sjulian return; 509114878Sjulian 510114878Sjulian for ( ; this != NULL; this = next) { 511114878Sjulian if (kread(kvmd, (u_long) this, (char *) &s, sizeof(s)) < 0) 512114878Sjulian return; 513114878Sjulian if (kread(kvmd, (u_long) s.l2so, (char *) &so, sizeof(so)) < 0) 514114878Sjulian return; 515114878Sjulian 516114878Sjulian next = LIST_NEXT(&s, next); 517114878Sjulian 518114878Sjulian if (first) { 519114878Sjulian first = 0; 520114878Sjulian fprintf(stdout, 521114878Sjulian"Active RFCOMM sessions\n" \ 522114878Sjulian"%-8.8s %-8.8s %-4.4s %-5.5s %-5.5s %-4.4s %s\n", 523114878Sjulian "L2PCB", 524114878Sjulian "PCB", 525114878Sjulian "Flags", 526114878Sjulian "MTU", 527114878Sjulian "Out-Q", 528114878Sjulian "DLCs", 529114878Sjulian "State"); 530114878Sjulian } 531114878Sjulian 532114878Sjulian fprintf(stdout, 533128076Semax"%-8lx %-8lx %-4x %-5d %-5d %-4s %s\n", 534128076Semax (unsigned long) so.so_pcb, 535128076Semax (unsigned long) this, 536114878Sjulian s.flags, 537114878Sjulian s.mtu, 538114878Sjulian s.outq.len, 539114878Sjulian LIST_EMPTY(&s.dlcs)? "No" : "Yes", 540114878Sjulian state2str(s.state)); 541114878Sjulian } 542114878Sjulian} /* rfcommpr_s */ 543114878Sjulian 544114878Sjulian/* 545121054Semax * Return BD_ADDR as string 546121054Semax */ 547121054Semax 548121054Semaxstatic char * 549121054Semaxbdaddrpr(bdaddr_p const ba, char *str, int len) 550121054Semax{ 551121054Semax static char buffer[MAXHOSTNAMELEN]; 552121054Semax struct hostent *he = NULL; 553121054Semax 554121054Semax if (str == NULL) { 555121054Semax str = buffer; 556121054Semax len = sizeof(buffer); 557121054Semax } 558121054Semax 559121054Semax if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { 560121054Semax str[0] = '*'; 561121054Semax str[1] = 0; 562121054Semax 563121054Semax return (str); 564121054Semax } 565121054Semax 566121054Semax if (!numeric_bdaddr && 567121054Semax (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { 568121054Semax strlcpy(str, he->h_name, len); 569121054Semax 570121054Semax return (str); 571121054Semax } 572121054Semax 573121054Semax bt_ntoa(ba, str); 574121054Semax 575121054Semax return (str); 576121054Semax} /* bdaddrpr */ 577121054Semax 578121054Semax/* 579107120Sjulian * Open kvm 580107120Sjulian */ 581107120Sjulian 582107120Sjulianstatic kvm_t * 583107120Sjuliankopen(char const *memf) 584107120Sjulian{ 585107120Sjulian kvm_t *kvmd = NULL; 586107120Sjulian char errbuf[_POSIX2_LINE_MAX]; 587107120Sjulian 588107120Sjulian kvmd = kvm_openfiles(NULL, memf, NULL, O_RDONLY, errbuf); 589287345Sdelphij if (setgid(getgid()) != 0) 590287345Sdelphij err(1, "setgid"); 591107120Sjulian if (kvmd == NULL) { 592107120Sjulian warnx("kvm_openfiles: %s", errbuf); 593107120Sjulian return (NULL); 594107120Sjulian } 595107120Sjulian 596107120Sjulian if (kvm_nlist(kvmd, nl) < 0) { 597107120Sjulian warnx("kvm_nlist: %s", kvm_geterr(kvmd)); 598107120Sjulian goto fail; 599107120Sjulian } 600107120Sjulian 601107120Sjulian if (nl[0].n_type == 0) { 602107120Sjulian warnx("kvm_nlist: no namelist"); 603107120Sjulian goto fail; 604107120Sjulian } 605107120Sjulian 606107120Sjulian return (kvmd); 607107120Sjulianfail: 608107120Sjulian kvm_close(kvmd); 609107120Sjulian 610107120Sjulian return (NULL); 611107120Sjulian} /* kopen */ 612107120Sjulian 613107120Sjulian/* 614107120Sjulian * Read kvm 615107120Sjulian */ 616107120Sjulian 617107120Sjulianstatic int 618107120Sjuliankread(kvm_t *kvmd, u_long addr, char *buffer, int size) 619107120Sjulian{ 620107120Sjulian if (kvmd == NULL || buffer == NULL) 621107120Sjulian return (-1); 622107120Sjulian 623107120Sjulian if (kvm_read(kvmd, addr, buffer, size) != size) { 624107120Sjulian warnx("kvm_read: %s", kvm_geterr(kvmd)); 625107120Sjulian return (-1); 626107120Sjulian } 627107120Sjulian 628107120Sjulian return (0); 629107120Sjulian} /* kread */ 630107120Sjulian 631107120Sjulian/* 632107120Sjulian * Print usage and exit 633107120Sjulian */ 634107120Sjulian 635107120Sjulianstatic void 636107120Sjulianusage(void) 637107120Sjulian{ 638121054Semax fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n"); 639107120Sjulian exit(255); 640107120Sjulian} /* usage */ 641107120Sjulian 642