Title: Python cannot access hci_channel field in sockaddr_hci
Type: Stage:
Components: Library (Lib) Versions: Python 3.8
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Jeffrey.Kintscher, bsder, matrixise, ukBaz
Priority: normal Keywords:

Created on 2019-02-27 11:10 by bsder, last changed 2019-07-09 07:01 by Jeffrey.Kintscher.

Messages (4)
msg336743 - (view) Author: Andrew P. Lentvorski, Jr. (bsder) Date: 2019-02-27 11:10
On Linux, sockaddr_hci is:

struct sockaddr_hci {
        sa_family_t     hci_family;
        unsigned short  hci_dev;
        unsigned short  hci_channel;

Unfortunately, it seems like python does not allow any way to initialize hci_channel, so you can't use a user channel socket (hci_channel == 0) or a monitor channel.  There is probably a larger discussion of how to enable people to use a new field that appears in a structure like this, but that's above my pay grade ...

Even worse, this appears to have been known for a while (since 2013 at least! by Chromium), but while people complained, nobody actually took the time to file it upstream with Python.

So, I'm filing it upstream.  Hopefully this is easy to fix by someone who knows what's up.



class BluetoothUserSocket(SuperSocket):
    desc = "read/write H4 over a Bluetooth user channel"
    def __init__(self, adapter=0):
        # s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
        # s.bind((0,1))

        # yeah, if only
        # thanks to Python's weak ass socket and bind implementations, we have
        # to call down into libc with ctypes

        sockaddr_hcip = POINTER(sockaddr_hci)
        libc = CDLL("")

        socket_c = libc.socket
        socket_c.argtypes = (c_int, c_int, c_int);
        socket_c.restype = c_int

        bind = libc.bind
        bind.argtypes = (c_int, POINTER(sockaddr_hci), c_int)
        bind.restype = c_int

        ## actual code

        s = socket_c(31, 3, 1) # (AF_BLUETOOTH, SOCK_RAW, HCI_CHANNEL_USER)
        if s < 0:
            raise BluetoothSocketError("Unable to open PF_BLUETOOTH socket")

        sa = sockaddr_hci()
        sa.sin_family = 31  # AF_BLUETOOTH
        sa.hci_dev = adapter # adapter index
        sa.hci_channel = 1   # HCI_USER_CHANNEL

r = bind(s, sockaddr_hcip(sa), sizeof(sa))
msg336744 - (view) Author: St├ęphane Wirtel (matrixise) * (Python committer) Date: 2019-02-27 11:13
Thank you,

I have changed the related versions of Python to 3.8 because it's a new feature and the other releases are in security mode or bugfix mode.
msg336784 - (view) Author: Andrew P. Lentvorski, Jr. (bsder) Date: 2019-02-27 23:50
It's up to you how you folks want to deal with this, but classifying it as a "bug" for those versions in bugfix is likely acceptable.

You already have to call bind with a tuple, so as long as it is *optional* to add an extra field to that tuple (and I can't imagine that any fix would not do that as it would break existing code), it's not going to break things.

However, since nobody seems to have felt the need to file this, fixing this in 3.8 is probably just fine.
msg347289 - (view) Author: Barry Byford (ukBaz) Date: 2019-07-04 16:42
I was looking to control Bluetooth on Linux machines using the BlueZ Management API available at:

The Bluetooth management sockets can be created by setting the hci_channel
member of struct sockaddr_hci to HCI_CHANNEL_CONTROL (3) when creating a
raw HCI socket.

The resolution of this issue would enable access to that API.
Date User Action Args
2019-07-09 07:01:38Jeffrey.Kintschersetnosy: + Jeffrey.Kintscher
2019-07-04 16:42:52ukBazsetnosy: + ukBaz
messages: + msg347289
2019-02-27 23:50:48bsdersetmessages: + msg336784
2019-02-27 11:13:49matrixisesetnosy: + matrixise

messages: + msg336744
versions: - Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7
2019-02-27 11:10:31bsdercreate