~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to net/bluetooth/bnep/core.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   BNEP implementation for Linux Bluetooth stack (BlueZ).
 
3
   Copyright (C) 2001-2002 Inventel Systemes
 
4
   Written 2001-2002 by
 
5
        ClĆ©ment Moreau <clement.moreau@inventel.fr>
 
6
        David Libault  <david.libault@inventel.fr>
 
7
 
 
8
   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
 
9
 
 
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;
 
13
 
 
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.
 
22
 
 
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.
 
26
*/
 
27
 
 
28
#include <linux/module.h>
 
29
 
 
30
#include <linux/kernel.h>
 
31
#include <linux/sched.h>
 
32
#include <linux/signal.h>
 
33
#include <linux/init.h>
 
34
#include <linux/wait.h>
 
35
#include <linux/freezer.h>
 
36
#include <linux/errno.h>
 
37
#include <linux/net.h>
 
38
#include <linux/slab.h>
 
39
#include <linux/kthread.h>
 
40
#include <net/sock.h>
 
41
 
 
42
#include <linux/socket.h>
 
43
#include <linux/file.h>
 
44
 
 
45
#include <linux/netdevice.h>
 
46
#include <linux/etherdevice.h>
 
47
#include <linux/skbuff.h>
 
48
 
 
49
#include <asm/unaligned.h>
 
50
 
 
51
#include <net/bluetooth/bluetooth.h>
 
52
#include <net/bluetooth/hci_core.h>
 
53
#include <net/bluetooth/l2cap.h>
 
54
 
 
55
#include "bnep.h"
 
56
 
 
57
#define VERSION "1.3"
 
58
 
 
59
static int compress_src = 1;
 
60
static int compress_dst = 1;
 
61
 
 
62
static LIST_HEAD(bnep_session_list);
 
63
static DECLARE_RWSEM(bnep_session_sem);
 
64
 
 
65
static struct bnep_session *__bnep_get_session(u8 *dst)
 
66
{
 
67
        struct bnep_session *s;
 
68
        struct list_head *p;
 
69
 
 
70
        BT_DBG("");
 
71
 
 
72
        list_for_each(p, &bnep_session_list) {
 
73
                s = list_entry(p, struct bnep_session, list);
 
74
                if (!compare_ether_addr(dst, s->eh.h_source))
 
75
                        return s;
 
76
        }
 
77
        return NULL;
 
78
}
 
79
 
 
80
static void __bnep_link_session(struct bnep_session *s)
 
81
{
 
82
        list_add(&s->list, &bnep_session_list);
 
83
}
 
84
 
 
85
static void __bnep_unlink_session(struct bnep_session *s)
 
86
{
 
87
        list_del(&s->list);
 
88
}
 
89
 
 
90
static int bnep_send(struct bnep_session *s, void *data, size_t len)
 
91
{
 
92
        struct socket *sock = s->sock;
 
93
        struct kvec iv = { data, len };
 
94
 
 
95
        return kernel_sendmsg(sock, &s->msg, &iv, 1, len);
 
96
}
 
97
 
 
98
static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
 
99
{
 
100
        struct bnep_control_rsp rsp;
 
101
        rsp.type = BNEP_CONTROL;
 
102
        rsp.ctrl = ctrl;
 
103
        rsp.resp = htons(resp);
 
104
        return bnep_send(s, &rsp, sizeof(rsp));
 
105
}
 
106
 
 
107
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
 
108
static inline void bnep_set_default_proto_filter(struct bnep_session *s)
 
109
{
 
110
        /* (IPv4, ARP)  */
 
111
        s->proto_filter[0].start = ETH_P_IP;
 
112
        s->proto_filter[0].end   = ETH_P_ARP;
 
113
        /* (RARP, AppleTalk) */
 
114
        s->proto_filter[1].start = ETH_P_RARP;
 
115
        s->proto_filter[1].end   = ETH_P_AARP;
 
116
        /* (IPX, IPv6) */
 
117
        s->proto_filter[2].start = ETH_P_IPX;
 
118
        s->proto_filter[2].end   = ETH_P_IPV6;
 
119
}
 
120
#endif
 
121
 
 
122
static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len)
 
