diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 51 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 2 |
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); | |||
953 | void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); | 953 | void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); |
954 | 954 | ||
955 | /* ----- HCI Sockets ----- */ | 955 | /* ----- HCI Sockets ----- */ |
956 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, | 956 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); |
957 | struct sock *skip_sk); | 957 | void 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 */ |
88 | void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, | 88 | void 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 | ||
140 | clone: | ||
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 */ | ||
149 | void 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; |