[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <560BF5C6.9090506@osg.samsung.com>
Date: Wed, 30 Sep 2015 16:46:30 +0200
From: Stefan Schmidt <stefan@....samsung.com>
To: Alexander Aring <alex.aring@...il.com>, linux-wpan@...r.kernel.org
Cc: kernel@...gutronix.de, netdev@...r.kernel.org,
phoebe.buckheister@...m.fraunhofer.de
Subject: Re: [PATCH wpan-tools 1/2] security: add nl802154 security support
Hello.
A really huge patch. I will start on it. Not sure I can do a full review
in one go though.
On 28/09/15 09:25, Alexander Aring wrote:
> This patch introduce support for the experimental seucirty support for
Type. Security.
> nl802154. We currently support add/del settings for manipulating
> security table entries. The dump functionality is a "really" keep it
is really a
> short and stupid handling, the dump will printout the printout the right
dump will printout the right calls to add the entry
> add calls which was called to add the entry. This can be used for
> storing the current security tables by some script. The interface
> argument is replaced by $WPAN_DEV variable, so it's possible to move one
> interface configuration to another one.
>
> Signed-off-by: Alexander Aring <alex.aring@...il.com>
> ---
> src/Makefile.am | 1 +
> src/interface.c | 100 +++++
> src/nl802154.h | 191 ++++++++++
> src/security.c | 1118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 1410 insertions(+)
> create mode 100644 src/security.c
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 2d54576..b2177a2 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -9,6 +9,7 @@ iwpan_SOURCES = \
> interface.c \
> phy.c \
> mac.c \
> + security.c \
> nl_extras.h \
> nl802154.h
>
> diff --git a/src/interface.c b/src/interface.c
> index 85d40a8..076e7c3 100644
> --- a/src/interface.c
> +++ b/src/interface.c
> @@ -10,6 +10,7 @@
> #include <netlink/msg.h>
> #include <netlink/attr.h>
>
> +#define CONFIG_IEEE802154_NL802154_EXPERIMENTAL
> #include "nl802154.h"
> #include "nl_extras.h"
> #include "iwpan.h"
> @@ -226,6 +227,105 @@ static int print_iface_handler(struct nl_msg *msg, void *arg)
> if (tb_msg[NL802154_ATTR_ACKREQ_DEFAULT])
> printf("%s\tackreq_default %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_ACKREQ_DEFAULT]));
>
> + if (tb_msg[NL802154_ATTR_SEC_ENABLED])
> + printf("%s\tsecurity %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_SEC_ENABLED]));
> + if (tb_msg[NL802154_ATTR_SEC_OUT_LEVEL])
> + printf("%s\tout_level %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_SEC_OUT_LEVEL]));
> + if (tb_msg[NL802154_ATTR_SEC_OUT_KEY_ID]) {
> + struct nlattr *tb_key_id[NL802154_KEY_ID_ATTR_MAX + 1];
> + static struct nla_policy key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
> + [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
> + [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
> + [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
> + [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
> + [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
> + };
> +
> + nla_parse_nested(tb_key_id, NL802154_KEY_ID_ATTR_MAX,
> + tb_msg[NL802154_ATTR_SEC_OUT_KEY_ID], key_id_policy);
> + printf("%s\tout_key_id\n", indent);
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_MODE]) {
> + enum nl802154_key_id_modes key_id_mode;
> +
> + key_id_mode = nla_get_u32(tb_key_id[NL802154_KEY_ID_ATTR_MODE]);
> + switch (key_id_mode) {
> + case NL802154_KEY_ID_MODE_IMPLICIT:
> + printf("%s\t\tmode implicit\n", indent);
> + if (tb_key_id[NL802154_KEY_ID_ATTR_IMPLICIT]) {
> + struct nlattr *tb_dev_addr[NL802154_DEV_ADDR_ATTR_MAX + 1];
> + static struct nla_policy dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
> + [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
> + [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
> + [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
> + [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
> + };
> +
> + nla_parse_nested(tb_dev_addr, NL802154_DEV_ADDR_ATTR_MAX,
> + tb_key_id[NL802154_KEY_ID_ATTR_IMPLICIT],
> + dev_addr_policy);
> +
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_PAN_ID])
> + printf("%s\t\tpan_id 0x%04x\n", indent,
> + le16toh(nla_get_u16(tb_dev_addr[NL802154_DEV_ADDR_ATTR_PAN_ID])));
> +
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_MODE]) {
> + enum nl802154_dev_addr_modes dev_addr_mode;
> + dev_addr_mode = nla_get_u32(tb_dev_addr[NL802154_DEV_ADDR_ATTR_MODE]);
> + printf("%s\t\taddr_mode %d\n", indent, dev_addr_mode);
> + switch (dev_addr_mode) {
> + case NL802154_DEV_ADDR_SHORT:
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_SHORT])
> + printf("%s\t\tshort_addr 0x%04x\n", indent,
> + le16toh(nla_get_u16(tb_dev_addr[NL802154_DEV_ADDR_ATTR_SHORT])));
> + break;
> + case NL802154_DEV_ADDR_EXTENDED:
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_EXTENDED])
> + printf("%s\t\textended_addr 0x%016" PRIx64 "\n", indent,
> + le64toh(nla_get_u64(tb_dev_addr[NL802154_DEV_ADDR_ATTR_EXTENDED])));
> + break;
> + default:
> + printf("%s\t\tunkown address\n", indent);
> + break;
> + }
> + }
> + }
> + break;
> + case NL802154_KEY_ID_MODE_INDEX:
> + printf("%s\t\tmode index\n", indent);
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("%s\t\tindex 0x%02x\n", indent,
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_SHORT:
> + printf("%s\t\tmode index_short\n", indent);
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("%s\t\tindex 0x%02x\n", indent,
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
> + printf("%s\t\tsource_short 0x%08lx\n", indent,
> + le32toh(nla_get_u32(tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_SHORT])));
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
> + printf("%s\t\tmode index_extended\n", indent);
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("%s\t\tindex 0x%02x\n", indent,
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
> + printf("%s\t\tsource_extended 0x%" PRIx64 "\n", indent,
> + le64toh(nla_get_u64(tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])));
> + break;
> + default:
> + printf("%s\t\tkey_mode unknown\n", indent);
> + }
> + }
> + }
> +
> + if (tb_msg[NL802154_ATTR_SEC_FRAME_COUNTER])
> + printf("%s\tframe_counter 0x%08lx\n", indent, be32toh(nla_get_u32(tb_msg[NL802154_ATTR_SEC_FRAME_COUNTER])));
> +
> return NL_SKIP;
> }
>
> diff --git a/src/nl802154.h b/src/nl802154.h
> index cf2713d..32cb3e5 100644
> --- a/src/nl802154.h
> +++ b/src/nl802154.h
> @@ -56,6 +56,22 @@ enum nl802154_commands {
>
> /* add new commands above here */
>
> +#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
> + NL802154_CMD_SET_SEC_PARAMS,
> + NL802154_CMD_GET_SEC_KEY, /* can dump */
> + NL802154_CMD_NEW_SEC_KEY,
> + NL802154_CMD_DEL_SEC_KEY,
> + NL802154_CMD_GET_SEC_DEV, /* can dump */
> + NL802154_CMD_NEW_SEC_DEV,
> + NL802154_CMD_DEL_SEC_DEV,
> + NL802154_CMD_GET_SEC_DEVKEY, /* can dump */
> + NL802154_CMD_NEW_SEC_DEVKEY,
> + NL802154_CMD_DEL_SEC_DEVKEY,
> + NL802154_CMD_GET_SEC_LEVEL, /* can dump */
> + NL802154_CMD_NEW_SEC_LEVEL,
> + NL802154_CMD_DEL_SEC_LEVEL,
> +#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
> +
> /* used to define NL802154_CMD_MAX below */
> __NL802154_CMD_AFTER_LAST,
> NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1
> @@ -110,6 +126,18 @@ enum nl802154_attrs {
>
> /* add attributes here, update the policy in nl802154.c */
>
> +#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
> + NL802154_ATTR_SEC_ENABLED,
> + NL802154_ATTR_SEC_OUT_LEVEL,
> + NL802154_ATTR_SEC_OUT_KEY_ID,
> + NL802154_ATTR_SEC_FRAME_COUNTER,
> +
> + NL802154_ATTR_SEC_LEVEL,
> + NL802154_ATTR_SEC_DEVICE,
> + NL802154_ATTR_SEC_DEVKEY,
> + NL802154_ATTR_SEC_KEY,
> +#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
> +
> __NL802154_ATTR_AFTER_LAST,
> NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
> };
> @@ -247,4 +275,167 @@ enum nl802154_supported_bool_states {
> NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1
> };
>
> +#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
> +
> +enum nl802154_dev_addr_modes {
> + NL802154_DEV_ADDR_NONE,
> + __NL802154_DEV_ADDR_INVALID,
> + NL802154_DEV_ADDR_SHORT,
> + NL802154_DEV_ADDR_EXTENDED,
> +
> + /* keep last */
> + __NL802154_DEV_ADDR_AFTER_LAST,
Hmm, why bother with AFTER_LAST here and not just use ADDR_MAX as
sentinal for this enum? Looks redundant to me.
> + NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1
> +};
> +
> +enum nl802154_dev_addr_attrs {
> + NL802154_DEV_ADDR_ATTR_UNSPEC,
> +
> + NL802154_DEV_ADDR_ATTR_PAN_ID,
> + NL802154_DEV_ADDR_ATTR_MODE,
> + NL802154_DEV_ADDR_ATTR_SHORT,
> + NL802154_DEV_ADDR_ATTR_EXTENDED,
> +
> + /* keep last */
> + __NL802154_DEV_ADDR_ATTR_AFTER_LAST,
> + NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1
Same as above
> +};
> +
> +enum nl802154_key_id_modes {
> + NL802154_KEY_ID_MODE_IMPLICIT,
> + NL802154_KEY_ID_MODE_INDEX,
> + NL802154_KEY_ID_MODE_INDEX_SHORT,
> + NL802154_KEY_ID_MODE_INDEX_EXTENDED,
> +
> + /* keep last */
> + __NL802154_KEY_ID_MODE_AFTER_LAST,
> + NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1
Same as above.
> +};
> +
> +enum nl802154_key_id_attrs {
> + NL802154_KEY_ID_ATTR_UNSPEC,
> +
> + NL802154_KEY_ID_ATTR_MODE,
> + NL802154_KEY_ID_ATTR_INDEX,
> + NL802154_KEY_ID_ATTR_IMPLICIT,
> + NL802154_KEY_ID_ATTR_SOURCE_SHORT,
> + NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
> +
> + /* keep last */
> + __NL802154_KEY_ID_ATTR_AFTER_LAST,
> + NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1
Above
> +};
> +
> +enum nl802154_seclevels {
> + NL802154_SECLEVEL_NONE,
> + NL802154_SECLEVEL_MIC32,
> + NL802154_SECLEVEL_MIC64,
> + NL802154_SECLEVEL_MIC128,
> + NL802154_SECLEVEL_ENC,
> + NL802154_SECLEVEL_ENC_MIC32,
> + NL802154_SECLEVEL_ENC_MIC64,
> + NL802154_SECLEVEL_ENC_MIC128,
> +
> + /* keep last */
> + __NL802154_SECLEVEL_AFTER_LAST,
> + NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1
Above
> +};
> +
> +enum nl802154_frames {
> + NL802154_FRAME_BEACON,
> + NL802154_FRAME_DATA,
> + NL802154_FRAME_ACK,
> + NL802154_FRAME_CMD,
> +
> + /* keep last */
> + __NL802154_FRAME_AFTER_LAST,
> + NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1
Above
> +};
> +
> +enum nl802154_cmd_frames {
> + __NL802154_CMD_FRAME_INVALID,
> + NL802154_CMD_FRAME_ASSOC_REQUEST,
> + NL802154_CMD_FRAME_ASSOC_RESPONSE,
> + NL802154_CMD_FRAME_DISASSOC_NOTIFY,
> + NL802154_CMD_FRAME_DATA_REQUEST,
> + NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY,
> + NL802154_CMD_FRAME_ORPHAN_NOTIFY,
> + NL802154_CMD_FRAME_BEACON_REQUEST,
> + NL802154_CMD_FRAME_COORD_REALIGNMENT,
> + NL802154_CMD_FRAME_GTS_REQUEST,
> +
> + /* keep last */
> + __NL802154_CMD_FRAME_AFTER_LAST,
> + NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1
Above, and for all other below.
> +};
> +
> +enum nl802154_seclevel_attrs {
> + NL802154_SECLEVEL_ATTR_UNSPEC,
> +
> + NL802154_SECLEVEL_ATTR_LEVELS,
> + NL802154_SECLEVEL_ATTR_FRAME,
> + NL802154_SECLEVEL_ATTR_CMD_FRAME,
> + NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
> +
> + /* keep last */
> + __NL802154_SECLEVEL_ATTR_AFTER_LAST,
> + NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1
> +};
> +
> +/* TODO what is this? couldn't find in mib */
> +enum {
> + NL802154_DEVKEY_IGNORE,
> + NL802154_DEVKEY_RESTRICT,
> + NL802154_DEVKEY_RECORD,
> +
> + /* keep last */
> + __NL802154_DEVKEY_AFTER_LAST,
> + NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1
> +};
> +
> +enum nl802154_dev {
> + NL802154_DEV_ATTR_UNSPEC,
> +
> + NL802154_DEV_ATTR_FRAME_COUNTER,
> + NL802154_DEV_ATTR_PAN_ID,
> + NL802154_DEV_ATTR_SHORT_ADDR,
> + NL802154_DEV_ATTR_EXTENDED_ADDR,
> + NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
> + NL802154_DEV_ATTR_KEY_MODE,
> +
> + /* keep last */
> + __NL802154_DEV_ATTR_AFTER_LAST,
> + NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1
> +};
> +
> +enum nl802154_devkey {
> + NL802154_DEVKEY_ATTR_UNSPEC,
> +
> + NL802154_DEVKEY_ATTR_FRAME_COUNTER,
> + NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
> + NL802154_DEVKEY_ATTR_ID,
> +
> + /* keep last */
> + __NL802154_DEVKEY_ATTR_AFTER_LAST,
> + NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1
> +};
> +
> +enum nl802154_key {
> + NL802154_KEY_ATTR_UNSPEC,
> +
> + NL802154_KEY_ATTR_ID,
> + NL802154_KEY_ATTR_USAGE_FRAMES,
> + NL802154_KEY_ATTR_USAGE_CMDS,
> + NL802154_KEY_ATTR_BYTES,
> +
> + /* keep last */
> + __NL802154_KEY_ATTR_AFTER_LAST,
> + NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1
> +};
> +
> +#define NL802154_KEY_SIZE 16
> +#define NL802154_CMD_FRAME_NR_IDS 256
> +
> +#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
> +
> #endif /* __NL802154_H */
> diff --git a/src/security.c b/src/security.c
> new file mode 100644
> index 0000000..3928dee
> --- /dev/null
> +++ b/src/security.c
> @@ -0,0 +1,1118 @@
> +#include <net/if.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +
> +#include <netlink/genl/genl.h>
> +#include <netlink/genl/family.h>
> +#include <netlink/genl/ctrl.h>
> +#include <netlink/msg.h>
> +#include <netlink/attr.h>
> +
> +#include "nl_extras.h"
> +#define CONFIG_IEEE802154_NL802154_EXPERIMENTAL
> +#include "nl802154.h"
> +#include "iwpan.h"
> +
> +static int handle_security_set(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + unsigned long enabled;
> + char *end;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* enabled */
> + enabled = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (enabled > UINT8_MAX)
> + return 1;
> +
> + NLA_PUT_U8(msg, NL802154_ATTR_SEC_ENABLED, enabled);
> +
> + return 0;
> +
> +nla_put_failure:
> + return -ENOBUFS;
> +}
> +COMMAND(set, security, "<1|0>", NL802154_CMD_SET_SEC_PARAMS, 0, CIB_NETDEV,
> + handle_security_set, NULL);
> +
> +static int handle_parse_key_id(struct nl_msg *msg, int attrtype,
> + int *argc, char ***argv)
> +{
> + struct nl_msg *key_id_msg, *dev_addr_msg = NULL;
> + unsigned long key_mode, dev_addr_mode, short_addr, pan_id, index;
> + unsigned long long extended_addr;
> + char *end;
> +
> + if ((*argc) < 1)
> + return 1;
> +
> + /* key_mode */
> + key_mode = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + (*argc)--;
> + (*argv)++;
> +
> + switch (key_mode) {
> + case NL802154_KEY_ID_MODE_IMPLICIT:
> + if ((*argc) < 2)
> + return 1;
> +
> + /* pan_id */
> + pan_id = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (pan_id > UINT16_MAX)
> + return 1;
> +
> + (*argc)--;
> + (*argv)++;
> +
> + /* dev_addr_mode */
> + dev_addr_mode = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + (*argc)--;
> + (*argv)++;
> +
> + switch (dev_addr_mode) {
> + case NL802154_DEV_ADDR_SHORT:
> + if ((*argc) < 1)
> + return 1;
> +
> + /* dev_addr_short */
> + short_addr = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (short_addr > UINT16_MAX)
> + return 1;
> + break;
> + case NL802154_DEV_ADDR_EXTENDED:
> + if ((*argc) < 1)
> + return 1;
> +
> + /* dev_addr_short */
> + extended_addr = strtoull((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> + break;
> + default:
> + return 1;
> + }
> +
> + key_id_msg = nlmsg_alloc();
> + if (!key_id_msg)
> + return -ENOMEM;
> +
> + dev_addr_msg = nlmsg_alloc();
> + if (!dev_addr_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U16(dev_addr_msg, NL802154_DEV_ADDR_ATTR_PAN_ID, pan_id);
> + NLA_PUT_U32(dev_addr_msg, NL802154_DEV_ADDR_ATTR_MODE, dev_addr_mode);
> + NLA_PUT_U16(dev_addr_msg, NL802154_DEV_ADDR_ATTR_SHORT, htole16(short_addr));
> + NLA_PUT_U64(dev_addr_msg, NL802154_DEV_ADDR_ATTR_EXTENDED, htole64(extended_addr));
> +
> + nla_put_nested(key_id_msg, NL802154_KEY_ID_ATTR_IMPLICIT, dev_addr_msg);
> +
> + nlmsg_free(dev_addr_msg);
> + dev_addr_msg = NULL;
> +
> + break;
> + case NL802154_KEY_ID_MODE_INDEX:
> + if ((*argc) < 1)
> + return 1;
> +
> + /* index */
> + index = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (index > UINT8_MAX)
> + return 1;
> +
> + key_id_msg = nlmsg_alloc();
> + if (!key_id_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U8(key_id_msg, NL802154_KEY_ID_ATTR_INDEX, index);
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_SHORT:
> + if ((*argc) < 2)
> + return 1;
> +
> + /* index */
> + index = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (index > UINT8_MAX)
> + return 1;
> +
> + (*argc)--;
> + (*argv)++;
> +
> + /* source_short */
> + short_addr = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + key_id_msg = nlmsg_alloc();
> + if (!key_id_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U8(key_id_msg, NL802154_KEY_ID_ATTR_INDEX, index);
> + NLA_PUT_U32(key_id_msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT,
> + htole32(short_addr));
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
> + if ((*argc) < 2)
> + return 1;
> +
> + /* index */
> + index = strtoul((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (index > UINT8_MAX)
> + return 1;
> +
> + (*argc)--;
> + (*argv)++;
> +
> + /* source_extended */
> + extended_addr = strtoull((*argv)[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + key_id_msg = nlmsg_alloc();
> + if (!key_id_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U8(key_id_msg, NL802154_KEY_ID_ATTR_INDEX, index);
> + NLA_PUT_U64(key_id_msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
> + htole64(extended_addr));
> + break;
> + default:
> + return 1;
> + }
> +
> + NLA_PUT_U32(key_id_msg, NL802154_KEY_ID_ATTR_MODE, key_mode);
> + nla_put_nested(msg, attrtype, key_id_msg);
> +
> + nlmsg_free(key_id_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + if (!dev_addr_msg)
> + nlmsg_free(dev_addr_msg);
> +
> + nlmsg_free(key_id_msg);
> + return -ENOBUFS;
> +}
> +
> +static int handle_out_key_id_set(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + return handle_parse_key_id(msg, NL802154_ATTR_SEC_OUT_KEY_ID, &argc, &argv);
> +
> +}
> +COMMAND(set, out_key_id,
> + "<0 <pan_id> <2 <short_addr>|3 <extended_addr>>>|"
> + "<1 <index>>|"
> + "<2 <index> <source_short>>|"
> + "<3 <index> <source_extended>>",
What are these extra >>| for ?
> + NL802154_CMD_SET_SEC_PARAMS, 0, CIB_NETDEV,
> + handle_out_key_id_set, NULL);
> +
> +static int handle_out_seclevel_set(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + unsigned long seclevel;
> + char *end;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* seclevel */
> + seclevel = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + NLA_PUT_U32(msg, NL802154_ATTR_SEC_OUT_LEVEL, seclevel);
> +
> + return 0;
> +
> +nla_put_failure:
> + return -ENOBUFS;
> +}
> +COMMAND(set, out_level, "<out_level>", NL802154_CMD_SET_SEC_PARAMS, 0, CIB_NETDEV,
> + handle_out_seclevel_set, NULL);
> +
> +static int handle_frame_counter_set(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + unsigned long frame_counter;
> + char *end;
> +
> + /* frame_counter */
This command and the other above (index, etc) which just state the
variable name below are not really needed as they give no extra
information imho.
> + frame_counter = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + NLA_PUT_U32(msg, NL802154_ATTR_SEC_FRAME_COUNTER, htobe32(frame_counter));
> +
> + return 0;
> +
> +nla_put_failure:
> + return -ENOBUFS;
> +}
> +COMMAND(set, frame_counter, "<frame_counter>", NL802154_CMD_SET_SEC_PARAMS, 0, CIB_NETDEV,
> + handle_frame_counter_set, NULL);
> +
> +SECTION(seclevel);
> +
> +static int print_seclevel_handler(struct nl_msg *msg, void *arg)
> +{
> + struct nlattr *tb[NL802154_ATTR_MAX + 1];
> + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
> +
> + nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
> + genlmsg_attrlen(gnlh, 0), NULL);
> +
> + if (tb[NL802154_ATTR_SEC_LEVEL]) {
> + struct nlattr *tb_seclevel[NL802154_SECLEVEL_ATTR_MAX + 1];
> + static struct nla_policy seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
> + [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U32 },
> + [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
> + [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
> + [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
> + };
> +
> + if (nla_parse_nested(tb_seclevel, NL802154_SECLEVEL_ATTR_MAX,
> + tb[NL802154_ATTR_SEC_LEVEL],
> + seclevel_policy)) {
> + fprintf(stderr, "failed to parse nested attributes!\n");
> + return NL_SKIP;
> + }
> +
> + printf("iwpan dev $WPAN_DEV seclevel add ");
> +
> + if (tb_seclevel[NL802154_SECLEVEL_ATTR_LEVELS])
> + printf("0x%02lx ", nla_get_u8(tb_seclevel[NL802154_SECLEVEL_ATTR_LEVELS]));
> + if (tb_seclevel[NL802154_SECLEVEL_ATTR_FRAME])
> + printf("%d ", nla_get_u32(tb_seclevel[NL802154_SECLEVEL_ATTR_FRAME]));
> + if (tb_seclevel[NL802154_SECLEVEL_ATTR_CMD_FRAME])
> + printf("%d ", nla_get_u32(tb_seclevel[NL802154_SECLEVEL_ATTR_CMD_FRAME]));
> + if (tb_seclevel[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
> + printf("%d ", nla_get_u8(tb_seclevel[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]));
> + }
> +
> + printf("\n");
> +
> + return NL_SKIP;
> +}
> +
> +static int handle_seclevel_dump(struct nl802154_state *state,
> + struct nl_cb *cb,
> + struct nl_msg *msg,
> + int argc, char **argv,
> + enum id_input id)
> +{
> + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_seclevel_handler, NULL);
> + return 0;
> +}
> +COMMAND(seclevel, dump, NULL,
> + NL802154_CMD_GET_SEC_LEVEL, NLM_F_DUMP, CIB_NETDEV, handle_seclevel_dump,
> + NULL);
> +
> +static int handle_seclevel_add(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *seclevel_msg;
> + unsigned long levels, frame, cmd_id, dev_override;
> + char *end;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* levels */
> + levels = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* frame */
> + frame = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (frame == NL802154_FRAME_CMD) {
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* cmd_frame */
> + cmd_id = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> + }
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* dev_override */
> + dev_override = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (dev_override > UINT8_MAX)
> + return 1;
> +
> + seclevel_msg = nlmsg_alloc();
> + if (!seclevel_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U32(seclevel_msg, NL802154_SECLEVEL_ATTR_LEVELS, levels);
> + NLA_PUT_U32(seclevel_msg, NL802154_SECLEVEL_ATTR_FRAME, frame);
> + if (frame == NL802154_FRAME_CMD)
> + NLA_PUT_U32(seclevel_msg, NL802154_SECLEVEL_ATTR_CMD_FRAME, cmd_id);
> + NLA_PUT_U8(seclevel_msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, dev_override);
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_LEVEL, seclevel_msg);
> + nlmsg_free(seclevel_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(seclevel_msg);
> + return -ENOBUFS;
> +}
> +COMMAND(seclevel, add, "<levels> <frame_type|3 <cmd_id>> <dev_override>", NL802154_CMD_NEW_SEC_LEVEL, 0, CIB_NETDEV,
> + handle_seclevel_add, NULL);
> +COMMAND(seclevel, del, "<levels> <frame_type|3 <cmd_id>> <dev_override>", NL802154_CMD_DEL_SEC_LEVEL, 0, CIB_NETDEV,
> + handle_seclevel_add, NULL);
> +
> +SECTION(device);
> +
> +static int print_device_handler(struct nl_msg *msg, void *arg)
> +{
> + struct nlattr *tb[NL802154_ATTR_MAX + 1];
> + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
> +
> + nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
> + genlmsg_attrlen(gnlh, 0), NULL);
> +
> + if (tb[NL802154_ATTR_SEC_DEVICE]) {
> + struct nlattr *tb_device[NL802154_DEV_ATTR_MAX + 1];
> + static struct nla_policy device_policy[NL802154_DEV_ATTR_MAX + 1] = {
> + [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
> + [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
> + [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
> + [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
> + [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
> + [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
> + };
> +
> + if (nla_parse_nested(tb_device, NL802154_DEV_ATTR_MAX,
> + tb[NL802154_ATTR_SEC_DEVICE],
> + device_policy)) {
> + fprintf(stderr, "failed to parse nested attributes!\n");
> + return NL_SKIP;
> + }
> +
> + printf("iwpan dev $WPAN_DEV device add ");
> +
> + if (tb_device[NL802154_DEV_ATTR_FRAME_COUNTER])
> + printf("0x%08lx ", nla_get_u32(tb_device[NL802154_DEV_ATTR_FRAME_COUNTER]));
> + if (tb_device[NL802154_DEV_ATTR_PAN_ID])
> + printf("0x%04lx ", le16toh(nla_get_u16(tb_device[NL802154_DEV_ATTR_PAN_ID])));
> + if (tb_device[NL802154_DEV_ATTR_SHORT_ADDR])
> + printf("0x%04lx ", le16toh(nla_get_u16(tb_device[NL802154_DEV_ATTR_SHORT_ADDR])));
> + if (tb_device[NL802154_DEV_ATTR_EXTENDED_ADDR])
> + printf("0x%016" PRIx64 " ", le64toh(nla_get_u64(tb_device[NL802154_DEV_ATTR_EXTENDED_ADDR])));
> + if (tb_device[NL802154_DEV_ATTR_SECLEVEL_EXEMPT])
> + printf("%d ", nla_get_u8(tb_device[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]));
> + if (tb_device[NL802154_DEV_ATTR_KEY_MODE])
> + printf("%d ", nla_get_u32(tb_device[NL802154_DEV_ATTR_KEY_MODE]));
> + }
> +
> + printf("\n");
> +
> + return NL_SKIP;
> +}
> +
> +static int handle_device_dump(struct nl802154_state *state,
> + struct nl_cb *cb,
> + struct nl_msg *msg,
> + int argc, char **argv,
> + enum id_input id)
> +{
> + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_device_handler, NULL);
> + return 0;
> +}
> +COMMAND(device, dump, NULL,
> + NL802154_CMD_GET_SEC_DEV, NLM_F_DUMP, CIB_NETDEV, handle_device_dump,
> + NULL);
> +
> +static int handle_device_add(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *device_msg;
> + unsigned long long extended_addr;
> + unsigned long frame_counter, pan_id, short_addr,
> + seclevel_exempt, key_mode;
> + char *end;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* frame_counter */
> + frame_counter = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* pan_id */
> + pan_id = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (pan_id > UINT16_MAX)
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* short_addr */
> + short_addr = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (short_addr > UINT16_MAX)
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* extended_addr */
> + extended_addr = strtoull(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* seclevel_exempt */
> + seclevel_exempt = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + if (seclevel_exempt > UINT8_MAX)
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* key_mode */
> + key_mode = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + device_msg = nlmsg_alloc();
> + if (!device_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U32(device_msg, NL802154_DEV_ATTR_FRAME_COUNTER, frame_counter);
> + NLA_PUT_U16(device_msg, NL802154_DEV_ATTR_PAN_ID, htole16(pan_id));
> + NLA_PUT_U16(device_msg, NL802154_DEV_ATTR_SHORT_ADDR, htole16(short_addr));
> + NLA_PUT_U64(device_msg, NL802154_DEV_ATTR_EXTENDED_ADDR, htole64(extended_addr));
> + NLA_PUT_U8(device_msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, seclevel_exempt);
> + NLA_PUT_U32(device_msg, NL802154_DEV_ATTR_KEY_MODE, key_mode);
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_DEVICE, device_msg);
> + nlmsg_free(device_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(device_msg);
> + return -ENOBUFS;
> +}
> +COMMAND(device, add, "<frame_counter> <pan_id> <short_addr> <extended_addr> <seclevel_exempt> <key_mode>",
> + NL802154_CMD_NEW_SEC_DEV, 0, CIB_NETDEV, handle_device_add, NULL);
> +
> +static int handle_device_del(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *device_msg;
> + unsigned long long extended_addr;
> + char *end;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* extended_addr */
> + extended_addr = strtoull(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + device_msg = nlmsg_alloc();
> + if (!device_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U64(device_msg, NL802154_DEV_ATTR_EXTENDED_ADDR, htole64(extended_addr));
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_DEVICE, device_msg);
> + nlmsg_free(device_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(device_msg);
> + return -ENOBUFS;
> +}
> +COMMAND(device, del, "<extended_addr>",
> + NL802154_CMD_DEL_SEC_DEV, 0, CIB_NETDEV, handle_device_del, NULL);
> +
> +SECTION(devkey);
> +
> +static int print_key_id(struct nlattr *tb) {
> + struct nlattr *tb_key_id[NL802154_KEY_ID_ATTR_MAX + 1];
> + static struct nla_policy key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
> + [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
> + [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
> + [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
> + [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
> + [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
> + };
> +
> + nla_parse_nested(tb_key_id, NL802154_KEY_ID_ATTR_MAX, tb, key_id_policy);
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_MODE]) {
> + enum nl802154_key_id_modes key_id_mode;
> +
> + key_id_mode = nla_get_u32(tb_key_id[NL802154_KEY_ID_ATTR_MODE]);
> + printf("%d ", key_id_mode);
> + switch (key_id_mode) {
> + case NL802154_KEY_ID_MODE_IMPLICIT:
> + if (tb_key_id[NL802154_KEY_ID_ATTR_IMPLICIT]) {
> + struct nlattr *tb_dev_addr[NL802154_DEV_ADDR_ATTR_MAX + 1];
> + static struct nla_policy dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
> + [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
> + [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
> + [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
> + [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
> + };
> +
> + nla_parse_nested(tb_dev_addr, NL802154_DEV_ADDR_ATTR_MAX,
> + tb_key_id[NL802154_KEY_ID_ATTR_IMPLICIT],
> + dev_addr_policy);
> +
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_PAN_ID])
> + printf("0x%04x ",
> + le16toh(nla_get_u16(tb_dev_addr[NL802154_DEV_ADDR_ATTR_PAN_ID])));
> +
> + if (tb_dev_addr[NL802154_DEV_ADDR_ATTR_MODE]) {
> + enum nl802154_dev_addr_modes dev_addr_mode;
> + dev_addr_mode = nla_get_u32(tb_dev_addr[NL802154_DEV_ADDR_ATTR_MODE]);
> + printf("%d ", dev_addr_mode);
> + switch (dev_addr_mode) {
> + case NL802154_DEV_ADDR_SHORT:
> + printf("0x%04x ",
> + le16toh(nla_get_u16(tb_dev_addr[NL802154_DEV_ADDR_ATTR_SHORT])));
> + break;
> + case NL802154_DEV_ADDR_EXTENDED:
> + printf("0x%016" PRIx64 " ",
> + le64toh(nla_get_u64(tb_dev_addr[NL802154_DEV_ADDR_ATTR_SHORT])));
> + break;
> + default:
> + /* TODO error handling */
> + break;
> + }
> + }
> + }
> + break;
> + case NL802154_KEY_ID_MODE_INDEX:
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("0x%02x ",
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_SHORT:
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("0x%02x ",
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
> + printf("0x%08lx ",
> + le32toh(nla_get_u32(tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_SHORT])));
> + break;
> + case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
> + if (tb_key_id[NL802154_KEY_ID_ATTR_INDEX])
> + printf("0x%02x ",
> + nla_get_u8(tb_key_id[NL802154_KEY_ID_ATTR_INDEX]));
> +
> + if (tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
> + printf("0x%016" PRIx64 " ",
> + le64toh(nla_get_u64(tb_key_id[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])));
> + break;
> + default:
> + /* TODO error handling */
> + return 0;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int print_devkey_handler(struct nl_msg *msg, void *arg)
> +{
> + struct nlattr *tb[NL802154_ATTR_MAX + 1];
> + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
> +
> + nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
> + genlmsg_attrlen(gnlh, 0), NULL);
> +
> + if (tb[NL802154_ATTR_SEC_DEVKEY]) {
> + struct nlattr *tb_devkey[NL802154_DEVKEY_ATTR_MAX + 1];
> + static struct nla_policy devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
> + [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
> + [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
> + [NL802154_DEVKEY_ATTR_ID] = { .type = NLA_NESTED },
> + };
> +
> + if (nla_parse_nested(tb_devkey, NL802154_DEVKEY_ATTR_MAX,
> + tb[NL802154_ATTR_SEC_DEVKEY],
> + devkey_policy)) {
> + fprintf(stderr, "failed to parse nested attributes!\n");
> + return NL_SKIP;
> + }
> +
> + printf("iwpan dev $WPAN_DEV devkey add ");
> +
> + if (tb_devkey[NL802154_DEV_ATTR_FRAME_COUNTER])
> + printf("0x%08lx ", nla_get_u32(tb_devkey[NL802154_DEVKEY_ATTR_FRAME_COUNTER]));
> + if (tb_devkey[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
> + printf("0x%016" PRIx64 " ", le64toh(nla_get_u64(tb_devkey[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])));
> +
> + if (tb_devkey[NL802154_DEVKEY_ATTR_ID])
> + print_key_id(tb_devkey[NL802154_DEVKEY_ATTR_ID]);
> + }
> +
> + printf("\n");
> +
> + return NL_SKIP;
> +}
> +
> +static int handle_devkey_dump(struct nl802154_state *state,
> + struct nl_cb *cb,
> + struct nl_msg *msg,
> + int argc, char **argv,
> + enum id_input id)
> +{
> + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_devkey_handler, NULL);
> + return 0;
> +}
> +COMMAND(devkey, dump, NULL,
> + NL802154_CMD_GET_SEC_DEVKEY, NLM_F_DUMP, CIB_NETDEV, handle_devkey_dump,
> + NULL);
> +
> +static int handle_devkey_add(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *devkey_msg = NULL;
> + unsigned long long extended_addr;
> + unsigned long frame_counter;
> + char *end;
> + int ret;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* frame_counter */
> + frame_counter = strtoul(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* extended_addr */
> + extended_addr = strtoull(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + devkey_msg = nlmsg_alloc();
> + if (!devkey_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U32(devkey_msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER, frame_counter);
> + NLA_PUT_U64(devkey_msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, htole64(extended_addr));
> +
> + ret = handle_parse_key_id(devkey_msg, NL802154_DEVKEY_ATTR_ID, &argc, &argv);
> + if (ret) {
> + nlmsg_free(devkey_msg);
> + return ret;
> + }
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_DEVKEY, devkey_msg);
> + nlmsg_free(devkey_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(devkey_msg);
> + return -ENOBUFS;
> +
> +}
> +COMMAND(devkey, add, "<frame_counter> <extended_addr> "
> + "<0 <pan_id> <2 <short_addr>|3 <extended_addr>>>|"
> + "<1 <index>>|"
> + "<2 <index> <source_short>>|"
> + "<3 <index> <source_extended>>",
> + NL802154_CMD_NEW_SEC_DEVKEY, 0, CIB_NETDEV, handle_devkey_add, NULL);
> +
> +static int handle_devkey_del(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *devkey_msg = NULL;
> + unsigned long long extended_addr;
> + char *end;
> + int ret;
> +
> + if (argc < 1)
> + return 1;
> +
> + /* extended_addr */
> + extended_addr = strtoull(argv[0], &end, 0);
> + if (*end != '\0')
> + return 1;
> +
> + argc--;
> + argv++;
> +
> + devkey_msg = nlmsg_alloc();
> + if (!devkey_msg)
> + return -ENOMEM;
> +
> + NLA_PUT_U64(devkey_msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, htole64(extended_addr));
> +
> + ret = handle_parse_key_id(devkey_msg, NL802154_DEVKEY_ATTR_ID, &argc, &argv);
> + if (ret) {
> + nlmsg_free(devkey_msg);
> + return ret;
> + }
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_DEVKEY, devkey_msg);
> + nlmsg_free(devkey_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(devkey_msg);
> + return -ENOBUFS;
> +
> +}
> +COMMAND(devkey, del, "<extended_addr> "
> + "<0 <pan_id> <2 <short_addr>|3 <extended_addr>>>|"
> + "<1 <index>>|"
> + "<2 <index> <source_short>>|"
> + "<3 <index> <source_extended>>",
> + NL802154_CMD_DEL_SEC_DEVKEY, 0, CIB_NETDEV, handle_devkey_del, NULL);
> +
> +SECTION(key);
> +
> +static void key_to_str(char *key, unsigned char *arg)
> +{
> + int i, l;
> +
> + l = 0;
> + for (i = 0; i < NL802154_KEY_SIZE ; i++) {
> + if (i == 0) {
> + sprintf(key+l, "%02x", arg[i]);
> + l += 2;
> + } else {
> + sprintf(key+l, ":%02x", arg[i]);
> + l += 3;
> + }
> + }
> +}
> +
> +static int print_key_handler(struct nl_msg *msg, void *arg)
> +{
> + struct nlattr *tb[NL802154_ATTR_MAX + 1];
> + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
> +
> + nla_parse(tb, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
> + genlmsg_attrlen(gnlh, 0), NULL);
> +
> + if (tb[NL802154_ATTR_SEC_KEY]) {
> + struct nlattr *tb_key[NL802154_KEY_ATTR_MAX + 1];
> + static struct nla_policy key_policy[NL802154_KEY_ATTR_MAX + 1] = {
> + [NL802154_KEY_ATTR_ID] = { NLA_NESTED },
> + [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
> + [NL802154_KEY_ATTR_USAGE_CMDS] = { .minlen = NL802154_CMD_FRAME_NR_IDS / 8 },
> + [NL802154_KEY_ATTR_BYTES] = { .minlen = NL802154_KEY_SIZE },
> + };
> +
> + if (nla_parse_nested(tb_key, NL802154_KEY_ATTR_MAX,
> + tb[NL802154_ATTR_SEC_KEY],
> + key_policy)) {
> + fprintf(stderr, "failed to parse nested attributes!\n");
> + return NL_SKIP;
> + }
> +
> + printf("iwpan dev $WPAN_DEV key add ");
> +
> + if (tb_key[NL802154_KEY_ATTR_USAGE_FRAMES])
> + printf("0x%02x ", nla_get_u8(tb_key[NL802154_KEY_ATTR_USAGE_FRAMES]));
> +
> + if (tb_key[NL802154_KEY_ATTR_USAGE_CMDS]) {
> + uint32_t cmds[NL802154_CMD_FRAME_NR_IDS / 32];
> +
> + nla_memcpy(cmds, tb_key[NL802154_KEY_ATTR_USAGE_CMDS],
> + NL802154_CMD_FRAME_NR_IDS / 8);
> + printf("0x%08x ", cmds[7]);
> + }
> +
> + if (tb_key[NL802154_KEY_ATTR_BYTES]) {
> + uint8_t key[NL802154_KEY_SIZE];
> + char key_str[512] = "";
> +
> + nla_memcpy(key, tb_key[NL802154_KEY_ATTR_BYTES],
> + NL802154_KEY_SIZE);
> +
> + key_to_str(key_str, key);
> + printf("%s ", key_str);
> + }
> +
> + if (tb_key[NL802154_KEY_ATTR_ID])
> + print_key_id(tb_key[NL802154_KEY_ATTR_ID]);
> + }
> +
> + printf("\n");
> +
> + return NL_SKIP;
> +}
> +
> +static int handle_key_dump(struct nl802154_state *state,
> + struct nl_cb *cb,
> + struct nl_msg *msg,
> + int argc, char **argv,
> + enum id_input id)
> +{
> + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_key_handler, NULL);
> + return 0;
> +}
> +COMMAND(key, dump, NULL,
> + NL802154_CMD_GET_SEC_KEY, NLM_F_DUMP, CIB_NETDEV, handle_key_dump,
> + NULL);
> +
> +#define BIT(x) (1 << (x))
> +
> +static int str_to_key(unsigned char *key, char *arg)
> +{
> + int i;
> +
> + for (i = 0; i < NL802154_KEY_SIZE; i++) {
> + int temp;
> + char *cp = strchr(arg, ':');
> + if (cp) {
> + *cp = 0;
> + cp++;
> + }
> + if (sscanf(arg, "%x", &temp) != 1)
> + return -1;
> + if (temp < 0 || temp > 255)
> + return -1;
> +
> + key[i] = temp;
> + if (!cp)
> + break;
> + arg = cp;
> + }
> + if (i < NL802154_KEY_SIZE - 1)
> + return -1;
> +
> + return 0;
> +}
> +
> +static int handle_key_add(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *key_msg = NULL;
> + uint8_t key_bytes[NL802154_KEY_SIZE] = { };
> + uint32_t commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
> + unsigned long tmp;
> + char *end;
> + int ret, i;
> +
> + key_msg = nlmsg_alloc();
> + if (!key_msg)
> + return -ENOMEM;
> +
> + if (argc < 1) {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + /* frame_types */
> + tmp = strtoul(argv[0], &end, 0);
> + if (*end != '\0') {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + if (tmp > UINT8_MAX) {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + NLA_PUT_U8(key_msg, NL802154_KEY_ATTR_USAGE_FRAMES, tmp);
> +
> + argc--;
> + argv++;
> +
> + if (tmp & BIT(NL802154_FRAME_CMD)) {
> + if (argc < 1) {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + /* commands[7] */
> + commands[7] = strtoul(argv[0], &end, 0);
> + if (*end != '\0') {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + NLA_PUT(key_msg, NL802154_KEY_ATTR_USAGE_CMDS,
> + NL802154_CMD_FRAME_NR_IDS / 8, commands);
> +
> + argc--;
> + argv++;
> + }
> +
> + if (argc < 1) {
> + nlmsg_free(key_msg);
> + return 1;
> + }
> +
> + str_to_key(key_bytes, argv[0]);
> +
> + NLA_PUT(key_msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE, key_bytes);
> +
> + argc--;
> + argv++;
> +
> + ret = handle_parse_key_id(key_msg, NL802154_KEY_ATTR_ID, &argc, &argv);
> + if (ret) {
> + nlmsg_free(key_msg);
> + return ret;
> + }
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_KEY, key_msg);
> + nlmsg_free(key_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(key_msg);
> + return -ENOBUFS;
> +
> +}
> +COMMAND(key, add, "<frame_types <if 0x4 is set commands[7]>>> <key <hex as 00:11:..>> "
> + "<0 <pan_id> <2 <short_addr>|3 <extended_addr>>>|"
> + "<1 <index>>|"
> + "<2 <index> <source_short>>|"
> + "<3 <index> <source_extended>>",
> + NL802154_CMD_NEW_SEC_KEY, 0, CIB_NETDEV, handle_key_add, NULL);
> +
> +static int handle_key_del(struct nl802154_state *state, struct nl_cb *cb,
> + struct nl_msg *msg, int argc, char **argv,
> + enum id_input id)
> +{
> + struct nl_msg *key_msg = NULL;
> + int ret;
> +
> + key_msg = nlmsg_alloc();
> + if (!key_msg)
> + return -ENOMEM;
> +
> + ret = handle_parse_key_id(key_msg, NL802154_KEY_ATTR_ID, &argc, &argv);
> + if (ret) {
> + nlmsg_free(key_msg);
> + return ret;
> + }
> +
> + nla_put_nested(msg, NL802154_ATTR_SEC_KEY, key_msg);
> + nlmsg_free(key_msg);
> +
> + return 0;
> +
> +nla_put_failure:
> + nlmsg_free(key_msg);
> + return -ENOBUFS;
> +
> +}
> +COMMAND(key, del,
> + "<0 <pan_id> <2 <short_addr>|3 <extended_addr>>>|"
> + "<1 <index>>|"
> + "<2 <index> <source_short>>|"
> + "<3 <index> <source_extended>>",
> + NL802154_CMD_DEL_SEC_KEY, 0, CIB_NETDEV, handle_key_del, NULL);
regards
Stefan Schmidt
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists