1

I am trying to use the BlueZ HCI function:

int hci_open_dev(int dev_id) {...}

which internally tries to create a socket like this:

socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);

I tried to understand the linux kernel code for socket() but feel lost.

Id like to know what exactly does it mean to create a socket for the given domain (AF_BLUETOOTH), data transmission type (SOCK_RAW) and protocol (BTPROTO_HCI).

The man page just states that it takes these params, creates a socket and returns a device descriptor.

But id like to understand what exactly happens and the exact kernel steps involved in creating a socket.

Ace
  • 1,303
  • 2
  • 26
  • 42
  • If you want to know the exact kernel steps, then you have to read the kernel code. Since you've already attempted that, I don't see how this question can be answered. Even asking for an overview of the process is too broad, since it involves a discussion of 1) how file descriptors work, 2) how protocol stacks work, and 3) how device drivers work. Those topics could easily fill a book, or at least 3 chapters in a book. – user3386109 Jul 22 '19 at 19:32
  • Fair enough, but Id like to understand at some level of abstraction, how exactly does socket() sit between user process making the socket() system call and the hardware device (Bluetooth Chipset in this case). – Ace Jul 22 '19 at 19:38
  • I reckon you already read `bluetooth/af_bluetooth.c` but since you're not mentioning the file, you might not have. – Cheatah Jul 22 '19 at 19:57
  • @Cheatah I have looked into that file while searching for AF_BLUETOOTH domain definition. But unfortunately could not contextualize the information in it. – Ace Jul 22 '19 at 19:59
  • I personally wouldn't vote to close this question as "too broad". Answering it would entail quite a bit of effort, but it's a specific question about `AF_BLUETOOTH` sockets on Linux, and therefore I'd say it's answerable. I'm not going to put in the effort needed to answer it, but I don't feel that's a strong enough reason to close it. A summary of what happens in the kernel can probably be done in a few tens of lines. – Andrew Henle Jul 22 '19 at 20:04
  • @AndrewHenle Thank you! This question is important to us in the context of low latency / real time systems. Using DBus APIs wont make the cut. Knowing details like socket creation mechanics help in realizing a lightweight optimal kernel system which achieves our application objectives. – Ace Jul 22 '19 at 20:09
  • @AndrewHenle: "but it's a specific question about AF_BLUETOOTH sockets on Linux, and therefore I'd say it's answerable." - It would be answerable when the author states which socket-related **knowledge he already has**. Current answers are by no means specific. And the accepted one even doesn't contain "AF_BLUETOOTH" word... – Tsyvarev Jul 22 '19 at 21:00
  • @Tsyvarev To clarify, both were equally good answers! But we cannot accept both of them, only one. But the author of the accepted answer gives a broader picture with which specific conclusions about AF_BLUETOOTH protocol family can be arrived at. – Ace Jul 22 '19 at 21:04
  • @Tsyvarev This is a very clear question: "what exactly does it mean to create a socket for the given domain (AF_BLUETOOTH), data transmission type (SOCK_RAW) and protocol (BTPROTO_HCI)." and "the exact kernel steps involved in creating a socket." That's very specific. The question even has the necessary code: `socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);` along with an effort to actually research the question: "I tried to understand the linux kernel code for socket() but feel lost." A good answer may require a lot of effort and wind up fairly long, but that's not "too broad". – Andrew Henle Jul 22 '19 at 22:32
  • @AndrewHenle: "the exact kernel steps involved in creating a *socket*" is detailed as e.g. "the exact kernel steps involved when load an *executable*". BTW, the whole code contained in the question post (`hci_open_dev` and `socket` functions) is an **user space** code. It is unclear whether the author will understand the **kernel code**, which is what he asked. – Tsyvarev Jul 22 '19 at 22:42
  • If **Please explain the `exec()` function and its family** isn't too broad, this question surely isn't. Too old? How about **What happens to the data in the socket when read and write system calls are used?** Or **What happens when a thread forks?** (I'm not actually linking those so as not to pollute the "Linked" and "Related" panels.) That's a clear precedent there, and this question is a whole lot more specific than those. – Andrew Henle Jul 22 '19 at 22:52
  • @Tsyvarev *is detailed as e.g. "the exact kernel steps involved when load an executable".* [Funny that you mention that](https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861). Yes, I did link that one. – Andrew Henle Jul 22 '19 at 22:56
  • @AndrewHenle: The [mostly upvoted question](https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861) looks "too broad" too. It is not marked so because of being relatively old and, possibly, for having the duplicate target for many similar questions. The other two questions you point, and many questions from the google request are actually **specific**. They ask specifically about the data in the socket, and "unusual" scenario with forking in the thread. – Tsyvarev Jul 22 '19 at 23:42

2 Answers2

3

Here is a very broad description (hope that helps understanding the main scheme).
Kernel developers will probably be horrified...

A socket is common abstract interface for many different communication means.
It provides many generic operations, such as closing, sending/receiving data, setting/retrieving options, which can be used on almost any kind of socket.

Creating a socket implies specifying the exact properties of this communication means.
It's a bit like the instantiation of a concrete type implementing an interface.

These properties are first organised by protocol families; this is the first argument to the socket() call.
For example:

  • PF_INET is used for communications relying on IPv4,
  • PF_INET6 is used for communications relying on IPv6,
  • PF_LOCAL is used for inter-process communication inside the system (kind of pipe),
  • PF_NETLINK is used for communication with the OS kernel,
  • PF_PACKET is used for direct communication with network interfaces,
  • ... (there exist many of them)

Once a protocol family is chosen, you have to specify, which protocol you want to use amongst those which are provided by this family; this is the second argument to the socket() call.
For example:

  • SOCK_DGRAM is used for UDP over IPv4 or IPv6, or distinct messages in PF_LOCAL,
  • SOCK_STREAM is used for TCP over IPv4 or IPv6, or a continuous byte stream in PF_LOCAL,
  • SOCK_RAW, accesses directly is the raw underlying protocol in the family if any (IPv4, or IPv6 for example),
  • ... (each family can provide many on them)

Some protocols can accept some variants or some restrictions; this is the third argument to the socket() call.
Often 0 is sufficient, but for example we can find:

  • PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) to capture any kind of network packet received on a network interface,
  • PF_PACKET, SOCK_RAW, htons(ETH_P_ARP) to capture only ARP frames,