123
{
 
124
        int n;
 
125
 
 
126
        if (len < 2)
 
127
                return -EILSEQ;
 
128
 
 
129
        n = get_unaligned_be16(data);
 
130
        data++;
 
131
        len -= 2;
 
132
 
 
133
        if (len < n)
 
134
                return -EILSEQ;
 
135
 
 
136
        BT_DBG("filter len %d", n);
 
137
 
 
138
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
 
139
        n /= 4;
 
140
        if (n <= BNEP_MAX_PROTO_FILTERS) {
 
141
                struct bnep_proto_filter *f = s->proto_filter;
 
142
                int i;
 
143
 
 
144
                for (i = 0; i < n; i++) {
 
145
                        f[i].start = get_unaligned_be16(data++);
 
146
                        f[i].end   = get_unaligned_be16(data++);
 
147
 
 
148
                        BT_DBG("proto filter start %d end %d",
 
149
                                f[i].start, f[i].end);
 
150
                }
 
151
 
 
152
                if (i < BNEP_MAX_PROTO_FILTERS)
 
153
                        memset(f + i, 0, sizeof(*f));
 
154
 
 
155
                if (n == 0)
 
156
                        bnep_set_default_proto_filter(s);
 
157
 
 
158
                bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS);
 
159
        } else {
 
160
                bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED);
 
161
        }
 
162
#else
 
163
        bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
 
164
#endif
 
165
        return 0;
 
166
}
 
167
 
 
168
static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
 
169
{
 
170
        int n;
 
171
 
 
172
        if (len < 2)
 
173
                return -EILSEQ;
 
174
 
 
175
        n = get_unaligned_be16(data);
 
176
        data += 2;
 
177
        len -= 2;
 
178
 
 
179
        if (len < n)
 
180
                return -EILSEQ;
 
181
 
 
182
        BT_DBG("filter len %d", n);
 
183
 
 
184
#ifdef CONFIG_BT_BNEP_MC_FILTER
 
185
        n /= (ETH_ALEN * 2);
 
186
 
 
187
        if (n > 0) {
 
188
                int i;
 
189
 
 
190
                s->mc_filter = 0;
 
191
 
 
192
                /* Always send broadcast */
 
193
                set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
 
194
 
 
195
                /* Add address ranges to the multicast hash */
 
196
                for (; n > 0; n--) {
 
197
                        u8 a1[6], *a2;
 
198
 
 
199
                        memcpy(a1, data, ETH_ALEN);
 
200
                        data += ETH_ALEN;
 
201
                        a2 = data;
 
202
                        data += ETH_ALEN;
 
203
 
 
204
                        BT_DBG("mc filter %s -> %s",
 
205
                                batostr((void *) a1), batostr((void *) a2));
 
206
 
 
207
                        /* Iterate from a1 to a2 */
 
208
                        set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
 
209
                        while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) {
 
210
                                /* Increment a1 */
 
211
                                i = 5;
 
212
                                while (i >= 0 && ++a1[i--] == 0)
 
213
                                        ;
 
214
 
 
215
                                set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
 
216
                        }
 
217
                }
 
218
        }
 
219
 
 
220
        BT_DBG("mc filter hash 0x%llx", s->mc_filter);
 
221
 
 
222
        bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_SUCCESS);
 
223
#else
 
224
        bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
 
225
#endif
 
226
        return 0;
 
227
}
 
228
 
 
229
static int bnep_rx_control(struct bnep_session *s, void *data, int len)
 
230
{
 
231
        u8  cmd = *(u8 *)data;
 
232
        int err = 0;
 
233
 
 
234
        data++;
 
235
        len--;
 
236
 
 
237
        switch (cmd) {
 
238
        case BNEP_CMD_NOT_UNDERSTOOD:
 
239
        case BNEP_SETUP_CONN_RSP:
 
240
        case BNEP_FILTER_NET_TYPE_RSP:
 
241
        case BNEP_FILTER_MULTI_ADDR_RSP:
 
242
                /* Ignore these for now */
 
243
                break;
 
244
 
 
245
        case BNEP_FILTER_NET_TYPE_SET:
 
246
                err = bnep_ctrl_set_netfilter(s, data, len);
 
247
                break;
 
248
 
 
249
        case BNEP_FILTER_MULTI_ADDR_SET:
 
250
                err = bnep_ctrl_set_mcfilter(s, data, len);
 
251
                break;
 
252
 
 
253
        case BNEP_SETUP_CONN_REQ:
 
254
                err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP, BNEP_CONN_NOT_ALLOWED);
 
255
                break;
 
256
 
 
257
        default: {
 
258
                        u8 pkt[3];
 
259
                        pkt[0] = BNEP_CONTROL;
 
260
                        pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
 
261
                        pkt[2] = cmd;
 
262
                        bnep_send(s, pkt, sizeof(pkt));
 
263
                }
 
264
                break;
 
265
        }
 
