aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp/sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/llcp/sock.c')
-rw-r--r--net/nfc/llcp/sock.c101
1 files changed, 88 insertions, 13 deletions
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index ddeb9aa398f..63e4cdc9237 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;
@@ -300,9 +354,6 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr,
300 pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx, 354 pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx,
301 llcp_sock->dsap, llcp_sock->ssap); 355 llcp_sock->dsap, llcp_sock->ssap);
302 356
303 if (llcp_sock == NULL || llcp_sock->dev == NULL)
304 return -EBADFD;
305
306 uaddr->sa_family = AF_NFC; 357 uaddr->sa_family = AF_NFC;
307 358
308 *len = sizeof(struct sockaddr_nfc_llcp); 359 *len = sizeof(struct sockaddr_nfc_llcp);
@@ -421,7 +472,10 @@ static int llcp_sock_release(struct socket *sock)
421 472
422 release_sock(sk); 473 release_sock(sk);
423 474
424 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);
425 479
426out: 480out:
427 sock_orphan(sk); 481 sock_orphan(sk);
@@ -443,15 +497,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
443 pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); 497 pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
444 498
445 if (!addr || len < sizeof(struct sockaddr_nfc) || 499 if (!addr || len < sizeof(struct sockaddr_nfc) ||
446 addr->sa_family != AF_NFC) { 500 addr->sa_family != AF_NFC)
447 pr_err("Invalid socket\n");
448 return -EINVAL; 501 return -EINVAL;
449 }
450 502
451 if (addr->service_name_len == 0 && addr->dsap == 0) { 503 if (addr->service_name_len == 0 && addr->dsap == 0)
452 pr_err("Missing service name or dsap\n");
453 return -EINVAL; 504 return -EINVAL;
454 }
455 505
456 pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx, 506 pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx,
457 addr->target_idx, addr->nfc_protocol); 507 addr->target_idx, addr->nfc_protocol);
@@ -617,7 +667,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
617 if (!(flags & MSG_PEEK)) { 667 if (!(flags & MSG_PEEK)) {
618 668
619 /* SOCK_STREAM: re-queue skb if it contains unreceived data */ 669 /* SOCK_STREAM: re-queue skb if it contains unreceived data */
620 if (sk->sk_type == SOCK_STREAM) { 670 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) {
621 skb_pull(skb, copied); 671 skb_pull(skb, copied);
622 if (skb->len) { 672 if (skb->len) {
623 skb_queue_head(&sk->sk_receive_queue, skb); 673 skb_queue_head(&sk->sk_receive_queue, skb);
@@ -658,6 +708,26 @@ static const struct proto_ops llcp_sock_ops = {
658 .mmap = sock_no_mmap, 708 .mmap = sock_no_mmap,
659}; 709};
660 710
711static const struct proto_ops llcp_rawsock_ops = {
712 .family = PF_NFC,
713 .owner = THIS_MODULE,
714 .bind = llcp_raw_sock_bind,
715 .connect = sock_no_connect,
716 .release = llcp_sock_release,
717 .socketpair = sock_no_socketpair,
718 .accept = sock_no_accept,
719 .getname = llcp_sock_getname,
720 .poll = llcp_sock_poll,
721 .ioctl = sock_no_ioctl,
722 .listen = sock_no_listen,
723 .shutdown = sock_no_shutdown,
724 .setsockopt = sock_no_setsockopt,
725 .getsockopt = sock_no_getsockopt,
726 .sendmsg = sock_no_sendmsg,
727 .recvmsg = llcp_sock_recvmsg,
728 .mmap = sock_no_mmap,
729};
730
661static void llcp_sock_destruct(struct sock *sk) 731static void llcp_sock_destruct(struct sock *sk)
662{ 732{
663 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 733 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -735,10 +805,15 @@ static int llcp_sock_create(struct net *net, struct socket *sock,
735 805
736 pr_debug("%p\n", sock); 806 pr_debug("%p\n", sock);
737 807
738 if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) 808 if (sock->type != SOCK_STREAM &&
809 sock->type != SOCK_DGRAM &&
810 sock->type != SOCK_RAW)
739 return -ESOCKTNOSUPPORT; 811 return -ESOCKTNOSUPPORT;
740 812
741 sock->ops = &llcp_sock_ops; 813 if (sock->type == SOCK_RAW)
814 sock->ops = &llcp_rawsock_ops;
815 else
816 sock->ops = &llcp_sock_ops;
742 817
743 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); 818 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC);
744 if (sk == NULL) 819 if (sk == NULL)