aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorHiren Tandel <hirent@marvell.com>2014-05-05 06:43:31 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-05-19 18:06:04 -0400
commit57be1f3f3ec1ccab6432615ca161c4c9ece2a2aa (patch)
treebb0021acf67dcb66957f0482cb89f894d8fa77f0 /net/nfc
parentc79d9f9ef86683824c195b093106222ff0611c10 (diff)
NFC: Add RAW socket type support for SOCKPROTO_RAW
This allows for a more generic NFC sniffing by using SOCKPROTO_RAW SOCK_RAW to read RAW NFC frames. This is for sniffing anything but LLCP (HCI, NCI, etc...). Signed-off-by: Hiren Tandel <hirent@marvell.com> Signed-off-by: Rahul Tank <rahult@marvell.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/llcp_commands.c2
-rw-r--r--net/nfc/llcp_core.c11
-rw-r--r--net/nfc/nfc.h6
-rw-r--r--net/nfc/rawsock.c94
4 files changed, 102 insertions, 11 deletions
diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index bec6ed15f503..a3ad69a4c648 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -387,7 +387,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
387 387
388 __net_timestamp(skb); 388 __net_timestamp(skb);
389 389
390 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX); 390 nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX);
391 391
392 return nfc_data_exchange(dev, local->target_idx, skb, 392 return nfc_data_exchange(dev, local->target_idx, skb,
393 nfc_llcp_recv, local); 393 nfc_llcp_recv, local);
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index b4671958fcf9..f6278da68763 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -680,16 +680,17 @@ void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
680 continue; 680 continue;
681 681
682 if (skb_copy == NULL) { 682 if (skb_copy == NULL) {
683 skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE, 683 skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE,
684 GFP_ATOMIC); 684 GFP_ATOMIC);
685 685
686 if (skb_copy == NULL) 686 if (skb_copy == NULL)
687 continue; 687 continue;
688 688
689 data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE); 689 data = skb_push(skb_copy, NFC_RAW_HEADER_SIZE);
690 690
691 data[0] = local->dev ? local->dev->idx : 0xFF; 691 data[0] = local->dev ? local->dev->idx : 0xFF;
692 data[1] = direction; 692 data[1] = direction & 0x01;
693 data[1] |= (RAW_PAYLOAD_LLCP << 1);
693 } 694 }
694 695
695 nskb = skb_clone(skb_copy, GFP_ATOMIC); 696 nskb = skb_clone(skb_copy, GFP_ATOMIC);
@@ -747,7 +748,7 @@ static void nfc_llcp_tx_work(struct work_struct *work)
747 __net_timestamp(skb); 748 __net_timestamp(skb);
748 749
749 nfc_llcp_send_to_raw_sock(local, skb, 750 nfc_llcp_send_to_raw_sock(local, skb,
750 NFC_LLCP_DIRECTION_TX); 751 NFC_DIRECTION_TX);
751 752
752 ret = nfc_data_exchange(local->dev, local->target_idx, 753 ret = nfc_data_exchange(local->dev, local->target_idx,
753 skb, nfc_llcp_recv, local); 754 skb, nfc_llcp_recv, local);
@@ -1476,7 +1477,7 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1476 1477
1477 __net_timestamp(skb); 1478 __net_timestamp(skb);
1478 1479
1479 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX); 1480 nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_RX);
1480 1481
1481 nfc_llcp_rx_skb(local, skb); 1482 nfc_llcp_rx_skb(local, skb);
1482 1483
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 9d6e74f7e6b3..88d60064890e 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -40,6 +40,12 @@ struct nfc_rawsock {
40 struct work_struct tx_work; 40 struct work_struct tx_work;
41 bool tx_work_scheduled; 41 bool tx_work_scheduled;
42}; 42};
43
44struct nfc_sock_list {
45 struct hlist_head head;
46 rwlock_t lock;
47};
48
43#define nfc_rawsock(sk) ((struct nfc_rawsock *) sk) 49#define nfc_rawsock(sk) ((struct nfc_rawsock *) sk)
44#define to_rawsock_sk(_tx_work) \ 50#define to_rawsock_sk(_tx_work) \
45 ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work)) 51 ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index c27a6e86cae4..8627c75063e2 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -27,6 +27,24 @@
27 27
28#include "nfc.h" 28#include "nfc.h"
29 29
30static struct nfc_sock_list raw_sk_list = {
31 .lock = __RW_LOCK_UNLOCKED(raw_sk_list.lock)
32};
33
34void nfc_sock_link(struct nfc_sock_list *l, struct sock *sk)
35{
36 write_lock(&l->lock);
37 sk_add_node(sk, &l->head);
38 write_unlock(&l->lock);
39}
40
41void nfc_sock_unlink(struct nfc_sock_list *l, struct sock *sk)
42{
43 write_lock(&l->lock);
44 sk_del_node_init(sk);
45 write_unlock(&l->lock);
46}
47
30static void rawsock_write_queue_purge(struct sock *sk) 48static void rawsock_write_queue_purge(struct sock *sk)
31{ 49{
32 pr_debug("sk=%p\n", sk); 50 pr_debug("sk=%p\n", sk);
@@ -57,6 +75,9 @@ static int rawsock_release(struct socket *sock)
57 if (!sk) 75 if (!sk)
58 return 0; 76 return 0;
59 77
78 if (sock->type == SOCK_RAW)
79 nfc_sock_unlink(&raw_sk_list, sk);
80
60 sock_orphan(sk); 81 sock_orphan(sk);
61 sock_put(sk); 82 sock_put(sk);
62 83
@@ -275,6 +296,26 @@ static const struct proto_ops rawsock_ops = {
275 .mmap = sock_no_mmap, 296 .mmap = sock_no_mmap,
276}; 297};
277 298
299static const struct proto_ops rawsock_raw_ops = {
300 .family = PF_NFC,
301 .owner = THIS_MODULE,
302 .release = rawsock_release,
303 .bind = sock_no_bind,
304 .connect = sock_no_connect,
305 .socketpair = sock_no_socketpair,
306 .accept = sock_no_accept,
307 .getname = sock_no_getname,
308 .poll = datagram_poll,
309 .ioctl = sock_no_ioctl,
310 .listen = sock_no_listen,
311 .shutdown = sock_no_shutdown,
312 .setsockopt = sock_no_setsockopt,
313 .getsockopt = sock_no_getsockopt,
314 .sendmsg = sock_no_sendmsg,
315 .recvmsg = rawsock_recvmsg,
316 .mmap = sock_no_mmap,
317};
318
278static void rawsock_destruct(struct sock *sk) 319static void rawsock_destruct(struct sock *sk)
279{ 320{
280 pr_debug("sk=%p\n", sk); 321 pr_debug("sk=%p\n", sk);
@@ -300,10 +341,13 @@ static int rawsock_create(struct net *net, struct socket *sock,
300 341
301 pr_debug("sock=%p\n", sock); 342 pr_debug("sock=%p\n", sock);
302 343
303 if (sock->type != SOCK_SEQPACKET) 344 if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW))
304 return -ESOCKTNOSUPPORT; 345 return -ESOCKTNOSUPPORT;
305 346
306 sock->ops = &rawsock_ops; 347 if (sock->type == SOCK_RAW)
348 sock->ops = &rawsock_raw_ops;
349 else
350 sock->ops = &rawsock_ops;
307 351
308 sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto); 352 sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto);
309 if (!sk) 353 if (!sk)
@@ -313,13 +357,53 @@ static int rawsock_create(struct net *net, struct socket *sock,
313 sk->sk_protocol = nfc_proto->id; 357 sk->sk_protocol = nfc_proto->id;
314 sk->sk_destruct = rawsock_destruct; 358 sk->sk_destruct = rawsock_destruct;
315 sock->state = SS_UNCONNECTED; 359 sock->state = SS_UNCONNECTED;
316 360 if (sock->type == SOCK_RAW)
317 INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work); 361 nfc_sock_link(&raw_sk_list, sk);
318 nfc_rawsock(sk)->tx_work_scheduled = false; 362 else {
363 INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work);
364 nfc_rawsock(sk)->tx_work_scheduled = false;
365 }
319 366
320 return 0; 367 return 0;
321} 368}
322 369
370void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb,
371 u8 payload_type, u8 direction)
372{
373 struct sk_buff *skb_copy = NULL, *nskb;
374 struct sock *sk;
375 u8 *data;
376
377 read_lock(&raw_sk_list.lock);
378
379 sk_for_each(sk, &raw_sk_list.head) {
380 if (!skb_copy) {
381 skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE,
382 GFP_ATOMIC);
383 if (!skb_copy)
384 continue;
385
386 data = skb_push(skb_copy, NFC_RAW_HEADER_SIZE);
387
388 data[0] = dev ? dev->idx : 0xFF;
389 data[1] = direction & 0x01;
390 data[1] |= (payload_type << 1);
391 }
392
393 nskb = skb_clone(skb_copy, GFP_ATOMIC);
394 if (!nskb)
395 continue;
396
397 if (sock_queue_rcv_skb(sk, nskb))
398 kfree_skb(nskb);
399 }
400
401 read_unlock(&raw_sk_list.lock);
402
403 kfree_skb(skb_copy);
404}
405EXPORT_SYMBOL(nfc_send_to_raw_sock);
406
323static struct proto rawsock_proto = { 407static struct proto rawsock_proto = {
324 .name = "NFC_RAW", 408 .name = "NFC_RAW",
325 .owner = THIS_MODULE, 409 .owner = THIS_MODULE,