266
 
 
267
        return err;
 
268
}
 
269
 
 
270
static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
 
271
{
 
272
        struct bnep_ext_hdr *h;
 
273
        int err = 0;
 
274
 
 
275
        do {
 
276
                h = (void *) skb->data;
 
277
                if (!skb_pull(skb, sizeof(*h))) {
 
278
                        err = -EILSEQ;
 
279
                        break;
 
280
                }
 
281
 
 
282
                BT_DBG("type 0x%x len %d", h->type, h->len);
 
283
 
 
284
                switch (h->type & BNEP_TYPE_MASK) {
 
285
                case BNEP_EXT_CONTROL:
 
286
                        bnep_rx_control(s, skb->data, skb->len);
 
287
                        break;
 
288
 
 
289
                default:
 
290
                        /* Unknown extension, skip it. */
 
291
                        break;
 
292
                }
 
293
 
 
294
                if (!skb_pull(skb, h->len)) {
 
295
                        err = -EILSEQ;
 
296
                        break;
 
297
                }
 
298
        } while (!err && (h->type & BNEP_EXT_HEADER));
 
299
 
 
300
        return err;
 
301
}
 
302
 
 
303
static u8 __bnep_rx_hlen[] = {
 
304
        ETH_HLEN,     /* BNEP_GENERAL */
 
305
        0,            /* BNEP_CONTROL */
 
306
        2,            /* BNEP_COMPRESSED */
 
307
        ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */
 
308
        ETH_ALEN + 2  /* BNEP_COMPRESSED_DST_ONLY */
 
309
};
 
310
 
 
311
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
 
312
{
 
313
        struct net_device *dev = s->dev;
 
314
        struct sk_buff *nskb;
 
315
        u8 type;
 
316
 
 
317
        dev->stats.rx_bytes += skb->len;
 
318
 
 
319
        type = *(u8 *) skb->data;
 
320
        skb_pull(skb, 1);
 
321
 
 
322
        if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
 
323
                goto badframe;
 
324
 
 
325
        if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
 
326
                bnep_rx_control(s, skb->data, skb->len);
 
327
                kfree_skb(skb);
 
328
                return 0;
 
329
        }
 
330
 
 
331
        skb_reset_mac_header(skb);
 
332
 
 
333
        /* Verify and pull out header */
 
334
        if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
 
335
                goto badframe;
 
336
 
 
337
        s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
 
338
 
 
339
        if (type & BNEP_EXT_HEADER) {
 
340
                if (bnep_rx_extension(s, skb) < 0)
 
341
                        goto badframe;
 
342
        }
 
343
 
 
344
        /* Strip 802.1p header */
 
345
        if (ntohs(s->eh.h_proto) == 0x8100) {
 
346
                if (!skb_pull(skb, 4))
 
347
                        goto badframe;
 
348
                s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
 
349
        }
 
350
 
 
351
        /* We have to alloc new skb and copy data here :(. Because original skb
 
352
         * may not be modified and because of the alignment requirements. */
 
353
        nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
 
354
        if (!nskb) {
 
355
                dev->stats.rx_dropped++;
 
356
                kfree_skb(skb);
 
357
                return -ENOMEM;
 
358
        }
 
359
        skb_reserve(nskb, 2);
 
360
 
 
361
        /* Decompress header and construct ether frame */
 
362
        switch (type & BNEP_TYPE_MASK) {
 
363
        case BNEP_COMPRESSED:
 
364
                memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
 
365
                break;
 
366
 
 
367
        case BNEP_COMPRESSED_SRC_ONLY:
 
368
                memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
 
369
                memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), ETH_ALEN);
 
370
                put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
 
371
                break;
 
372
 
 
373
        case BNEP_COMPRESSED_DST_ONLY:
 
374
                memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb),
 
375
                                                                ETH_ALEN);
 
376
                memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source,
 
377
                                                                ETH_ALEN + 2);
 
378
                break;
 
379
 
 
380
        case BNEP_GENERAL:
 
381
                memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb),
 
