summaryrefslogtreecommitdiffstats
path: root/usr.bin/bluetooth/btsockstat/btsockstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/bluetooth/btsockstat/btsockstat.c')
-rw-r--r--usr.bin/bluetooth/btsockstat/btsockstat.c484
1 files changed, 484 insertions, 0 deletions
diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.c b/usr.bin/bluetooth/btsockstat/btsockstat.c
new file mode 100644
index 0000000..d123502
--- /dev/null
+++ b/usr.bin/bluetooth/btsockstat/btsockstat.c
@@ -0,0 +1,484 @@
+/*
+ * btsockstat.c
+ *
+ * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: btsockstat.c,v 1.2 2002/09/16 19:40:14 max Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/callout.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <bitstring.h>
+#include <err.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+
+#include <ng_hci.h>
+#include <ng_l2cap.h>
+#include <ng_btsocket.h>
+#include <ng_btsocket_hci_raw.h>
+#include <ng_btsocket_l2cap.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void hcirawpr (kvm_t *kvmd, u_long addr);
+static void l2caprawpr (kvm_t *kvmd, u_long addr);
+static void l2cappr (kvm_t *kvmd, u_long addr);
+static void l2caprtpr (kvm_t *kvmd, u_long addr);
+
+static kvm_t * kopen (char const *memf);
+static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size);
+
+static void usage (void);
+
+/*
+ * List of symbols
+ */
+
+static struct nlist nl[] = {
+#define N_HCI_RAW 0
+ { "_ng_btsocket_hci_raw_sockets" },
+#define N_L2CAP_RAW 1
+ { "_ng_btsocket_l2cap_raw_sockets" },
+#define N_L2CAP 2
+ { "_ng_btsocket_l2cap_sockets" },
+#define N_L2CAP_RAW_RT 3
+ { "_ng_btsocket_l2cap_raw_rt" },
+#define N_L2CAP_RT 4
+ { "_ng_btsocket_l2cap_rt" },
+ { "" },
+};
+
+/*
+ * Main
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int opt, proto = -1, route = 0;
+ kvm_t *kvmd = NULL;
+ char *memf = NULL;
+
+ while ((opt = getopt(argc, argv, "hM:p:r")) != -1) {
+ switch (opt) {
+ case 'M':
+ memf = optarg;
+ break;
+
+ case 'p':
+ if (strcasecmp(optarg, "hci_raw") == 0)
+ proto = N_HCI_RAW;
+ else if (strcasecmp(optarg, "l2cap_raw") == 0)
+ proto = N_L2CAP_RAW;
+ else if (strcasecmp(optarg, "l2cap") == 0)
+ proto = N_L2CAP;
+ else
+ usage();
+ /* NOT REACHED */
+ break;
+
+ case 'r':
+ route = 1;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ /* NOT REACHED */
+ }
+ }
+
+ if (proto == N_HCI_RAW && route)
+ usage();
+ /* NOT REACHED */
+
+ kvmd = kopen(memf);
+ if (kvmd == NULL)
+ return (1);
+
+ switch (proto) {
+ case N_HCI_RAW:
+ hcirawpr(kvmd, nl[N_HCI_RAW].n_value);
+ break;
+
+ case N_L2CAP_RAW:
+ if (route)
+ l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);
+ else
+ l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);
+ break;
+
+ case N_L2CAP:
+ if (route)
+ l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);
+ else
+ l2cappr(kvmd, nl[N_L2CAP].n_value);
+ break;
+
+ default:
+ if (route) {
+ l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);
+ l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);
+ } else {
+ hcirawpr(kvmd, nl[N_HCI_RAW].n_value);
+ l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);
+ l2cappr(kvmd, nl[N_L2CAP].n_value);
+ }
+ break;
+ }
+
+ return (kvm_close(kvmd));
+} /* main */
+
+/*
+ * Print raw HCI sockets
+ */
+
+static void
+hcirawpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_hci_raw_pcb_p this = NULL, next = NULL;
+ ng_btsocket_hci_raw_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active raw HCI sockets\n" \
+"%-8.8s %-8.8s %-6.6s %-6.6s %-6.6s %-16.16s\n",
+ "Socket",
+ "PCB",
+ "Flags",
+ "Recv-Q",
+ "Send-Q",
+ "Local address");
+ }
+
+ if (pcb.addr.hci_node[0] == 0) {
+ pcb.addr.hci_node[0] = '*';
+ pcb.addr.hci_node[1] = 0;
+ }
+
+ fprintf(stdout,
+"%-8.8x %-8.8x %-6.6x %6d %6d %-16.16s\n",
+ (int) pcb.so,
+ (int) this,
+ pcb.flags,
+ so.so_rcv.sb_cc,
+ so.so_snd.sb_cc,
+ pcb.addr.hci_node);
+ }
+} /* hcirawpr */
+
+/*
+ * Print raw L2CAP sockets
+ */
+
+static void
+l2caprawpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_l2cap_raw_pcb_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_raw_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+ char bdaddr[32];
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active raw L2CAP sockets\n" \
+"%-8.8s %-8.8s %-6.6s %-6.6s %-18.18s\n",
+ "Socket",
+ "PCB",
+ "Recv-Q",
+ "Send-Q",
+ "Local address");
+ }
+
+ if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) {
+ bdaddr[0] = '*';
+ bdaddr[1] = 0;
+ } else
+ snprintf(bdaddr, sizeof(bdaddr),
+"%02x:%02x:%02x:%02x:%02x:%02x",
+ pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
+ pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]);
+
+ fprintf(stdout,
+"%-8.8x %-8.8x %6d %6d %-18.18s\n",
+ (int) pcb.so,
+ (int) this,
+ so.so_rcv.sb_cc,
+ so.so_snd.sb_cc,
+ bdaddr);
+ }
+} /* l2caprawpr */
+
+/*
+ * Print L2CAP sockets
+ */
+
+static void
+l2cappr(kvm_t *kvmd, u_long addr)
+{
+ static char const * const states[] = {
+ /* NG_BTSOCKET_L2CAP_CLOSED */ "CLOSED",
+ /* NG_BTSOCKET_L2CAP_CONNECTING */ "CON",
+ /* NG_BTSOCKET_L2CAP_CONFIGURING */ "CONFIG",
+ /* NG_BTSOCKET_L2CAP_OPEN */ "OPEN",
+ /* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON"
+ };
+#define state2str(x) \
+ (((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)])
+
+ ng_btsocket_l2cap_pcb_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+ char local[32], remote[32];
+
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active L2CAP sockets\n" \
+"%-8.8s %-6.6s %-6.6s %-24.24s %-18.18s %-5.5s %s\n",
+ "PCB",
+ "Recv-Q",
+ "Send-Q",
+ "Local address/PSM",
+ "Foreign address",
+ "CID",
+ "State");
+ }
+
+ if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0)
+ snprintf(local, sizeof(local), "*/%d", pcb.psm);
+ else
+ snprintf(local, sizeof(local),
+"%02x:%02x:%02x:%02x:%02x:%02x/%d",
+ pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
+ pcb.src.b[2], pcb.src.b[1], pcb.src.b[0],
+ pcb.psm);
+
+ if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) {
+ remote[0] = '*';
+ remote[1] = 0;
+ } else
+ snprintf(remote, sizeof(remote),
+"%02x:%02x:%02x:%02x:%02x:%02x",
+ pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3],
+ pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]);
+
+ fprintf(stdout,
+"%-8.8x %6d %6d %-24.24s %-18.18s %-5d %s\n",
+ (int) this,
+ so.so_rcv.sb_cc,
+ so.so_snd.sb_cc,
+ local,
+ remote,
+ pcb.cid,
+ (so.so_options & SO_ACCEPTCONN)?
+ "LISTEN" : state2str(pcb.state));
+ }
+} /* l2cappr */
+
+/*
+ * Print L2CAP routing table
+ */
+
+static void
+l2caprtpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_rtentry_t rt;
+ int first = 1;
+ char bdaddr[32];
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &rt, sizeof(rt)) < 0)
+ return;
+
+ next = LIST_NEXT(&rt, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : "");
+ fprintf(stdout,
+"%-8.8s %-8.8s %-18.18s\n", "RTentry",
+ "Hook",
+ "BD_ADDR");
+ }
+
+ if (memcmp(&rt.src, NG_HCI_BDADDR_ANY, sizeof(rt.src)) == 0) {
+ bdaddr[0] = '-';
+ bdaddr[1] = 0;
+ } else
+ snprintf(bdaddr, sizeof(bdaddr),
+"%02x:%02x:%02x:%02x:%02x:%02x", rt.src.b[5], rt.src.b[4], rt.src.b[3],
+ rt.src.b[2], rt.src.b[1], rt.src.b[0]);
+
+ fprintf(stdout,
+"%-8.8x %-8.8x %-18.18s\n",
+ (int) this,
+ (int) rt.hook,
+ bdaddr);
+ }
+} /* l2caprtpr */
+
+/*
+ * Open kvm
+ */
+
+static kvm_t *
+kopen(char const *memf)
+{
+ kvm_t *kvmd = NULL;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ /*
+ * Discard setgid privileges if not the running kernel so that
+ * bad guys can't print interesting stuff from kernel memory.
+ */
+
+ if (memf != NULL)
+ setgid(getgid());
+
+ kvmd = kvm_openfiles(NULL, memf, NULL, O_RDONLY, errbuf);
+ if (kvmd == NULL) {
+ warnx("kvm_openfiles: %s", errbuf);
+ return (NULL);
+ }
+
+ if (kvm_nlist(kvmd, nl) < 0) {
+ warnx("kvm_nlist: %s", kvm_geterr(kvmd));
+ goto fail;
+ }
+
+ if (nl[0].n_type == 0) {
+ warnx("kvm_nlist: no namelist");
+ goto fail;
+ }
+
+ return (kvmd);
+fail:
+ kvm_close(kvmd);
+
+ return (NULL);
+} /* kopen */
+
+/*
+ * Read kvm
+ */
+
+static int
+kread(kvm_t *kvmd, u_long addr, char *buffer, int size)
+{
+ if (kvmd == NULL || buffer == NULL)
+ return (-1);
+
+ if (kvm_read(kvmd, addr, buffer, size) != size) {
+ warnx("kvm_read: %s", kvm_geterr(kvmd));
+ return (-1);
+ }
+
+ return (0);
+} /* kread */
+
+/*
+ * Print usage and exit
+ */
+
+static void
+usage(void)
+{
+ fprintf(stdout, "Usage: btsockstat [-M core ] [-p proto] [-r]\n");
+ exit(255);
+} /* usage */
+
OpenPOWER on IntegriCloud