When we ask for the creation of a socket with these three arguments, the operating system creates an internal resource associated with the socket handle which will be obtained.
Of course, the exact structure of this resource depends on the chosen family/protocol/variant, and it is associated to kernel callbacks which are specific to it.
Each time an operation in invoked on this socket (through a system call), the specific callback will be called.

prog-fh
  • 7,550
  • 1
  • 3
  • 21
  • Thanks, that is great information. I am going to harp on the last statement you made. "Each time an operation in invoked on this socket (through a system call), the specific callback will be called." – Ace Jul 22 '19 at 20:22
  • What do these callbacks do? Interact with hardware? Wifi chips for IPV4/IPV6 sockets and/or Broadcomm chips for bluetooth HCI sockets? – Ace Jul 22 '19 at 20:23
  • Want to really really know that missing link between socket's internal kernel call (upon socket operation as you say) and literally pin signals going out to chipset. – Ace Jul 22 '19 at 20:25
  • 1
    @Ace "interact with hardware" yes but probably not directly. Depending on the exact context, there may exist several levels between this abstraction and the exact hardware driver. – prog-fh Jul 22 '19 at 20:25
  • @Ace I'm sorry, I don't have such a specific knowledge. – prog-fh Jul 22 '19 at 20:27
  • I am accepting this as the answer! Thanks for the detailed and painstaking response. – Ace Jul 22 '19 at 20:29
2

Please look here: it's a good high-level description of the BlueZ Linux implemention of the Bluetooth stack:

Linux Without Wires The Basics of Bluetooth. Specifically, it gives you a good overview of these BlueZ kernel drivers:

  • bluetooth.ko, which contains core infrastructure of BlueZ. It exports sockets of the Bluetooth family AF_BLUETOOTH. All BlueZ modules utilise its services.

  • Bluetooth HCI packets are transported over UART or USB. The corresponding BlueZ HCI implementation is hci_uart.ko and hci_usb.ko.

  • The L2CAP layer of Bluetooth, which is responsible for segmentation, reassembly and protocol multiplexing, is implemented by l2cap.ko.

  • With the help of bnep.ko, TCP/IP applications can run over Bluetooth. This emulates an Ethernet port over the L2CAP layer. The kernel thread named kbnepd is responsible for BNEP connections.

  • rfcomm.ko is responsible for running serial port applications like the terminal. This emulates serial ports over the L2CAP layer. The kernel thread named krfcommd is responsible for RFCOMM connections.

  • hidp.ko implements the HID (human interface device) layer. The user mode daemon hidd allows BlueZ to handle input devices like Bluetooth mice.

  • sco.ko implements the synchronous connection oriented (SCO) layer to handle audio. SCO connections do not specify a channel to connect to a remote host; only the host address is specified.

Another excellent resource is the BlueZ project page:

paulsm4
  • 99,714
  • 15
  • 125
  • 160