2 BNEP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2001-2002 Inventel Systemes
5 Clément Moreau <clement.moreau@inventel.fr>
6 David Libault <david.libault@inventel.fr>
8 Copyright (C) 2002 Maxim Krasnyanskiy <maxk@qualcomm.com>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
18 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
25 SOFTWARE IS DISCLAIMED.
29 * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $
32 #define __KERNEL_SYSCALLS__
34 #include <linux/config.h>
35 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/signal.h>
40 #include <linux/init.h>
41 #include <linux/wait.h>
42 #include <linux/errno.h>
43 #include <linux/smp_lock.h>
44 #include <linux/net.h>
47 #include <linux/socket.h>
48 #include <linux/file.h>
50 #include <linux/netdevice.h>
51 #include <linux/etherdevice.h>
52 #include <linux/skbuff.h>
54 #include <asm/unaligned.h>
56 #include <net/bluetooth/bluetooth.h>
57 #include <net/bluetooth/l2cap.h>
61 #ifndef CONFIG_BT_BNEP_DEBUG
68 static LIST_HEAD(bnep_session_list);
69 static DECLARE_RWSEM(bnep_session_sem);
71 static struct bnep_session *__bnep_get_session(u8 *dst)
73 struct bnep_session *s;
78 list_for_each(p, &bnep_session_list) {
79 s = list_entry(p, struct bnep_session, list);
80 if (!memcmp(dst, s->eh.h_source, ETH_ALEN))
86 static void __bnep_link_session(struct bnep_session *s)
88 /* It's safe to call __module_get() here because sessions are added
89 by the socket layer which has to hold the refference to this module.
91 __module_get(THIS_MODULE);
92 list_add(&s->list, &bnep_session_list);
95 static void __bnep_unlink_session(struct bnep_session *s)
98 module_put(THIS_MODULE);
101 static int bnep_send(struct bnep_session *s, void *data, size_t len)
103 struct socket *sock = s->sock;
104 struct iovec iv = { data, len };
106 s->msg.msg_iov = &iv;
107 s->msg.msg_iovlen = 1;
108 return sock_sendmsg(sock, &s->msg, len);
111 static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
113 struct bnep_control_rsp rsp;
114 rsp.type = BNEP_CONTROL;
116 rsp.resp = htons(resp);
117 return bnep_send(s, &rsp, sizeof(rsp));
120 static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
127 n = ntohs(get_unaligned(data));
133 BT_DBG("filter len %d", n);
135 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
137 if (n <= BNEP_MAX_PROTO_FILTERS) {
138 struct bnep_proto_filter *f = s->proto_filter;
141 for (i = 0; i < n; i++) {
142 f[i].start = get_unaligned(data++);
143 f[i].end = get_unaligned(data++);
145 BT_DBG("proto filter start %d end %d",
146 f[i].start, f[i].end);
148 if (i < BNEP_MAX_PROTO_FILTERS)
149 memset(f + i, 0, sizeof(*f));
151 bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS);
153 bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED);
156 bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
161 static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
168 n = ntohs(get_unaligned((u16 *) data));
174 BT_DBG("filter len %d", n);
176 #ifdef CONFIG_BT_BNEP_MC_FILTER
182 /* Always send broadcast */
183 set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
185 /* Add address ranges to the multicast hash */
189 memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
190 a2 = data; data += ETH_ALEN;
192 BT_DBG("mc filter %s -> %s",
193 batostr((void *) a1), batostr((void *) a2));
195 #define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); }
197 /* Iterate from a1 to a2 */
198 set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
199 while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) {
201 set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
206 BT_DBG("mc filter hash 0x%llx", s->mc_filter);
208 bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_SUCCESS);
210 bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
215 static int bnep_rx_control(struct bnep_session *s, void *data, int len)
217 u8 cmd = *(u8 *)data;
223 case BNEP_CMD_NOT_UNDERSTOOD:
224 case BNEP_SETUP_CONN_REQ:
225 case BNEP_SETUP_CONN_RSP:
226 case BNEP_FILTER_NET_TYPE_RSP:
227 case BNEP_FILTER_MULTI_ADDR_RSP:
228 /* Ignore these for now */
231 case BNEP_FILTER_NET_TYPE_SET:
232 err = bnep_ctrl_set_netfilter(s, data, len);
235 case BNEP_FILTER_MULTI_ADDR_SET:
236 err = bnep_ctrl_set_mcfilter(s, data, len);
241 pkt[0] = BNEP_CONTROL;
242 pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
244 bnep_send(s, pkt, sizeof(pkt));
252 static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
254 struct bnep_ext_hdr *h;
258 h = (void *) skb->data;
259 if (!skb_pull(skb, sizeof(*h))) {
264 BT_DBG("type 0x%x len %d", h->type, h->len);
266 switch (h->type & BNEP_TYPE_MASK) {
267 case BNEP_EXT_CONTROL:
268 bnep_rx_control(s, skb->data, skb->len);
272 /* Unknown extension, skip it. */
276 if (!skb_pull(skb, h->len)) {
280 } while (!err && (h->type & BNEP_EXT_HEADER));
285 static u8 __bnep_rx_hlen[] = {
286 ETH_HLEN, /* BNEP_GENERAL */
287 0, /* BNEP_CONTROL */
288 2, /* BNEP_COMPRESSED */
289 ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */
290 ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */
292 #define BNEP_RX_TYPES (sizeof(__bnep_rx_hlen) - 1)
294 static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
296 struct net_device *dev = s->dev;
297 struct sk_buff *nskb;
300 dev->last_rx = jiffies;
301 s->stats.rx_bytes += skb->len;
303 type = *(u8 *) skb->data; skb_pull(skb, 1);
305 if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
308 if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
309 bnep_rx_control(s, skb->data, skb->len);
314 skb->mac.raw = skb->data;
316 /* Verify and pull out header */
317 if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
320 s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
322 if (type & BNEP_EXT_HEADER) {
323 if (bnep_rx_extension(s, skb) < 0)
327 /* Strip 802.1p header */
328 if (ntohs(s->eh.h_proto) == 0x8100) {
329 if (!skb_pull(skb, 4))
331 s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
334 /* We have to alloc new skb and copy data here :(. Because original skb
335 * may not be modified and because of the alignment requirements. */
336 nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
338 s->stats.rx_dropped++;
342 skb_reserve(nskb, 2);
344 /* Decompress header and construct ether frame */
345 switch (type & BNEP_TYPE_MASK) {
346 case BNEP_COMPRESSED:
347 memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
350 case BNEP_COMPRESSED_SRC_ONLY:
351 memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
352 memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
353 put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
356 case BNEP_COMPRESSED_DST_ONLY:
357 memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
358 memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, ETH_ALEN + 2);
362 memcpy(__skb_put(nskb, ETH_ALEN * 2), skb->mac.raw, ETH_ALEN * 2);
363 put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
367 memcpy(__skb_put(nskb, skb->len), skb->data, skb->len);
370 s->stats.rx_packets++;
372 nskb->ip_summed = CHECKSUM_UNNECESSARY;
373 nskb->protocol = eth_type_trans(nskb, dev);
378 s->stats.rx_errors++;
383 static u8 __bnep_tx_types[] = {
385 BNEP_COMPRESSED_SRC_ONLY,
386 BNEP_COMPRESSED_DST_ONLY,
390 static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
392 struct ethhdr *eh = (void *) skb->data;
393 struct socket *sock = s->sock;
398 BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type);
401 /* Control frame sent by us */
405 iv[il++] = (struct iovec) { &type, 1 };
408 if (!memcmp(eh->h_dest, s->eh.h_source, ETH_ALEN))
411 if (!memcmp(eh->h_source, s->eh.h_dest, ETH_ALEN))
415 skb_pull(skb, ETH_ALEN * 2);
417 type = __bnep_tx_types[type];
419 case BNEP_COMPRESSED_SRC_ONLY:
420 iv[il++] = (struct iovec) { eh->h_source, ETH_ALEN };
424 case BNEP_COMPRESSED_DST_ONLY:
425 iv[il++] = (struct iovec) { eh->h_dest, ETH_ALEN };
431 iv[il++] = (struct iovec) { skb->data, skb->len };
434 /* FIXME: linearize skb */
437 s->msg.msg_iovlen = il;
438 len = sock_sendmsg(sock, &s->msg, len);
443 s->stats.tx_bytes += len;
444 s->stats.tx_packets++;
451 static int bnep_session(void *arg)
453 struct bnep_session *s = arg;
454 struct net_device *dev = s->dev;
455 struct sock *sk = s->sock->sk;
461 daemonize("kbnepd %s", dev->name);
462 set_user_nice(current, -15);
463 current->flags |= PF_IOTHREAD;
467 init_waitqueue_entry(&wait, current);
468 add_wait_queue(sk->sk_sleep, &wait);
469 while (!atomic_read(&s->killed)) {
470 set_current_state(TASK_INTERRUPTIBLE);
473 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
475 bnep_rx_frame(s, skb);
478 if (sk->sk_state != BT_CONNECTED)
482 while ((skb = skb_dequeue(&sk->sk_write_queue)))
483 if (bnep_tx_frame(s, skb))
485 netif_wake_queue(dev);
489 set_current_state(TASK_RUNNING);
490 remove_wait_queue(sk->sk_sleep, &wait);
492 /* Cleanup session */
493 down_write(&bnep_session_sem);
495 /* Delete network device */
496 unregister_netdev(dev);
498 /* Release the socket */
501 __bnep_unlink_session(s);
503 up_write(&bnep_session_sem);
508 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
510 struct net_device *dev;
511 struct bnep_session *s, *ss;
512 u8 dst[ETH_ALEN], src[ETH_ALEN];
517 baswap((void *) dst, &bt_sk(sock->sk)->dst);
518 baswap((void *) src, &bt_sk(sock->sk)->src);
520 /* session struct allocated as private part of net_device */
521 dev = alloc_netdev(sizeof(struct bnep_session),
522 (*req->device) ? req->device : "bnep%d",
528 down_write(&bnep_session_sem);
530 ss = __bnep_get_session(dst);
531 if (ss && ss->state == BT_CONNECTED) {
538 /* This is rx header therefore addresses are swapped.
539 * ie eh.h_dest is our local address. */
540 memcpy(s->eh.h_dest, &src, ETH_ALEN);
541 memcpy(s->eh.h_source, &dst, ETH_ALEN);
542 memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
547 s->state = BT_CONNECTED;
549 s->msg.msg_flags = MSG_NOSIGNAL;
551 #ifdef CONFIG_BT_BNEP_MC_FILTER
552 /* Set default mc filter */
553 set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
556 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
557 /* Set default protocol filter */
560 s->proto_filter[0].start = htons(0x0800);
561 s->proto_filter[0].end = htons(0x0806);
562 /* (RARP, AppleTalk) */
563 s->proto_filter[1].start = htons(0x8035);
564 s->proto_filter[1].end = htons(0x80F3);
566 s->proto_filter[2].start = htons(0x8137);
567 s->proto_filter[2].end = htons(0x86DD);
570 err = register_netdev(dev);
575 __bnep_link_session(s);
577 err = kernel_thread(bnep_session, s, CLONE_KERNEL);
579 /* Session thread start failed, gotta cleanup. */
580 unregister_netdev(dev);
581 __bnep_unlink_session(s);
585 up_write(&bnep_session_sem);
586 strcpy(req->device, dev->name);
590 up_write(&bnep_session_sem);
595 int bnep_del_connection(struct bnep_conndel_req *req)
597 struct bnep_session *s;
602 down_read(&bnep_session_sem);
604 s = __bnep_get_session(req->dst);
606 /* Wakeup user-space which is polling for socket errors.
607 * This is temporary hack untill we have shutdown in L2CAP */
608 s->sock->sk->sk_err = EUNATCH;
610 /* Kill session thread */
611 atomic_inc(&s->killed);
612 wake_up_interruptible(s->sock->sk->sk_sleep);
616 up_read(&bnep_session_sem);
620 static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
622 memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
623 strcpy(ci->device, s->dev->name);
624 ci->flags = s->flags;
625 ci->state = s->state;
629 int bnep_get_connlist(struct bnep_connlist_req *req)
634 down_read(&bnep_session_sem);
636 list_for_each(p, &bnep_session_list) {
637 struct bnep_session *s;
638 struct bnep_conninfo ci;
640 s = list_entry(p, struct bnep_session, list);
642 __bnep_copy_ci(&ci, s);
644 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
649 if (++n >= req->cnum)
656 up_read(&bnep_session_sem);
660 int bnep_get_conninfo(struct bnep_conninfo *ci)
662 struct bnep_session *s;
665 down_read(&bnep_session_sem);
667 s = __bnep_get_session(ci->dst);
669 __bnep_copy_ci(ci, s);
673 up_read(&bnep_session_sem);
677 static int __init bnep_init_module(void)
683 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
684 strcat(flt, "protocol ");
687 #ifdef CONFIG_BT_BNEP_MC_FILTER
688 strcat(flt, "multicast");
691 BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
693 BT_INFO("BNEP filters: %s", flt);
699 static void __exit bnep_cleanup_module(void)
704 module_init(bnep_init_module);
705 module_exit(bnep_cleanup_module);
707 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
708 MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyanskiy <maxk@qualcomm.com>");
709 MODULE_LICENSE("GPL");
710 MODULE_ALIAS("bt-proto-4");