382
                                                                ETH_ALEN * 2);
 
383
                put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
 
384
                break;
 
385
        }
 
386
 
 
387
        skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len);
 
388
        kfree_skb(skb);
 
389
 
 
390
        dev->stats.rx_packets++;
 
391
        nskb->ip_summed = CHECKSUM_NONE;
 
392
        nskb->protocol  = eth_type_trans(nskb, dev);
 
393
        netif_rx_ni(nskb);
 
394
        return 0;
 
395
 
 
396
badframe:
 
397
        dev->stats.rx_errors++;
 
398
        kfree_skb(skb);
 
399
        return 0;
 
400
}
 
401
 
 
402
static u8 __bnep_tx_types[] = {
 
403
        BNEP_GENERAL,
 
404
        BNEP_COMPRESSED_SRC_ONLY,
 
405
        BNEP_COMPRESSED_DST_ONLY,
 
406
        BNEP_COMPRESSED
 
407
};
 
408
 
 
409
static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
 
410
{
 
411
        struct ethhdr *eh = (void *) skb->data;
 
412
        struct socket *sock = s->sock;
 
413
        struct kvec iv[3];
 
414
        int len = 0, il = 0;
 
415
        u8 type = 0;
 
416
 
 
417
        BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type);
 
418
 
 
419
        if (!skb->dev) {
 
420
                /* Control frame sent by us */
 
421
                goto send;
 
422
        }
 
423
 
 
424
        iv[il++] = (struct kvec) { &type, 1 };
 
425
        len++;
 
426
 
 
427
        if (compress_src && !compare_ether_addr(eh->h_dest, s->eh.h_source))
 
428
                type |= 0x01;
 
429
 
 
430
        if (compress_dst && !compare_ether_addr(eh->h_source, s->eh.h_dest))
 
431
                type |= 0x02;
 
432
 
 
433
        if (type)
 
434
                skb_pull(skb, ETH_ALEN * 2);
 
435
 
 
436
        type = __bnep_tx_types[type];
 
437
        switch (type) {
 
438
        case BNEP_COMPRESSED_SRC_ONLY:
 
439
                iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
 
440
                len += ETH_ALEN;
 
441
                break;
 
442
 
 
443
        case BNEP_COMPRESSED_DST_ONLY:
 
444
                iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
 
445
                len += ETH_ALEN;
 
446
                break;
 
447
        }
 
448
 
 
449
send:
 
450
        iv[il++] = (struct kvec) { skb->data, skb->len };
 
451
        len += skb->len;
 
452
 
 
453
        /* FIXME: linearize skb */
 
454
        {
 
455
                len = kernel_sendmsg(sock, &s->msg, iv, il, len);
 
456
        }
 
457
        kfree_skb(skb);
 
458
 
 
459
        if (len > 0) {
 
460
                s->dev->stats.tx_bytes += len;
 
461
                s->dev->stats.tx_packets++;
 
462
                return 0;
 
463
        }
 
464
 
 
465
        return len;
 
466
}
 
467
 
 
468
static int bnep_session(void *arg)
 
469
{
 
470
        struct bnep_session *s = arg;
 
471
        struct net_device *dev = s->dev;
 
472
        struct sock *sk = s->sock->sk;
 
473
        struct sk_buff *skb;
 
474
        wait_queue_t wait;
 
475
 
 
476
        BT_DBG("");
 
477
 
 
478
        set_user_nice(current, -15);
 
479
 
 
480
        init_waitqueue_entry(&wait, current);
 
481
        add_wait_queue(sk_sleep(sk), &wait);
 
482
        while (1) {
 
483
                set_current_state(TASK_INTERRUPTIBLE);
 
484
 
 
485
                if (atomic_read(&s->terminate))
 
486
                        break;
 
487
                /* RX */
 
488
                while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
 
489
                        skb_orphan(skb);
 
490
                        if (!skb_linearize(skb))
 
491
                                bnep_rx_frame(s, skb);
 
492
                        else
 
493
                                kfree_skb(skb);
 
494
                }
 
495
 
 
496
                if (sk->sk_state != BT_CONNECTED)
 
497
                        break;
 
498
 
 
499
                /* TX */
 
500
                while ((skb = skb_dequeue(&sk->sk_write_queue)))
 
501
                        if (bnep_tx_frame(s, skb))
 
502
                                break;
 
503
                netif_wake_queue(dev);
 
504
 
 
505
                schedule();
 
506
        }
 
