^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Netlink interface for IEEE 802.15.4 stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2007, 2008 Siemens AG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Written by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Sergey Lapin <slapin@ossfans.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Maxim Osipov <maxim.osipov@siemens.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/ieee802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/nl802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/af_ieee802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/ieee802154_netdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/cfg802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "ieee802154.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int padattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return nla_put_u64_64bit(msg, type, swab64((__force u64)hwaddr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) padattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static __le64 nla_get_hwaddr(const struct nlattr *nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return ieee802154_devaddr_from_raw(nla_data(nla));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return nla_put_u16(msg, type, le16_to_cpu(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static __le16 nla_get_shortaddr(const struct nlattr *nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return cpu_to_le16(nla_get_u16(nla));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) msg = ieee802154_nl_create(0, IEEE802154_START_CONF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dev->dev_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 seq, int flags, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct wpan_phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct ieee802154_mlme_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) __le16 short_addr, pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) IEEE802154_LIST_IFACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) phy = dev->ieee802154_ptr->wpan_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) BUG_ON(!phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) get_device(&phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) short_addr = dev->ieee802154_ptr->short_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) pan_id = dev->ieee802154_ptr->pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev->dev_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (ops->get_mac_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct ieee802154_mac_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ops->get_mac_params(dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) params.transmit_power / 100) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) params.cca.mode) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) params.cca_ed_level / 100) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) params.csma_retries) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) params.min_be) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) params.max_be) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) params.frame_retries))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) wpan_phy_put(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) wpan_phy_put(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Requests from userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) char name[IFNAMSIZ + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) sizeof(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev = dev_get_by_name(&init_net, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev = dev_get_by_index(&init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (dev->type != ARPHRD_IEEE802154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct ieee802154_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u8 page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) !info->attrs[IEEE802154_ATTR_CAPABILITY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!ieee802154_mlme_ops(dev)->assoc_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) addr.mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) addr.extended_addr = nla_get_hwaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) addr.mode = IEEE802154_ADDR_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) addr.short_addr = nla_get_shortaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) addr.pan_id = nla_get_shortaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (info->attrs[IEEE802154_ATTR_PAGE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct ieee802154_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!info->attrs[IEEE802154_ATTR_STATUS] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!ieee802154_mlme_ops(dev)->assoc_resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) addr.mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) addr.extended_addr = nla_get_hwaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) addr.pan_id = dev->ieee802154_ptr->pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct ieee802154_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) !info->attrs[IEEE802154_ATTR_REASON])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!ieee802154_mlme_ops(dev)->disassoc_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) addr.mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) addr.extended_addr = nla_get_hwaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) addr.mode = IEEE802154_ADDR_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) addr.short_addr = nla_get_shortaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) addr.pan_id = dev->ieee802154_ptr->pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* PANid, channel, beacon_order = 15, superframe_order = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * PAN_coordinator, battery_life_extension = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * coord_realignment = 0, security_enable = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct ieee802154_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u8 channel, bcn_ord, sf_ord;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u8 page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int pan_coord, blx, coord_realign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) !info->attrs[IEEE802154_ATTR_CHANNEL] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) !info->attrs[IEEE802154_ATTR_BCN_ORD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) !info->attrs[IEEE802154_ATTR_SF_ORD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) !info->attrs[IEEE802154_ATTR_PAN_COORD] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) !info->attrs[IEEE802154_ATTR_BAT_EXT] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) !info->attrs[IEEE802154_ATTR_COORD_REALIGN]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (netif_running(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!ieee802154_mlme_ops(dev)->start_req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) addr.mode = IEEE802154_ADDR_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) addr.short_addr = nla_get_shortaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) addr.pan_id = nla_get_shortaddr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (info->attrs[IEEE802154_ATTR_PAGE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) bcn_ord, sf_ord, pan_coord, blx, coord_realign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* FIXME: add validation for unused parameters to be sane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * for SoftMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u32 channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u8 duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u8 page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) !info->attrs[IEEE802154_ATTR_CHANNELS] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) !info->attrs[IEEE802154_ATTR_DURATION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!ieee802154_mlme_ops(dev)->scan_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (info->attrs[IEEE802154_ATTR_PAGE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) page, duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Request for interface name, index, type, IEEE address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * PAN Id, short address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int rc = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 0, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int s_idx = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) for_each_netdev(net, dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (idx < s_idx || dev->type != ARPHRD_IEEE802154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) NLM_F_MULTI, dev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) cb->args[0] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct ieee802154_mlme_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct ieee802154_mac_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct wpan_phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (!ops->get_mac_params || !ops->set_mac_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (netif_running(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) phy = dev->ieee802154_ptr->wpan_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) get_device(&phy->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ops->get_mac_params(dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (info->attrs[IEEE802154_ATTR_TXPOWER])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (info->attrs[IEEE802154_ATTR_LBT_ENABLED])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (info->attrs[IEEE802154_ATTR_CCA_MODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) params.cca.mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) rc = ops->set_mac_params(dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) wpan_phy_put(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ieee802154_llsec_parse_key_id(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct ieee802154_llsec_key_id *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) memset(desc, 0, sizeof(*desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!info->attrs[IEEE802154_ATTR_PAN_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (info->attrs[IEEE802154_ATTR_SHORT_ADDR]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) desc->device_addr.mode = IEEE802154_ADDR_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!info->attrs[IEEE802154_ATTR_HW_ADDR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) desc->device_addr.mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) desc->id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) switch (desc->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case IEEE802154_SCF_KEY_SHORT_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) desc->short_source = cpu_to_le32(source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case IEEE802154_SCF_KEY_HW_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) desc->extended_source = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ieee802154_llsec_fill_key_id(struct sk_buff *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) const struct ieee802154_llsec_key_id *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_MODE, desc->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) desc->device_addr.pan_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (desc->device_addr.mode == IEEE802154_ADDR_SHORT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) desc->device_addr.short_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (desc->device_addr.mode == IEEE802154_ADDR_LONG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) desc->device_addr.extended_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) IEEE802154_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_ID, desc->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) nla_put_u32(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) le32_to_cpu(desc->short_source)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) nla_put_hwaddr(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) desc->extended_source, IEEE802154_ATTR_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int rc = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct ieee802154_mlme_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct ieee802154_llsec_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!ops->llsec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) IEEE802154_LLSEC_GETPARAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) rc = ops->llsec->get_params(dev, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_ENABLED, params.enabled) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) be32_to_cpu(params.frame_counter)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) rc = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return ieee802154_nl_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int ieee802154_llsec_setparams(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct ieee802154_mlme_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct ieee802154_llsec_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) pr_debug("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!info->attrs[IEEE802154_ATTR_LLSEC_ENABLED] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (!ops->llsec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) params.enabled = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) changed |= IEEE802154_LLSEC_PARAM_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (ieee802154_llsec_parse_key_id(info, ¶ms.out_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) params.out_level = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) u32 fc = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) params.frame_counter = cpu_to_be32(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) rc = ops->llsec->set_params(dev, ¶ms, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct llsec_dump_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) int s_idx, s_idx2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) int portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int nlmsg_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct ieee802154_mlme_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct ieee802154_llsec_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) int (*step)(struct llsec_dump_data *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct llsec_dump_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int first_dev = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) for_each_netdev(net, dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) data.ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (!data.ops->llsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) data.skb = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) data.s_idx = cb->args[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) data.s_idx2 = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) data.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) data.portid = NETLINK_CB(cb->skb).portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) data.nlmsg_seq = cb->nlh->nlmsg_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) data.ops->llsec->lock_table(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) data.ops->llsec->get_table(data.dev, &data.table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) rc = step(&data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) data.ops->llsec->unlock_table(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) cb->args[0] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) ieee802154_nl_llsec_change(struct sk_buff *skb, struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int (*fn)(struct net_device*, struct genl_info*))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) dev = ieee802154_nl_get_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (!ieee802154_mlme_ops(dev)->llsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) rc = fn(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) ieee802154_llsec_parse_key(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct ieee802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) u8 frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) u32 commands[256 / 32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) memset(key, 0, sizeof(*key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) frames = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if ((frames & BIT(IEEE802154_FC_TYPE_MAC_CMD)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) !info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) nla_memcpy(commands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 256 / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (commands[0] || commands[1] || commands[2] || commands[3] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) commands[4] || commands[5] || commands[6] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) commands[7] >= BIT(IEEE802154_CMD_GTS_REQ + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) key->cmd_frame_ids = commands[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) key->frame_types = frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) nla_memcpy(key->key, info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) IEEE802154_LLSEC_KEY_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int llsec_add_key(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct ieee802154_llsec_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct ieee802154_llsec_key_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (ieee802154_llsec_parse_key(info, &key) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ieee802154_llsec_parse_key_id(info, &id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return ops->llsec->add_key(dev, &id, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) int ieee802154_llsec_add_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) (NLM_F_CREATE | NLM_F_EXCL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return ieee802154_nl_llsec_change(skb, info, llsec_add_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static int llsec_remove_key(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct ieee802154_llsec_key_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (ieee802154_llsec_parse_key_id(info, &id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return ops->llsec->del_key(dev, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int ieee802154_llsec_del_key(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return ieee802154_nl_llsec_change(skb, info, llsec_remove_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ieee802154_nl_fill_key(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) const struct ieee802154_llsec_key_entry *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) u32 commands[256 / 32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) IEEE802154_LLSEC_LIST_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ieee802154_llsec_fill_key_id(msg, &key->id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) key->key->frame_types))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (key->key->frame_types & BIT(IEEE802154_FC_TYPE_MAC_CMD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) memset(commands, 0, sizeof(commands));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) commands[7] = key->key->cmd_frame_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) sizeof(commands), commands))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) IEEE802154_LLSEC_KEY_SIZE, key->key->key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int llsec_iter_keys(struct llsec_dump_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct ieee802154_llsec_key_entry *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) int rc = 0, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) list_for_each_entry(pos, &data->table->keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (idx++ < data->s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (ieee802154_nl_fill_key(data->skb, data->portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) data->nlmsg_seq, pos, data->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) data->s_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) int ieee802154_llsec_dump_keys(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) llsec_parse_dev(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct ieee802154_llsec_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) memset(dev, 0, sizeof(*dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) !info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) (!!info->attrs[IEEE802154_ATTR_PAN_ID] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) !!info->attrs[IEEE802154_ATTR_SHORT_ADDR]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (info->attrs[IEEE802154_ATTR_PAN_ID]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) dev->pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev->short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dev->short_addr = cpu_to_le16(IEEE802154_ADDR_UNDEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) dev->hwaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) dev->frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dev->seclevel_exempt = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dev->key_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (dev->key_mode >= __IEEE802154_LLSEC_DEVKEY_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int llsec_add_dev(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct ieee802154_llsec_device desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (llsec_parse_dev(info, &desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return ops->llsec->add_dev(dev, &desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int ieee802154_llsec_add_dev(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) (NLM_F_CREATE | NLM_F_EXCL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return ieee802154_nl_llsec_change(skb, info, llsec_add_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int llsec_del_dev(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) __le64 devaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!info->attrs[IEEE802154_ATTR_HW_ADDR])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return ops->llsec->del_dev(dev, devaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int ieee802154_llsec_del_dev(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return ieee802154_nl_llsec_change(skb, info, llsec_del_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ieee802154_nl_fill_dev(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) const struct ieee802154_llsec_device *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) IEEE802154_LLSEC_LIST_DEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, desc->pan_id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) desc->short_addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) IEEE802154_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) desc->frame_counter) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) desc->seclevel_exempt) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE, desc->key_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static int llsec_iter_devs(struct llsec_dump_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct ieee802154_llsec_device *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) int rc = 0, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) list_for_each_entry(pos, &data->table->devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (idx++ < data->s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (ieee802154_nl_fill_dev(data->skb, data->portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) data->nlmsg_seq, pos, data->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) data->s_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int ieee802154_llsec_dump_devs(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static int llsec_add_devkey(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct ieee802154_llsec_device_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) __le64 devaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ieee802154_llsec_parse_key_id(info, &key.key_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) key.frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return ops->llsec->add_devkey(dev, devaddr, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) int ieee802154_llsec_add_devkey(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) (NLM_F_CREATE | NLM_F_EXCL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return ieee802154_nl_llsec_change(skb, info, llsec_add_devkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) static int llsec_del_devkey(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct ieee802154_llsec_device_key key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) __le64 devaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (!info->attrs[IEEE802154_ATTR_HW_ADDR] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ieee802154_llsec_parse_key_id(info, &key.key_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return ops->llsec->del_devkey(dev, devaddr, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) int ieee802154_llsec_del_devkey(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return ieee802154_nl_llsec_change(skb, info, llsec_del_devkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ieee802154_nl_fill_devkey(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) __le64 devaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) const struct ieee802154_llsec_device_key *devkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) IEEE802154_LLSEC_LIST_DEVKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) IEEE802154_ATTR_PAD) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) devkey->frame_counter) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ieee802154_llsec_fill_key_id(msg, &devkey->key_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static int llsec_iter_devkeys(struct llsec_dump_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct ieee802154_llsec_device *dpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) struct ieee802154_llsec_device_key *kpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) int rc = 0, idx = 0, idx2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) list_for_each_entry(dpos, &data->table->devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (idx++ < data->s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) idx2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) list_for_each_entry(kpos, &dpos->keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (idx2++ < data->s_idx2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (ieee802154_nl_fill_devkey(data->skb, data->portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) data->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) dpos->hwaddr, kpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) data->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) data->s_idx2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) data->s_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) int ieee802154_llsec_dump_devkeys(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) llsec_parse_seclevel(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) struct ieee802154_llsec_seclevel *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) memset(sl, 0, sizeof(*sl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) sl->frame_type = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (!info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) sl->cmd_frame_id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) sl->sec_levels = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) sl->device_override = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) static int llsec_add_seclevel(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) struct ieee802154_llsec_seclevel sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (llsec_parse_seclevel(info, &sl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return ops->llsec->add_seclevel(dev, &sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int ieee802154_llsec_add_seclevel(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) (NLM_F_CREATE | NLM_F_EXCL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return ieee802154_nl_llsec_change(skb, info, llsec_add_seclevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static int llsec_del_seclevel(struct net_device *dev, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct ieee802154_llsec_seclevel sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (llsec_parse_seclevel(info, &sl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return ops->llsec->del_seclevel(dev, &sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) int ieee802154_llsec_del_seclevel(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return ieee802154_nl_llsec_change(skb, info, llsec_del_seclevel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) ieee802154_nl_fill_seclevel(struct sk_buff *msg, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) const struct ieee802154_llsec_seclevel *sl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) const struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) IEEE802154_LLSEC_LIST_SECLEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_FRAME_TYPE, sl->frame_type) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVELS, sl->sec_levels) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) sl->device_override))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) nla_put_u8(msg, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) sl->cmd_frame_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) genlmsg_end(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) genlmsg_cancel(msg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int llsec_iter_seclevels(struct llsec_dump_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct ieee802154_llsec_seclevel *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) int rc = 0, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) list_for_each_entry(pos, &data->table->security_levels, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (idx++ < data->s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (ieee802154_nl_fill_seclevel(data->skb, data->portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) data->nlmsg_seq, pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) data->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) rc = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) data->s_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) int ieee802154_llsec_dump_seclevels(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return ieee802154_llsec_dump_table(skb, cb, llsec_iter_seclevels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }