aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h4
-rw-r--r--net/bluetooth/hci_core.c4
-rw-r--r--net/bluetooth/hci_event.c2
-rw-r--r--net/bluetooth/hci_sock.c51
-rw-r--r--net/bluetooth/mgmt.c2
5 files changed, 45 insertions, 18 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2aafeb3a8793..9209e4c8a211 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -953,8 +953,8 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
953void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); 953void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
954 954
955/* ----- HCI Sockets ----- */ 955/* ----- HCI Sockets ----- */
956void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, 956void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
957 struct sock *skip_sk); 957void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk);
958 958
959/* Management interface */ 959/* Management interface */
960#define MGMT_ADDR_BREDR 0x00 960#define MGMT_ADDR_BREDR 0x00
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fabca080ae70..638fa8c393d8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2131,7 +2131,7 @@ static int hci_send_frame(struct sk_buff *skb)
2131 /* Time stamp */ 2131 /* Time stamp */
2132 __net_timestamp(skb); 2132 __net_timestamp(skb);
2133 2133
2134 hci_send_to_sock(hdev, skb, NULL); 2134 hci_send_to_sock(hdev, skb);
2135 } 2135 }
2136 2136
2137 /* Get rid of skb owner, prior to sending to the driver. */ 2137 /* Get rid of skb owner, prior to sending to the driver. */
@@ -2818,7 +2818,7 @@ static void hci_rx_work(struct work_struct *work)
2818 while ((skb = skb_dequeue(&hdev->rx_q))) { 2818 while ((skb = skb_dequeue(&hdev->rx_q))) {
2819 if (atomic_read(&hdev->promisc)) { 2819 if (atomic_read(&hdev->promisc)) {
2820 /* Send copy to the sockets */ 2820 /* Send copy to the sockets */
2821 hci_send_to_sock(hdev, skb, NULL); 2821 hci_send_to_sock(hdev, skb);
2822 } 2822 }
2823 2823
2824 if (test_bit(HCI_RAW, &hdev->flags)) { 2824 if (test_bit(HCI_RAW, &hdev->flags)) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 04fb1f02dfcc..e69db4a7b3ef 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3571,7 +3571,7 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
3571 3571
3572 bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 3572 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
3573 skb->dev = (void *) hdev; 3573 skb->dev = (void *) hdev;
3574 hci_send_to_sock(hdev, skb, NULL); 3574 hci_send_to_sock(hdev, skb);
3575 kfree_skb(skb); 3575 kfree_skb(skb);
3576} 3576}
3577 3577
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 9e854d9fb460..b5b3bc8d2848 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -85,8 +85,7 @@ static struct bt_sock_list hci_sk_list = {
85}; 85};
86 86
87/* Send frame to RAW socket */ 87/* Send frame to RAW socket */
88void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, 88void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
89 struct sock *skip_sk)
90{ 89{
91 struct sock *sk; 90 struct sock *sk;
92 struct hlist_node *node; 91 struct hlist_node *node;
@@ -94,13 +93,11 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
94 BT_DBG("hdev %p len %d", hdev, skb->len); 93 BT_DBG("hdev %p len %d", hdev, skb->len);
95 94
96 read_lock(&hci_sk_list.lock); 95 read_lock(&hci_sk_list.lock);
96
97 sk_for_each(sk, node, &hci_sk_list.head) { 97 sk_for_each(sk, node, &hci_sk_list.head) {
98 struct hci_filter *flt; 98 struct hci_filter *flt;
99 struct sk_buff *nskb; 99 struct sk_buff *nskb;
100 100
101 if (sk == skip_sk)
102 continue;
103
104 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 101 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
105 continue; 102 continue;
106 103
@@ -108,12 +105,9 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
108 if (skb->sk == sk) 105 if (skb->sk == sk)
109 continue; 106 continue;
110 107
111 if (bt_cb(skb)->channel != hci_pi(sk)->channel) 108 if (hci_pi(sk)->channel != HCI_CHANNEL_RAW)
112 continue; 109 continue;
113 110
114 if (bt_cb(skb)->channel == HCI_CHANNEL_CONTROL)
115 goto clone;
116
117 /* Apply filter */ 111 /* Apply filter */
118 flt = &hci_pi(sk)->filter; 112 flt = &hci_pi(sk)->filter;
119 113
@@ -137,18 +131,51 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
137 continue; 131 continue;
138 } 132 }
139 133
140clone:
141 nskb = skb_clone(skb, GFP_ATOMIC); 134 nskb = skb_clone(skb, GFP_ATOMIC);
142 if (!nskb) 135 if (!nskb)
143 continue; 136 continue;
144 137
145 /* Put type byte before the data */ 138 /* Put type byte before the data */
146 if (bt_cb(skb)->channel == HCI_CHANNEL_RAW) 139 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
147 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1); 140
141 if (sock_queue_rcv_skb(sk, nskb))
142 kfree_skb(nskb);
143 }
144
145 read_unlock(&hci_sk_list.lock);
146}
147
148/* Send frame to control socket */
149void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
150{
151 struct sock *sk;
152 struct hlist_node *node;
153
154 BT_DBG("len %d", skb->len);
155
156 read_lock(&hci_sk_list.lock);
157
158 sk_for_each(sk, node, &hci_sk_list.head) {
159 struct sk_buff *nskb;
160
161 /* Skip the original socket */
162 if (sk == skip_sk)
163 continue;
164
165 if (sk->sk_state != BT_BOUND)
166 continue;
167
168 if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
169 continue;
170
171 nskb = skb_clone(skb, GFP_ATOMIC);
172 if (!nskb)
173 continue;
148 174
149 if (sock_queue_rcv_skb(sk, nskb)) 175 if (sock_queue_rcv_skb(sk, nskb))
150 kfree_skb(nskb); 176 kfree_skb(nskb);
151 } 177 }
178
152 read_unlock(&hci_sk_list.lock); 179 read_unlock(&hci_sk_list.lock);
153} 180}
154 181
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 18d593f23934..1695d04d927d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -924,7 +924,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
924 if (data) 924 if (data)
925 memcpy(skb_put(skb, data_len), data, data_len); 925 memcpy(skb_put(skb, data_len), data, data_len);
926 926
927 hci_send_to_sock(NULL, skb, skip_sk); 927 hci_send_to_control(skb, skip_sk);
928 kfree_skb(skb); 928 kfree_skb(skb);
929 929
930 return 0; 930 return 0;