aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp/commands.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 21:07:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 21:07:07 -0500
commit6be35c700f742e911ecedd07fcc43d4439922334 (patch)
treeca9f37214d204465fcc2d79c82efd291e357c53c /net/nfc/llcp/commands.c
parente37aa63e87bd581f9be5555ed0ba83f5295c92fc (diff)
parent520dfe3a3645257bf83660f672c47f8558f3d4c4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: 1) Allow to dump, monitor, and change the bridge multicast database using netlink. From Cong Wang. 2) RFC 5961 TCP blind data injection attack mitigation, from Eric Dumazet. 3) Networking user namespace support from Eric W. Biederman. 4) tuntap/virtio-net multiqueue support by Jason Wang. 5) Support for checksum offload of encapsulated packets (basically, tunneled traffic can still be checksummed by HW). From Joseph Gasparakis. 6) Allow BPF filter access to VLAN tags, from Eric Dumazet and Daniel Borkmann. 7) Bridge port parameters over netlink and BPDU blocking support from Stephen Hemminger. 8) Improve data access patterns during inet socket demux by rearranging socket layout, from Eric Dumazet. 9) TIPC protocol updates and cleanups from Ying Xue, Paul Gortmaker, and Jon Maloy. 10) Update TCP socket hash sizing to be more in line with current day realities. The existing heurstics were choosen a decade ago. From Eric Dumazet. 11) Fix races, queue bloat, and excessive wakeups in ATM and associated drivers, from Krzysztof Mazur and David Woodhouse. 12) Support DOVE (Distributed Overlay Virtual Ethernet) extensions in VXLAN driver, from David Stevens. 13) Add "oops_only" mode to netconsole, from Amerigo Wang. 14) Support set and query of VEB/VEPA bridge mode via PF_BRIDGE, also allow DCB netlink to work on namespaces other than the initial namespace. From John Fastabend. 15) Support PTP in the Tigon3 driver, from Matt Carlson. 16) tun/vhost zero copy fixes and improvements, plus turn it on by default, from Michael S. Tsirkin. 17) Support per-association statistics in SCTP, from Michele Baldessari. And many, many, driver updates, cleanups, and improvements. Too numerous to mention individually. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1722 commits) net/mlx4_en: Add support for destination MAC in steering rules net/mlx4_en: Use generic etherdevice.h functions. net: ethtool: Add destination MAC address to flow steering API bridge: add support of adding and deleting mdb entries bridge: notify mdb changes via netlink ndisc: Unexport ndisc_{build,send}_skb(). uapi: add missing netconf.h to export list pkt_sched: avoid requeues if possible solos-pci: fix double-free of TX skb in DMA mode bnx2: Fix accidental reversions. bna: Driver Version Updated to 3.1.2.1 bna: Firmware update bna: Add RX State bna: Rx Page Based Allocation bna: TX Intr Coalescing Fix bna: Tx and Rx Optimizations bna: Code Cleanup and Enhancements ath9k: check pdata variable before dereferencing it ath5k: RX timestamp is reported at end of frame ath9k_htc: RX timestamp is reported at end of frame ...
Diffstat (limited to 'net/nfc/llcp/commands.c')
-rw-r--r--net/nfc/llcp/commands.c148
1 files changed, 127 insertions, 21 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index c45ccd6c094c..df24be48d4da 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -261,7 +261,6 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
261 struct sk_buff *skb; 261 struct sk_buff *skb;
262 struct nfc_dev *dev; 262 struct nfc_dev *dev;
263 struct nfc_llcp_local *local; 263 struct nfc_llcp_local *local;
264 u16 size = 0;
265 264
266 pr_debug("Sending DISC\n"); 265 pr_debug("Sending DISC\n");
267 266
@@ -273,17 +272,10 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
273 if (dev == NULL) 272 if (dev == NULL)
274 return -ENODEV; 273 return -ENODEV;
275 274
276 size += LLCP_HEADER_SIZE; 275 skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
277 size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
278
279 skb = alloc_skb(size, GFP_ATOMIC);
280 if (skb == NULL) 276 if (skb == NULL)
281 return -ENOMEM; 277 return -ENOMEM;
282 278
283 skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
284
285 skb = llcp_add_header(skb, sock->dsap, sock->ssap, LLCP_PDU_DISC);
286
287 skb_queue_tail(&local->tx_queue, skb); 279 skb_queue_tail(&local->tx_queue, skb);
288 280
289 return 0; 281 return 0;
@@ -324,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
324 struct sk_buff *skb; 316 struct sk_buff *skb;
325 u8 *service_name_tlv = NULL, service_name_tlv_length; 317 u8 *service_name_tlv = NULL, service_name_tlv_length;
326 u8 *miux_tlv = NULL, miux_tlv_length; 318 u8 *miux_tlv = NULL, miux_tlv_length;
327 u8 *rw_tlv = NULL, rw_tlv_length, rw; 319 u8 *rw_tlv = NULL, rw_tlv_length;
328 __be16 miux;
329 int err; 320 int err;
330 u16 size = 0; 321 u16 size = 0;
331 322
@@ -343,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
343 size += service_name_tlv_length; 334 size += service_name_tlv_length;
344 } 335 }
345 336
346 miux = cpu_to_be16(LLCP_MAX_MIUX); 337 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
347 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
348 &miux_tlv_length); 338 &miux_tlv_length);
349 size += miux_tlv_length; 339 size += miux_tlv_length;
350 340
351 rw = LLCP_MAX_RW; 341 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
352 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
353 size += rw_tlv_length; 342 size += rw_tlv_length;
354 343
355 pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); 344 pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
@@ -386,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
386 struct nfc_llcp_local *local; 375 struct nfc_llcp_local *local;
387 struct sk_buff *skb; 376 struct sk_buff *skb;
388 u8 *miux_tlv = NULL, miux_tlv_length; 377 u8 *miux_tlv = NULL, miux_tlv_length;
389 u8 *rw_tlv = NULL, rw_tlv_length, rw; 378 u8 *rw_tlv = NULL, rw_tlv_length;
390 __be16 miux;
391 int err; 379 int err;
392 u16 size = 0; 380 u16 size = 0;
393 381
@@ -397,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
397 if (local == NULL) 385 if (local == NULL)
398 return -ENODEV; 386 return -ENODEV;
399 387
400 miux = cpu_to_be16(LLCP_MAX_MIUX); 388 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
401 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
402 &miux_tlv_length); 389 &miux_tlv_length);
403 size += miux_tlv_length; 390 size += miux_tlv_length;
404 391
405 rw = LLCP_MAX_RW; 392 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
406 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
407 size += rw_tlv_length; 393 size += rw_tlv_length;
408 394
409 skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); 395 skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
@@ -428,6 +414,52 @@ error_tlv:
428 return err; 414 return err;
429} 415}
430 416
417int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap)
418{
419 struct sk_buff *skb;
420 struct nfc_dev *dev;
421 u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2];
422 u16 size = 0;
423
424 pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap);
425
426 if (local == NULL)
427 return -ENODEV;
428
429 dev = local->dev;
430 if (dev == NULL)
431 return -ENODEV;
432
433 sdres[0] = tid;
434 sdres[1] = sap;
435 sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0,
436 &sdres_tlv_length);
437 if (sdres_tlv == NULL)
438 return -ENOMEM;
439
440 size += LLCP_HEADER_SIZE;
441 size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
442 size += sdres_tlv_length;
443
444 skb = alloc_skb(size, GFP_KERNEL);
445 if (skb == NULL) {
446 kfree(sdres_tlv);
447 return -ENOMEM;
448 }
449
450 skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
451
452 skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);
453
454 memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length);
455
456 skb_queue_tail(&local->tx_queue, skb);
457
458 kfree(sdres_tlv);
459
460 return 0;
461}
462
431int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) 463int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
432{ 464{
433 struct sk_buff *skb; 465 struct sk_buff *skb;
@@ -496,6 +528,23 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
496 if (local == NULL) 528 if (local == NULL)
497 return -ENODEV; 529 return -ENODEV;
498 530
531 /* Remote is ready but has not acknowledged our frames */
532 if((sock->remote_ready &&
533 skb_queue_len(&sock->tx_pending_queue) >= sock->rw &&
534 skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
535 pr_err("Pending queue is full %d frames\n",
536 skb_queue_len(&sock->tx_pending_queue));
537 return -ENOBUFS;
538 }
539
540 /* Remote is not ready and we've been queueing enough frames */
541 if ((!sock->remote_ready &&
542 skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
543 pr_err("Tx queue is full %d frames\n",
544 skb_queue_len(&sock->tx_queue));
545 return -ENOBUFS;
546 }
547
499 msg_data = kzalloc(len, GFP_KERNEL); 548 msg_data = kzalloc(len, GFP_KERNEL);
500 if (msg_data == NULL) 549 if (msg_data == NULL)
501 return -ENOMEM; 550 return -ENOMEM;
@@ -541,6 +590,63 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
541 return len; 590 return len;
542} 591}
543 592
593int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
594 struct msghdr *msg, size_t len)
595{
596 struct sk_buff *pdu;
597 struct nfc_llcp_local *local;
598 size_t frag_len = 0, remaining_len;
599 u8 *msg_ptr, *msg_data;
600 int err;
601
602 pr_debug("Send UI frame len %zd\n", len);
603
604 local = sock->local;
605 if (local == NULL)
606 return -ENODEV;
607
608 msg_data = kzalloc(len, GFP_KERNEL);
609 if (msg_data == NULL)
610 return -ENOMEM;
611
612 if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
613 kfree(msg_data);
614 return -EFAULT;
615 }
616
617 remaining_len = len;
618 msg_ptr = msg_data;
619
620 while (remaining_len > 0) {
621
622 frag_len = min_t(size_t, sock->miu, remaining_len);
623
624 pr_debug("Fragment %zd bytes remaining %zd",
625 frag_len, remaining_len);
626
627 pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
628 frag_len + LLCP_HEADER_SIZE, &err);
629 if (pdu == NULL) {
630 pr_err("Could not allocate PDU\n");
631 continue;
632 }
633
634 pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
635
636 memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
637
638 /* No need to check for the peer RW for UI frames */
639 skb_queue_tail(&local->tx_queue, pdu);
640
641 remaining_len -= frag_len;
642 msg_ptr += frag_len;
643 }
644
645 kfree(msg_data);
646
647 return len;
648}
649
544int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) 650int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
545{ 651{
546 struct sk_buff *skb; 652 struct sk_buff *skb;