Path: blob/main/usr.bin/bluetooth/btsockstat/btsockstat.c
34859 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* btsockstat.c4*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: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $30*/3132#include <sys/types.h>33#include <sys/callout.h>34#include <sys/param.h>35#include <sys/protosw.h>36#include <sys/queue.h>37#include <sys/socket.h>38#define _WANT_SOCKET39#include <sys/socketvar.h>4041#include <net/if.h>4243#define L2CAP_SOCKET_CHECKED44#include <bluetooth.h>45#include <err.h>46#include <fcntl.h>47#include <kvm.h>48#include <limits.h>49#include <nlist.h>5051#include <netgraph/bluetooth/include/ng_bluetooth.h>52#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h>53#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>54#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>5556#include <stdio.h>57#include <stdlib.h>58#include <string.h>59#include <unistd.h>6061static void hcirawpr (kvm_t *kvmd, u_long addr);62static void l2caprawpr (kvm_t *kvmd, u_long addr);63static void l2cappr (kvm_t *kvmd, u_long addr);64static void l2caprtpr (kvm_t *kvmd, u_long addr);65static void rfcommpr (kvm_t *kvmd, u_long addr);66static void rfcommpr_s (kvm_t *kvmd, u_long addr);6768static char * bdaddrpr (bdaddr_p const ba, char *str, int len);6970static kvm_t * kopen (char const *memf);71static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size);7273static void usage (void);7475/*76* List of symbols77*/7879static struct nlist nl[] = {80#define N_HCI_RAW 081{ "_ng_btsocket_hci_raw_sockets" },82#define N_L2CAP_RAW 183{ "_ng_btsocket_l2cap_raw_sockets" },84#define N_L2CAP 285{ "_ng_btsocket_l2cap_sockets" },86#define N_L2CAP_RAW_RT 387{ "_ng_btsocket_l2cap_raw_rt" },88#define N_L2CAP_RT 489{ "_ng_btsocket_l2cap_rt" },90#define N_RFCOMM 591{ "_ng_btsocket_rfcomm_sockets" },92#define N_RFCOMM_S 693{ "_ng_btsocket_rfcomm_sessions" },94{ "" },95};9697#define state2str(x) \98(((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)])99100/*101* Main102*/103104static int numeric_bdaddr = 0;105106int107main(int argc, char *argv[])108{109int opt, proto = -1, route = 0;110kvm_t *kvmd = NULL;111char *memf = NULL;112113while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) {114switch (opt) {115case 'n':116numeric_bdaddr = 1;117break;118119case 'M':120memf = optarg;121break;122123case 'p':124if (strcasecmp(optarg, "hci_raw") == 0)125proto = N_HCI_RAW;126else if (strcasecmp(optarg, "l2cap_raw") == 0)127proto = N_L2CAP_RAW;128else if (strcasecmp(optarg, "l2cap") == 0)129proto = N_L2CAP;130else if (strcasecmp(optarg, "rfcomm") == 0)131proto = N_RFCOMM;132else if (strcasecmp(optarg, "rfcomm_s") == 0)133proto = N_RFCOMM_S;134else135usage();136/* NOT REACHED */137break;138139case 'r':140route = 1;141break;142143case 'h':144default:145usage();146/* NOT REACHED */147}148}149150if ((proto == N_HCI_RAW || proto == N_RFCOMM || proto == N_RFCOMM_S) && route)151usage();152/* NOT REACHED */153154/*155* Discard setgid privileges if not the running kernel so that156* bad guys can't print interesting stuff from kernel memory.157*/158if (memf != NULL)159if (setgid(getgid()) != 0)160err(1, "setgid");161162kvmd = kopen(memf);163if (kvmd == NULL)164return (1);165166switch (proto) {167case N_HCI_RAW:168hcirawpr(kvmd, nl[N_HCI_RAW].n_value);169break;170171case N_L2CAP_RAW:172if (route)173l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);174else175l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);176break;177178case N_L2CAP:179if (route)180l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);181else182l2cappr(kvmd, nl[N_L2CAP].n_value);183break;184185case N_RFCOMM:186rfcommpr(kvmd, nl[N_RFCOMM].n_value);187break;188189case N_RFCOMM_S:190rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);191break;192193default:194if (route) {195l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);196l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);197} else {198hcirawpr(kvmd, nl[N_HCI_RAW].n_value);199l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);200l2cappr(kvmd, nl[N_L2CAP].n_value);201rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);202rfcommpr(kvmd, nl[N_RFCOMM].n_value);203}204break;205}206207return (kvm_close(kvmd));208} /* main */209210/*211* Print raw HCI sockets212*/213214static void215hcirawpr(kvm_t *kvmd, u_long addr)216{217ng_btsocket_hci_raw_pcb_p this = NULL, next = NULL;218ng_btsocket_hci_raw_pcb_t pcb;219struct socket so;220int first = 1;221222if (addr == 0)223return;224225if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)226return;227228for ( ; this != NULL; this = next) {229if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)230return;231if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)232return;233234next = LIST_NEXT(&pcb, next);235236if (first) {237first = 0;238fprintf(stdout,239"Active raw HCI sockets\n" \240"%-8.8s %-8.8s %-6.6s %-6.6s %-6.6s %-16.16s\n",241"Socket",242"PCB",243"Flags",244"Recv-Q",245"Send-Q",246"Local address");247}248249if (pcb.addr.hci_node[0] == 0) {250pcb.addr.hci_node[0] = '*';251pcb.addr.hci_node[1] = 0;252}253254fprintf(stdout,255"%-8lx %-8lx %-6.6x %6d %6d %-16.16s\n",256(unsigned long) pcb.so,257(unsigned long) this,258pcb.flags,259so.so_rcv.sb_ccc,260so.so_snd.sb_ccc,261pcb.addr.hci_node);262}263} /* hcirawpr */264265/*266* Print raw L2CAP sockets267*/268269static void270l2caprawpr(kvm_t *kvmd, u_long addr)271{272ng_btsocket_l2cap_raw_pcb_p this = NULL, next = NULL;273ng_btsocket_l2cap_raw_pcb_t pcb;274struct socket so;275int first = 1;276277if (addr == 0)278return;279280if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)281return;282283for ( ; this != NULL; this = next) {284if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)285return;286if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)287return;288289next = LIST_NEXT(&pcb, next);290291if (first) {292first = 0;293fprintf(stdout,294"Active raw L2CAP sockets\n" \295"%-8.8s %-8.8s %-6.6s %-6.6s %-17.17s\n",296"Socket",297"PCB",298"Recv-Q",299"Send-Q",300"Local address");301}302303fprintf(stdout,304"%-8lx %-8lx %6d %6d %-17.17s\n",305(unsigned long) pcb.so,306(unsigned long) this,307so.so_rcv.sb_ccc,308so.so_snd.sb_ccc,309bdaddrpr(&pcb.src, NULL, 0));310}311} /* l2caprawpr */312313/*314* Print L2CAP sockets315*/316317static void318l2cappr(kvm_t *kvmd, u_long addr)319{320static char const * const states[] = {321/* NG_BTSOCKET_L2CAP_CLOSED */ "CLOSED",322/* NG_BTSOCKET_L2CAP_CONNECTING */ "CON",323/* NG_BTSOCKET_L2CAP_CONFIGURING */ "CONFIG",324/* NG_BTSOCKET_L2CAP_OPEN */ "OPEN",325/* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON"326};327328ng_btsocket_l2cap_pcb_p this = NULL, next = NULL;329ng_btsocket_l2cap_pcb_t pcb;330struct socket so;331int first = 1;332char local[24], remote[24];333334if (addr == 0)335return;336337if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)338return;339340for ( ; this != NULL; this = next) {341if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)342return;343if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)344return;345346next = LIST_NEXT(&pcb, next);347348if (first) {349first = 0;350fprintf(stdout,351"Active L2CAP sockets\n" \352"%-8.8s %-6.6s %-6.6s %-23.23s %-17.17s %-5.5s %s\n",353"PCB",354"Recv-Q",355"Send-Q",356"Local address/PSM",357"Foreign address",358"CID",359"State");360}361362fprintf(stdout,363"%-8lx %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n",364(unsigned long) this,365so.so_rcv.sb_ccc,366so.so_snd.sb_ccc,367bdaddrpr(&pcb.src, local, sizeof(local)),368pcb.psm,369bdaddrpr(&pcb.dst, remote, sizeof(remote)),370pcb.cid,371(so.so_options & SO_ACCEPTCONN)?372"LISTEN" : state2str(pcb.state));373}374} /* l2cappr */375376/*377* Print L2CAP routing table378*/379380static void381l2caprtpr(kvm_t *kvmd, u_long addr)382{383ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL;384ng_btsocket_l2cap_rtentry_t rt;385int first = 1;386387if (addr == 0)388return;389390if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)391return;392393for ( ; this != NULL; this = next) {394if (kread(kvmd, (u_long) this, (char *) &rt, sizeof(rt)) < 0)395return;396397next = LIST_NEXT(&rt, next);398399if (first) {400first = 0;401fprintf(stdout,402"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : "");403fprintf(stdout,404"%-8.8s %-8.8s %-17.17s\n", "RTentry",405"Hook",406"BD_ADDR");407}408409fprintf(stdout,410"%-8lx %-8lx %-17.17s\n",411(unsigned long) this,412(unsigned long) rt.hook,413bdaddrpr(&rt.src, NULL, 0));414}415} /* l2caprtpr */416417/*418* Print RFCOMM sockets419*/420421static void422rfcommpr(kvm_t *kvmd, u_long addr)423{424static char const * const states[] = {425/* NG_BTSOCKET_RFCOMM_DLC_CLOSED */ "CLOSED",426/* NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT */ "W4CON",427/* NG_BTSOCKET_RFCOMM_DLC_CONFIGURING */ "CONFIG",428/* NG_BTSOCKET_RFCOMM_DLC_CONNECTING */ "CONN",429/* NG_BTSOCKET_RFCOMM_DLC_CONNECTED */ "OPEN",430/* NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING */ "DISCON"431};432433ng_btsocket_rfcomm_pcb_p this = NULL, next = NULL;434ng_btsocket_rfcomm_pcb_t pcb;435struct socket so;436int first = 1;437char local[24], remote[24];438439if (addr == 0)440return;441442if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)443return;444445for ( ; this != NULL; this = next) {446if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)447return;448if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)449return;450451next = LIST_NEXT(&pcb, next);452453if (first) {454first = 0;455fprintf(stdout,456"Active RFCOMM sockets\n" \457"%-8.8s %-6.6s %-6.6s %-17.17s %-17.17s %-4.4s %-4.4s %s\n",458"PCB",459"Recv-Q",460"Send-Q",461"Local address",462"Foreign address",463"Chan",464"DLCI",465"State");466}467468fprintf(stdout,469"%-8lx %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n",470(unsigned long) this,471so.so_rcv.sb_ccc,472so.so_snd.sb_ccc,473bdaddrpr(&pcb.src, local, sizeof(local)),474bdaddrpr(&pcb.dst, remote, sizeof(remote)),475pcb.channel,476pcb.dlci,477(so.so_options & SO_ACCEPTCONN)?478"LISTEN" : state2str(pcb.state));479}480} /* rfcommpr */481482/*483* Print RFCOMM sessions484*/485486static void487rfcommpr_s(kvm_t *kvmd, u_long addr)488{489static char const * const states[] = {490/* NG_BTSOCKET_RFCOMM_SESSION_CLOSED */ "CLOSED",491/* NG_BTSOCKET_RFCOMM_SESSION_LISTENING */ "LISTEN",492/* NG_BTSOCKET_RFCOMM_SESSION_CONNECTING */ "CONNECTING",493/* NG_BTSOCKET_RFCOMM_SESSION_CONNECTED */ "CONNECTED",494/* NG_BTSOCKET_RFCOMM_SESSION_OPEN */ "OPEN",495/* NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING */ "DISCONNECTING"496};497498ng_btsocket_rfcomm_session_p this = NULL, next = NULL;499ng_btsocket_rfcomm_session_t s;500struct socket so;501int first = 1;502503if (addr == 0)504return;505506if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)507return;508509for ( ; this != NULL; this = next) {510if (kread(kvmd, (u_long) this, (char *) &s, sizeof(s)) < 0)511return;512if (kread(kvmd, (u_long) s.l2so, (char *) &so, sizeof(so)) < 0)513return;514515next = LIST_NEXT(&s, next);516517if (first) {518first = 0;519fprintf(stdout,520"Active RFCOMM sessions\n" \521"%-8.8s %-8.8s %-4.4s %-5.5s %-5.5s %-4.4s %s\n",522"L2PCB",523"PCB",524"Flags",525"MTU",526"Out-Q",527"DLCs",528"State");529}530531fprintf(stdout,532"%-8lx %-8lx %-4x %-5d %-5d %-4s %s\n",533(unsigned long) so.so_pcb,534(unsigned long) this,535s.flags,536s.mtu,537s.outq.len,538LIST_EMPTY(&s.dlcs)? "No" : "Yes",539state2str(s.state));540}541} /* rfcommpr_s */542543/*544* Return BD_ADDR as string545*/546547static char *548bdaddrpr(bdaddr_p const ba, char *str, int len)549{550static char buffer[MAXHOSTNAMELEN];551struct hostent *he = NULL;552553if (str == NULL) {554str = buffer;555len = sizeof(buffer);556}557558if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {559str[0] = '*';560str[1] = 0;561562return (str);563}564565if (!numeric_bdaddr &&566(he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {567strlcpy(str, he->h_name, len);568569return (str);570}571572bt_ntoa(ba, str);573574return (str);575} /* bdaddrpr */576577/*578* Open kvm579*/580581static kvm_t *582kopen(char const *memf)583{584kvm_t *kvmd = NULL;585char errbuf[_POSIX2_LINE_MAX];586587kvmd = kvm_openfiles(NULL, memf, NULL, O_RDONLY, errbuf);588if (setgid(getgid()) != 0)589err(1, "setgid");590if (kvmd == NULL) {591warnx("kvm_openfiles: %s", errbuf);592return (NULL);593}594595if (kvm_nlist(kvmd, nl) < 0) {596warnx("kvm_nlist: %s", kvm_geterr(kvmd));597goto fail;598}599600if (nl[0].n_type == 0) {601warnx("kvm_nlist: no namelist");602goto fail;603}604605return (kvmd);606fail:607kvm_close(kvmd);608609return (NULL);610} /* kopen */611612/*613* Read kvm614*/615616static int617kread(kvm_t *kvmd, u_long addr, char *buffer, int size)618{619if (kvmd == NULL || buffer == NULL)620return (-1);621622if (kvm_read(kvmd, addr, buffer, size) != size) {623warnx("kvm_read: %s", kvm_geterr(kvmd));624return (-1);625}626627return (0);628} /* kread */629630/*631* Print usage and exit632*/633634static void635usage(void)636{637fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n");638exit(255);639} /* usage */640641642643