Commit 7e21addcd0ad87696c17409399e56e874931da57

Authored by Marcel Holtmann
1 parent 2da31939a4

Bluetooth: Return ENETDOWN when interface is down

Sending commands to a down interface results in a timeout while clearly
it should just return ENETDOWN. When using the ioctls this works fine,
but not when using the HCI sockets sendmsg interface.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

Showing 1 changed file with 5 additions and 0 deletions Inline Diff

net/bluetooth/hci_sock.c
1 /* 1 /*
2 BlueZ - Bluetooth protocol stack for Linux 2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated 3 Copyright (C) 2000-2001 Qualcomm Incorporated
4 4
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6 6
7 This program is free software; you can redistribute it and/or modify 7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as 8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation; 9 published by the Free Software Foundation;
10 10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED. 22 SOFTWARE IS DISCLAIMED.
23 */ 23 */
24 24
25 /* Bluetooth HCI sockets. */ 25 /* Bluetooth HCI sockets. */
26 26
27 #include <linux/module.h> 27 #include <linux/module.h>
28 28
29 #include <linux/types.h> 29 #include <linux/types.h>
30 #include <linux/capability.h> 30 #include <linux/capability.h>
31 #include <linux/errno.h> 31 #include <linux/errno.h>
32 #include <linux/kernel.h> 32 #include <linux/kernel.h>
33 #include <linux/slab.h> 33 #include <linux/slab.h>
34 #include <linux/poll.h> 34 #include <linux/poll.h>
35 #include <linux/fcntl.h> 35 #include <linux/fcntl.h>
36 #include <linux/init.h> 36 #include <linux/init.h>
37 #include <linux/skbuff.h> 37 #include <linux/skbuff.h>
38 #include <linux/workqueue.h> 38 #include <linux/workqueue.h>
39 #include <linux/interrupt.h> 39 #include <linux/interrupt.h>
40 #include <linux/compat.h> 40 #include <linux/compat.h>
41 #include <linux/socket.h> 41 #include <linux/socket.h>
42 #include <linux/ioctl.h> 42 #include <linux/ioctl.h>
43 #include <net/sock.h> 43 #include <net/sock.h>
44 44
45 #include <asm/system.h> 45 #include <asm/system.h>
46 #include <asm/uaccess.h> 46 #include <asm/uaccess.h>
47 #include <asm/unaligned.h> 47 #include <asm/unaligned.h>
48 48
49 #include <net/bluetooth/bluetooth.h> 49 #include <net/bluetooth/bluetooth.h>
50 #include <net/bluetooth/hci_core.h> 50 #include <net/bluetooth/hci_core.h>
51 51
52 /* ----- HCI socket interface ----- */ 52 /* ----- HCI socket interface ----- */
53 53
54 static inline int hci_test_bit(int nr, void *addr) 54 static inline int hci_test_bit(int nr, void *addr)
55 { 55 {
56 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); 56 return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
57 } 57 }
58 58
59 /* Security filter */ 59 /* Security filter */
60 static struct hci_sec_filter hci_sec_filter = { 60 static struct hci_sec_filter hci_sec_filter = {
61 /* Packet types */ 61 /* Packet types */
62 0x10, 62 0x10,
63 /* Events */ 63 /* Events */
64 { 0x1000d9fe, 0x0000b00c }, 64 { 0x1000d9fe, 0x0000b00c },
65 /* Commands */ 65 /* Commands */
66 { 66 {
67 { 0x0 }, 67 { 0x0 },
68 /* OGF_LINK_CTL */ 68 /* OGF_LINK_CTL */
69 { 0xbe000006, 0x00000001, 0x00000000, 0x00 }, 69 { 0xbe000006, 0x00000001, 0x00000000, 0x00 },
70 /* OGF_LINK_POLICY */ 70 /* OGF_LINK_POLICY */
71 { 0x00005200, 0x00000000, 0x00000000, 0x00 }, 71 { 0x00005200, 0x00000000, 0x00000000, 0x00 },
72 /* OGF_HOST_CTL */ 72 /* OGF_HOST_CTL */
73 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 }, 73 { 0xaab00200, 0x2b402aaa, 0x05220154, 0x00 },
74 /* OGF_INFO_PARAM */ 74 /* OGF_INFO_PARAM */
75 { 0x000002be, 0x00000000, 0x00000000, 0x00 }, 75 { 0x000002be, 0x00000000, 0x00000000, 0x00 },
76 /* OGF_STATUS_PARAM */ 76 /* OGF_STATUS_PARAM */
77 { 0x000000ea, 0x00000000, 0x00000000, 0x00 } 77 { 0x000000ea, 0x00000000, 0x00000000, 0x00 }
78 } 78 }
79 }; 79 };
80 80
81 static struct bt_sock_list hci_sk_list = { 81 static struct bt_sock_list hci_sk_list = {
82 .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) 82 .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
83 }; 83 };
84 84
85 /* Send frame to RAW socket */ 85 /* Send frame to RAW socket */
86 void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) 86 void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
87 { 87 {
88 struct sock *sk; 88 struct sock *sk;
89 struct hlist_node *node; 89 struct hlist_node *node;
90 90
91 BT_DBG("hdev %p len %d", hdev, skb->len); 91 BT_DBG("hdev %p len %d", hdev, skb->len);
92 92
93 read_lock(&hci_sk_list.lock); 93 read_lock(&hci_sk_list.lock);
94 sk_for_each(sk, node, &hci_sk_list.head) { 94 sk_for_each(sk, node, &hci_sk_list.head) {
95 struct hci_filter *flt; 95 struct hci_filter *flt;
96 struct sk_buff *nskb; 96 struct sk_buff *nskb;
97 97
98 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev) 98 if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
99 continue; 99 continue;
100 100
101 /* Don't send frame to the socket it came from */ 101 /* Don't send frame to the socket it came from */
102 if (skb->sk == sk) 102 if (skb->sk == sk)
103 continue; 103 continue;
104 104
105 /* Apply filter */ 105 /* Apply filter */
106 flt = &hci_pi(sk)->filter; 106 flt = &hci_pi(sk)->filter;
107 107
108 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ? 108 if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
109 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask)) 109 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
110 continue; 110 continue;
111 111
112 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) { 112 if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
113 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS); 113 register int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
114 114
115 if (!hci_test_bit(evt, &flt->event_mask)) 115 if (!hci_test_bit(evt, &flt->event_mask))
116 continue; 116 continue;
117 117
118 if (flt->opcode && 118 if (flt->opcode &&
119 ((evt == HCI_EV_CMD_COMPLETE && 119 ((evt == HCI_EV_CMD_COMPLETE &&
120 flt->opcode != 120 flt->opcode !=
121 get_unaligned((__le16 *)(skb->data + 3))) || 121 get_unaligned((__le16 *)(skb->data + 3))) ||
122 (evt == HCI_EV_CMD_STATUS && 122 (evt == HCI_EV_CMD_STATUS &&
123 flt->opcode != 123 flt->opcode !=
124 get_unaligned((__le16 *)(skb->data + 4))))) 124 get_unaligned((__le16 *)(skb->data + 4)))))
125 continue; 125 continue;
126 } 126 }
127 127
128 if (!(nskb = skb_clone(skb, GFP_ATOMIC))) 128 if (!(nskb = skb_clone(skb, GFP_ATOMIC)))
129 continue; 129 continue;
130 130
131 /* Put type byte before the data */ 131 /* Put type byte before the data */
132 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1); 132 memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
133 133
134 if (sock_queue_rcv_skb(sk, nskb)) 134 if (sock_queue_rcv_skb(sk, nskb))
135 kfree_skb(nskb); 135 kfree_skb(nskb);
136 } 136 }
137 read_unlock(&hci_sk_list.lock); 137 read_unlock(&hci_sk_list.lock);
138 } 138 }
139 139
140 static int hci_sock_release(struct socket *sock) 140 static int hci_sock_release(struct socket *sock)
141 { 141 {
142 struct sock *sk = sock->sk; 142 struct sock *sk = sock->sk;
143 struct hci_dev *hdev; 143 struct hci_dev *hdev;
144 144
145 BT_DBG("sock %p sk %p", sock, sk); 145 BT_DBG("sock %p sk %p", sock, sk);
146 146
147 if (!sk) 147 if (!sk)
148 return 0; 148 return 0;
149 149
150 hdev = hci_pi(sk)->hdev; 150 hdev = hci_pi(sk)->hdev;
151 151
152 bt_sock_unlink(&hci_sk_list, sk); 152 bt_sock_unlink(&hci_sk_list, sk);
153 153
154 if (hdev) { 154 if (hdev) {
155 atomic_dec(&hdev->promisc); 155 atomic_dec(&hdev->promisc);
156 hci_dev_put(hdev); 156 hci_dev_put(hdev);
157 } 157 }
158 158
159 sock_orphan(sk); 159 sock_orphan(sk);
160 160
161 skb_queue_purge(&sk->sk_receive_queue); 161 skb_queue_purge(&sk->sk_receive_queue);
162 skb_queue_purge(&sk->sk_write_queue); 162 skb_queue_purge(&sk->sk_write_queue);
163 163
164 sock_put(sk); 164 sock_put(sk);
165 return 0; 165 return 0;
166 } 166 }
167 167
168 /* Ioctls that require bound socket */ 168 /* Ioctls that require bound socket */
169 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg) 169 static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
170 { 170 {
171 struct hci_dev *hdev = hci_pi(sk)->hdev; 171 struct hci_dev *hdev = hci_pi(sk)->hdev;
172 172
173 if (!hdev) 173 if (!hdev)
174 return -EBADFD; 174 return -EBADFD;
175 175
176 switch (cmd) { 176 switch (cmd) {
177 case HCISETRAW: 177 case HCISETRAW:
178 if (!capable(CAP_NET_ADMIN)) 178 if (!capable(CAP_NET_ADMIN))
179 return -EACCES; 179 return -EACCES;
180 180
181 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) 181 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
182 return -EPERM; 182 return -EPERM;
183 183
184 if (arg) 184 if (arg)
185 set_bit(HCI_RAW, &hdev->flags); 185 set_bit(HCI_RAW, &hdev->flags);
186 else 186 else
187 clear_bit(HCI_RAW, &hdev->flags); 187 clear_bit(HCI_RAW, &hdev->flags);
188 188
189 return 0; 189 return 0;
190 190
191 case HCIGETCONNINFO: 191 case HCIGETCONNINFO:
192 return hci_get_conn_info(hdev, (void __user *) arg); 192 return hci_get_conn_info(hdev, (void __user *) arg);
193 193
194 case HCIGETAUTHINFO: 194 case HCIGETAUTHINFO:
195 return hci_get_auth_info(hdev, (void __user *) arg); 195 return hci_get_auth_info(hdev, (void __user *) arg);
196 196
197 default: 197 default:
198 if (hdev->ioctl) 198 if (hdev->ioctl)
199 return hdev->ioctl(hdev, cmd, arg); 199 return hdev->ioctl(hdev, cmd, arg);
200 return -EINVAL; 200 return -EINVAL;
201 } 201 }
202 } 202 }
203 203
204 static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 204 static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
205 { 205 {
206 struct sock *sk = sock->sk; 206 struct sock *sk = sock->sk;
207 void __user *argp = (void __user *) arg; 207 void __user *argp = (void __user *) arg;
208 int err; 208 int err;
209 209
210 BT_DBG("cmd %x arg %lx", cmd, arg); 210 BT_DBG("cmd %x arg %lx", cmd, arg);
211 211
212 switch (cmd) { 212 switch (cmd) {
213 case HCIGETDEVLIST: 213 case HCIGETDEVLIST:
214 return hci_get_dev_list(argp); 214 return hci_get_dev_list(argp);
215 215
216 case HCIGETDEVINFO: 216 case HCIGETDEVINFO:
217 return hci_get_dev_info(argp); 217 return hci_get_dev_info(argp);
218 218
219 case HCIGETCONNLIST: 219 case HCIGETCONNLIST:
220 return hci_get_conn_list(argp); 220 return hci_get_conn_list(argp);
221 221
222 case HCIDEVUP: 222 case HCIDEVUP:
223 if (!capable(CAP_NET_ADMIN)) 223 if (!capable(CAP_NET_ADMIN))
224 return -EACCES; 224 return -EACCES;
225 return hci_dev_open(arg); 225 return hci_dev_open(arg);
226 226
227 case HCIDEVDOWN: 227 case HCIDEVDOWN:
228 if (!capable(CAP_NET_ADMIN)) 228 if (!capable(CAP_NET_ADMIN))
229 return -EACCES; 229 return -EACCES;
230 return hci_dev_close(arg); 230 return hci_dev_close(arg);
231 231
232 case HCIDEVRESET: 232 case HCIDEVRESET:
233 if (!capable(CAP_NET_ADMIN)) 233 if (!capable(CAP_NET_ADMIN))
234 return -EACCES; 234 return -EACCES;
235 return hci_dev_reset(arg); 235 return hci_dev_reset(arg);
236 236
237 case HCIDEVRESTAT: 237 case HCIDEVRESTAT:
238 if (!capable(CAP_NET_ADMIN)) 238 if (!capable(CAP_NET_ADMIN))
239 return -EACCES; 239 return -EACCES;
240 return hci_dev_reset_stat(arg); 240 return hci_dev_reset_stat(arg);
241 241
242 case HCISETSCAN: 242 case HCISETSCAN:
243 case HCISETAUTH: 243 case HCISETAUTH:
244 case HCISETENCRYPT: 244 case HCISETENCRYPT:
245 case HCISETPTYPE: 245 case HCISETPTYPE:
246 case HCISETLINKPOL: 246 case HCISETLINKPOL:
247 case HCISETLINKMODE: 247 case HCISETLINKMODE:
248 case HCISETACLMTU: 248 case HCISETACLMTU:
249 case HCISETSCOMTU: 249 case HCISETSCOMTU:
250 if (!capable(CAP_NET_ADMIN)) 250 if (!capable(CAP_NET_ADMIN))
251 return -EACCES; 251 return -EACCES;
252 return hci_dev_cmd(cmd, argp); 252 return hci_dev_cmd(cmd, argp);
253 253
254 case HCIINQUIRY: 254 case HCIINQUIRY:
255 return hci_inquiry(argp); 255 return hci_inquiry(argp);
256 256
257 default: 257 default:
258 lock_sock(sk); 258 lock_sock(sk);
259 err = hci_sock_bound_ioctl(sk, cmd, arg); 259 err = hci_sock_bound_ioctl(sk, cmd, arg);
260 release_sock(sk); 260 release_sock(sk);
261 return err; 261 return err;
262 } 262 }
263 } 263 }
264 264
265 static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) 265 static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
266 { 266 {
267 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 267 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
268 struct sock *sk = sock->sk; 268 struct sock *sk = sock->sk;
269 struct hci_dev *hdev = NULL; 269 struct hci_dev *hdev = NULL;
270 int err = 0; 270 int err = 0;
271 271
272 BT_DBG("sock %p sk %p", sock, sk); 272 BT_DBG("sock %p sk %p", sock, sk);
273 273
274 if (!haddr || haddr->hci_family != AF_BLUETOOTH) 274 if (!haddr || haddr->hci_family != AF_BLUETOOTH)
275 return -EINVAL; 275 return -EINVAL;
276 276
277 lock_sock(sk); 277 lock_sock(sk);
278 278
279 if (hci_pi(sk)->hdev) { 279 if (hci_pi(sk)->hdev) {
280 err = -EALREADY; 280 err = -EALREADY;
281 goto done; 281 goto done;
282 } 282 }
283 283
284 if (haddr->hci_dev != HCI_DEV_NONE) { 284 if (haddr->hci_dev != HCI_DEV_NONE) {
285 if (!(hdev = hci_dev_get(haddr->hci_dev))) { 285 if (!(hdev = hci_dev_get(haddr->hci_dev))) {
286 err = -ENODEV; 286 err = -ENODEV;
287 goto done; 287 goto done;
288 } 288 }
289 289
290 atomic_inc(&hdev->promisc); 290 atomic_inc(&hdev->promisc);
291 } 291 }
292 292
293 hci_pi(sk)->hdev = hdev; 293 hci_pi(sk)->hdev = hdev;
294 sk->sk_state = BT_BOUND; 294 sk->sk_state = BT_BOUND;
295 295
296 done: 296 done:
297 release_sock(sk); 297 release_sock(sk);
298 return err; 298 return err;
299 } 299 }
300 300
301 static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer) 301 static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
302 { 302 {
303 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr; 303 struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
304 struct sock *sk = sock->sk; 304 struct sock *sk = sock->sk;
305 struct hci_dev *hdev = hci_pi(sk)->hdev; 305 struct hci_dev *hdev = hci_pi(sk)->hdev;
306 306
307 BT_DBG("sock %p sk %p", sock, sk); 307 BT_DBG("sock %p sk %p", sock, sk);
308 308
309 if (!hdev) 309 if (!hdev)
310 return -EBADFD; 310 return -EBADFD;
311 311
312 lock_sock(sk); 312 lock_sock(sk);
313 313
314 *addr_len = sizeof(*haddr); 314 *addr_len = sizeof(*haddr);
315 haddr->hci_family = AF_BLUETOOTH; 315 haddr->hci_family = AF_BLUETOOTH;
316 haddr->hci_dev = hdev->id; 316 haddr->hci_dev = hdev->id;
317 317
318 release_sock(sk); 318 release_sock(sk);
319 return 0; 319 return 0;
320 } 320 }
321 321
322 static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) 322 static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
323 { 323 {
324 __u32 mask = hci_pi(sk)->cmsg_mask; 324 __u32 mask = hci_pi(sk)->cmsg_mask;
325 325
326 if (mask & HCI_CMSG_DIR) { 326 if (mask & HCI_CMSG_DIR) {
327 int incoming = bt_cb(skb)->incoming; 327 int incoming = bt_cb(skb)->incoming;
328 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming); 328 put_cmsg(msg, SOL_HCI, HCI_CMSG_DIR, sizeof(incoming), &incoming);
329 } 329 }
330 330
331 if (mask & HCI_CMSG_TSTAMP) { 331 if (mask & HCI_CMSG_TSTAMP) {
332 struct timeval tv; 332 struct timeval tv;
333 void *data; 333 void *data;
334 int len; 334 int len;
335 335
336 skb_get_timestamp(skb, &tv); 336 skb_get_timestamp(skb, &tv);
337 337
338 data = &tv; 338 data = &tv;
339 len = sizeof(tv); 339 len = sizeof(tv);
340 #ifdef CONFIG_COMPAT 340 #ifdef CONFIG_COMPAT
341 if (msg->msg_flags & MSG_CMSG_COMPAT) { 341 if (msg->msg_flags & MSG_CMSG_COMPAT) {
342 struct compat_timeval ctv; 342 struct compat_timeval ctv;
343 ctv.tv_sec = tv.tv_sec; 343 ctv.tv_sec = tv.tv_sec;
344 ctv.tv_usec = tv.tv_usec; 344 ctv.tv_usec = tv.tv_usec;
345 data = &ctv; 345 data = &ctv;
346 len = sizeof(ctv); 346 len = sizeof(ctv);
347 } 347 }
348 #endif 348 #endif
349 349
350 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data); 350 put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, len, data);
351 } 351 }
352 } 352 }
353 353
354 static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 354 static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
355 struct msghdr *msg, size_t len, int flags) 355 struct msghdr *msg, size_t len, int flags)
356 { 356 {
357 int noblock = flags & MSG_DONTWAIT; 357 int noblock = flags & MSG_DONTWAIT;
358 struct sock *sk = sock->sk; 358 struct sock *sk = sock->sk;
359 struct sk_buff *skb; 359 struct sk_buff *skb;
360 int copied, err; 360 int copied, err;
361 361
362 BT_DBG("sock %p, sk %p", sock, sk); 362 BT_DBG("sock %p, sk %p", sock, sk);
363 363
364 if (flags & (MSG_OOB)) 364 if (flags & (MSG_OOB))
365 return -EOPNOTSUPP; 365 return -EOPNOTSUPP;
366 366
367 if (sk->sk_state == BT_CLOSED) 367 if (sk->sk_state == BT_CLOSED)
368 return 0; 368 return 0;
369 369
370 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) 370 if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))
371 return err; 371 return err;
372 372
373 msg->msg_namelen = 0; 373 msg->msg_namelen = 0;
374 374
375 copied = skb->len; 375 copied = skb->len;
376 if (len < copied) { 376 if (len < copied) {
377 msg->msg_flags |= MSG_TRUNC; 377 msg->msg_flags |= MSG_TRUNC;
378 copied = len; 378 copied = len;
379 } 379 }
380 380
381 skb_reset_transport_header(skb); 381 skb_reset_transport_header(skb);
382 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 382 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
383 383
384 hci_sock_cmsg(sk, msg, skb); 384 hci_sock_cmsg(sk, msg, skb);
385 385
386 skb_free_datagram(sk, skb); 386 skb_free_datagram(sk, skb);
387 387
388 return err ? : copied; 388 return err ? : copied;
389 } 389 }
390 390
391 static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 391 static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
392 struct msghdr *msg, size_t len) 392 struct msghdr *msg, size_t len)
393 { 393 {
394 struct sock *sk = sock->sk; 394 struct sock *sk = sock->sk;
395 struct hci_dev *hdev; 395 struct hci_dev *hdev;
396 struct sk_buff *skb; 396 struct sk_buff *skb;
397 int err; 397 int err;
398 398
399 BT_DBG("sock %p sk %p", sock, sk); 399 BT_DBG("sock %p sk %p", sock, sk);
400 400
401 if (msg->msg_flags & MSG_OOB) 401 if (msg->msg_flags & MSG_OOB)
402 return -EOPNOTSUPP; 402 return -EOPNOTSUPP;
403 403
404 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE)) 404 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_NOSIGNAL|MSG_ERRQUEUE))
405 return -EINVAL; 405 return -EINVAL;
406 406
407 if (len < 4 || len > HCI_MAX_FRAME_SIZE) 407 if (len < 4 || len > HCI_MAX_FRAME_SIZE)
408 return -EINVAL; 408 return -EINVAL;
409 409
410 lock_sock(sk); 410 lock_sock(sk);
411 411
412 if (!(hdev = hci_pi(sk)->hdev)) { 412 if (!(hdev = hci_pi(sk)->hdev)) {
413 err = -EBADFD; 413 err = -EBADFD;
414 goto done; 414 goto done;
415 } 415 }
416 416
417 if (!test_bit(HCI_UP, &hdev->flags)) {
418 err = -ENETDOWN;
419 goto done;
420 }
421
417 if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) 422 if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err)))
418 goto done; 423 goto done;
419 424
420 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { 425 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
421 err = -EFAULT; 426 err = -EFAULT;
422 goto drop; 427 goto drop;
423 } 428 }
424 429
425 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); 430 bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
426 skb_pull(skb, 1); 431 skb_pull(skb, 1);
427 skb->dev = (void *) hdev; 432 skb->dev = (void *) hdev;
428 433
429 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { 434 if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
430 u16 opcode = get_unaligned_le16(skb->data); 435 u16 opcode = get_unaligned_le16(skb->data);
431 u16 ogf = hci_opcode_ogf(opcode); 436 u16 ogf = hci_opcode_ogf(opcode);
432 u16 ocf = hci_opcode_ocf(opcode); 437 u16 ocf = hci_opcode_ocf(opcode);
433 438
434 if (((ogf > HCI_SFLT_MAX_OGF) || 439 if (((ogf > HCI_SFLT_MAX_OGF) ||
435 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) && 440 !hci_test_bit(ocf & HCI_FLT_OCF_BITS, &hci_sec_filter.ocf_mask[ogf])) &&
436 !capable(CAP_NET_RAW)) { 441 !capable(CAP_NET_RAW)) {
437 err = -EPERM; 442 err = -EPERM;
438 goto drop; 443 goto drop;
439 } 444 }
440 445
441 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) { 446 if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
442 skb_queue_tail(&hdev->raw_q, skb); 447 skb_queue_tail(&hdev->raw_q, skb);
443 hci_sched_tx(hdev); 448 hci_sched_tx(hdev);
444 } else { 449 } else {
445 skb_queue_tail(&hdev->cmd_q, skb); 450 skb_queue_tail(&hdev->cmd_q, skb);
446 hci_sched_cmd(hdev); 451 hci_sched_cmd(hdev);
447 } 452 }
448 } else { 453 } else {
449 if (!capable(CAP_NET_RAW)) { 454 if (!capable(CAP_NET_RAW)) {
450 err = -EPERM; 455 err = -EPERM;
451 goto drop; 456 goto drop;
452 } 457 }
453 458
454 skb_queue_tail(&hdev->raw_q, skb); 459 skb_queue_tail(&hdev->raw_q, skb);
455 hci_sched_tx(hdev); 460 hci_sched_tx(hdev);
456 } 461 }
457 462
458 err = len; 463 err = len;
459 464
460 done: 465 done:
461 release_sock(sk); 466 release_sock(sk);
462 return err; 467 return err;
463 468
464 drop: 469 drop:
465 kfree_skb(skb); 470 kfree_skb(skb);
466 goto done; 471 goto done;
467 } 472 }
468 473
469 static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len) 474 static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
470 { 475 {
471 struct hci_ufilter uf = { .opcode = 0 }; 476 struct hci_ufilter uf = { .opcode = 0 };
472 struct sock *sk = sock->sk; 477 struct sock *sk = sock->sk;
473 int err = 0, opt = 0; 478 int err = 0, opt = 0;
474 479
475 BT_DBG("sk %p, opt %d", sk, optname); 480 BT_DBG("sk %p, opt %d", sk, optname);
476 481
477 lock_sock(sk); 482 lock_sock(sk);
478 483
479 switch (optname) { 484 switch (optname) {
480 case HCI_DATA_DIR: 485 case HCI_DATA_DIR:
481 if (get_user(opt, (int __user *)optval)) { 486 if (get_user(opt, (int __user *)optval)) {
482 err = -EFAULT; 487 err = -EFAULT;
483 break; 488 break;
484 } 489 }
485 490
486 if (opt) 491 if (opt)
487 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; 492 hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
488 else 493 else
489 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR; 494 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_DIR;
490 break; 495 break;
491 496
492 case HCI_TIME_STAMP: 497 case HCI_TIME_STAMP:
493 if (get_user(opt, (int __user *)optval)) { 498 if (get_user(opt, (int __user *)optval)) {
494 err = -EFAULT; 499 err = -EFAULT;
495 break; 500 break;
496 } 501 }
497 502
498 if (opt) 503 if (opt)
499 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; 504 hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
500 else 505 else
501 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP; 506 hci_pi(sk)->cmsg_mask &= ~HCI_CMSG_TSTAMP;
502 break; 507 break;
503 508
504 case HCI_FILTER: 509 case HCI_FILTER:
505 { 510 {
506 struct hci_filter *f = &hci_pi(sk)->filter; 511 struct hci_filter *f = &hci_pi(sk)->filter;
507 512
508 uf.type_mask = f->type_mask; 513 uf.type_mask = f->type_mask;
509 uf.opcode = f->opcode; 514 uf.opcode = f->opcode;
510 uf.event_mask[0] = *((u32 *) f->event_mask + 0); 515 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
511 uf.event_mask[1] = *((u32 *) f->event_mask + 1); 516 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
512 } 517 }
513 518
514 len = min_t(unsigned int, len, sizeof(uf)); 519 len = min_t(unsigned int, len, sizeof(uf));
515 if (copy_from_user(&uf, optval, len)) { 520 if (copy_from_user(&uf, optval, len)) {
516 err = -EFAULT; 521 err = -EFAULT;
517 break; 522 break;
518 } 523 }
519 524
520 if (!capable(CAP_NET_RAW)) { 525 if (!capable(CAP_NET_RAW)) {
521 uf.type_mask &= hci_sec_filter.type_mask; 526 uf.type_mask &= hci_sec_filter.type_mask;
522 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0); 527 uf.event_mask[0] &= *((u32 *) hci_sec_filter.event_mask + 0);
523 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1); 528 uf.event_mask[1] &= *((u32 *) hci_sec_filter.event_mask + 1);
524 } 529 }
525 530
526 { 531 {
527 struct hci_filter *f = &hci_pi(sk)->filter; 532 struct hci_filter *f = &hci_pi(sk)->filter;
528 533
529 f->type_mask = uf.type_mask; 534 f->type_mask = uf.type_mask;
530 f->opcode = uf.opcode; 535 f->opcode = uf.opcode;
531 *((u32 *) f->event_mask + 0) = uf.event_mask[0]; 536 *((u32 *) f->event_mask + 0) = uf.event_mask[0];
532 *((u32 *) f->event_mask + 1) = uf.event_mask[1]; 537 *((u32 *) f->event_mask + 1) = uf.event_mask[1];
533 } 538 }
534 break; 539 break;
535 540
536 default: 541 default:
537 err = -ENOPROTOOPT; 542 err = -ENOPROTOOPT;
538 break; 543 break;
539 } 544 }
540 545
541 release_sock(sk); 546 release_sock(sk);
542 return err; 547 return err;
543 } 548 }
544 549
545 static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) 550 static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
546 { 551 {
547 struct hci_ufilter uf; 552 struct hci_ufilter uf;
548 struct sock *sk = sock->sk; 553 struct sock *sk = sock->sk;
549 int len, opt; 554 int len, opt;
550 555
551 if (get_user(len, optlen)) 556 if (get_user(len, optlen))
552 return -EFAULT; 557 return -EFAULT;
553 558
554 switch (optname) { 559 switch (optname) {
555 case HCI_DATA_DIR: 560 case HCI_DATA_DIR:
556 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR) 561 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_DIR)
557 opt = 1; 562 opt = 1;
558 else 563 else
559 opt = 0; 564 opt = 0;
560 565
561 if (put_user(opt, optval)) 566 if (put_user(opt, optval))
562 return -EFAULT; 567 return -EFAULT;
563 break; 568 break;
564 569
565 case HCI_TIME_STAMP: 570 case HCI_TIME_STAMP:
566 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP) 571 if (hci_pi(sk)->cmsg_mask & HCI_CMSG_TSTAMP)
567 opt = 1; 572 opt = 1;
568 else 573 else
569 opt = 0; 574 opt = 0;
570 575
571 if (put_user(opt, optval)) 576 if (put_user(opt, optval))
572 return -EFAULT; 577 return -EFAULT;
573 break; 578 break;
574 579
575 case HCI_FILTER: 580 case HCI_FILTER:
576 { 581 {
577 struct hci_filter *f = &hci_pi(sk)->filter; 582 struct hci_filter *f = &hci_pi(sk)->filter;
578 583
579 uf.type_mask = f->type_mask; 584 uf.type_mask = f->type_mask;
580 uf.opcode = f->opcode; 585 uf.opcode = f->opcode;
581 uf.event_mask[0] = *((u32 *) f->event_mask + 0); 586 uf.event_mask[0] = *((u32 *) f->event_mask + 0);
582 uf.event_mask[1] = *((u32 *) f->event_mask + 1); 587 uf.event_mask[1] = *((u32 *) f->event_mask + 1);
583 } 588 }
584 589
585 len = min_t(unsigned int, len, sizeof(uf)); 590 len = min_t(unsigned int, len, sizeof(uf));
586 if (copy_to_user(optval, &uf, len)) 591 if (copy_to_user(optval, &uf, len))
587 return -EFAULT; 592 return -EFAULT;
588 break; 593 break;
589 594
590 default: 595 default:
591 return -ENOPROTOOPT; 596 return -ENOPROTOOPT;
592 break; 597 break;
593 } 598 }
594 599
595 return 0; 600 return 0;
596 } 601 }
597 602
598 static const struct proto_ops hci_sock_ops = { 603 static const struct proto_ops hci_sock_ops = {
599 .family = PF_BLUETOOTH, 604 .family = PF_BLUETOOTH,
600 .owner = THIS_MODULE, 605 .owner = THIS_MODULE,
601 .release = hci_sock_release, 606 .release = hci_sock_release,
602 .bind = hci_sock_bind, 607 .bind = hci_sock_bind,
603 .getname = hci_sock_getname, 608 .getname = hci_sock_getname,
604 .sendmsg = hci_sock_sendmsg, 609 .sendmsg = hci_sock_sendmsg,
605 .recvmsg = hci_sock_recvmsg, 610 .recvmsg = hci_sock_recvmsg,
606 .ioctl = hci_sock_ioctl, 611 .ioctl = hci_sock_ioctl,
607 .poll = datagram_poll, 612 .poll = datagram_poll,
608 .listen = sock_no_listen, 613 .listen = sock_no_listen,
609 .shutdown = sock_no_shutdown, 614 .shutdown = sock_no_shutdown,
610 .setsockopt = hci_sock_setsockopt, 615 .setsockopt = hci_sock_setsockopt,
611 .getsockopt = hci_sock_getsockopt, 616 .getsockopt = hci_sock_getsockopt,
612 .connect = sock_no_connect, 617 .connect = sock_no_connect,
613 .socketpair = sock_no_socketpair, 618 .socketpair = sock_no_socketpair,
614 .accept = sock_no_accept, 619 .accept = sock_no_accept,
615 .mmap = sock_no_mmap 620 .mmap = sock_no_mmap
616 }; 621 };
617 622
618 static struct proto hci_sk_proto = { 623 static struct proto hci_sk_proto = {
619 .name = "HCI", 624 .name = "HCI",
620 .owner = THIS_MODULE, 625 .owner = THIS_MODULE,
621 .obj_size = sizeof(struct hci_pinfo) 626 .obj_size = sizeof(struct hci_pinfo)
622 }; 627 };
623 628
624 static int hci_sock_create(struct net *net, struct socket *sock, int protocol, 629 static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
625 int kern) 630 int kern)
626 { 631 {
627 struct sock *sk; 632 struct sock *sk;
628 633
629 BT_DBG("sock %p", sock); 634 BT_DBG("sock %p", sock);
630 635
631 if (sock->type != SOCK_RAW) 636 if (sock->type != SOCK_RAW)
632 return -ESOCKTNOSUPPORT; 637 return -ESOCKTNOSUPPORT;
633 638
634 sock->ops = &hci_sock_ops; 639 sock->ops = &hci_sock_ops;
635 640
636 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto); 641 sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto);
637 if (!sk) 642 if (!sk)
638 return -ENOMEM; 643 return -ENOMEM;
639 644
640 sock_init_data(sock, sk); 645 sock_init_data(sock, sk);
641 646
642 sock_reset_flag(sk, SOCK_ZAPPED); 647 sock_reset_flag(sk, SOCK_ZAPPED);
643 648
644 sk->sk_protocol = protocol; 649 sk->sk_protocol = protocol;
645 650
646 sock->state = SS_UNCONNECTED; 651 sock->state = SS_UNCONNECTED;
647 sk->sk_state = BT_OPEN; 652 sk->sk_state = BT_OPEN;
648 653
649 bt_sock_link(&hci_sk_list, sk); 654 bt_sock_link(&hci_sk_list, sk);
650 return 0; 655 return 0;
651 } 656 }
652 657
653 static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 658 static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
654 { 659 {
655 struct hci_dev *hdev = (struct hci_dev *) ptr; 660 struct hci_dev *hdev = (struct hci_dev *) ptr;
656 struct hci_ev_si_device ev; 661 struct hci_ev_si_device ev;
657 662
658 BT_DBG("hdev %s event %ld", hdev->name, event); 663 BT_DBG("hdev %s event %ld", hdev->name, event);
659 664
660 /* Send event to sockets */ 665 /* Send event to sockets */
661 ev.event = event; 666 ev.event = event;
662 ev.dev_id = hdev->id; 667 ev.dev_id = hdev->id;
663 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev); 668 hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);
664 669
665 if (event == HCI_DEV_UNREG) { 670 if (event == HCI_DEV_UNREG) {
666 struct sock *sk; 671 struct sock *sk;
667 struct hlist_node *node; 672 struct hlist_node *node;
668 673
669 /* Detach sockets from device */ 674 /* Detach sockets from device */
670 read_lock(&hci_sk_list.lock); 675 read_lock(&hci_sk_list.lock);
671 sk_for_each(sk, node, &hci_sk_list.head) { 676 sk_for_each(sk, node, &hci_sk_list.head) {
672 local_bh_disable(); 677 local_bh_disable();
673 bh_lock_sock_nested(sk); 678 bh_lock_sock_nested(sk);
674 if (hci_pi(sk)->hdev == hdev) { 679 if (hci_pi(sk)->hdev == hdev) {
675 hci_pi(sk)->hdev = NULL; 680 hci_pi(sk)->hdev = NULL;
676 sk->sk_err = EPIPE; 681 sk->sk_err = EPIPE;
677 sk->sk_state = BT_OPEN; 682 sk->sk_state = BT_OPEN;
678 sk->sk_state_change(sk); 683 sk->sk_state_change(sk);
679 684
680 hci_dev_put(hdev); 685 hci_dev_put(hdev);
681 } 686 }
682 bh_unlock_sock(sk); 687 bh_unlock_sock(sk);
683 local_bh_enable(); 688 local_bh_enable();
684 } 689 }
685 read_unlock(&hci_sk_list.lock); 690 read_unlock(&hci_sk_list.lock);
686 } 691 }
687 692
688 return NOTIFY_DONE; 693 return NOTIFY_DONE;
689 } 694 }
690 695
691 static const struct net_proto_family hci_sock_family_ops = { 696 static const struct net_proto_family hci_sock_family_ops = {
692 .family = PF_BLUETOOTH, 697 .family = PF_BLUETOOTH,
693 .owner = THIS_MODULE, 698 .owner = THIS_MODULE,
694 .create = hci_sock_create, 699 .create = hci_sock_create,
695 }; 700 };
696 701
697 static struct notifier_block hci_sock_nblock = { 702 static struct notifier_block hci_sock_nblock = {
698 .notifier_call = hci_sock_dev_event 703 .notifier_call = hci_sock_dev_event
699 }; 704 };
700 705
701 int __init hci_sock_init(void) 706 int __init hci_sock_init(void)
702 { 707 {
703 int err; 708 int err;
704 709
705 err = proto_register(&hci_sk_proto, 0); 710 err = proto_register(&hci_sk_proto, 0);
706 if (err < 0) 711 if (err < 0)
707 return err; 712 return err;
708 713
709 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); 714 err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
710 if (err < 0) 715 if (err < 0)
711 goto error; 716 goto error;
712 717
713 hci_register_notifier(&hci_sock_nblock); 718 hci_register_notifier(&hci_sock_nblock);
714 719
715 BT_INFO("HCI socket layer initialized"); 720 BT_INFO("HCI socket layer initialized");
716 721
717 return 0; 722 return 0;
718 723
719 error: 724 error:
720 BT_ERR("HCI socket registration failed"); 725 BT_ERR("HCI socket registration failed");
721 proto_unregister(&hci_sk_proto); 726 proto_unregister(&hci_sk_proto);
722 return err; 727 return err;
723 } 728 }
724 729
725 void __exit hci_sock_cleanup(void) 730 void __exit hci_sock_cleanup(void)
726 { 731 {
727 if (bt_sock_unregister(BTPROTO_HCI) < 0) 732 if (bt_sock_unregister(BTPROTO_HCI) < 0)
728 BT_ERR("HCI socket unregistration failed"); 733 BT_ERR("HCI socket unregistration failed");
729 734
730 hci_unregister_notifier(&hci_sock_nblock); 735 hci_unregister_notifier(&hci_sock_nblock);
731 736
732 proto_unregister(&hci_sk_proto); 737 proto_unregister(&hci_sk_proto);
733 } 738 }
734 739