aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2012-09-26 12:16:44 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-09-27 04:47:59 -0400
commit4463523bef98ff827a89cf8219db7dfac4350241 (patch)
tree50b87765b5b8e14074812b6fa3f442a6d5d661ab /net/nfc
parentee5e8d812ca25bf95a97b4368aec4e680678e75e (diff)
NFC: LLCP raw socket support
This adds support for socket of type SOCK_RAW to LLCP. sk_buff are copied and sent to raw sockets with a 2 bytes extra header: The first byte header contains the nfc adapter index. The second one contains flags: - 0x01 - Direction (0=RX, 1=TX) - 0x02-0x80 - Reserved A raw socket has to be explicitly bound to a nfc adapter. This is achieved by specifying the adapter index to be bound to in the dev_idx field of the sockaddr_nfc_llcp struct passed to bind(). Signed-off-by: Thierry Escande <thierry.escande@linux.intel.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/llcp.c46
-rw-r--r--net/nfc/llcp/llcp.h3
-rw-r--r--net/nfc/llcp/sock.c90
4 files changed, 137 insertions, 4 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b982b5b890d7..c45ccd6c094c 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -312,6 +312,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
312 312
313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); 313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
314 314
315 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX);
316
315 return nfc_data_exchange(dev, local->target_idx, skb, 317 return nfc_data_exchange(dev, local->target_idx, skb,
316 nfc_llcp_recv, local); 318 nfc_llcp_recv, local);
317} 319}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index d649fbf39d58..fc43747f0c33 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -558,6 +558,46 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
558 sock->recv_ack_n = (sock->recv_n - 1) % 16; 558 sock->recv_ack_n = (sock->recv_n - 1) % 16;
559} 559}
560 560
561void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
562 struct sk_buff *skb, u8 direction)
563{
564 struct hlist_node *node;
565 struct sk_buff *skb_copy = NULL, *nskb;
566 struct sock *sk;
567 u8 *data;
568
569 read_lock(&local->raw_sockets.lock);
570
571 sk_for_each(sk, node, &local->raw_sockets.head) {
572 if (sk->sk_state != LLCP_BOUND)
573 continue;
574
575 if (skb_copy == NULL) {
576 skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE,
577 GFP_ATOMIC);
578
579 if (skb_copy == NULL)
580 continue;
581
582 data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE);
583
584 data[0] = local->dev ? local->dev->idx : 0xFF;
585 data[1] = direction;
586 }
587
588 nskb = skb_clone(skb_copy, GFP_ATOMIC);
589 if (!nskb)
590 continue;
591
592 if (sock_queue_rcv_skb(sk, nskb))
593 kfree_skb(nskb);
594 }
595
596 read_unlock(&local->raw_sockets.lock);
597
598 kfree_skb(skb_copy);
599}
600
561static void nfc_llcp_tx_work(struct work_struct *work) 601static void nfc_llcp_tx_work(struct work_struct *work)
562{ 602{
563 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 603 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -578,6 +618,9 @@ static void nfc_llcp_tx_work(struct work_struct *work)
578 DUMP_PREFIX_OFFSET, 16, 1, 618 DUMP_PREFIX_OFFSET, 16, 1,
579 skb->data, skb->len, true); 619 skb->data, skb->len, true);
580 620
621 nfc_llcp_send_to_raw_sock(local, skb,
622 NFC_LLCP_DIRECTION_TX);
623
581 ret = nfc_data_exchange(local->dev, local->target_idx, 624 ret = nfc_data_exchange(local->dev, local->target_idx,
582 skb, nfc_llcp_recv, local); 625 skb, nfc_llcp_recv, local);
583 626
@@ -1022,6 +1065,8 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1022 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 1065 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
1023 16, 1, skb->data, skb->len, true); 1066 16, 1, skb->data, skb->len, true);
1024 1067
1068 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1069
1025 switch (ptype) { 1070 switch (ptype) {
1026 case LLCP_PDU_SYMM: 1071 case LLCP_PDU_SYMM:
1027 pr_debug("SYMM\n"); 1072 pr_debug("SYMM\n");
@@ -1158,6 +1203,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1158 1203
1159 rwlock_init(&local->sockets.lock); 1204 rwlock_init(&local->sockets.lock);
1160 rwlock_init(&local->connecting_sockets.lock); 1205 rwlock_init(&local->connecting_sockets.lock);
1206 rwlock_init(&local->raw_sockets.lock);
1161 1207
1162 nfc_llcp_build_gb(local); 1208 nfc_llcp_build_gb(local);
1163 1209
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index af395c9ceb03..fdb2d24e60bd 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -86,6 +86,7 @@ struct nfc_llcp_local {
86 /* sockets array */ 86 /* sockets array */
87 struct llcp_sock_list sockets; 87 struct llcp_sock_list sockets;
88 struct llcp_sock_list connecting_sockets; 88 struct llcp_sock_list connecting_sockets;
89 struct llcp_sock_list raw_sockets;
89}; 90};
90 91
91struct nfc_llcp_sock { 92struct nfc_llcp_sock {
@@ -184,6 +185,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
184u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 185u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
185void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); 186void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
186int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); 187int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock);
188void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
189 struct sk_buff *skb, u8 direction);
187 190
188/* Sock API */ 191/* Sock API */
189struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); 192struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 6e188d4020ba..40f056debf9a 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -142,6 +142,60 @@ error:
142 return ret; 142 return ret;
143} 143}
144 144
145static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
146 int alen)
147{
148 struct sock *sk = sock->sk;
149 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
150 struct nfc_llcp_local *local;
151 struct nfc_dev *dev;
152 struct sockaddr_nfc_llcp llcp_addr;
153 int len, ret = 0;
154
155 if (!addr || addr->sa_family != AF_NFC)
156 return -EINVAL;
157
158 pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
159
160 memset(&llcp_addr, 0, sizeof(llcp_addr));
161 len = min_t(unsigned int, sizeof(llcp_addr), alen);
162 memcpy(&llcp_addr, addr, len);
163
164 lock_sock(sk);
165
166 if (sk->sk_state != LLCP_CLOSED) {
167 ret = -EBADFD;
168 goto error;
169 }
170
171 dev = nfc_get_device(llcp_addr.dev_idx);
172 if (dev == NULL) {
173 ret = -ENODEV;
174 goto error;
175 }
176
177 local = nfc_llcp_find_local(dev);
178 if (local == NULL) {
179 ret = -ENODEV;
180 goto put_dev;
181 }
182
183 llcp_sock->dev = dev;
184 llcp_sock->local = nfc_llcp_local_get(local);
185 llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
186
187 nfc_llcp_sock_link(&local->raw_sockets, sk);
188
189 sk->sk_state = LLCP_BOUND;
190
191put_dev:
192 nfc_put_device(dev);
193
194error:
195 release_sock(sk);
196 return ret;
197}
198
145static int llcp_sock_listen(struct socket *sock, int backlog) 199static int llcp_sock_listen(struct socket *sock, int backlog)
146{ 200{
147 struct sock *sk = sock->sk; 201 struct sock *sk = sock->sk;
@@ -418,7 +472,10 @@ static int llcp_sock_release(struct socket *sock)
418 472
419 release_sock(sk); 473 release_sock(sk);
420 474
421 nfc_llcp_sock_unlink(&local->sockets, sk); 475 if (sock->type == SOCK_RAW)
476 nfc_llcp_sock_unlink(&local->raw_sockets, sk);
477 else
478 nfc_llcp_sock_unlink(&local->sockets, sk);
422 479
423out: 480out:
424 sock_orphan(sk); 481 sock_orphan(sk);
@@ -614,7 +671,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
614 if (!(flags & MSG_PEEK)) { 671 if (!(flags & MSG_PEEK)) {
615 672
616 /* SOCK_STREAM: re-queue skb if it contains unreceived data */ 673 /* SOCK_STREAM: re-queue skb if it contains unreceived data */
617 if (sk->sk_type == SOCK_STREAM) { 674 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) {
618 skb_pull(skb, copied); 675 skb_pull(skb, copied);
619 if (skb->len) { 676 if (skb->len) {
620 skb_queue_head(&sk->sk_receive_queue, skb); 677 skb_queue_head(&sk->sk_receive_queue, skb);
@@ -655,6 +712,26 @@ static const struct proto_ops llcp_sock_ops = {
655 .mmap = sock_no_mmap, 712 .mmap = sock_no_mmap,
656}; 713};
657 714
715static const struct proto_ops llcp_rawsock_ops = {
716 .family = PF_NFC,
717 .owner = THIS_MODULE,
718 .bind = llcp_raw_sock_bind,
719 .connect = sock_no_connect,
720 .release = llcp_sock_release,
721 .socketpair = sock_no_socketpair,
722 .accept = sock_no_accept,
723 .getname = llcp_sock_getname,
724 .poll = llcp_sock_poll,
725 .ioctl = sock_no_ioctl,
726 .listen = sock_no_listen,
727 .shutdown = sock_no_shutdown,
728 .setsockopt = sock_no_setsockopt,
729 .getsockopt = sock_no_getsockopt,
730 .sendmsg = sock_no_sendmsg,
731 .recvmsg = llcp_sock_recvmsg,
732 .mmap = sock_no_mmap,
733};
734
658static void llcp_sock_destruct(struct sock *sk) 735static void llcp_sock_destruct(struct sock *sk)
659{ 736{
660 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 737 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -732,10 +809,15 @@ static int llcp_sock_create(struct net *net, struct socket *sock,
732 809
733 pr_debug("%p\n", sock); 810 pr_debug("%p\n", sock);
734 811
735 if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) 812 if (sock->type != SOCK_STREAM &&
813 sock->type != SOCK_DGRAM &&
814 sock->type != SOCK_RAW)
736 return -ESOCKTNOSUPPORT; 815 return -ESOCKTNOSUPPORT;
737 816
738 sock->ops = &llcp_sock_ops; 817 if (sock->type == SOCK_RAW)
818 sock->ops = &llcp_rawsock_ops;
819 else
820 sock->ops = &llcp_sock_ops;
739 821
740 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); 822 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC);
741 if (sk == NULL) 823 if (sk == NULL)