507
        __set_current_state(TASK_RUNNING);
 
508
        remove_wait_queue(sk_sleep(sk), &wait);
 
509
 
 
510
        /* Cleanup session */
 
511
        down_write(&bnep_session_sem);
 
512
 
 
513
        /* Delete network device */
 
514
        unregister_netdev(dev);
 
515
 
 
516
        /* Wakeup user-space polling for socket errors */
 
517
        s->sock->sk->sk_err = EUNATCH;
 
518
 
 
519
        wake_up_interruptible(sk_sleep(s->sock->sk));
 
520
 
 
521
        /* Release the socket */
 
522
        fput(s->sock->file);
 
523
 
 
524
        __bnep_unlink_session(s);
 
525
 
 
526
        up_write(&bnep_session_sem);
 
527
        free_netdev(dev);
 
528
        module_put_and_exit(0);
 
529
        return 0;
 
530
}
 
531
 
 
532
static struct device *bnep_get_device(struct bnep_session *session)
 
533
{
 
534
        bdaddr_t *src = &bt_sk(session->sock->sk)->src;
 
535
        bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
 
536
        struct hci_dev *hdev;
 
537
        struct hci_conn *conn;
 
538
 
 
539
        hdev = hci_get_route(dst, src);
 
540
        if (!hdev)
 
541
                return NULL;
 
542
 
 
543
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
 
544
 
 
545
        hci_dev_put(hdev);
 
546
 
 
547
        return conn ? &conn->dev : NULL;
 
548
}
 
549
 
 
550
static struct device_type bnep_type = {
 
551
        .name   = "bluetooth",
 
552
};
 
553
 
 
554
int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 
555
{
 
556
        struct net_device *dev;
 
557
        struct bnep_session *s, *ss;
 
558
        u8 dst[ETH_ALEN], src[ETH_ALEN];
 
559
        int err;
 
560
 
 
561
        BT_DBG("");
 
562
 
 
563
        baswap((void *) dst, &bt_sk(sock->sk)->dst);
 
564
        baswap((void *) src, &bt_sk(sock->sk)->src);
 
565
 
 
566
        /* session struct allocated as private part of net_device */
 
567
        dev = alloc_netdev(sizeof(struct bnep_session),
 
568
                                (*req->device) ? req->device : "bnep%d",
 
569
                                bnep_net_setup);
 
570
        if (!dev)
 
571
                return -ENOMEM;
 
572
 
 
573
        down_write(&bnep_session_sem);
 
574
 
 
575
        ss = __bnep_get_session(dst);
 
576
        if (ss && ss->state == BT_CONNECTED) {
 
577
                err = -EEXIST;
 
578
                goto failed;
 
579
        }
 
580
 
 
581
        s = netdev_priv(dev);
 
582
 
 
583
        /* This is rx header therefore addresses are swapped.
 
584
         * ie. eh.h_dest is our local address. */
 
585
        memcpy(s->eh.h_dest,   &src, ETH_ALEN);
 
586
        memcpy(s->eh.h_source, &dst, ETH_ALEN);
 
587
        memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
588
 
 
589
        s->dev   = dev;
 
590
        s->sock  = sock;
 
591
        s->role  = req->role;
 
592
        s->state = BT_CONNECTED;
 
593
 
 
594
        s->msg.msg_flags = MSG_NOSIGNAL;
 
595
 
 
596
#ifdef CONFIG_BT_BNEP_MC_FILTER
 
597
        /* Set default mc filter */
 
598
        set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
 
599
#endif
 
600
 
 
601
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
 
602
        /* Set default protocol filter */
 
603
        bnep_set_default_proto_filter(s);
 
604
#endif
 
605
 
 
606
        SET_NETDEV_DEV(dev, bnep_get_device(s));
 
607
        SET_NETDEV_DEVTYPE(dev, &bnep_type);
 
608
 
 
609
        err = register_netdev(dev);
 
610
        if (err)
 
611
                goto failed;
 
612
 
 
613
        __bnep_link_session(s);
 
614
 
 
615
        __module_get(THIS_MODULE);
 
616
        s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
 
617
        if (IS_ERR(s->task)) {
 
618
                /* Session thread start failed, gotta cleanup. */
 
619
                module_put(THIS_MODULE);
 
620
                unregister_netdev(dev);
 
621
                __bnep_unlink_session(s);
 
622
                err = PTR_ERR(s->task);
 
623
                goto failed;
 
624
        }
 
625
 
 
626
        up_write(&bnep_session_sem);
 
627
        strcpy(req->device, dev->name);
 
628
        return 0;
 
629
 
 
630
failed:
 
631
        up_write(&bnep_session_sem);
 
632
        free_netdev(dev);
 
633
        return err;
 
634
}
 
