linux/net/nfc/llcp/commands.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011  Intel Corporation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the
  16 * Free Software Foundation, Inc.,
  17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18 */
  19
  20#define pr_fmt(fmt) "llcp: %s: " fmt, __func__
  21
  22#include <linux/init.h>
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/nfc.h>
  26
  27#include <net/nfc/nfc.h>
  28
  29#include "../nfc.h"
  30#include "llcp.h"
  31
  32static u8 llcp_tlv_length[LLCP_TLV_MAX] = {
  33        0,
  34        1, /* VERSION */
  35        2, /* MIUX */
  36        2, /* WKS */
  37        1, /* LTO */
  38        1, /* RW */
  39        0, /* SN */
  40        1, /* OPT */
  41        0, /* SDREQ */
  42        2, /* SDRES */
  43
  44};
  45
  46static u8 llcp_tlv8(u8 *tlv, u8 type)
  47{
  48        if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
  49                return 0;
  50
  51        return tlv[2];
  52}
  53
  54static u16 llcp_tlv16(u8 *tlv, u8 type)
  55{
  56        if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
  57                return 0;
  58
  59        return be16_to_cpu(*((__be16 *)(tlv + 2)));
  60}
  61
  62
  63static u8 llcp_tlv_version(u8 *tlv)
  64{
  65        return llcp_tlv8(tlv, LLCP_TLV_VERSION);
  66}
  67
  68static u16 llcp_tlv_miux(u8 *tlv)
  69{
  70        return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff;
  71}
  72
  73static u16 llcp_tlv_wks(u8 *tlv)
  74{
  75        return llcp_tlv16(tlv, LLCP_TLV_WKS);
  76}
  77
  78static u16 llcp_tlv_lto(u8 *tlv)
  79{
  80        return llcp_tlv8(tlv, LLCP_TLV_LTO);
  81}
  82
  83static u8 llcp_tlv_opt(u8 *tlv)
  84{
  85        return llcp_tlv8(tlv, LLCP_TLV_OPT);
  86}
  87
  88static u8 llcp_tlv_rw(u8 *tlv)
  89{
  90        return llcp_tlv8(tlv, LLCP_TLV_RW) & 0xf;
  91}
  92
  93u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
  94{
  95        u8 *tlv, length;
  96
  97        pr_debug("type %d\n", type);
  98
  99        if (type >= LLCP_TLV_MAX)
 100                return NULL;
 101
 102        length = llcp_tlv_length[type];
 103        if (length == 0 && value_length == 0)
 104                return NULL;
 105        else if (length == 0)
 106                length = value_length;
 107
 108        *tlv_length = 2 + length;
 109        tlv = kzalloc(2 + length, GFP_KERNEL);
 110        if (tlv == NULL)
 111                return tlv;
 112
 113        tlv[0] = type;
 114        tlv[1] = length;
 115        memcpy(tlv + 2, value, length);
 116
 117        return tlv;
 118}
 119
 120int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
 121                          u8 *tlv_array, u16 tlv_array_len)
 122{
 123        u8 *tlv = tlv_array, type, length, offset = 0;
 124
 125        pr_debug("TLV array length %d\n", tlv_array_len);
 126
 127        if (local == NULL)
 128                return -ENODEV;
 129
 130        while (offset < tlv_array_len) {
 131                type = tlv[0];
 132                length = tlv[1];
 133
 134                pr_debug("type 0x%x length %d\n", type, length);
 135
 136                switch (type) {
 137                case LLCP_TLV_VERSION:
 138                        local->remote_version = llcp_tlv_version(tlv);
 139                        break;
 140                case LLCP_TLV_MIUX:
 141                        local->remote_miu = llcp_tlv_miux(tlv) + 128;
 142                        break;
 143                case LLCP_TLV_WKS:
 144                        local->remote_wks = llcp_tlv_wks(tlv);
 145                        break;
 146                case LLCP_TLV_LTO:
 147                        local->remote_lto = llcp_tlv_lto(tlv) * 10;
 148                        break;
 149                case LLCP_TLV_OPT:
 150                        local->remote_opt = llcp_tlv_opt(tlv);
 151                        break;
 152                default:
 153                        pr_err("Invalid gt tlv value 0x%x\n", type);
 154                        break;
 155                }
 156
 157                offset += length + 2;
 158                tlv += length + 2;
 159        }
 160
 161        pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n",
 162                 local->remote_version, local->remote_miu,
 163                 local->remote_lto, local->remote_opt,
 164                 local->remote_wks);
 165
 166        return 0;
 167}
 168
 169int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 170                                  u8 *tlv_array, u16 tlv_array_len)
 171{
 172        u8 *tlv = tlv_array, type, length, offset = 0;
 173
 174        pr_debug("TLV array length %d\n", tlv_array_len);
 175
 176        if (sock == NULL)
 177                return -ENOTCONN;
 178
 179        while (offset < tlv_array_len) {
 180                type = tlv[0];
 181                length = tlv[1];
 182
 183                pr_debug("type 0x%x length %d\n", type, length);
 184
 185                switch (type) {
 186                case LLCP_TLV_MIUX:
 187                        sock->miu = llcp_tlv_miux(tlv) + 128;
 188                        break;
 189                case LLCP_TLV_RW:
 190                        sock->rw = llcp_tlv_rw(tlv);
 191                        break;
 192                case LLCP_TLV_SN:
 193                        break;
 194                default:
 195                        pr_err("Invalid gt tlv value 0x%x\n", type);
 196                        break;
 197                }
 198
 199                offset += length + 2;
 200                tlv += length + 2;
 201        }
 202
 203        pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu);
 204
 205        return 0;
 206}
 207
 208static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
 209                                       u8 dsap, u8 ssap, u8 ptype)
 210{
 211        u8 header[2];
 212
 213        pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap);
 214
 215        header[0] = (u8)((dsap << 2) | (ptype >> 2));
 216        header[1] = (u8)((ptype << 6) | ssap);
 217
 218        pr_debug("header 0x%x 0x%x\n", header[0], header[1]);
 219
 220        memcpy(skb_put(pdu, LLCP_HEADER_SIZE), header, LLCP_HEADER_SIZE);
 221
 222        return pdu;
 223}
 224
 225static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv,
 226                                    u8 tlv_length)
 227{
 228        /* XXX Add an skb length check */
 229
 230        if (tlv == NULL)
 231                return NULL;
 232
 233        memcpy(skb_put(pdu, tlv_length), tlv, tlv_length);
 234
 235        return pdu;
 236}
 237
 238static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
 239                                         u8 cmd, u16 size)
 240{
 241        struct sk_buff *skb;
 242        int err;
 243
 244        if (sock->ssap == 0)
 245                return NULL;
 246
 247        skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
 248                                 size + LLCP_HEADER_SIZE, &err);
 249        if (skb == NULL) {
 250                pr_err("Could not allocate PDU\n");
 251                return NULL;
 252        }
 253
 254        skb = llcp_add_header(skb, sock->dsap, sock->ssap, cmd);
 255
 256        return skb;
 257}
 258
 259int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
 260{
 261        struct sk_buff *skb;
 262        struct nfc_dev *dev;
 263        struct nfc_llcp_local *local;
 264
 265        pr_debug("Sending DISC\n");
 266
 267        local = sock->local;
 268        if (local == NULL)
 269                return -ENODEV;
 270
 271        dev = sock->dev;
 272        if (dev == NULL)
 273                return -ENODEV;
 274
 275        skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
 276        if (skb == NULL)
 277                return -ENOMEM;
 278
 279        skb_queue_tail(&local->tx_queue, skb);
 280
 281        return 0;
 282}
 283
 284int nfc_llcp_send_symm(struct nfc_dev *dev)
 285{
 286        struct sk_buff *skb;
 287        struct nfc_llcp_local *local;
 288        u16 size = 0;
 289
 290        pr_debug("Sending SYMM\n");
 291
 292        local = nfc_llcp_find_local(dev);
 293        if (local == NULL)
 294                return -ENODEV;
 295
 296        size += LLCP_HEADER_SIZE;
 297        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 298
 299        skb = alloc_skb(size, GFP_KERNEL);
 300        if (skb == NULL)
 301                return -ENOMEM;
 302
 303        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 304
 305        skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
 306
 307        __net_timestamp(skb);
 308
 309        nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX);
 310
 311        return nfc_data_exchange(dev, local->target_idx, skb,
 312                                 nfc_llcp_recv, local);
 313}
 314
 315int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 316{
 317        struct nfc_llcp_local *local;
 318        struct sk_buff *skb;
 319        u8 *service_name_tlv = NULL, service_name_tlv_length;
 320        u8 *miux_tlv = NULL, miux_tlv_length;
 321        u8 *rw_tlv = NULL, rw_tlv_length;
 322        int err;
 323        u16 size = 0;
 324
 325        pr_debug("Sending CONNECT\n");
 326
 327        local = sock->local;
 328        if (local == NULL)
 329                return -ENODEV;
 330
 331        if (sock->service_name != NULL) {
 332                service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN,
 333                                                      sock->service_name,
 334                                                      sock->service_name_len,
 335                                                      &service_name_tlv_length);
 336                size += service_name_tlv_length;
 337        }
 338
 339        miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
 340                                      &miux_tlv_length);
 341        size += miux_tlv_length;
 342
 343        rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
 344        size += rw_tlv_length;
 345
 346        pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
 347
 348        skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size);
 349        if (skb == NULL) {
 350                err = -ENOMEM;
 351                goto error_tlv;
 352        }
 353
 354        if (service_name_tlv != NULL)
 355                skb = llcp_add_tlv(skb, service_name_tlv,
 356                                   service_name_tlv_length);
 357
 358        skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
 359        skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 360
 361        skb_queue_tail(&local->tx_queue, skb);
 362
 363        return 0;
 364
 365error_tlv:
 366        pr_err("error %d\n", err);
 367
 368        kfree(service_name_tlv);
 369        kfree(miux_tlv);
 370        kfree(rw_tlv);
 371
 372        return err;
 373}
 374
 375int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
 376{
 377        struct nfc_llcp_local *local;
 378        struct sk_buff *skb;
 379        u8 *miux_tlv = NULL, miux_tlv_length;
 380        u8 *rw_tlv = NULL, rw_tlv_length;
 381        int err;
 382        u16 size = 0;
 383
 384        pr_debug("Sending CC\n");
 385
 386        local = sock->local;
 387        if (local == NULL)
 388                return -ENODEV;
 389
 390        miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
 391                                      &miux_tlv_length);
 392        size += miux_tlv_length;
 393
 394        rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
 395        size += rw_tlv_length;
 396
 397        skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
 398        if (skb == NULL) {
 399                err = -ENOMEM;
 400                goto error_tlv;
 401        }
 402
 403        skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
 404        skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 405
 406        skb_queue_tail(&local->tx_queue, skb);
 407
 408        return 0;
 409
 410error_tlv:
 411        pr_err("error %d\n", err);
 412
 413        kfree(miux_tlv);
 414        kfree(rw_tlv);
 415
 416        return err;
 417}
 418
 419int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap)
 420{
 421        struct sk_buff *skb;
 422        struct nfc_dev *dev;
 423        u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2];
 424        u16 size = 0;
 425
 426        pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap);
 427
 428        if (local == NULL)
 429                return -ENODEV;
 430
 431        dev = local->dev;
 432        if (dev == NULL)
 433                return -ENODEV;
 434
 435        sdres[0] = tid;
 436        sdres[1] = sap;
 437        sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0,
 438                                       &sdres_tlv_length);
 439        if (sdres_tlv == NULL)
 440                return -ENOMEM;
 441
 442        size += LLCP_HEADER_SIZE;
 443        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 444        size += sdres_tlv_length;
 445
 446        skb = alloc_skb(size, GFP_KERNEL);
 447        if (skb == NULL) {
 448                kfree(sdres_tlv);
 449                return -ENOMEM;
 450        }
 451
 452        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 453
 454        skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);
 455
 456        memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length);
 457
 458        skb_queue_tail(&local->tx_queue, skb);
 459
 460        kfree(sdres_tlv);
 461
 462        return 0;
 463}
 464
 465int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
 466{
 467        struct sk_buff *skb;
 468        struct nfc_dev *dev;
 469        u16 size = 1; /* Reason code */
 470
 471        pr_debug("Sending DM reason 0x%x\n", reason);
 472
 473        if (local == NULL)
 474                return -ENODEV;
 475
 476        dev = local->dev;
 477        if (dev == NULL)
 478                return -ENODEV;
 479
 480        size += LLCP_HEADER_SIZE;
 481        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 482
 483        skb = alloc_skb(size, GFP_KERNEL);
 484        if (skb == NULL)
 485                return -ENOMEM;
 486
 487        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 488
 489        skb = llcp_add_header(skb, dsap, ssap, LLCP_PDU_DM);
 490
 491        memcpy(skb_put(skb, 1), &reason, 1);
 492
 493        skb_queue_head(&local->tx_queue, skb);
 494
 495        return 0;
 496}
 497
 498int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock)
 499{
 500        struct sk_buff *skb;
 501        struct nfc_llcp_local *local;
 502
 503        pr_debug("Send DISC\n");
 504
 505        local = sock->local;
 506        if (local == NULL)
 507                return -ENODEV;
 508
 509        skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
 510        if (skb == NULL)
 511                return -ENOMEM;
 512
 513        skb_queue_head(&local->tx_queue, skb);
 514
 515        return 0;
 516}
 517
 518int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 519                          struct msghdr *msg, size_t len)
 520{
 521        struct sk_buff *pdu;
 522        struct sock *sk = &sock->sk;
 523        struct nfc_llcp_local *local;
 524        size_t frag_len = 0, remaining_len;
 525        u8 *msg_data, *msg_ptr;
 526
 527        pr_debug("Send I frame len %zd\n", len);
 528
 529        local = sock->local;
 530        if (local == NULL)
 531                return -ENODEV;
 532
 533        /* Remote is ready but has not acknowledged our frames */
 534        if((sock->remote_ready &&
 535            skb_queue_len(&sock->tx_pending_queue) >= sock->rw &&
 536            skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
 537                pr_err("Pending queue is full %d frames\n",
 538                       skb_queue_len(&sock->tx_pending_queue));
 539                return -ENOBUFS;
 540        }
 541
 542        /* Remote is not ready and we've been queueing enough frames */
 543        if ((!sock->remote_ready &&
 544             skb_queue_len(&sock->tx_queue) >= 2 * sock->rw)) {
 545                pr_err("Tx queue is full %d frames\n",
 546                       skb_queue_len(&sock->tx_queue));
 547                return -ENOBUFS;
 548        }
 549
 550        msg_data = kzalloc(len, GFP_KERNEL);
 551        if (msg_data == NULL)
 552                return -ENOMEM;
 553
 554        if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 555                kfree(msg_data);
 556                return -EFAULT;
 557        }
 558
 559        remaining_len = len;
 560        msg_ptr = msg_data;
 561
 562        while (remaining_len > 0) {
 563
 564                frag_len = min_t(size_t, sock->miu, remaining_len);
 565
 566                pr_debug("Fragment %zd bytes remaining %zd",
 567                         frag_len, remaining_len);
 568
 569                pdu = llcp_allocate_pdu(sock, LLCP_PDU_I,
 570                                        frag_len + LLCP_SEQUENCE_SIZE);
 571                if (pdu == NULL)
 572                        return -ENOMEM;
 573
 574                skb_put(pdu, LLCP_SEQUENCE_SIZE);
 575
 576                memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
 577
 578                skb_queue_tail(&sock->tx_queue, pdu);
 579
 580                lock_sock(sk);
 581
 582                nfc_llcp_queue_i_frames(sock);
 583
 584                release_sock(sk);
 585
 586                remaining_len -= frag_len;
 587                msg_ptr += frag_len;
 588        }
 589
 590        kfree(msg_data);
 591
 592        return len;
 593}
 594
 595int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
 596                           struct msghdr *msg, size_t len)
 597{
 598        struct sk_buff *pdu;
 599        struct nfc_llcp_local *local;
 600        size_t frag_len = 0, remaining_len;
 601        u8 *msg_ptr, *msg_data;
 602        int err;
 603
 604        pr_debug("Send UI frame len %zd\n", len);
 605
 606        local = sock->local;
 607        if (local == NULL)
 608                return -ENODEV;
 609
 610        msg_data = kzalloc(len, GFP_KERNEL);
 611        if (msg_data == NULL)
 612                return -ENOMEM;
 613
 614        if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 615                kfree(msg_data);
 616                return -EFAULT;
 617        }
 618
 619        remaining_len = len;
 620        msg_ptr = msg_data;
 621
 622        while (remaining_len > 0) {
 623
 624                frag_len = min_t(size_t, sock->miu, remaining_len);
 625
 626                pr_debug("Fragment %zd bytes remaining %zd",
 627                         frag_len, remaining_len);
 628
 629                pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
 630                                         frag_len + LLCP_HEADER_SIZE, &err);
 631                if (pdu == NULL) {
 632                        pr_err("Could not allocate PDU\n");
 633                        continue;
 634                }
 635
 636                pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
 637
 638                memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
 639
 640                /* No need to check for the peer RW for UI frames */
 641                skb_queue_tail(&local->tx_queue, pdu);
 642
 643                remaining_len -= frag_len;
 644                msg_ptr += frag_len;
 645        }
 646
 647        kfree(msg_data);
 648
 649        return len;
 650}
 651
 652int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
 653{
 654        struct sk_buff *skb;
 655        struct nfc_llcp_local *local;
 656
 657        pr_debug("Send rr nr %d\n", sock->recv_n);
 658
 659        local = sock->local;
 660        if (local == NULL)
 661                return -ENODEV;
 662
 663        skb = llcp_allocate_pdu(sock, LLCP_PDU_RR, LLCP_SEQUENCE_SIZE);
 664        if (skb == NULL)
 665                return -ENOMEM;
 666
 667        skb_put(skb, LLCP_SEQUENCE_SIZE);
 668
 669        skb->data[2] = sock->recv_n;
 670
 671        skb_queue_head(&local->tx_queue, skb);
 672
 673        return 0;
 674}
 675