NG_BTSOCKET(4)

πŸ’™ ng_btsocket β€” the Bluetooth sockets layer, bestie

okay so you opened the ng_btsocket(4) manual page and honestly? iconic behavior. this is the whole Bluetooth sockets layer situation and i'm gonna walk you through it like we're texting at 2am. grab a strawberry πŸ“


✨ SYNOPSIS ✨

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/bitstring.h>
#include <netgraph/bluetooth/include/ng_hci.h>
#include <netgraph/bluetooth/include/ng_l2cap.h>
#include <netgraph/bluetooth/include/ng_btsocket.h>

πŸ¦‹ DESCRIPTION πŸ¦‹

so the ng_btsocket module is out here implementing three Netgraph node types. and each one of those? implements one protocol inside the PF_BLUETOOTH domain. three nodes, three protocols, one slay module. periodt πŸ’…

πŸ’– BLUETOOTH_PROTO_HCI protocol

🌸 SOCK_RAW HCI sockets

this one's implemented by the btsock_hci_raw Netgraph type. Raw HCI sockets let you send raw HCI command datagrams only to correspondents named in send(2) calls. and raw HCI datagrams (HCI commands, events and data) are generally received with recvfrom(2), which hands you back the next datagram plus its return address. you can also use Raw HCI sockets to control HCI nodes. multitasking queen πŸ‘‘

The Bluetooth raw HCI socket address is defined as follows:

/* Bluetooth version of struct sockaddr for raw HCI sockets */
struct sockaddr_hci {
        u_char  hci_len;      /* total length */
        u_char  hci_family;   /* address family */
        char    hci_node[32]; /* address (size == NG_NODESIZ ) */
};

Raw HCI sockets support a number of ioctl(2) requests such as:

  • SIOC_HCI_RAW_NODE_GET_STATE β€” Returns current state for the HCI node.
  • SIOC_HCI_RAW_NODE_INIT β€” Turn on β€œinited” bit for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_DEBUG β€” Returns current debug level for the HCI node.
  • SIOC_HCI_RAW_NODE_SET_DEBUG β€” Sets current debug level for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_BUFFER β€” Returns current state of data buffers for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_BDADDR β€” Returns BD_ADDR for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_FEATURES β€” Returns the list of features supported by hardware for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_STAT β€” Returns various statistic counters for the HCI node.
  • SIOC_HCI_RAW_NODE_RESET_STAT β€” Resets all statistic counters for the HCI node to zero.
  • SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE β€” Remove all neighbor cache entries for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE β€” Returns content of the neighbor cache for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_CON_LIST β€” Returns list of active baseband connections (i.e., ACL and SCO links) for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK β€” Returns current link policy settings mask for the HCI node.
  • SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK β€” Sets current link policy settings mask for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_PACKET_MASK β€” Returns current packet mask for the HCI node.
  • SIOC_HCI_RAW_NODE_SET_PACKET_MASK β€” Sets current packet mask for the HCI node.
  • SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH β€” Returns current value of the role switch parameter for the HCI node.
  • SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH β€” Sets new value of the role switch parameter for the HCI node.

The net.bluetooth.hci.sockets.raw.ioctl_timeout variable, that can be examined and set via sysctl(8), controls the control request timeout (in seconds) for raw HCI sockets. ⏰

Raw HCI sockets support filters. the application can filter certain HCI datagram types. and for HCI event datagrams the application can set an additional filter. the raw HCI socket filter is defined as follows:

/*
 * Raw HCI socket filter.
 *
 * For packet mask use (1 << (HCI packet indicator - 1))
 * For event mask use (1 << (Event - 1))
 */

struct ng_btsocket_hci_raw_filter {
        bitstr_t bit_decl(packet_mask, 32);
        bitstr_t bit_decl(event_mask, (NG_HCI_EVENT_MASK_SIZE * 8));
};

The SO_HCI_RAW_FILTER option defined at SOL_HCI_RAW level can be used to obtain via getsockopt(2) or change via setsockopt(2) raw HCI socket's filter. customizing your feed fr fr ✨


πŸ’œ BLUETOOTH_PROTO_L2CAP protocol

The Bluetooth L2CAP socket address is defined as follows:

/* Bluetooth version of struct sockaddr for L2CAP sockets */
struct sockaddr_l2cap {
        u_char    l2cap_len;    /* total length */
        u_char    l2cap_family; /* address family */
        uint16_t  l2cap_psm;    /* Protocol/Service Multiplexor */
        bdaddr_t  l2cap_bdaddr; /* address */
};

πŸŽ€ SOCK_RAW L2CAP sockets

implemented by the btsock_l2c_raw Netgraph type. okay so plot twist: Raw L2CAP sockets do not provide access to raw L2CAP datagrams. these sockets are used to control L2CAP nodes and to issue special L2CAP requests such as ECHO_REQUEST and GET_INFO request. not what you expected but still doing the most πŸ’…

Raw L2CAP sockets support a number of ioctl(2) requests such as:

  • SIOC_L2CAP_NODE_GET_FLAGS β€” Returns current state for the L2CAP node.
  • SIOC_L2CAP_NODE_GET_DEBUG β€” Returns current debug level for the L2CAP node.
  • SIOC_L2CAP_NODE_SET_DEBUG β€” Sets current debug level for the L2CAP node.
  • SIOC_L2CAP_NODE_GET_CON_LIST β€” Returns list of active baseband connections (i.e., ACL links) for the L2CAP node.
  • SIOC_L2CAP_NODE_GET_CHAN_LIST β€” Returns list of active channels for the L2CAP node.
  • SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO β€” Returns current value of the auto disconnect timeout for the L2CAP node.
  • SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO β€” Sets current value of the auto disconnect timeout for the L2CAP node.
  • SIOC_L2CAP_L2CA_PING β€” Issues L2CAP ECHO_REQUEST.
  • SIOC_L2CAP_L2CA_GET_INFO β€” Issues L2CAP GET_INFO request.

