From 0381101fd6a73c7d6b545044dc1472d019fc64e3 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 8 Dec 2010 00:21:06 +0200 Subject: Bluetooth: Add initial Bluetooth Management interface callbacks Add initial code for handling Bluetooth Management interface messages. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Acked-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_sock.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'net/bluetooth/hci_sock.c') diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b3753ba..207be7a 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -49,6 +49,8 @@ #include #include +static int enable_mgmt; + /* ----- HCI socket interface ----- */ static inline int hci_test_bit(int nr, void *addr) @@ -353,25 +355,35 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) { - struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; + struct sockaddr_hci haddr; struct sock *sk = sock->sk; struct hci_dev *hdev = NULL; - int err = 0; + int len, err = 0; BT_DBG("sock %p sk %p", sock, sk); - if (!haddr || haddr->hci_family != AF_BLUETOOTH) + if (!addr) + return -EINVAL; + + memset(&haddr, 0, sizeof(haddr)); + len = min_t(unsigned int, sizeof(haddr), addr_len); + memcpy(&haddr, addr, len); + + if (haddr.hci_family != AF_BLUETOOTH) + return -EINVAL; + + if (haddr.hci_channel != HCI_CHANNEL_RAW && !enable_mgmt) return -EINVAL; lock_sock(sk); - if (hci_pi(sk)->hdev) { + if (sk->sk_state == BT_BOUND || hci_pi(sk)->hdev) { err = -EALREADY; goto done; } - if (haddr->hci_dev != HCI_DEV_NONE) { - hdev = hci_dev_get(haddr->hci_dev); + if (haddr.hci_dev != HCI_DEV_NONE) { + hdev = hci_dev_get(haddr.hci_dev); if (!hdev) { err = -ENODEV; goto done; @@ -380,6 +392,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le atomic_inc(&hdev->promisc); } + hci_pi(sk)->channel = haddr.hci_channel; hci_pi(sk)->hdev = hdev; sk->sk_state = BT_BOUND; @@ -502,6 +515,17 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, lock_sock(sk); + switch (hci_pi(sk)->channel) { + case HCI_CHANNEL_RAW: + break; + case HCI_CHANNEL_CONTROL: + err = mgmt_control(sk, msg, len); + goto done; + default: + err = -EINVAL; + goto done; + } + hdev = hci_pi(sk)->hdev; if (!hdev) { err = -EBADFD; @@ -831,3 +855,6 @@ void __exit hci_sock_cleanup(void) proto_unregister(&hci_sk_proto); } + +module_param(enable_mgmt, bool, 0644); +MODULE_PARM_DESC(enable_mgmt, "Enable Management interface"); -- cgit v1.1 From a40c406cbdd28dcca3483065bc2ba794cf5aaab7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 8 Dec 2010 00:21:07 +0200 Subject: Bluetooth: Make hci_send_to_sock usable for management control sockets In order to send data to management control sockets the function should: - skip checks intended for raw HCI data and stack internal events - make sure RAW HCI data or stack internal events don't go to management control sockets In order to accomplish this the patch adds a new member to the bluetooth skb private data to flag skb's that are destined for management control sockets. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_sock.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hci_sock.c') diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 207be7a..f6c18ab 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -104,6 +104,12 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) if (skb->sk == sk) continue; + if (bt_cb(skb)->channel != hci_pi(sk)->channel) + continue; + + if (bt_cb(skb)->channel == HCI_CHANNEL_CONTROL) + goto clone; + /* Apply filter */ flt = &hci_pi(sk)->filter; @@ -127,12 +133,14 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) continue; } +clone: nskb = skb_clone(skb, GFP_ATOMIC); if (!nskb) continue; /* Put type byte before the data */ - memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1); + if (bt_cb(skb)->channel == HCI_CHANNEL_RAW) + memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1); if (sock_queue_rcv_skb(sk, nskb)) kfree_skb(nskb); -- cgit v1.1 From 17f9cc3124c97f50a19a7597e5f29f915b5b835c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 22 Dec 2010 23:00:34 -0200 Subject: Bluetooth: Improve handling of HCI control channel in bind Does not allow any channel different of HCI_CHANNEL_RAW and HCI_CHANNEL_CONTROL to bind. Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_sock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hci_sock.c') diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f6c18ab..29827c7 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -380,7 +380,10 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le if (haddr.hci_family != AF_BLUETOOTH) return -EINVAL; - if (haddr.hci_channel != HCI_CHANNEL_RAW && !enable_mgmt) + if (haddr.hci_channel > HCI_CHANNEL_CONTROL) + return -EINVAL; + + if (haddr.hci_channel == HCI_CHANNEL_CONTROL && !enable_mgmt) return -EINVAL; lock_sock(sk); -- cgit v1.1