635
 
 
636
int bnep_del_connection(struct bnep_conndel_req *req)
 
637
{
 
638
        struct bnep_session *s;
 
639
        int  err = 0;
 
640
 
 
641
        BT_DBG("");
 
642
 
 
643
        down_read(&bnep_session_sem);
 
644
 
 
645
        s = __bnep_get_session(req->dst);
 
646
        if (s) {
 
647
                atomic_inc(&s->terminate);
 
648
                wake_up_process(s->task);
 
649
        } else
 
650
                err = -ENOENT;
 
651
 
 
652
        up_read(&bnep_session_sem);
 
653
        return err;
 
654
}
 
655
 
 
656
static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
 
657
{
 
658
        memset(ci, 0, sizeof(*ci));
 
659
        memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
 
660
        strcpy(ci->device, s->dev->name);
 
661
        ci->flags = s->flags;
 
662
        ci->state = s->state;
 
663
        ci->role  = s->role;
 
664
}
 
665
 
 
666
int bnep_get_connlist(struct bnep_connlist_req *req)
 
667
{
 
668
        struct list_head *p;
 
669
        int err = 0, n = 0;
 
670
 
 
671
        down_read(&bnep_session_sem);
 
672
 
 
673
        list_for_each(p, &bnep_session_list) {
 
674
                struct bnep_session *s;
 
675
                struct bnep_conninfo ci;
 
676
 
 
677
                s = list_entry(p, struct bnep_session, list);
 
678
 
 
679
                __bnep_copy_ci(&ci, s);
 
680
 
 
681
                if (copy_to_user(req->ci, &ci, sizeof(ci))) {
 
682
                        err = -EFAULT;
 
683
                        break;
 
684
                }
 
685
 
 
686
                if (++n >= req->cnum)
 
687
                        break;
 
688
 
 
689
                req->ci++;
 
690
        }
 
691
        req->cnum = n;
 
692
 
 
693
        up_read(&bnep_session_sem);
 
694
        return err;
 
695
}
 
696
 
 
697
int bnep_get_conninfo(struct bnep_conninfo *ci)
 
698
{
 
699
        struct bnep_session *s;
 
700
        int err = 0;
 
701
 
 
702
        down_read(&bnep_session_sem);
 
703
 
 
704
        s = __bnep_get_session(ci->dst);
 
705
        if (s)
 
706
                __bnep_copy_ci(ci, s);
 
707
        else
 
708
                err = -ENOENT;
 
709
 
 
710
        up_read(&bnep_session_sem);
 
711
        return err;
 
712
}
 
713
 
 
714
static int __init bnep_init(void)
 
715
{
 
716
        char flt[50] = "";
 
717
 
 
718
#ifdef CONFIG_BT_BNEP_PROTO_FILTER
 
719
        strcat(flt, "protocol ");
 
720
#endif
 
721
 
 
722
#ifdef CONFIG_BT_BNEP_MC_FILTER
 
723
        strcat(flt, "multicast");
 
724
#endif
 
725
 
 
726
        BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
 
727
        if (flt[0])
 
728
                BT_INFO("BNEP filters: %s", flt);
 
729
 
 
730
        bnep_sock_init();
 
731
        return 0;
 
732
}
 
733
 
 
734
static void __exit bnep_exit(void)
 
735
{
 
736
        bnep_sock_cleanup();
 
737
}
 
738
 
 
739
module_init(bnep_init);
 
740
module_exit(bnep_exit);
 
741
 
 
742
module_param(compress_src, bool, 0644);
 
743
MODULE_PARM_DESC(compress_src, "Compress sources headers");
 
744
 
 
745
module_param(compress_dst, bool, 0644);
 
746
MODULE_PARM_DESC(compress_dst, "Compress destination headers");
 
747
 
 
748
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 
749
MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
 
750
MODULE_VERSION(VERSION);
 
751
MODULE_LICENSE("GPL");
 
752
MODULE_ALIAS("bt-proto-4");