The net.bluetooth.l2cap.sockets.raw.ioctl_timeout variable, that can be examined and set via sysctl(8), controls the control request timeout (in seconds) for raw L2CAP sockets. ⏰

🌈 SOCK_SEQPACKET L2CAP sockets

implemented by the btsock_l2c Netgraph type. L2CAP sockets are either β€œactive” or β€œpassive”. active sockets initiate connections to passive sockets. by default, L2CAP sockets are created active; to create a passive socket, the listen(2) system call must be used after binding the socket with the bind(2) system call. only passive sockets may use the accept(2) call to accept incoming connections. only active sockets may use the connect(2) call to initiate connections. it's giving main character vs supporting character, and both are valid πŸ’–

L2CAP sockets support β€œwildcard addressing”. in this case, socket must be bound to NG_HCI_BDADDR_ANY address. note that PSM (Protocol/Service Multiplexor) field is always required. once a connection has been established, the socket's address is fixed by the peer entity's location. the address assigned to the socket is the address associated with the Bluetooth device through which packets are being transmitted and received, and PSM (Protocol/Service Multiplexor).

L2CAP sockets support a number of options defined at SOL_L2CAP level which can be set with setsockopt(2) and tested with getsockopt(2):

  • SO_L2CAP_IMTU β€” Get (set) maximum payload size the local socket is capable of accepting.
  • SO_L2CAP_OMTU β€” Get maximum payload size the remote socket is capable of accepting.
  • SO_L2CAP_IFLOW β€” Get incoming flow specification for the socket. Not implemented.
  • SO_L2CAP_OFLOW β€” Get (set) outgoing flow specification for the socket. Not implemented.
  • SO_L2CAP_FLUSH β€” Get (set) value of the flush timeout. Not implemented.
heads up bestie: those last three are marked Not implemented, so don't come for me when they don't do anything πŸ™ˆ

🧚 BLUETOOTH_PROTO_RFCOMM protocol

The Bluetooth RFCOMM socket address is defined as follows:

/* Bluetooth version of struct sockaddr for RFCOMM sockets */
struct sockaddr_rfcomm {
        u_char   rfcomm_len;     /* total length */
        u_char   rfcomm_family;  /* address family */
        bdaddr_t rfcomm_bdaddr;  /* address */
        uint8_t  rfcomm_channel; /* channel */
};

πŸ‘‘ SOCK_STREAM RFCOMM sockets

note that RFCOMM sockets do not have an associated Netgraph node type. RFCOMM sockets are implemented as an additional layer on top of L2CAP sockets. RFCOMM sockets are either β€œactive” or β€œpassive”. active sockets initiate connections to passive sockets. by default, RFCOMM sockets are created active; to create a passive socket, the listen(2) system call must be used after binding the socket with the bind(2) system call. only passive sockets may use the accept(2) call to accept incoming connections. only active sockets may use the connect(2) call to initiate connections. same energy as the L2CAP girlies, just one layer up πŸ’…

RFCOMM sockets support β€œwildcard addressing”. in this case, socket must be bound to NG_HCI_BDADDR_ANY address. note that RFCOMM channel field is always required. once a connection has been established, the socket's address is fixed by the peer entity's location. the address assigned to the socket is the address associated with the Bluetooth device through which packets are being transmitted and received, and RFCOMM channel.

The following options, which can be tested with getsockopt(2) call, are defined at SOL_RFCOMM level for RFCOMM sockets:

  • SO_RFCOMM_MTU β€” Returns the maximum transfer unit size (in bytes) for the underlying RFCOMM channel. Note that application still can write/read bigger chunks to/from the socket.
  • SO_RFCOMM_FC_INFO β€” Return the flow control information for the underlying RFCOMM channel.

The net.bluetooth.rfcomm.sockets.stream.timeout variable, that can be examined and set via sysctl(8), controls the connection timeout (in seconds) for RFCOMM sockets. ⏰


πŸͺ HOOKS πŸͺ

these node types support hooks with arbitrary names (as long as they are unique) and always accept hook connection requests. no gatekeeping here 🫢


πŸ“¨ NETGRAPH CONTROL MESSAGES πŸ“¨

these node types support the generic control messages. simple, clean, ate. ✨


πŸ›‘ SHUTDOWN πŸ›‘

these nodes are persistent and cannot be shut down. they're immortal, they're not leaving, they're the main character and they know it πŸ˜­πŸ’€


πŸ‘€ SEE ALSO πŸ‘€

btsockstat(1), socket(2), netgraph(4), ng_bluetooth(4), ng_hci(4), ng_l2cap(4), ngctl(8), sysctl(8)

go read those too, they're all part of the friend group 🌸


πŸ“œ HISTORY πŸ“œ

The ng_btsocket module was implemented in FreeBSD 5.0. a legacy icon honestly πŸ‘‘


🫢 AUTHORS 🫢

Maksim Yevmenkin <m_evmenkin@yahoo.com>


πŸ› BUGS πŸ›

Most likely. Please report if found.

not "most likely" being the entire bug section 😭 they said we're being honest today and i respect it fr fr

and that's the whole page bestie!! this one's from the Debian manual, dated November 13, 2012, and it's NG_BTSOCKET(4) β€” Bluetooth sockets layer. now go forth and slay those HCI, L2CAP and RFCOMM sockets πŸ’–βœ¨πŸŽ€πŸ¦‹πŸŒΈπŸ’…πŸ«ΆπŸ”₯πŸ‘‘πŸŒˆβ­πŸ’œ

πŸ“¦ where this page comes from