aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2013-08-27 18:47:24 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-24 20:35:05 -0400
commit5ce3f32b5264b337bfd13a780452a17705307725 (patch)
tree18dd3052e8d658c5e5682c695056890a382c564d /net/nfc
parent72b70b6ec4fa7da86a3ac0aacee699b18d94fc3b (diff)
NFC: netlink: SE API implementation
Implementation of the NFC_CMD_SE_IO command for sending ISO7816 APDUs to NFC embedded secure elements. The reply is forwarded to user space through NFC_CMD_SE_IO as well. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/netlink.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 68063b2025da..a3dee05cb64b 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -58,6 +58,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
58 [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, 58 [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED },
59 [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, 59 [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING,
60 .len = NFC_FIRMWARE_NAME_MAXSIZE }, 60 .len = NFC_FIRMWARE_NAME_MAXSIZE },
61 [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY },
61}; 62};
62 63
63static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { 64static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = {
@@ -1278,6 +1279,91 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
1278 return 0; 1279 return 0;
1279} 1280}
1280 1281
1282struct se_io_ctx {
1283 u32 dev_idx;
1284 u32 se_idx;
1285};
1286
1287void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err)
1288{
1289 struct se_io_ctx *ctx = context;
1290 struct sk_buff *msg;
1291 void *hdr;
1292
1293 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1294 if (!msg) {
1295 kfree(ctx);
1296 return;
1297 }
1298
1299 hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
1300 NFC_CMD_SE_IO);
1301 if (!hdr)
1302 goto free_msg;
1303
1304 if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, ctx->dev_idx) ||
1305 nla_put_u32(msg, NFC_ATTR_SE_INDEX, ctx->se_idx) ||
1306 nla_put(msg, NFC_ATTR_SE_APDU, apdu_len, apdu))
1307 goto nla_put_failure;
1308
1309 genlmsg_end(msg, hdr);
1310
1311 genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
1312
1313 kfree(ctx);
1314
1315 return;
1316
1317nla_put_failure:
1318 genlmsg_cancel(msg, hdr);
1319free_msg:
1320 nlmsg_free(msg);
1321 kfree(ctx);
1322
1323 return;
1324}
1325
1326static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info)
1327{
1328 struct nfc_dev *dev;
1329 struct se_io_ctx *ctx;
1330 u32 dev_idx, se_idx;
1331 u8 *apdu;
1332 size_t apdu_len;
1333
1334 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
1335 !info->attrs[NFC_ATTR_SE_INDEX] ||
1336 !info->attrs[NFC_ATTR_SE_APDU])
1337 return -EINVAL;
1338
1339 dev_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
1340 se_idx = nla_get_u32(info->attrs[NFC_ATTR_SE_INDEX]);
1341
1342 dev = nfc_get_device(dev_idx);
1343 if (!dev)
1344 return -ENODEV;
1345
1346 if (!dev->ops || !dev->ops->se_io)
1347 return -ENOTSUPP;
1348
1349 apdu_len = nla_len(info->attrs[NFC_ATTR_SE_APDU]);
1350 if (apdu_len == 0)
1351 return -EINVAL;
1352
1353 apdu = nla_data(info->attrs[NFC_ATTR_SE_APDU]);
1354 if (!apdu)
1355 return -EINVAL;
1356
1357 ctx = kzalloc(sizeof(struct se_io_ctx), GFP_KERNEL);
1358 if (!ctx)
1359 return -ENOMEM;
1360
1361 ctx->dev_idx = dev_idx;
1362 ctx->se_idx = se_idx;
1363
1364 return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
1365}
1366
1281static struct genl_ops nfc_genl_ops[] = { 1367static struct genl_ops nfc_genl_ops[] = {
1282 { 1368 {
1283 .cmd = NFC_CMD_GET_DEVICE, 1369 .cmd = NFC_CMD_GET_DEVICE,
@@ -1358,6 +1444,11 @@ static struct genl_ops nfc_genl_ops[] = {
1358 .done = nfc_genl_dump_ses_done, 1444 .done = nfc_genl_dump_ses_done,
1359 .policy = nfc_genl_policy, 1445 .policy = nfc_genl_policy,
1360 }, 1446 },
1447 {
1448 .cmd = NFC_CMD_SE_IO,
1449 .doit = nfc_genl_se_io,
1450 .policy = nfc_genl_policy,
1451 },
1361}; 1452};
1362 1453
1363 1454