Blame view
net/nfc/llcp_sock.c
22.4 KB
d646960f7 NFC: Initial LLCP... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * Copyright (C) 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License |
98b32decc nfc: Fix FSF addr... |
15 |
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
d646960f7 NFC: Initial LLCP... |
16 17 18 19 20 21 22 23 |
*/ #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/nfc.h> |
174cd4b1e sched/headers: Pr... |
24 |
#include <linux/sched/signal.h> |
d646960f7 NFC: Initial LLCP... |
25 |
|
30cc45876 NFC: Move LLCP co... |
26 |
#include "nfc.h" |
d646960f7 NFC: Initial LLCP... |
27 |
#include "llcp.h" |
ff353d86a NFC: LLCP connect... |
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
static int sock_wait_state(struct sock *sk, int state, unsigned long timeo) { DECLARE_WAITQUEUE(wait, current); int err = 0; pr_debug("sk %p", sk); add_wait_queue(sk_sleep(sk), &wait); set_current_state(TASK_INTERRUPTIBLE); while (sk->sk_state != state) { if (!timeo) { err = -EINPROGRESS; break; } if (signal_pending(current)) { err = sock_intr_errno(timeo); break; } release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); set_current_state(TASK_INTERRUPTIBLE); err = sock_error(sk); if (err) break; } __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); return err; } |
d646960f7 NFC: Initial LLCP... |
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
static struct proto llcp_sock_proto = { .name = "NFC_LLCP", .owner = THIS_MODULE, .obj_size = sizeof(struct nfc_llcp_sock), }; static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); struct nfc_llcp_local *local; struct nfc_dev *dev; struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; |
f6a5885fc NFC: Add sockaddr... |
77 78 |
if (!addr || alen < offsetofend(struct sockaddr, sa_family) || addr->sa_family != AF_NFC) |
d646960f7 NFC: Initial LLCP... |
79 |
return -EINVAL; |
c66433dc5 NFC: Dereference ... |
80 81 |
pr_debug("sk %p addr %p family %d ", sk, addr, addr->sa_family); |
d646960f7 NFC: Initial LLCP... |
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
memset(&llcp_addr, 0, sizeof(llcp_addr)); len = min_t(unsigned int, sizeof(llcp_addr), alen); memcpy(&llcp_addr, addr, len); /* This is going to be a listening socket, dsap must be 0 */ if (llcp_addr.dsap != 0) return -EINVAL; lock_sock(sk); if (sk->sk_state != LLCP_CLOSED) { ret = -EBADFD; goto error; } dev = nfc_get_device(llcp_addr.dev_idx); if (dev == NULL) { ret = -ENODEV; goto error; } local = nfc_llcp_find_local(dev); if (local == NULL) { ret = -ENODEV; goto put_dev; } llcp_sock->dev = dev; |
c7aa12252 NFC: Take a refer... |
110 |
llcp_sock->local = nfc_llcp_local_get(local); |
d646960f7 NFC: Initial LLCP... |
111 112 |
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; llcp_sock->service_name_len = min_t(unsigned int, |
427a2eb1f NFC: LLCP code id... |
113 114 |
llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME); |
d646960f7 NFC: Initial LLCP... |
115 |
llcp_sock->service_name = kmemdup(llcp_addr.service_name, |
427a2eb1f NFC: LLCP code id... |
116 117 |
llcp_sock->service_name_len, GFP_KERNEL); |
d646960f7 NFC: Initial LLCP... |
118 119 |
llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); |
8b7e8eda5 NFC: Forbid LLCP ... |
120 121 |
if (llcp_sock->ssap == LLCP_SAP_MAX) { ret = -EADDRINUSE; |
d646960f7 NFC: Initial LLCP... |
122 |
goto put_dev; |
8b7e8eda5 NFC: Forbid LLCP ... |
123 |
} |
d646960f7 NFC: Initial LLCP... |
124 |
|
cbbf47218 NFC: Release LLCP... |
125 |
llcp_sock->reserved_ssap = llcp_sock->ssap; |
a69f32af8 NFC: Socket linke... |
126 |
nfc_llcp_sock_link(&local->sockets, sk); |
d646960f7 NFC: Initial LLCP... |
127 128 129 130 131 132 133 134 135 136 137 138 139 |
pr_debug("Socket bound to SAP %d ", llcp_sock->ssap); sk->sk_state = LLCP_BOUND; put_dev: nfc_put_device(dev); error: release_sock(sk); return ret; } |
4463523be NFC: LLCP raw soc... |
140 141 142 143 144 145 146 147 148 |
static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) { struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); struct nfc_llcp_local *local; struct nfc_dev *dev; struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; |
f6a5885fc NFC: Add sockaddr... |
149 150 |
if (!addr || alen < offsetofend(struct sockaddr, sa_family) || addr->sa_family != AF_NFC) |
4463523be NFC: LLCP raw soc... |
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
return -EINVAL; pr_debug("sk %p addr %p family %d ", sk, addr, addr->sa_family); memset(&llcp_addr, 0, sizeof(llcp_addr)); len = min_t(unsigned int, sizeof(llcp_addr), alen); memcpy(&llcp_addr, addr, len); lock_sock(sk); if (sk->sk_state != LLCP_CLOSED) { ret = -EBADFD; goto error; } dev = nfc_get_device(llcp_addr.dev_idx); if (dev == NULL) { ret = -ENODEV; goto error; } local = nfc_llcp_find_local(dev); if (local == NULL) { ret = -ENODEV; goto put_dev; } llcp_sock->dev = dev; llcp_sock->local = nfc_llcp_local_get(local); llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; nfc_llcp_sock_link(&local->raw_sockets, sk); sk->sk_state = LLCP_BOUND; put_dev: nfc_put_device(dev); error: release_sock(sk); return ret; } |
d646960f7 NFC: Initial LLCP... |
194 195 196 197 198 199 200 201 202 |
static int llcp_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; int ret = 0; pr_debug("sk %p backlog %d ", sk, backlog); lock_sock(sk); |
874934f4d NFC: Fix style is... |
203 204 |
if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) || sk->sk_state != LLCP_BOUND) { |
d646960f7 NFC: Initial LLCP... |
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
ret = -EBADFD; goto error; } sk->sk_max_ack_backlog = backlog; sk->sk_ack_backlog = 0; pr_debug("Socket listening "); sk->sk_state = LLCP_LISTEN; error: release_sock(sk); return ret; } |
26fd76cab NFC: llcp: Implem... |
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); u32 opt; int err = 0; pr_debug("%p optname %d ", sk, optname); if (level != SOL_NFC) return -ENOPROTOOPT; lock_sock(sk); switch (optname) { case NFC_LLCP_RW: if (sk->sk_state == LLCP_CONNECTED || sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) { err = -EINVAL; break; } if (get_user(opt, (u32 __user *) optval)) { err = -EFAULT; break; } if (opt > LLCP_MAX_RW) { err = -EINVAL; break; } llcp_sock->rw = (u8) opt; break; case NFC_LLCP_MIUX: if (sk->sk_state == LLCP_CONNECTED || sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) { err = -EINVAL; break; } if (get_user(opt, (u32 __user *) optval)) { err = -EFAULT; break; } if (opt > LLCP_MAX_MIUX) { err = -EINVAL; break; } |
5eef66697 NFC: llcp: Socket... |
277 |
llcp_sock->miux = cpu_to_be16((u16) opt); |
26fd76cab NFC: llcp: Implem... |
278 279 280 281 282 283 284 285 286 |
break; default: err = -ENOPROTOOPT; break; } release_sock(sk); |
06d44f806 NFC: llcp: Use so... |
287 288 289 |
pr_debug("%p rw %d miux %d ", llcp_sock, llcp_sock->rw, llcp_sock->miux); |
26fd76cab NFC: llcp: Implem... |
290 291 292 293 294 295 |
return err; } static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { |
00e856db4 NFC: llcp: Fall b... |
296 |
struct nfc_llcp_local *local; |
26fd76cab NFC: llcp: Implem... |
297 298 299 |
struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); int len, err = 0; |
064f370c5 NFC: llcp: Add su... |
300 |
u16 miux, remote_miu; |
00e856db4 NFC: llcp: Fall b... |
301 |
u8 rw; |
26fd76cab NFC: llcp: Implem... |
302 303 304 305 306 307 308 309 310 |
pr_debug("%p optname %d ", sk, optname); if (level != SOL_NFC) return -ENOPROTOOPT; if (get_user(len, optlen)) return -EFAULT; |
00e856db4 NFC: llcp: Fall b... |
311 312 313 |
local = llcp_sock->local; if (!local) return -ENODEV; |
26fd76cab NFC: llcp: Implem... |
314 315 316 317 318 319 |
len = min_t(u32, len, sizeof(u32)); lock_sock(sk); switch (optname) { case NFC_LLCP_RW: |
00e856db4 NFC: llcp: Fall b... |
320 321 |
rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw; if (put_user(rw, (u32 __user *) optval)) |
26fd76cab NFC: llcp: Implem... |
322 323 324 325 326 |
err = -EFAULT; break; case NFC_LLCP_MIUX: |
00e856db4 NFC: llcp: Fall b... |
327 328 329 330 |
miux = be16_to_cpu(llcp_sock->miux) > LLCP_MAX_MIUX ? be16_to_cpu(local->miux) : be16_to_cpu(llcp_sock->miux); if (put_user(miux, (u32 __user *) optval)) |
26fd76cab NFC: llcp: Implem... |
331 332 333 |
err = -EFAULT; break; |
064f370c5 NFC: llcp: Add su... |
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
case NFC_LLCP_REMOTE_MIU: remote_miu = llcp_sock->remote_miu > LLCP_MAX_MIU ? local->remote_miu : llcp_sock->remote_miu; if (put_user(remote_miu, (u32 __user *) optval)) err = -EFAULT; break; case NFC_LLCP_REMOTE_LTO: if (put_user(local->remote_lto / 10, (u32 __user *) optval)) err = -EFAULT; break; case NFC_LLCP_REMOTE_RW: if (put_user(llcp_sock->remote_rw, (u32 __user *) optval)) |
26fd76cab NFC: llcp: Implem... |
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
err = -EFAULT; break; default: err = -ENOPROTOOPT; break; } release_sock(sk); if (put_user(len, optlen)) return -EFAULT; return err; } |
d646960f7 NFC: Initial LLCP... |
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
void nfc_llcp_accept_unlink(struct sock *sk) { struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); pr_debug("state %d ", sk->sk_state); list_del_init(&llcp_sock->accept_queue); sk_acceptq_removed(llcp_sock->parent); llcp_sock->parent = NULL; sock_put(sk); } void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk) { struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); struct nfc_llcp_sock *llcp_sock_parent = nfc_llcp_sock(parent); /* Lock will be free from unlink */ sock_hold(sk); list_add_tail(&llcp_sock->accept_queue, |
427a2eb1f NFC: LLCP code id... |
390 |
&llcp_sock_parent->accept_queue); |
d646960f7 NFC: Initial LLCP... |
391 392 393 394 395 |
llcp_sock->parent = parent; sk_acceptq_added(parent); } struct sock *nfc_llcp_accept_dequeue(struct sock *parent, |
427a2eb1f NFC: LLCP code id... |
396 |
struct socket *newsock) |
d646960f7 NFC: Initial LLCP... |
397 398 399 400 401 402 403 |
{ struct nfc_llcp_sock *lsk, *n, *llcp_parent; struct sock *sk; llcp_parent = nfc_llcp_sock(parent); list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue, |
427a2eb1f NFC: LLCP code id... |
404 |
accept_queue) { |
d646960f7 NFC: Initial LLCP... |
405 406 407 408 409 410 411 412 413 414 |
sk = &lsk->sk; lock_sock(sk); if (sk->sk_state == LLCP_CLOSED) { release_sock(sk); nfc_llcp_accept_unlink(sk); continue; } if (sk->sk_state == LLCP_CONNECTED || !newsock) { |
39a352a5b NFC: llcp: Keep t... |
415 416 |
list_del_init(&lsk->accept_queue); sock_put(sk); |
d646960f7 NFC: Initial LLCP... |
417 418 419 420 421 422 423 |
if (newsock) sock_graft(sk, newsock); release_sock(sk); pr_debug("Returning sk state %d ", sk->sk_state); |
b141e811a NFC: llcp: Decrea... |
424 |
sk_acceptq_removed(parent); |
d646960f7 NFC: Initial LLCP... |
425 426 427 428 429 430 431 432 433 434 |
return sk; } release_sock(sk); } return NULL; } static int llcp_sock_accept(struct socket *sock, struct socket *newsock, |
cdfbabfb2 net: Work around ... |
435 |
int flags, bool kern) |
d646960f7 NFC: Initial LLCP... |
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
{ DECLARE_WAITQUEUE(wait, current); struct sock *sk = sock->sk, *new_sk; long timeo; int ret = 0; pr_debug("parent %p ", sk); lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_state != LLCP_LISTEN) { ret = -EBADFD; goto error; } timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); /* Wait for an incoming connection. */ add_wait_queue_exclusive(sk_sleep(sk), &wait); while (!(new_sk = nfc_llcp_accept_dequeue(sk, newsock))) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) { ret = -EAGAIN; break; } if (signal_pending(current)) { ret = sock_intr_errno(timeo); break; } release_sock(sk); timeo = schedule_timeout(timeo); lock_sock_nested(sk, SINGLE_DEPTH_NESTING); } __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); if (ret) goto error; newsock->state = SS_CONNECTED; pr_debug("new socket %p ", new_sk); error: release_sock(sk); return ret; } |
12e5bdfef NFC: Fix LLCP get... |
489 |
static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, |
d646960f7 NFC: Initial LLCP... |
490 491 |
int *len, int peer) { |
d646960f7 NFC: Initial LLCP... |
492 493 |
struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
12e5bdfef NFC: Fix LLCP get... |
494 |
DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, llcp_addr, uaddr); |
d646960f7 NFC: Initial LLCP... |
495 |
|
fe3c094ab NFC: Check for ll... |
496 497 |
if (llcp_sock == NULL || llcp_sock->dev == NULL) return -EBADFD; |
12e5bdfef NFC: Fix LLCP get... |
498 499 500 |
pr_debug("%p %d %d %d ", sk, llcp_sock->target_idx, llcp_sock->dsap, llcp_sock->ssap); |
d646960f7 NFC: Initial LLCP... |
501 |
|
5ffedc6ed NFC: llcp: two bu... |
502 |
memset(llcp_addr, 0, sizeof(*llcp_addr)); |
d646960f7 NFC: Initial LLCP... |
503 |
*len = sizeof(struct sockaddr_nfc_llcp); |
03c053555 NFC: Close a race... |
504 505 506 507 508 |
lock_sock(sk); if (!llcp_sock->dev) { release_sock(sk); return -EBADFD; } |
5ffedc6ed NFC: llcp: two bu... |
509 |
llcp_addr->sa_family = AF_NFC; |
d646960f7 NFC: Initial LLCP... |
510 |
llcp_addr->dev_idx = llcp_sock->dev->idx; |
12e5bdfef NFC: Fix LLCP get... |
511 |
llcp_addr->target_idx = llcp_sock->target_idx; |
5ffedc6ed NFC: llcp: two bu... |
512 |
llcp_addr->nfc_protocol = llcp_sock->nfc_protocol; |
d646960f7 NFC: Initial LLCP... |
513 514 515 516 |
llcp_addr->dsap = llcp_sock->dsap; llcp_addr->ssap = llcp_sock->ssap; llcp_addr->service_name_len = llcp_sock->service_name_len; memcpy(llcp_addr->service_name, llcp_sock->service_name, |
427a2eb1f NFC: LLCP code id... |
517 |
llcp_addr->service_name_len); |
03c053555 NFC: Close a race... |
518 |
release_sock(sk); |
d646960f7 NFC: Initial LLCP... |
519 520 521 522 523 524 |
return 0; } static inline unsigned int llcp_accept_poll(struct sock *parent) { |
413df10bb NFC: llcp: Use li... |
525 |
struct nfc_llcp_sock *llcp_sock, *parent_sock; |
d646960f7 NFC: Initial LLCP... |
526 527 528 |
struct sock *sk; parent_sock = nfc_llcp_sock(parent); |
413df10bb NFC: llcp: Use li... |
529 530 |
list_for_each_entry(llcp_sock, &parent_sock->accept_queue, accept_queue) { |
d646960f7 NFC: Initial LLCP... |
531 532 533 534 535 536 537 538 539 540 |
sk = &llcp_sock->sk; if (sk->sk_state == LLCP_CONNECTED) return POLLIN | POLLRDNORM; } return 0; } static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, |
427a2eb1f NFC: LLCP code id... |
541 |
poll_table *wait) |
d646960f7 NFC: Initial LLCP... |
542 543 544 545 546 547 548 549 550 551 552 553 554 |
{ struct sock *sk = sock->sk; unsigned int mask = 0; pr_debug("%p ", sk); sock_poll_wait(file, sk_sleep(sk), wait); if (sk->sk_state == LLCP_LISTEN) return llcp_accept_poll(sk); if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
7d4c04fc1 net: add option t... |
555 |
mask |= POLLERR | |
8facd5fb7 net: fix smatch w... |
556 |
(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); |
d646960f7 NFC: Initial LLCP... |
557 558 |
if (!skb_queue_empty(&sk->sk_receive_queue)) |
4260c13ba NFC: Update the L... |
559 |
mask |= POLLIN | POLLRDNORM; |
d646960f7 NFC: Initial LLCP... |
560 561 562 |
if (sk->sk_state == LLCP_CLOSED) mask |= POLLHUP; |
4260c13ba NFC: Update the L... |
563 564 565 566 567 |
if (sk->sk_shutdown & RCV_SHUTDOWN) mask |= POLLRDHUP | POLLIN | POLLRDNORM; if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; |
b4011239a NFC: llcp: Fix no... |
568 |
if (sock_writeable(sk) && sk->sk_state == LLCP_CONNECTED) |
4260c13ba NFC: Update the L... |
569 570 |
mask |= POLLOUT | POLLWRNORM | POLLWRBAND; else |
9cd3e072b net: rename SOCK_... |
571 |
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
4260c13ba NFC: Update the L... |
572 573 574 |
pr_debug("mask 0x%x ", mask); |
d646960f7 NFC: Initial LLCP... |
575 576 577 578 579 580 581 582 |
return mask; } static int llcp_sock_release(struct socket *sock) { struct sock *sk = sock->sk; struct nfc_llcp_local *local; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
40c75f81d NFC: Fix LLCP soc... |
583 |
int err = 0; |
d646960f7 NFC: Initial LLCP... |
584 585 586 587 588 589 590 591 |
if (!sk) return 0; pr_debug("%p ", sk); local = llcp_sock->local; |
40c75f81d NFC: Fix LLCP soc... |
592 593 594 595 |
if (local == NULL) { err = -ENODEV; goto out; } |
d646960f7 NFC: Initial LLCP... |
596 |
|
d646960f7 NFC: Initial LLCP... |
597 598 599 600 |
lock_sock(sk); /* Send a DISC */ if (sk->sk_state == LLCP_CONNECTED) |
58e3dd155 NFC: Rename nfc_l... |
601 |
nfc_llcp_send_disconnect(llcp_sock); |
d646960f7 NFC: Initial LLCP... |
602 603 604 605 606 607 |
if (sk->sk_state == LLCP_LISTEN) { struct nfc_llcp_sock *lsk, *n; struct sock *accept_sk; list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
427a2eb1f NFC: LLCP code id... |
608 |
accept_queue) { |
d646960f7 NFC: Initial LLCP... |
609 610 |
accept_sk = &lsk->sk; lock_sock(accept_sk); |
58e3dd155 NFC: Rename nfc_l... |
611 |
nfc_llcp_send_disconnect(lsk); |
d646960f7 NFC: Initial LLCP... |
612 613 614 |
nfc_llcp_accept_unlink(accept_sk); release_sock(accept_sk); |
d646960f7 NFC: Initial LLCP... |
615 616 |
} } |
cbbf47218 NFC: Release LLCP... |
617 618 |
if (llcp_sock->reserved_ssap < LLCP_SAP_MAX) nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
d646960f7 NFC: Initial LLCP... |
619 |
|
d646960f7 NFC: Initial LLCP... |
620 |
release_sock(sk); |
17f7ae16a NFC: Keep socket ... |
621 622 623 624 625 626 |
/* Keep this sock alive and therefore do not remove it from the sockets * list until the DISC PDU has been actually sent. Otherwise we would * reply with DM PDUs before sending the DISC one. */ if (sk->sk_state == LLCP_DISCONNECTING) return err; |
4463523be NFC: LLCP raw soc... |
627 628 629 630 |
if (sock->type == SOCK_RAW) nfc_llcp_sock_unlink(&local->raw_sockets, sk); else nfc_llcp_sock_unlink(&local->sockets, sk); |
a69f32af8 NFC: Socket linke... |
631 |
|
40c75f81d NFC: Fix LLCP soc... |
632 |
out: |
d646960f7 NFC: Initial LLCP... |
633 634 |
sock_orphan(sk); sock_put(sk); |
40c75f81d NFC: Fix LLCP soc... |
635 |
return err; |
d646960f7 NFC: Initial LLCP... |
636 637 638 |
} static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, |
427a2eb1f NFC: LLCP code id... |
639 |
int len, int flags) |
d646960f7 NFC: Initial LLCP... |
640 641 642 643 644 645 646 647 648 649 |
{ struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); struct sockaddr_nfc_llcp *addr = (struct sockaddr_nfc_llcp *)_addr; struct nfc_dev *dev; struct nfc_llcp_local *local; int ret = 0; pr_debug("sock %p sk %p flags 0x%x ", sock, sk, flags); |
608c4adfc nfc: Fix the sock... |
650 |
if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC) |
d646960f7 NFC: Initial LLCP... |
651 |
return -EINVAL; |
d646960f7 NFC: Initial LLCP... |
652 |
|
32418cfe4 Remove noisy prin... |
653 |
if (addr->service_name_len == 0 && addr->dsap == 0) |
d646960f7 NFC: Initial LLCP... |
654 |
return -EINVAL; |
d646960f7 NFC: Initial LLCP... |
655 656 657 |
pr_debug("addr dev_idx=%u target_idx=%u protocol=%u ", addr->dev_idx, |
427a2eb1f NFC: LLCP code id... |
658 |
addr->target_idx, addr->nfc_protocol); |
d646960f7 NFC: Initial LLCP... |
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 |
lock_sock(sk); if (sk->sk_state == LLCP_CONNECTED) { ret = -EISCONN; goto error; } dev = nfc_get_device(addr->dev_idx); if (dev == NULL) { ret = -ENODEV; goto error; } local = nfc_llcp_find_local(dev); if (local == NULL) { ret = -ENODEV; goto put_dev; } device_lock(&dev->dev); if (dev->dep_link_up == false) { ret = -ENOLINK; device_unlock(&dev->dev); goto put_dev; } device_unlock(&dev->dev); if (local->rf_mode == NFC_RF_INITIATOR && |
427a2eb1f NFC: LLCP code id... |
688 |
addr->target_idx != local->target_idx) { |
d646960f7 NFC: Initial LLCP... |
689 690 691 692 693 |
ret = -ENOLINK; goto put_dev; } llcp_sock->dev = dev; |
c7aa12252 NFC: Take a refer... |
694 |
llcp_sock->local = nfc_llcp_local_get(local); |
d646960f7 NFC: Initial LLCP... |
695 696 697 698 699 |
llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { ret = -ENOMEM; goto put_dev; } |
cbbf47218 NFC: Release LLCP... |
700 701 |
llcp_sock->reserved_ssap = llcp_sock->ssap; |
d646960f7 NFC: Initial LLCP... |
702 703 704 705 706 707 |
if (addr->service_name_len == 0) llcp_sock->dsap = addr->dsap; else llcp_sock->dsap = LLCP_SAP_SDP; llcp_sock->nfc_protocol = addr->nfc_protocol; llcp_sock->service_name_len = min_t(unsigned int, |
427a2eb1f NFC: LLCP code id... |
708 709 |
addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME); |
d646960f7 NFC: Initial LLCP... |
710 |
llcp_sock->service_name = kmemdup(addr->service_name, |
427a2eb1f NFC: LLCP code id... |
711 712 |
llcp_sock->service_name_len, GFP_KERNEL); |
d646960f7 NFC: Initial LLCP... |
713 |
|
a69f32af8 NFC: Socket linke... |
714 |
nfc_llcp_sock_link(&local->connecting_sockets, sk); |
d646960f7 NFC: Initial LLCP... |
715 716 717 |
ret = nfc_llcp_send_connect(llcp_sock); if (ret) |
a69f32af8 NFC: Socket linke... |
718 |
goto sock_unlink; |
d646960f7 NFC: Initial LLCP... |
719 |
|
b4011239a NFC: llcp: Fix no... |
720 |
sk->sk_state = LLCP_CONNECTING; |
ff353d86a NFC: LLCP connect... |
721 722 |
ret = sock_wait_state(sk, LLCP_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); |
b4011239a NFC: llcp: Fix no... |
723 |
if (ret && ret != -EINPROGRESS) |
a69f32af8 NFC: Socket linke... |
724 |
goto sock_unlink; |
d646960f7 NFC: Initial LLCP... |
725 726 |
release_sock(sk); |
ff353d86a NFC: LLCP connect... |
727 |
|
b4011239a NFC: llcp: Fix no... |
728 |
return ret; |
d646960f7 NFC: Initial LLCP... |
729 |
|
a69f32af8 NFC: Socket linke... |
730 731 732 733 |
sock_unlink: nfc_llcp_put_ssap(local, llcp_sock->ssap); nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
d646960f7 NFC: Initial LLCP... |
734 735 736 737 738 739 740 |
put_dev: nfc_put_device(dev); error: release_sock(sk); return ret; } |
1b7841404 net: Remove iocb ... |
741 742 |
static int llcp_sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
53a0ac2ee NFC: LLCP socket ... |
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 |
{ struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); int ret; pr_debug("sock %p sk %p", sock, sk); ret = sock_error(sk); if (ret) return ret; if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; lock_sock(sk); |
b874dec21 NFC: Implement LL... |
758 |
if (sk->sk_type == SOCK_DGRAM) { |
342dfc306 net: add build-ti... |
759 760 |
DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, addr, msg->msg_name); |
b874dec21 NFC: Implement LL... |
761 762 763 |
if (msg->msg_namelen < sizeof(*addr)) { release_sock(sk); |
b874dec21 NFC: Implement LL... |
764 765 766 767 768 769 770 771 |
return -EINVAL; } release_sock(sk); return nfc_llcp_send_ui_frame(llcp_sock, addr->dsap, addr->ssap, msg, len); } |
53a0ac2ee NFC: LLCP socket ... |
772 773 774 775 776 777 778 779 780 |
if (sk->sk_state != LLCP_CONNECTED) { release_sock(sk); return -ENOTCONN; } release_sock(sk); return nfc_llcp_send_i_frame(llcp_sock, msg, len); } |
1b7841404 net: Remove iocb ... |
781 782 |
static int llcp_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags) |
d646960f7 NFC: Initial LLCP... |
783 784 785 786 787 788 789 790 791 792 793 794 795 |
{ int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; unsigned int copied, rlen; struct sk_buff *skb, *cskb; int err = 0; pr_debug("%p %zu ", sk, len); lock_sock(sk); if (sk->sk_state == LLCP_CLOSED && |
427a2eb1f NFC: LLCP code id... |
796 |
skb_queue_empty(&sk->sk_receive_queue)) { |
d646960f7 NFC: Initial LLCP... |
797 798 799 800 801 802 803 804 805 806 807 808 |
release_sock(sk); return 0; } release_sock(sk); if (flags & (MSG_OOB)) return -EOPNOTSUPP; skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { pr_err("Recv datagram failed state %d %d %d", |
427a2eb1f NFC: LLCP code id... |
809 |
sk->sk_state, err, sock_error(sk)); |
d646960f7 NFC: Initial LLCP... |
810 811 812 813 814 815 |
if (sk->sk_shutdown & RCV_SHUTDOWN) return 0; return err; } |
427a2eb1f NFC: LLCP code id... |
816 |
rlen = skb->len; /* real length of skb */ |
d646960f7 NFC: Initial LLCP... |
817 818 819 |
copied = min_t(unsigned int, rlen, len); cskb = skb; |
51f3d02b9 net: Add and use ... |
820 |
if (skb_copy_datagram_msg(cskb, 0, msg, copied)) { |
d646960f7 NFC: Initial LLCP... |
821 822 823 824 |
if (!(flags & MSG_PEEK)) skb_queue_head(&sk->sk_receive_queue, skb); return -EFAULT; } |
2c2d45bdc NFC: Add support ... |
825 |
sock_recv_timestamp(msg, sk, skb); |
31ca61a8d NFC: Forward LLCP... |
826 827 |
if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); |
342dfc306 net: add build-ti... |
828 829 |
DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, sockaddr, msg->msg_name); |
31ca61a8d NFC: Forward LLCP... |
830 |
|
fad2e371b NFC: Avoid memcpy... |
831 |
msg->msg_namelen = sizeof(struct sockaddr_nfc_llcp); |
31ca61a8d NFC: Forward LLCP... |
832 |
|
fad2e371b NFC: Avoid memcpy... |
833 834 |
pr_debug("Datagram socket %d %d ", ui_cb->dsap, ui_cb->ssap); |
31ca61a8d NFC: Forward LLCP... |
835 |
|
d26d6504f NFC: llcp: fix in... |
836 |
memset(sockaddr, 0, sizeof(*sockaddr)); |
fad2e371b NFC: Avoid memcpy... |
837 838 839 840 |
sockaddr->sa_family = AF_NFC; sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; sockaddr->dsap = ui_cb->dsap; sockaddr->ssap = ui_cb->ssap; |
31ca61a8d NFC: Forward LLCP... |
841 |
} |
d646960f7 NFC: Initial LLCP... |
842 843 844 845 |
/* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { /* SOCK_STREAM: re-queue skb if it contains unreceived data */ |
31ca61a8d NFC: Forward LLCP... |
846 847 848 |
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { |
d646960f7 NFC: Initial LLCP... |
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 |
skb_pull(skb, copied); if (skb->len) { skb_queue_head(&sk->sk_receive_queue, skb); goto done; } } kfree_skb(skb); } /* XXX Queue backlogged skbs */ done: /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) copied = rlen; return copied; } static const struct proto_ops llcp_sock_ops = { .family = PF_NFC, .owner = THIS_MODULE, .bind = llcp_sock_bind, .connect = llcp_sock_connect, .release = llcp_sock_release, .socketpair = sock_no_socketpair, .accept = llcp_sock_accept, .getname = llcp_sock_getname, .poll = llcp_sock_poll, .ioctl = sock_no_ioctl, .listen = llcp_sock_listen, .shutdown = sock_no_shutdown, |
26fd76cab NFC: llcp: Implem... |
882 883 |
.setsockopt = nfc_llcp_setsockopt, .getsockopt = nfc_llcp_getsockopt, |
53a0ac2ee NFC: LLCP socket ... |
884 |
.sendmsg = llcp_sock_sendmsg, |
d646960f7 NFC: Initial LLCP... |
885 886 887 |
.recvmsg = llcp_sock_recvmsg, .mmap = sock_no_mmap, }; |
4463523be NFC: LLCP raw soc... |
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
static const struct proto_ops llcp_rawsock_ops = { .family = PF_NFC, .owner = THIS_MODULE, .bind = llcp_raw_sock_bind, .connect = sock_no_connect, .release = llcp_sock_release, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = llcp_sock_getname, .poll = llcp_sock_poll, .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = sock_no_sendmsg, .recvmsg = llcp_sock_recvmsg, .mmap = sock_no_mmap, }; |
d646960f7 NFC: Initial LLCP... |
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 |
static void llcp_sock_destruct(struct sock *sk) { struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); pr_debug("%p ", sk); if (sk->sk_state == LLCP_CONNECTED) nfc_put_device(llcp_sock->dev); skb_queue_purge(&sk->sk_receive_queue); nfc_llcp_sock_free(llcp_sock); if (!sock_flag(sk, SOCK_DEAD)) { pr_err("Freeing alive NFC LLCP socket %p ", sk); return; } } |
11aa9c28b net: Pass kern fr... |
927 |
struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp, int kern) |
d646960f7 NFC: Initial LLCP... |
928 929 930 |
{ struct sock *sk; struct nfc_llcp_sock *llcp_sock; |
11aa9c28b net: Pass kern fr... |
931 |
sk = sk_alloc(&init_net, PF_NFC, gfp, &llcp_sock_proto, kern); |
d646960f7 NFC: Initial LLCP... |
932 933 934 935 936 937 938 939 940 941 942 943 944 |
if (!sk) return NULL; llcp_sock = nfc_llcp_sock(sk); sock_init_data(sock, sk); sk->sk_state = LLCP_CLOSED; sk->sk_protocol = NFC_SOCKPROTO_LLCP; sk->sk_type = type; sk->sk_destruct = llcp_sock_destruct; llcp_sock->ssap = 0; llcp_sock->dsap = LLCP_SAP_SDP; |
06d44f806 NFC: llcp: Use so... |
945 |
llcp_sock->rw = LLCP_MAX_RW + 1; |
5eef66697 NFC: llcp: Socket... |
946 |
llcp_sock->miux = cpu_to_be16(LLCP_MAX_MIUX + 1); |
d646960f7 NFC: Initial LLCP... |
947 948 949 |
llcp_sock->send_n = llcp_sock->send_ack_n = 0; llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; llcp_sock->remote_ready = 1; |
cbbf47218 NFC: Release LLCP... |
950 |
llcp_sock->reserved_ssap = LLCP_SAP_MAX; |
abd18d433 NFC: llcp: Reset ... |
951 |
nfc_llcp_socket_remote_param_init(llcp_sock); |
d646960f7 NFC: Initial LLCP... |
952 953 |
skb_queue_head_init(&llcp_sock->tx_queue); skb_queue_head_init(&llcp_sock->tx_pending_queue); |
d646960f7 NFC: Initial LLCP... |
954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
INIT_LIST_HEAD(&llcp_sock->accept_queue); if (sock != NULL) sock->state = SS_UNCONNECTED; return sk; } void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) { kfree(sock->service_name); skb_queue_purge(&sock->tx_queue); skb_queue_purge(&sock->tx_pending_queue); |
d646960f7 NFC: Initial LLCP... |
968 969 |
list_del_init(&sock->accept_queue); |
40c75f81d NFC: Fix LLCP soc... |
970 |
|
d646960f7 NFC: Initial LLCP... |
971 |
sock->parent = NULL; |
c7aa12252 NFC: Take a refer... |
972 973 |
nfc_llcp_local_put(sock->local); |
d646960f7 NFC: Initial LLCP... |
974 975 976 |
} static int llcp_sock_create(struct net *net, struct socket *sock, |
11aa9c28b net: Pass kern fr... |
977 |
const struct nfc_protocol *nfc_proto, int kern) |
d646960f7 NFC: Initial LLCP... |
978 979 980 981 982 |
{ struct sock *sk; pr_debug("%p ", sock); |
4463523be NFC: LLCP raw soc... |
983 984 985 |
if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) |
d646960f7 NFC: Initial LLCP... |
986 |
return -ESOCKTNOSUPPORT; |
4463523be NFC: LLCP raw soc... |
987 988 989 990 |
if (sock->type == SOCK_RAW) sock->ops = &llcp_rawsock_ops; else sock->ops = &llcp_sock_ops; |
d646960f7 NFC: Initial LLCP... |
991 |
|
11aa9c28b net: Pass kern fr... |
992 |
sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC, kern); |
d646960f7 NFC: Initial LLCP... |
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 |
if (sk == NULL) return -ENOMEM; return 0; } static const struct nfc_protocol llcp_nfc_proto = { .id = NFC_SOCKPROTO_LLCP, .proto = &llcp_sock_proto, .owner = THIS_MODULE, .create = llcp_sock_create }; int __init nfc_llcp_sock_init(void) { return nfc_proto_register(&llcp_nfc_proto); } void nfc_llcp_sock_exit(void) { nfc_proto_unregister(&llcp_nfc_proto); } |