aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r--net/nfc/netlink.c175
1 files changed, 173 insertions, 2 deletions
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 504b883439f1..f0c4d61f37c0 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -28,8 +28,7 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29 29
30#include "nfc.h" 30#include "nfc.h"
31 31#include "llcp.h"
32#include "llcp/llcp.h"
33 32
34static struct genl_multicast_group nfc_genl_event_mcgrp = { 33static struct genl_multicast_group nfc_genl_event_mcgrp = {
35 .name = NFC_GENL_MCAST_EVENT_NAME, 34 .name = NFC_GENL_MCAST_EVENT_NAME,
@@ -53,6 +52,15 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
53 [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, 52 [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
54 [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, 53 [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 },
55 [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, 54 [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 },
55 [NFC_ATTR_LLC_PARAM_LTO] = { .type = NLA_U8 },
56 [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 },
57 [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 },
58 [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED },
59};
60
61static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = {
62 [NFC_SDP_ATTR_URI] = { .type = NLA_STRING },
63 [NFC_SDP_ATTR_SAP] = { .type = NLA_U8 },
56}; 64};
57 65
58static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, 66static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
@@ -348,6 +356,74 @@ free_msg:
348 return -EMSGSIZE; 356 return -EMSGSIZE;
349} 357}
350 358
359int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list)
360{
361 struct sk_buff *msg;
362 struct nlattr *sdp_attr, *uri_attr;
363 struct nfc_llcp_sdp_tlv *sdres;
364 struct hlist_node *n;
365 void *hdr;
366 int rc = -EMSGSIZE;
367 int i;
368
369 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
370 if (!msg)
371 return -ENOMEM;
372
373 hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
374 NFC_EVENT_LLC_SDRES);
375 if (!hdr)
376 goto free_msg;
377
378 if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
379 goto nla_put_failure;
380
381 sdp_attr = nla_nest_start(msg, NFC_ATTR_LLC_SDP);
382 if (sdp_attr == NULL) {
383 rc = -ENOMEM;
384 goto nla_put_failure;
385 }
386
387 i = 1;
388 hlist_for_each_entry_safe(sdres, n, sdres_list, node) {
389 pr_debug("uri: %s, sap: %d\n", sdres->uri, sdres->sap);
390
391 uri_attr = nla_nest_start(msg, i++);
392 if (uri_attr == NULL) {
393 rc = -ENOMEM;
394 goto nla_put_failure;
395 }
396
397 if (nla_put_u8(msg, NFC_SDP_ATTR_SAP, sdres->sap))
398 goto nla_put_failure;
399
400 if (nla_put_string(msg, NFC_SDP_ATTR_URI, sdres->uri))
401 goto nla_put_failure;
402
403 nla_nest_end(msg, uri_attr);
404
405 hlist_del(&sdres->node);
406
407 nfc_llcp_free_sdp_tlv(sdres);
408 }
409
410 nla_nest_end(msg, sdp_attr);
411
412 genlmsg_end(msg, hdr);
413
414 return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
415
416nla_put_failure:
417 genlmsg_cancel(msg, hdr);
418
419free_msg:
420 nlmsg_free(msg);
421
422 nfc_llcp_free_sdp_tlv_list(sdres_list);
423
424 return rc;
425}
426
351static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, 427static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
352 u32 portid, u32 seq, 428 u32 portid, u32 seq,
353 struct netlink_callback *cb, 429 struct netlink_callback *cb,
@@ -859,6 +935,96 @@ exit:
859 return rc; 935 return rc;
860} 936}
861 937
938static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
939{
940 struct nfc_dev *dev;
941 struct nfc_llcp_local *local;
942 struct nlattr *attr, *sdp_attrs[NFC_SDP_ATTR_MAX+1];
943 u32 idx;
944 u8 tid;
945 char *uri;
946 int rc = 0, rem;
947 size_t uri_len, tlvs_len;
948 struct hlist_head sdreq_list;
949 struct nfc_llcp_sdp_tlv *sdreq;
950
951 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
952 !info->attrs[NFC_ATTR_LLC_SDP])
953 return -EINVAL;
954
955 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
956
957 dev = nfc_get_device(idx);
958 if (!dev) {
959 rc = -ENODEV;
960 goto exit;
961 }
962
963 device_lock(&dev->dev);
964
965 if (dev->dep_link_up == false) {
966 rc = -ENOLINK;
967 goto exit;
968 }
969
970 local = nfc_llcp_find_local(dev);
971 if (!local) {
972 nfc_put_device(dev);
973 rc = -ENODEV;
974 goto exit;
975 }
976
977 INIT_HLIST_HEAD(&sdreq_list);
978
979 tlvs_len = 0;
980
981 nla_for_each_nested(attr, info->attrs[NFC_ATTR_LLC_SDP], rem) {
982 rc = nla_parse_nested(sdp_attrs, NFC_SDP_ATTR_MAX, attr,
983 nfc_sdp_genl_policy);
984
985 if (rc != 0) {
986 rc = -EINVAL;
987 goto exit;
988 }
989
990 if (!sdp_attrs[NFC_SDP_ATTR_URI])
991 continue;
992
993 uri_len = nla_len(sdp_attrs[NFC_SDP_ATTR_URI]);
994 if (uri_len == 0)
995 continue;
996
997 uri = nla_data(sdp_attrs[NFC_SDP_ATTR_URI]);
998 if (uri == NULL || *uri == 0)
999 continue;
1000
1001 tid = local->sdreq_next_tid++;
1002
1003 sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
1004 if (sdreq == NULL) {
1005 rc = -ENOMEM;
1006 goto exit;
1007 }
1008
1009 tlvs_len += sdreq->tlv_len;
1010
1011 hlist_add_head(&sdreq->node, &sdreq_list);
1012 }
1013
1014 if (hlist_empty(&sdreq_list)) {
1015 rc = -EINVAL;
1016 goto exit;
1017 }
1018
1019 rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
1020exit:
1021 device_unlock(&dev->dev);
1022
1023 nfc_put_device(dev);
1024
1025 return rc;
1026}
1027
862static struct genl_ops nfc_genl_ops[] = { 1028static struct genl_ops nfc_genl_ops[] = {
863 { 1029 {
864 .cmd = NFC_CMD_GET_DEVICE, 1030 .cmd = NFC_CMD_GET_DEVICE,
@@ -913,6 +1079,11 @@ static struct genl_ops nfc_genl_ops[] = {
913 .doit = nfc_genl_llc_set_params, 1079 .doit = nfc_genl_llc_set_params,
914 .policy = nfc_genl_policy, 1080 .policy = nfc_genl_policy,
915 }, 1081 },
1082 {
1083 .cmd = NFC_CMD_LLC_SDREQ,
1084 .doit = nfc_genl_llc_sdreq,
1085 .policy = nfc_genl_policy,
1086 },
916}; 1087};
917 1088
918 1089