btsockstat.c revision 281210
1107120Sjulian/* 2107120Sjulian * btsockstat.c 3107120Sjulian * 4107120Sjulian * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5107120Sjulian * All rights reserved. 6107120Sjulian * 7107120Sjulian * Redistribution and use in source and binary forms, with or without 8107120Sjulian * modification, are permitted provided that the following conditions 9107120Sjulian * are met: 10107120Sjulian * 1. Redistributions of source code must retain the above copyright 11107120Sjulian * notice, this list of conditions and the following disclaimer. 12107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer in the 14107120Sjulian * documentation and/or other materials provided with the distribution. 15107120Sjulian * 16107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26107120Sjulian * SUCH DAMAGE. 27107120Sjulian * 28121054Semax * $Id: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $ 29107120Sjulian * $FreeBSD: head/usr.bin/bluetooth/btsockstat/btsockstat.c 281210 2015-04-07 16:48:23Z takawata $ 30107120Sjulian */ 31107120Sjulian 32107120Sjulian#include <sys/types.h> 33107120Sjulian#include <sys/callout.h> 34107120Sjulian#include <sys/param.h> 35180964Semax#include <sys/protosw.h> 36107120Sjulian#include <sys/queue.h> 37107120Sjulian#include <sys/socket.h> 38107120Sjulian#include <sys/socketvar.h> 39107120Sjulian 40107120Sjulian#include <net/if.h> 41107120Sjulian 42281210Stakawata#define L2CAP_SOCKET_CHECKED 43121054Semax#include <bluetooth.h> 44107120Sjulian#include <err.h> 45107120Sjulian#include <fcntl.h> 46107120Sjulian#include <kvm.h> 47107120Sjulian#include <limits.h> 48121064Sbde#include <nlist.h> 49107120Sjulian 50121054Semax#include <netgraph/bluetooth/include/ng_bluetooth.h> 51121054Semax#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h> 52121054Semax#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h> 53121054Semax#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h> 54107120Sjulian 55107120Sjulian#include <stdio.h> 56107120Sjulian#include <stdlib.h> 57107120Sjulian#include <string.h> 58107120Sjulian#include <unistd.h> 59107120Sjulian 60107120Sjulianstatic void hcirawpr (kvm_t *kvmd, u_long addr); 61107120Sjulianstatic void l2caprawpr (kvm_t *kvmd, u_long addr); 62107120Sjulianstatic void l2cappr (kvm_t *kvmd, u_long addr); 63107120Sjulianstatic void l2caprtpr (kvm_t *kvmd, u_long addr); 64114878Sjulianstatic void rfcommpr (kvm_t *kvmd, u_long addr); 65114878Sjulianstatic void rfcommpr_s (kvm_t *kvmd, u_long addr); 66107120Sjulian 67121054Semaxstatic char * bdaddrpr (bdaddr_p const ba, char *str, int len); 68121054Semax 69107120Sjulianstatic kvm_t * kopen (char const *memf); 70107120Sjulianstatic int kread (kvm_t *kvmd, u_long addr, char *buffer, int size); 71107120Sjulian 72107120Sjulianstatic void usage (void); 73107120Sjulian 74107120Sjulian/* 75107120Sjulian * List of symbols 76107120Sjulian */ 77107120Sjulian 78107120Sjulianstatic struct nlist nl[] = { 79107120Sjulian#define N_HCI_RAW 0 80107120Sjulian { "_ng_btsocket_hci_raw_sockets" }, 81107120Sjulian#define N_L2CAP_RAW 1 82107120Sjulian { "_ng_btsocket_l2cap_raw_sockets" }, 83107120Sjulian#define N_L2CAP 2 84107120Sjulian { "_ng_btsocket_l2cap_sockets" }, 85107120Sjulian#define N_L2CAP_RAW_RT 3 86107120Sjulian { "_ng_btsocket_l2cap_raw_rt" }, 87107120Sjulian#define N_L2CAP_RT 4 88107120Sjulian { "_ng_btsocket_l2cap_rt" }, 89114878Sjulian#define N_RFCOMM 5 90114878Sjulian { "_ng_btsocket_rfcomm_sockets" }, 91114878Sjulian#define N_RFCOMM_S 6 92114878Sjulian { "_ng_btsocket_rfcomm_sessions" }, 93107120Sjulian { "" }, 94107120Sjulian}; 95107120Sjulian 96114878Sjulian#define state2str(x) \ 97114878Sjulian (((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)]) 98114878Sjulian 99107120Sjulian/* 100107120Sjulian * Main 101107120Sjulian */ 102107120Sjulian 103121054Semaxstatic int numeric_bdaddr = 0; 104121054Semax 105107120Sjulianint 106107120Sjulianmain(int argc, char *argv[]) 107107120Sjulian{ 108107120Sjulian int opt, proto = -1, route = 0; 109107120Sjulian kvm_t *kvmd = NULL; 110107120Sjulian char *memf = NULL; 111107120Sjulian 112121054Semax while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) { 113107120Sjulian switch (opt) { 114121054Semax case 'n': 115121054Semax numeric_bdaddr = 1; 116121054Semax break; 117121054Semax 118107120Sjulian case 'M': 119107120Sjulian memf = optarg; 120107120Sjulian break; 121107120Sjulian 122107120Sjulian case 'p': 123107120Sjulian if (strcasecmp(optarg, "hci_raw") == 0) 124107120Sjulian proto = N_HCI_RAW; 125107120Sjulian else if (strcasecmp(optarg, "l2cap_raw") == 0) 126107120Sjulian proto = N_L2CAP_RAW; 127107120Sjulian else if (strcasecmp(optarg, "l2cap") == 0) 128107120Sjulian proto = N_L2CAP; 129114878Sjulian else if (strcasecmp(optarg, "rfcomm") == 0) 130114878Sjulian proto = N_RFCOMM; 131114878Sjulian else if (strcasecmp(optarg, "rfcomm_s") == 0) 132114878Sjulian proto = N_RFCOMM_S; 133107120Sjulian else 134107120Sjulian usage(); 135107120Sjulian /* NOT REACHED */ 136107120Sjulian break; 137107120Sjulian 138107120Sjulian case 'r': 139107120Sjulian route = 1; 140107120Sjulian break; 141107120Sjulian 142107120Sjulian case 'h': 143107120Sjulian default: 144107120Sjulian usage(); 145107120Sjulian /* NOT REACHED */ 146107120Sjulian } 147107120Sjulian } 148107120Sjulian 149114878Sjulian if ((proto == N_HCI_RAW || proto == N_RFCOMM || proto == N_RFCOMM_S) && route) 150107120Sjulian usage(); 151107120Sjulian /* NOT REACHED */ 152107120Sjulian 153114878Sjulian /* 154114878Sjulian * Discard setgid privileges if not the running kernel so that 155114878Sjulian * bad guys can't print interesting stuff from kernel memory. 156114878Sjulian */ 157114878Sjulian 158114878Sjulian if (memf != NULL) 159114878Sjulian setgid(getgid()); 160114878Sjulian 161107120Sjulian kvmd = kopen(memf); 162107120Sjulian if (kvmd == NULL) 163107120Sjulian return (1); 164107120Sjulian 165107120Sjulian switch (proto) { 166107120Sjulian case N_HCI_RAW: 167107120Sjulian hcirawpr(kvmd, nl[N_HCI_RAW].n_value); 168107120Sjulian break; 169107120Sjulian 170107120Sjulian case N_L2CAP_RAW: 171107120Sjulian if (route) 172107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value); 173107120Sjulian else 174107120Sjulian l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value); 175107120Sjulian break; 176107120Sjulian 177107120Sjulian case N_L2CAP: 178107120Sjulian if (route) 179107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value); 180107120Sjulian else 181107120Sjulian l2cappr(kvmd, nl[N_L2CAP].n_value); 182107120Sjulian break; 183107120Sjulian 184114878Sjulian case N_RFCOMM: 185114878Sjulian rfcommpr(kvmd, nl[N_RFCOMM].n_value); 186114878Sjulian break; 187114878Sjulian 188114878Sjulian case N_RFCOMM_S: 189114878Sjulian rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value); 190114878Sjulian break; 191114878Sjulian 192107120Sjulian default: 193107120Sjulian if (route) { 194107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value); 195107120Sjulian l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value); 196107120Sjulian } else { 197107120Sjulian hcirawpr(kvmd, nl[N_HCI_RAW].n_value); 198107120Sjulian l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value); 199107120Sjulian l2cappr(kvmd, nl[N_L2CAP].n_value); 200114878Sjulian rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value); 201114878Sjulian rfcommpr(kvmd, nl[N_RFCOMM].n_value); 202107120Sjulian } 203107120Sjulian break; 204107120Sjulian } 205107120Sjulian 206107120Sjulian return (kvm_close(kvmd)); 207107120Sjulian} /* main */ 208107120Sjulian 209107120Sjulian/* 210107120Sjulian * Print raw HCI sockets 211107120Sjulian */ 212107120Sjulian 213107120Sjulianstatic void 214107120Sjulianhcirawpr(kvm_t *kvmd, u_long addr) 215107120Sjulian{ 216107120Sjulian ng_btsocket_hci_raw_pcb_p this = NULL, next = NULL; 217107120Sjulian ng_btsocket_hci_raw_pcb_t pcb; 218107120Sjulian struct socket so; 219107120Sjulian int first = 1; 220107120Sjulian 221107120Sjulian if (addr == 0) 222107120Sjulian return; 223107120Sjulian 224107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 225107120Sjulian return; 226107120Sjulian 227107120Sjulian for ( ; this != NULL; this = next) { 228107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 229107120Sjulian return; 230107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 231107120Sjulian return; 232107120Sjulian 233107120Sjulian next = LIST_NEXT(&pcb, next); 234107120Sjulian 235107120Sjulian if (first) { 236107120Sjulian first = 0; 237107120Sjulian fprintf(stdout, 238107120Sjulian"Active raw HCI sockets\n" \ 239107120Sjulian"%-8.8s %-8.8s %-6.6s %-6.6s %-6.6s %-16.16s\n", 240107120Sjulian "Socket", 241107120Sjulian "PCB", 242107120Sjulian "Flags", 243107120Sjulian "Recv-Q", 244107120Sjulian "Send-Q", 245107120Sjulian "Local address"); 246107120Sjulian } 247107120Sjulian 248107120Sjulian if (pcb.addr.hci_node[0] == 0) { 249107120Sjulian pcb.addr.hci_node[0] = '*'; 250107120Sjulian pcb.addr.hci_node[1] = 0; 251107120Sjulian } 252107120Sjulian 253107120Sjulian fprintf(stdout, 254128076Semax"%-8lx %-8lx %-6.6x %6d %6d %-16.16s\n", 255128076Semax (unsigned long) pcb.so, 256128076Semax (unsigned long) this, 257107120Sjulian pcb.flags, 258275326Sglebius so.so_rcv.sb_ccc, 259275326Sglebius so.so_snd.sb_ccc, 260107120Sjulian pcb.addr.hci_node); 261107120Sjulian } 262107120Sjulian} /* hcirawpr */ 263107120Sjulian 264107120Sjulian/* 265107120Sjulian * Print raw L2CAP sockets 266107120Sjulian */ 267107120Sjulian 268107120Sjulianstatic void 269107120Sjulianl2caprawpr(kvm_t *kvmd, u_long addr) 270107120Sjulian{ 271107120Sjulian ng_btsocket_l2cap_raw_pcb_p this = NULL, next = NULL; 272107120Sjulian ng_btsocket_l2cap_raw_pcb_t pcb; 273107120Sjulian struct socket so; 274107120Sjulian int first = 1; 275107120Sjulian 276107120Sjulian if (addr == 0) 277107120Sjulian return; 278107120Sjulian 279107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 280107120Sjulian return; 281107120Sjulian 282107120Sjulian for ( ; this != NULL; this = next) { 283107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 284107120Sjulian return; 285107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 286107120Sjulian return; 287107120Sjulian 288107120Sjulian next = LIST_NEXT(&pcb, next); 289107120Sjulian 290107120Sjulian if (first) { 291107120Sjulian first = 0; 292107120Sjulian fprintf(stdout, 293107120Sjulian"Active raw L2CAP sockets\n" \ 294114878Sjulian"%-8.8s %-8.8s %-6.6s %-6.6s %-17.17s\n", 295107120Sjulian "Socket", 296107120Sjulian "PCB", 297107120Sjulian "Recv-Q", 298107120Sjulian "Send-Q", 299107120Sjulian "Local address"); 300107120Sjulian } 301107120Sjulian 302107120Sjulian fprintf(stdout, 303128076Semax"%-8lx %-8lx %6d %6d %-17.17s\n", 304128076Semax (unsigned long) pcb.so, 305128076Semax (unsigned long) this, 306275326Sglebius so.so_rcv.sb_ccc, 307275326Sglebius so.so_snd.sb_ccc, 308121054Semax bdaddrpr(&pcb.src, NULL, 0)); 309107120Sjulian } 310107120Sjulian} /* l2caprawpr */ 311107120Sjulian 312107120Sjulian/* 313107120Sjulian * Print L2CAP sockets 314107120Sjulian */ 315107120Sjulian 316107120Sjulianstatic void 317107120Sjulianl2cappr(kvm_t *kvmd, u_long addr) 318107120Sjulian{ 319107120Sjulian static char const * const states[] = { 320107120Sjulian /* NG_BTSOCKET_L2CAP_CLOSED */ "CLOSED", 321107120Sjulian /* NG_BTSOCKET_L2CAP_CONNECTING */ "CON", 322107120Sjulian /* NG_BTSOCKET_L2CAP_CONFIGURING */ "CONFIG", 323107120Sjulian /* NG_BTSOCKET_L2CAP_OPEN */ "OPEN", 324107120Sjulian /* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON" 325107120Sjulian }; 326107120Sjulian 327107120Sjulian ng_btsocket_l2cap_pcb_p this = NULL, next = NULL; 328107120Sjulian ng_btsocket_l2cap_pcb_t pcb; 329107120Sjulian struct socket so; 330107120Sjulian int first = 1; 331121054Semax char local[24], remote[24]; 332107120Sjulian 333107120Sjulian if (addr == 0) 334107120Sjulian return; 335107120Sjulian 336107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 337107120Sjulian return; 338107120Sjulian 339107120Sjulian for ( ; this != NULL; this = next) { 340107120Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 341107120Sjulian return; 342107120Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 343107120Sjulian return; 344107120Sjulian 345107120Sjulian next = LIST_NEXT(&pcb, next); 346107120Sjulian 347107120Sjulian if (first) { 348107120Sjulian first = 0; 349107120Sjulian fprintf(stdout, 350107120Sjulian"Active L2CAP sockets\n" \ 351114878Sjulian"%-8.8s %-6.6s %-6.6s %-23.23s %-17.17s %-5.5s %s\n", 352107120Sjulian "PCB", 353107120Sjulian "Recv-Q", 354107120Sjulian "Send-Q", 355107120Sjulian "Local address/PSM", 356107120Sjulian "Foreign address", 357107120Sjulian "CID", 358107120Sjulian "State"); 359107120Sjulian } 360107120Sjulian 361107120Sjulian fprintf(stdout, 362128076Semax"%-8lx %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n", 363128076Semax (unsigned long) this, 364275326Sglebius so.so_rcv.sb_ccc, 365275326Sglebius so.so_snd.sb_ccc, 366121054Semax bdaddrpr(&pcb.src, local, sizeof(local)), 367121054Semax pcb.psm, 368121054Semax bdaddrpr(&pcb.dst, remote, sizeof(remote)), 369107120Sjulian pcb.cid, 370107120Sjulian (so.so_options & SO_ACCEPTCONN)? 371107120Sjulian "LISTEN" : state2str(pcb.state)); 372107120Sjulian } 373107120Sjulian} /* l2cappr */ 374107120Sjulian 375107120Sjulian/* 376107120Sjulian * Print L2CAP routing table 377107120Sjulian */ 378107120Sjulian 379107120Sjulianstatic void 380107120Sjulianl2caprtpr(kvm_t *kvmd, u_long addr) 381107120Sjulian{ 382107120Sjulian ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL; 383107120Sjulian ng_btsocket_l2cap_rtentry_t rt; 384107120Sjulian int first = 1; 385107120Sjulian 386107120Sjulian if (addr == 0) 387107120Sjulian return; 388107120Sjulian 389107120Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 390107120Sjulian return; 391107120Sjulian 392107120Sjulian for ( ; this != NULL; this = next) { 393107120Sjulian if (kread(kvmd, (u_long) this, (char *) &rt, sizeof(rt)) < 0) 394107120Sjulian return; 395107120Sjulian 396107120Sjulian next = LIST_NEXT(&rt, next); 397107120Sjulian 398107120Sjulian if (first) { 399107120Sjulian first = 0; 400107120Sjulian fprintf(stdout, 401107120Sjulian"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : ""); 402107120Sjulian fprintf(stdout, 403114878Sjulian"%-8.8s %-8.8s %-17.17s\n", "RTentry", 404107120Sjulian "Hook", 405107120Sjulian "BD_ADDR"); 406107120Sjulian } 407107120Sjulian 408107120Sjulian fprintf(stdout, 409128076Semax"%-8lx %-8lx %-17.17s\n", 410128076Semax (unsigned long) this, 411128076Semax (unsigned long) rt.hook, 412121054Semax bdaddrpr(&rt.src, NULL, 0)); 413107120Sjulian } 414107120Sjulian} /* l2caprtpr */ 415107120Sjulian 416107120Sjulian/* 417114878Sjulian * Print RFCOMM sockets 418114878Sjulian */ 419114878Sjulian 420114878Sjulianstatic void 421114878Sjulianrfcommpr(kvm_t *kvmd, u_long addr) 422114878Sjulian{ 423114878Sjulian static char const * const states[] = { 424114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CLOSED */ "CLOSED", 425114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT */ "W4CON", 426114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONFIGURING */ "CONFIG", 427114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONNECTING */ "CONN", 428114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_CONNECTED */ "OPEN", 429114878Sjulian /* NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING */ "DISCON" 430114878Sjulian }; 431114878Sjulian 432114878Sjulian ng_btsocket_rfcomm_pcb_p this = NULL, next = NULL; 433114878Sjulian ng_btsocket_rfcomm_pcb_t pcb; 434114878Sjulian struct socket so; 435114878Sjulian int first = 1; 436121054Semax char local[24], remote[24]; 437114878Sjulian 438114878Sjulian if (addr == 0) 439114878Sjulian return; 440114878Sjulian 441114878Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 442114878Sjulian return; 443114878Sjulian 444114878Sjulian for ( ; this != NULL; this = next) { 445114878Sjulian if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0) 446114878Sjulian return; 447114878Sjulian if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0) 448114878Sjulian return; 449114878Sjulian 450114878Sjulian next = LIST_NEXT(&pcb, next); 451114878Sjulian 452114878Sjulian if (first) { 453114878Sjulian first = 0; 454114878Sjulian fprintf(stdout, 455114878Sjulian"Active RFCOMM sockets\n" \ 456114878Sjulian"%-8.8s %-6.6s %-6.6s %-17.17s %-17.17s %-4.4s %-4.4s %s\n", 457114878Sjulian "PCB", 458114878Sjulian "Recv-Q", 459114878Sjulian "Send-Q", 460114878Sjulian "Local address", 461114878Sjulian "Foreign address", 462114878Sjulian "Chan", 463114878Sjulian "DLCI", 464114878Sjulian "State"); 465114878Sjulian } 466114878Sjulian 467114878Sjulian fprintf(stdout, 468128076Semax"%-8lx %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n", 469128076Semax (unsigned long) this, 470275326Sglebius so.so_rcv.sb_ccc, 471275326Sglebius so.so_snd.sb_ccc, 472121054Semax bdaddrpr(&pcb.src, local, sizeof(local)), 473121054Semax bdaddrpr(&pcb.dst, remote, sizeof(remote)), 474114878Sjulian pcb.channel, 475114878Sjulian pcb.dlci, 476114878Sjulian (so.so_options & SO_ACCEPTCONN)? 477114878Sjulian "LISTEN" : state2str(pcb.state)); 478114878Sjulian } 479114878Sjulian} /* rfcommpr */ 480114878Sjulian 481114878Sjulian/* 482114878Sjulian * Print RFCOMM sessions 483114878Sjulian */ 484114878Sjulian 485114878Sjulianstatic void 486114878Sjulianrfcommpr_s(kvm_t *kvmd, u_long addr) 487114878Sjulian{ 488114878Sjulian static char const * const states[] = { 489114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CLOSED */ "CLOSED", 490114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_LISTENING */ "LISTEN", 491114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTING */ "CONNECTING", 492114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTED */ "CONNECTED", 493114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_OPEN */ "OPEN", 494114878Sjulian /* NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING */ "DISCONNECTING" 495114878Sjulian }; 496114878Sjulian 497114878Sjulian ng_btsocket_rfcomm_session_p this = NULL, next = NULL; 498114878Sjulian ng_btsocket_rfcomm_session_t s; 499114878Sjulian struct socket so; 500114878Sjulian int first = 1; 501114878Sjulian 502114878Sjulian if (addr == 0) 503114878Sjulian return; 504114878Sjulian 505114878Sjulian if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0) 506114878Sjulian return; 507114878Sjulian 508114878Sjulian for ( ; this != NULL; this = next) { 509114878Sjulian if (kread(kvmd, (u_long) this, (char *) &s, sizeof(s)) < 0) 510114878Sjulian return; 511114878Sjulian if (kread(kvmd, (u_long) s.l2so, (char *) &so, sizeof(so)) < 0) 512114878Sjulian return; 513114878Sjulian 514114878Sjulian next = LIST_NEXT(&s, next); 515114878Sjulian 516114878Sjulian if (first) { 517114878Sjulian first = 0; 518114878Sjulian fprintf(stdout, 519114878Sjulian"Active RFCOMM sessions\n" \ 520114878Sjulian"%-8.8s %-8.8s %-4.4s %-5.5s %-5.5s %-4.4s %s\n", 521114878Sjulian "L2PCB", 522114878Sjulian "PCB", 523114878Sjulian "Flags", 524114878Sjulian "MTU", 525114878Sjulian "Out-Q", 526114878Sjulian "DLCs", 527114878Sjulian "State"); 528114878Sjulian } 529114878Sjulian 530114878Sjulian fprintf(stdout, 531128076Semax"%-8lx %-8lx %-4x %-5d %-5d %-4s %s\n", 532128076Semax (unsigned long) so.so_pcb, 533128076Semax (unsigned long) this, 534114878Sjulian s.flags, 535114878Sjulian s.mtu, 536114878Sjulian s.outq.len, 537114878Sjulian LIST_EMPTY(&s.dlcs)? "No" : "Yes", 538114878Sjulian state2str(s.state)); 539114878Sjulian } 540114878Sjulian} /* rfcommpr_s */ 541114878Sjulian 542114878Sjulian/* 543121054Semax * Return BD_ADDR as string 544121054Semax */ 545121054Semax 546121054Semaxstatic char * 547121054Semaxbdaddrpr(bdaddr_p const ba, char *str, int len) 548121054Semax{ 549121054Semax static char buffer[MAXHOSTNAMELEN]; 550121054Semax struct hostent *he = NULL; 551121054Semax 552121054Semax if (str == NULL) { 553121054Semax str = buffer; 554121054Semax len = sizeof(buffer); 555121054Semax } 556121054Semax 557121054Semax if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { 558121054Semax str[0] = '*'; 559121054Semax str[1] = 0; 560121054Semax 561121054Semax return (str); 562121054Semax } 563121054Semax 564121054Semax if (!numeric_bdaddr && 565121054Semax (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { 566121054Semax strlcpy(str, he->h_name, len); 567121054Semax 568121054Semax return (str); 569121054Semax } 570121054Semax 571121054Semax bt_ntoa(ba, str); 572121054Semax 573121054Semax return (str); 574121054Semax} /* bdaddrpr */ 575121054Semax 576121054Semax/* 577107120Sjulian * Open kvm 578107120Sjulian */ 579107120Sjulian 580107120Sjulianstatic kvm_t * 581107120Sjuliankopen(char const *memf) 582107120Sjulian{ 583107120Sjulian kvm_t *kvmd = NULL; 584107120Sjulian char errbuf[_POSIX2_LINE_MAX]; 585107120Sjulian 586107120Sjulian /* 587107120Sjulian * Discard setgid privileges if not the running kernel so that 588107120Sjulian * bad guys can't print interesting stuff from kernel memory. 589107120Sjulian */ 590107120Sjulian 591107120Sjulian if (memf != NULL) 592107120Sjulian setgid(getgid()); 593107120Sjulian 594107120Sjulian kvmd = kvm_openfiles(NULL, memf, NULL, O_RDONLY, errbuf); 595107120Sjulian if (kvmd == NULL) { 596107120Sjulian warnx("kvm_openfiles: %s", errbuf); 597107120Sjulian return (NULL); 598107120Sjulian } 599107120Sjulian 600107120Sjulian if (kvm_nlist(kvmd, nl) < 0) { 601107120Sjulian warnx("kvm_nlist: %s", kvm_geterr(kvmd)); 602107120Sjulian goto fail; 603107120Sjulian } 604107120Sjulian 605107120Sjulian if (nl[0].n_type == 0) { 606107120Sjulian warnx("kvm_nlist: no namelist"); 607107120Sjulian goto fail; 608107120Sjulian } 609107120Sjulian 610107120Sjulian return (kvmd); 611107120Sjulianfail: 612107120Sjulian kvm_close(kvmd); 613107120Sjulian 614107120Sjulian return (NULL); 615107120Sjulian} /* kopen */ 616107120Sjulian 617107120Sjulian/* 618107120Sjulian * Read kvm 619107120Sjulian */ 620107120Sjulian 621107120Sjulianstatic int 622107120Sjuliankread(kvm_t *kvmd, u_long addr, char *buffer, int size) 623107120Sjulian{ 624107120Sjulian if (kvmd == NULL || buffer == NULL) 625107120Sjulian return (-1); 626107120Sjulian 627107120Sjulian if (kvm_read(kvmd, addr, buffer, size) != size) { 628107120Sjulian warnx("kvm_read: %s", kvm_geterr(kvmd)); 629107120Sjulian return (-1); 630107120Sjulian } 631107120Sjulian 632107120Sjulian return (0); 633107120Sjulian} /* kread */ 634107120Sjulian 635107120Sjulian/* 636107120Sjulian * Print usage and exit 637107120Sjulian */ 638107120Sjulian 639107120Sjulianstatic void 640107120Sjulianusage(void) 641107120Sjulian{ 642121054Semax fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n"); 643107120Sjulian exit(255); 644107120Sjulian} /* usage */ 645107120Sjulian 646