178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov/* 278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Netlink inteface for IEEE 802.15.4 stack 378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Copyright 2007, 2008 Siemens AG 578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * This program is free software; you can redistribute it and/or modify 778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * it under the terms of the GNU General Public License version 2 878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * as published by the Free Software Foundation. 978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 1078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * This program is distributed in the hope that it will be useful, 1178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * but WITHOUT ANY WARRANTY; without even the implied warranty of 1278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * GNU General Public License for more details. 1478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 1578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * You should have received a copy of the GNU General Public License along 1678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * with this program; if not, write to the Free Software Foundation, Inc., 1778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 1878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * 1978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Written by: 2078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Sergey Lapin <slapin@ossfans.org> 2178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 2278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * Maxim Osipov <maxim.osipov@siemens.com> 2378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov */ 2478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 2678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <linux/kernel.h> 2778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <linux/if_arp.h> 2878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <linux/netdevice.h> 2978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/netlink.h> 3078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/genetlink.h> 3178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/sock.h> 3278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <linux/nl802154.h> 33bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 3478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/af_ieee802154.h> 3578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/nl802154.h> 3678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/ieee802154.h> 3778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include <net/ieee802154_netdev.h> 380a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov#include <net/wpan-phy.h> 3978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 4078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov#include "ieee802154.h" 4178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 42ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheisterstatic int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr) 43ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister{ 44ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister return nla_put_u64(msg, type, swab64((__force u64)hwaddr)); 45ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister} 46ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister 47ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheisterstatic __le64 nla_get_hwaddr(const struct nlattr *nla) 48ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister{ 49ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister return ieee802154_devaddr_from_raw(nla_data(nla)); 50ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister} 51ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister 52ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheisterstatic int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr) 53ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister{ 54ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister return nla_put_u16(msg, type, le16_to_cpu(addr)); 55ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister} 56ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister 57ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheisterstatic __le16 nla_get_shortaddr(const struct nlattr *nla) 58ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister{ 59ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister return cpu_to_le16(nla_get_u16(nla)); 60ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister} 61ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister 6278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovint ieee802154_nl_assoc_indic(struct net_device *dev, 634710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram struct ieee802154_addr *addr, 644710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u8 cap) 6578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 6678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 6778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 6878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 6978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 70ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister if (addr->mode != IEEE802154_ADDR_LONG) { 7178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_err("%s: received non-long source address!\n", __func__); 7278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 7378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 7478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 7578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); 7678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 7778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 7878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 79be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 80be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 81be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 82be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 83ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, 84ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr->extended_addr) || 85be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) 86be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 8778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 882a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 8978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 9078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 9178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 9278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 9378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 9478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_assoc_indic); 9578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 96b70ab2e87f17176d18f67ef331064441a032b5f3Phoebe Buckheisterint ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, 974710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u8 status) 9878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 9978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 10078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 10178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 10278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 10378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF); 10478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 10578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 10678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 107be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 108be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 109be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 110be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 111ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || 112be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) 113be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 1142a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 11578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 11678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 11778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 11878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 11978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 12078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_assoc_confirm); 12178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 12278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovint ieee802154_nl_disassoc_indic(struct net_device *dev, 1234710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram struct ieee802154_addr *addr, 1244710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u8 reason) 12578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 12678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 12778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 12878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 12978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 13078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); 13178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 13278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 13378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 134be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 135be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 136be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 137be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr)) 138be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 139ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister if (addr->mode == IEEE802154_ADDR_LONG) { 140ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, 141ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr->extended_addr)) 142be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 143be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller } else { 144ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, 145ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr->short_addr)) 146be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 147be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller } 148be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) 149be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 1502a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 15178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 15278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 15378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 15478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 15578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 15678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_disassoc_indic); 15778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 15878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovint ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) 15978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 16078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 16178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 16278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 16378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 16478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF); 16578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 16678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 16778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 168be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 169be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 170be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 171be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 172be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) 173be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 1742a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 17578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 17678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 17778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 17878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 17978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 18078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); 18178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 182b70ab2e87f17176d18f67ef331064441a032b5f3Phoebe Buckheisterint ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, 183b70ab2e87f17176d18f67ef331064441a032b5f3Phoebe Buckheister __le16 coord_addr) 18478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 18578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 18678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 18778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 18878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 18978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); 19078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 19178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 19278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 193be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 194be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 195be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 196be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 197ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, 198ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister coord_addr) || 199ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) 200be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 2012a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 20278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 20378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 20478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 20578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 20678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 20778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_beacon_indic); 20878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 20978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovint ieee802154_nl_scan_confirm(struct net_device *dev, 2104710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u8 status, u8 scan_type, 2114710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u32 unscanned, u8 page, 2124710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u8 *edl/* , struct list_head *pan_desc_list */) 21378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 21478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 21578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 21678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 21778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 21878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF); 21978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 22078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 22178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 222be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 223be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 224be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 225be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 226be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) || 227be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) || 228be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) || 229be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) || 230be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller (edl && 231be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl))) 232be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 2332a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 23478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 23578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 23678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 23778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 23878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 23978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_scan_confirm); 24078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 24178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovint ieee802154_nl_start_confirm(struct net_device *dev, u8 status) 24278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 24378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 24478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 24578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 24678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 24778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov msg = ieee802154_nl_create(0, IEEE802154_START_CONF); 24878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 24978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 25078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 251be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 252be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 253be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 254be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 255be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) 256be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 2572a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); 25878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 25978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 26078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 26178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENOBUFS; 26278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 26378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-SolenikovEXPORT_SYMBOL(ieee802154_nl_start_confirm); 26478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 26515e473046cb6e5d18a4d0057e61d76315230382bEric W. Biedermanstatic int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, 2664710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram u32 seq, int flags, struct net_device *dev) 26778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 26878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov void *hdr; 2690a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov struct wpan_phy *phy; 270e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct ieee802154_mlme_ops *ops; 271ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister __le16 short_addr, pan_id; 27278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 27378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 27478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 27578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, 2764710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram IEEE802154_LIST_IFACE); 27778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!hdr) 27878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov goto out; 27978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 280e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister ops = ieee802154_mlme_ops(dev); 281e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister phy = ops->get_phy(dev); 2820a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov BUG_ON(!phy); 2830a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov 284e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister short_addr = ops->get_short_addr(dev); 285e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister pan_id = ops->get_pan_id(dev); 286b70ab2e87f17176d18f67ef331064441a032b5f3Phoebe Buckheister 287be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 288be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || 289be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 290be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, 291be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller dev->dev_addr) || 292ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || 293ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id)) 294be51da0f3e346eb520c4ffdaecb8ba6fb4337a76David S. Miller goto nla_put_failure; 295e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 296e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (ops->get_mac_params) { 297e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct ieee802154_mac_params params; 298e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 299e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister ops->get_mac_params(dev, ¶ms); 300e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 301e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, 302e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.transmit_power) || 303e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) || 304e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, 305e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.cca_mode) || 306e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, 307e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.cca_ed_level) || 308e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, 309e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.csma_retries) || 310e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, 311e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.min_be) || 312e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, 313e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.max_be) || 314e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, 315e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.frame_retries)) 316e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister goto nla_put_failure; 317e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister } 318e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 3190a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov wpan_phy_put(phy); 32078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return genlmsg_end(msg, hdr); 32178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 32278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovnla_put_failure: 3230a868b26c8ba32f6988f87dd81697917a2f612b6Dmitry Eremin-Solenikov wpan_phy_put(phy); 32478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov genlmsg_cancel(msg, hdr); 32578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovout: 32678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EMSGSIZE; 32778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 32878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 32978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov/* Requests from userspace */ 33078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovstatic struct net_device *ieee802154_nl_get_dev(struct genl_info *info) 33178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 33278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 33378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 33478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { 33578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov char name[IFNAMSIZ + 1]; 3364710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram 33778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], 3384710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram sizeof(name)); 33978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = dev_get_by_name(&init_net, name); 3404710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) { 34178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = dev_get_by_index(&init_net, 34278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); 3434710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram } else { 34478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return NULL; 3454710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram } 34678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 34778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 34878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return NULL; 34978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 35078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (dev->type != ARPHRD_IEEE802154) { 35178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 35278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return NULL; 35378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 35478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 35578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return dev; 35678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 35778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 3581c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info) 35978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 36078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 361ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister struct ieee802154_addr addr; 36278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 page; 36356aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger int ret = -EOPNOTSUPP; 36478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 36578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!info->attrs[IEEE802154_ATTR_CHANNEL] || 36678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || 36778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] && 36878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) || 36978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_CAPABILITY]) 37078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 37178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 37278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 37378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 37478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 37556aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger if (!ieee802154_mlme_ops(dev)->assoc_req) 37656aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger goto out; 37778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 37878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { 379ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_LONG; 380ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.extended_addr = nla_get_hwaddr( 381ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]); 38278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } else { 383ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_SHORT; 384ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.short_addr = nla_get_shortaddr( 38578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); 38678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 387ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.pan_id = nla_get_shortaddr( 388ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); 38978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 39078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_PAGE]) 39178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); 39278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov else 39378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = 0; 39478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 39578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr, 39678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]), 39778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page, 39878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); 39978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 40056aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesbergerout: 40178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 40278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return ret; 40378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 40478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 4051c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info) 40678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 40778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 408ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister struct ieee802154_addr addr; 40956aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger int ret = -EOPNOTSUPP; 41078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 41178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!info->attrs[IEEE802154_ATTR_STATUS] || 41278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || 41378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) 41478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 41578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 41678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 41778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 41878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 41956aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger if (!ieee802154_mlme_ops(dev)->assoc_resp) 42056aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger goto out; 42178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 422ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_LONG; 423ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.extended_addr = nla_get_hwaddr( 424ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); 425ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 42678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 42778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, 428ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), 42978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); 43078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 43156aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesbergerout: 43278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 43378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return ret; 43478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 43578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 4361c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info) 43778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 43878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 439ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister struct ieee802154_addr addr; 44056aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger int ret = -EOPNOTSUPP; 44178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 44278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && 4434710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || 44478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_REASON]) 44578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 44678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 44778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 44878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 44978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 45056aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger if (!ieee802154_mlme_ops(dev)->disassoc_req) 45156aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger goto out; 45278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 45378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { 454ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_LONG; 455ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.extended_addr = nla_get_hwaddr( 456ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); 45778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } else { 458ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_SHORT; 459ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.short_addr = nla_get_shortaddr( 46078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); 46178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 462ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); 46378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 46478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, 46578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); 46678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 46756aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesbergerout: 46878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 46978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return ret; 47078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 47178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 4724710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram/* PANid, channel, beacon_order = 15, superframe_order = 15, 47378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * PAN_coordinator, battery_life_extension = 0, 47478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov * coord_realignment = 0, security_enable = 0 47578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov*/ 4761c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) 47778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 47878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 479ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister struct ieee802154_addr addr; 48078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 48178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 channel, bcn_ord, sf_ord; 48278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 page; 48378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov int pan_coord, blx, coord_realign; 48456aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger int ret = -EOPNOTSUPP; 48578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 48678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || 48778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || 48878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_CHANNEL] || 48978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_BCN_ORD] || 49078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_SF_ORD] || 49178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_PAN_COORD] || 49278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_BAT_EXT] || 49378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_COORD_REALIGN] 49478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ) 49578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 49678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 49778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 49878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 49978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 50056aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger if (!ieee802154_mlme_ops(dev)->start_req) 50156aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger goto out; 50278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 503ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.mode = IEEE802154_ADDR_SHORT; 504ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.short_addr = nla_get_shortaddr( 50578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); 506ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister addr.pan_id = nla_get_shortaddr( 507ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); 50878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 50978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); 51078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); 51178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]); 51278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]); 51378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); 51478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); 51578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 51678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_PAGE]) 51778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); 51878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov else 51978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = 0; 52078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 52178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 522ae531b9475f62c5e1863508604cd6b3faf362d56Phoebe Buckheister if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) { 52378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); 52478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 52578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 52678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 52778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 52878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, 52978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov bcn_ord, sf_ord, pan_coord, blx, coord_realign); 53078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 53156aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesbergerout: 53278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 53378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return ret; 53478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 53578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 5361c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) 53778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 53878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 53956aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger int ret = -EOPNOTSUPP; 54078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 type; 54178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u32 channels; 54278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 duration; 54378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov u8 page; 54478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 54578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || 54678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_CHANNELS] || 54778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov !info->attrs[IEEE802154_ATTR_DURATION]) 54878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -EINVAL; 54978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 55078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 55178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 55278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 55356aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger if (!ieee802154_mlme_ops(dev)->scan_req) 55456aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesberger goto out; 55578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 55678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); 55778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); 55878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); 55978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 56078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (info->attrs[IEEE802154_ATTR_PAGE]) 56178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); 56278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov else 56378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov page = 0; 56478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 56578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 5664710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, 5674710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram page, duration); 56878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 56956aa091d60a63fee83d2c894edb69b7c159966c7Werner Almesbergerout: 57078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 57178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return ret; 57278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 57378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 5741c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) 57578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 57678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov /* Request for interface name, index, type, IEEE address, 5774710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram * PAN Id, short address 5784710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram */ 57978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct sk_buff *msg; 58078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev = NULL; 58178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov int rc = -ENOBUFS; 58278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 58378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 58478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 58578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev = ieee802154_nl_get_dev(info); 58678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!dev) 58778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return -ENODEV; 58878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 58958050fce3530939372e6c2f4b4beb76fcb4caa65Thomas Graf msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 59078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (!msg) 59178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov goto out_dev; 59278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 59315e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq, 5944710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram 0, dev); 59578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (rc < 0) 59678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov goto out_free; 59778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 59878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 59978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 60078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return genlmsg_reply(msg, info); 60178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovout_free: 60278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov nlmsg_free(msg); 60378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovout_dev: 60478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov dev_put(dev); 60578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return rc; 60678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 60778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 6081c582d915da13ca21ad375ae04ec1bd6193418b2Johannes Bergint ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) 60978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov{ 61078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net *net = sock_net(skb->sk); 61178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov struct net_device *dev; 61278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov int idx; 61378fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov int s_idx = cb->args[0]; 61478fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 61578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov pr_debug("%s\n", __func__); 61678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 61778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov idx = 0; 61878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov for_each_netdev(net, dev) { 61978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) 62078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov goto cont; 62178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 62215e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid, 6234710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram cb->nlh->nlmsg_seq, 6244710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram NLM_F_MULTI, dev) < 0) 62578fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov break; 62678fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikovcont: 62778fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov idx++; 62878fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov } 62978fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov cb->args[0] = idx; 63078fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov 63178fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov return skb->len; 63278fe738d1a631ec34a29d830880e38f5c14c1371Dmitry Eremin-Solenikov} 633e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 634e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheisterint ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) 635e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister{ 636e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct net_device *dev = NULL; 637e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct ieee802154_mlme_ops *ops; 638e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct ieee802154_mac_params params; 639e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister struct wpan_phy *phy; 640e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister int rc = -EINVAL; 641e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 642e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister pr_debug("%s\n", __func__); 643e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 644e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister dev = ieee802154_nl_get_dev(info); 645e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (!dev) 646e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister return -ENODEV; 647e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 648e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister ops = ieee802154_mlme_ops(dev); 649e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 650e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (!ops->get_mac_params || !ops->set_mac_params) { 651e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister rc = -EOPNOTSUPP; 652e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister goto out; 653e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister } 654e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 655e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (netif_running(dev)) { 656e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister rc = -EBUSY; 657e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister goto out; 658e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister } 659e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 660e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] && 661e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_CCA_MODE] && 662e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] && 663e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] && 664e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] && 665e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] && 666e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) 667e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister goto out; 668e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 669e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister phy = ops->get_phy(dev); 670e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 671e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) || 672e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) || 673e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister (!phy->set_cca_ed_level && 674e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) || 675e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister (!phy->set_csma_params && 676e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] || 677e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] || 678e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) || 679e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister (!phy->set_frame_retries && 680e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) { 681e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister rc = -EOPNOTSUPP; 682e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister goto out_phy; 683e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister } 684e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 685e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister ops->get_mac_params(dev, ¶ms); 686e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 687e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_TXPOWER]) 688e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); 689e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 690e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) 691e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]); 692e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 693e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_CCA_MODE]) 694e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]); 695e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 696e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) 697e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]); 698e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 699e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES]) 700e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]); 701e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 702e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]) 703e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]); 704e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 705e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) 706e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]); 707e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 708e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) 709e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]); 710e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 711e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister rc = ops->set_mac_params(dev, ¶ms); 712e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 713e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister wpan_phy_put(phy); 714e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister dev_put(dev); 715e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister return rc; 716e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister 717e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheisterout_phy: 718e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister wpan_phy_put(phy); 719e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheisterout: 720e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister dev_put(dev); 721e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister return rc; 722e462ded699aa2cca04b68fbf203ea4675d4c44d4Phoebe Buckheister} 7233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 7273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_llsec_parse_key_id(struct genl_info *info, 7283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key_id *desc) 7293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 7303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister memset(desc, 0, sizeof(*desc)); 7313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]) 7333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 7343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]); 7363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) { 7383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_PAN_ID] && 7393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] || 7403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister info->attrs[IEEE802154_ATTR_HW_ADDR])) 7413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 7423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]); 7443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_SHORT_ADDR]) { 7463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.mode = IEEE802154_ADDR_SHORT; 7473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]); 7483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } else { 7493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.mode = IEEE802154_ADDR_LONG; 7503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); 7513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 7523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 7533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT && 7553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID]) 7563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 7573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX && 7593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]) 7603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 7613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX && 7633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED]) 7643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 7653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT) 7673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID]); 7683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister switch (desc->mode) { 7703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister case IEEE802154_SCF_KEY_SHORT_INDEX: 7713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister { 7723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]); 7734710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram 7743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->short_source = cpu_to_le32(source); 7753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 7763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 7773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister case IEEE802154_SCF_KEY_HW_INDEX: 7783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->extended_source = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED]); 7793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 7803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 7813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 7833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 7843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 7863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_llsec_fill_key_id(struct sk_buff *msg, 7873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct ieee802154_llsec_key_id *desc) 7883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 7893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_MODE, desc->mode)) 7903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 7913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) { 7933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, 7943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.pan_id)) 7953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 7963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 7973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->device_addr.mode == IEEE802154_ADDR_SHORT && 7983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, 7993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.short_addr)) 8003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 8013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->device_addr.mode == IEEE802154_ADDR_LONG && 8033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, 8043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->device_addr.extended_addr)) 8053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 8063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 8073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT && 8093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_ID, desc->id)) 8103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 8113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX && 8133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT, 8143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister le32_to_cpu(desc->short_source))) 8153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 8163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX && 8183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_hwaddr(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED, 8193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->extended_source)) 8203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 8213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 8233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 8243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info) 8263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 8273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct sk_buff *msg; 8283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net_device *dev = NULL; 8293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = -ENOBUFS; 8303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops; 8313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister void *hdr; 8323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_params params; 8333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister pr_debug("%s\n", __func__); 8353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev = ieee802154_nl_get_dev(info); 8373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!dev) 8383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -ENODEV; 8393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ops = ieee802154_mlme_ops(dev); 841b3f7a7b48f429e52f3d3dc36d253627c2a73803bDan Carpenter if (!ops->llsec) { 842b3f7a7b48f429e52f3d3dc36d253627c2a73803bDan Carpenter rc = -EOPNOTSUPP; 843b3f7a7b48f429e52f3d3dc36d253627c2a73803bDan Carpenter goto out_dev; 844b3f7a7b48f429e52f3d3dc36d253627c2a73803bDan Carpenter } 8453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 8473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!msg) 8483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out_dev; 8493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0, 8514710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram IEEE802154_LLSEC_GETPARAMS); 8523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!hdr) 8533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out_free; 8543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = ops->llsec->get_params(dev, ¶ms); 8563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (rc < 0) 8573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out_free; 8583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 8603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 8613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_ENABLED, params.enabled) || 8623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) || 8633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, 8643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister be32_to_cpu(params.frame_counter)) || 8653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) 8663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out_free; 8673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev_put(dev); 8693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_reply(msg, info); 8713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout_free: 8723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nlmsg_free(msg); 8733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout_dev: 8743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev_put(dev); 8753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 8763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 8773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_setparams(struct sk_buff *skb, struct genl_info *info) 8793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 8803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net_device *dev = NULL; 8813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = -EINVAL; 8823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops; 8833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_params params; 8843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int changed = 0; 8853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister pr_debug("%s\n", __func__); 8873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev = ieee802154_nl_get_dev(info); 8893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!dev) 8903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -ENODEV; 8913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_ENABLED] && 8933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE] && 8943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) 8953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 8963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 8973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ops = ieee802154_mlme_ops(dev); 8983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!ops->llsec) { 8993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = -EOPNOTSUPP; 9003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 9013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL] && 9043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) > 7) 9053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 9063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]) { 9083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister params.enabled = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]); 9093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister changed |= IEEE802154_LLSEC_PARAM_ENABLED; 9103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]) { 9133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_llsec_parse_key_id(info, ¶ms.out_key)) 9143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 9153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister changed |= IEEE802154_LLSEC_PARAM_OUT_KEY; 9173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) { 9203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister params.out_level = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]); 9213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL; 9223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]) { 9253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister u32 fc = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]); 9263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister params.frame_counter = cpu_to_be32(fc); 9283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER; 9293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = ops->llsec->set_params(dev, ¶ms, changed); 9323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev_put(dev); 9343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 9363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout: 9373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev_put(dev); 9383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 9393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 9403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstruct llsec_dump_data { 9443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct sk_buff *skb; 9453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int s_idx, s_idx2; 9463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int portid; 9473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int nlmsg_seq; 9483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net_device *dev; 9493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops; 9503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_table *table; 9513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister}; 9523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 9543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb, 9554710d806fcb825156e0a7b3a81104915c5e90f5dVarka Bhadram int (*step)(struct llsec_dump_data *)) 9563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 9573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net *net = sock_net(skb->sk); 9583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net_device *dev; 9593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct llsec_dump_data data; 9603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int idx = 0; 9613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int first_dev = cb->args[0]; 9623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc; 9633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister for_each_netdev(net, dev) { 9653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx < first_dev || dev->type != ARPHRD_IEEE802154) 9663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto skip; 9673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.ops = ieee802154_mlme_ops(dev); 9693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!data.ops->llsec) 9703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto skip; 9713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.skb = skb; 9733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.s_idx = cb->args[1]; 9743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.s_idx2 = cb->args[2]; 9753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.dev = dev; 9763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.portid = NETLINK_CB(cb->skb).portid; 9773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.nlmsg_seq = cb->nlh->nlmsg_seq; 9783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.ops->llsec->lock_table(dev); 9803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.ops->llsec->get_table(data.dev, &data.table); 9813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = step(&data); 9823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data.ops->llsec->unlock_table(dev); 9833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (rc < 0) 9853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 9863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterskip: 9883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister idx++; 9893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 9903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister cb->args[0] = idx; 9913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return skb->len; 9933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 9943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 9953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 9963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_nl_llsec_change(struct sk_buff *skb, struct genl_info *info, 9973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int (*fn)(struct net_device*, struct genl_info*)) 9983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 9993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct net_device *dev = NULL; 10003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = -EINVAL; 10013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev = ieee802154_nl_get_dev(info); 10033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!dev) 10043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -ENODEV; 10053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!ieee802154_mlme_ops(dev)->llsec) 10073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = -EOPNOTSUPP; 10083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister else 10093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = fn(dev, info); 10103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev_put(dev); 10123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 10133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 10183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_llsec_parse_key(struct genl_info *info, 10193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key *key) 10203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister u8 frames; 10223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister u32 commands[256 / 32]; 10233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister memset(key, 0, sizeof(*key)); 10253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES] || 10273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES]) 10283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister frames = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES]); 10313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if ((frames & BIT(IEEE802154_FC_TYPE_MAC_CMD)) && 10323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS]) 10333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS]) { 10363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_memcpy(commands, 10373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS], 10383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 256 / 8); 10393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (commands[0] || commands[1] || commands[2] || commands[3] || 10413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister commands[4] || commands[5] || commands[6] || 10423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister commands[7] >= BIT(IEEE802154_CMD_GTS_REQ + 1)) 10433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister key->cmd_frame_ids = commands[7]; 10463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 10473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister key->frame_types = frames; 10493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_memcpy(key->key, info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES], 10513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_KEY_SIZE); 10523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 10543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_add_key(struct net_device *dev, struct genl_info *info) 10573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 10593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key key; 10603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key_id id; 10613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_llsec_parse_key(info, &key) || 10633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_parse_key_id(info, &id)) 10643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->add_key(dev, &id, &key); 10673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_add_key(struct sk_buff *skb, struct genl_info *info) 10703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) != 10723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister (NLM_F_CREATE | NLM_F_EXCL)) 10733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_add_key); 10763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_remove_key(struct net_device *dev, struct genl_info *info) 10793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 10813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key_id id; 10823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_llsec_parse_key_id(info, &id)) 10843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 10853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->del_key(dev, &id); 10873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_del_key(struct sk_buff *skb, struct genl_info *info) 10903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_remove_key); 10923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 10933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 10943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 10953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_nl_fill_key(struct sk_buff *msg, u32 portid, u32 seq, 10963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct ieee802154_llsec_key_entry *key, 10973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct net_device *dev) 10983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 10993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister void *hdr; 11003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister u32 commands[256 / 32]; 11013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI, 11033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_LIST_KEY); 11043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!hdr) 11053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 11063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 11083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 11093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_fill_key_id(msg, &key->id) || 11103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES, 11113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister key->key->frame_types)) 11123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 11133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (key->key->frame_types & BIT(IEEE802154_FC_TYPE_MAC_CMD)) { 11153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister memset(commands, 0, sizeof(commands)); 11163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister commands[7] = key->key->cmd_frame_ids; 11173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS, 11183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sizeof(commands), commands)) 11193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 11203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 11213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_BYTES, 11233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_KEY_SIZE, key->key->key)) 11243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 11253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_end(msg, hdr); 11273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 11283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisternla_put_failure: 11303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_cancel(msg, hdr); 11313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout: 11323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 11333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 11343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_iter_keys(struct llsec_dump_data *data) 11363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 11373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_key_entry *pos; 11383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = 0, idx = 0; 11393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister list_for_each_entry(pos, &data->table->keys, list) { 11413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx++ < data->s_idx) 11423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister continue; 11433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_nl_fill_key(data->skb, data->portid, 11453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->nlmsg_seq, pos, data->dev)) { 11463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = -EMSGSIZE; 11473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 11483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 11493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->s_idx++; 11513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 11523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 11543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 11553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_dump_keys(struct sk_buff *skb, struct netlink_callback *cb) 11573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 11583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys); 11593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 11603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 11643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterllsec_parse_dev(struct genl_info *info, 11653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device *dev) 11663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 11673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister memset(dev, 0, sizeof(*dev)); 11683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] || 11703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_HW_ADDR] || 11713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE] || 11723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE] || 11733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister (!!info->attrs[IEEE802154_ATTR_PAN_ID] != 11743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !!info->attrs[IEEE802154_ATTR_SHORT_ADDR])) 11753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 11763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (info->attrs[IEEE802154_ATTR_PAN_ID]) { 11783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]); 11793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]); 11803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } else { 11813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->short_addr = cpu_to_le16(IEEE802154_ADDR_UNDEF); 11823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 11833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->hwaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); 11853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]); 11863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->seclevel_exempt = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]); 11873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dev->key_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE]); 11883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (dev->key_mode >= __IEEE802154_LLSEC_DEVKEY_MAX) 11903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 11913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 11933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 11943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 11953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_add_dev(struct net_device *dev, struct genl_info *info) 11963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 11973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 11983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device desc; 11993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (llsec_parse_dev(info, &desc)) 12013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 12023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->add_dev(dev, &desc); 12043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_add_dev(struct sk_buff *skb, struct genl_info *info) 12073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) != 12093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister (NLM_F_CREATE | NLM_F_EXCL)) 12103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 12113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_add_dev); 12133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_del_dev(struct net_device *dev, struct genl_info *info) 12163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 12183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister __le64 devaddr; 12193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_HW_ADDR]) 12213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 12223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); 12243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->del_dev(dev, devaddr); 12263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_del_dev(struct sk_buff *skb, struct genl_info *info) 12293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_del_dev); 12313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 12343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_nl_fill_dev(struct sk_buff *msg, u32 portid, u32 seq, 12353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct ieee802154_llsec_device *desc, 12363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct net_device *dev) 12373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister void *hdr; 12393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI, 12413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_LIST_DEV); 12423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!hdr) 12433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 12443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 12463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 12473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, desc->pan_id) || 12483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, 12493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->short_addr) || 12503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr) || 12513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, 12523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->frame_counter) || 12533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE, 12543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister desc->seclevel_exempt) || 12553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE, desc->key_mode)) 12563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 12573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_end(msg, hdr); 12593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 12603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisternla_put_failure: 12623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_cancel(msg, hdr); 12633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout: 12643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 12653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_iter_devs(struct llsec_dump_data *data) 12683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device *pos; 12703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = 0, idx = 0; 12713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister list_for_each_entry(pos, &data->table->devices, list) { 12733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx++ < data->s_idx) 12743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister continue; 12753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_nl_fill_dev(data->skb, data->portid, 12773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->nlmsg_seq, pos, data->dev)) { 12783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = -EMSGSIZE; 12793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 12803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 12813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->s_idx++; 12833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 12843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 12863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_dump_devs(struct sk_buff *skb, struct netlink_callback *cb) 12893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs); 12913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 12923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 12953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_add_devkey(struct net_device *dev, struct genl_info *info) 12963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 12973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 12983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device_key key; 12993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister __le64 devaddr; 13003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] || 13023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_HW_ADDR] || 13033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_parse_key_id(info, &key.key_id)) 13043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 13053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); 13073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister key.frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]); 13083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->add_devkey(dev, devaddr, &key); 13103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 13113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_add_devkey(struct sk_buff *skb, struct genl_info *info) 13133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 13143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) != 13153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister (NLM_F_CREATE | NLM_F_EXCL)) 13163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 13173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_add_devkey); 13193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 13203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_del_devkey(struct net_device *dev, struct genl_info *info) 13223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 13233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 13243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device_key key; 13253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister __le64 devaddr; 13263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_HW_ADDR] || 13283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_parse_key_id(info, &key.key_id)) 13293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 13303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); 13323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->del_devkey(dev, devaddr, &key); 13343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 13353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_del_devkey(struct sk_buff *skb, struct genl_info *info) 13373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 13383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_del_devkey); 13393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 13403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 13423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_nl_fill_devkey(struct sk_buff *msg, u32 portid, u32 seq, 13433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister __le64 devaddr, 13443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct ieee802154_llsec_device_key *devkey, 13453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct net_device *dev) 13463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 13473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister void *hdr; 13483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI, 13503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_LIST_DEVKEY); 13513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!hdr) 13523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 13533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 13553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 13563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr) || 13573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, 13583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister devkey->frame_counter) || 13593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister ieee802154_llsec_fill_key_id(msg, &devkey->key_id)) 13603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 13613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_end(msg, hdr); 13633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 13643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisternla_put_failure: 13663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_cancel(msg, hdr); 13673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout: 13683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 13693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 13703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_iter_devkeys(struct llsec_dump_data *data) 13723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 13733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device *dpos; 13743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_device_key *kpos; 13753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = 0, idx = 0, idx2; 13763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister list_for_each_entry(dpos, &data->table->devices, list) { 13783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx++ < data->s_idx) 13793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister continue; 13803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister idx2 = 0; 13823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister list_for_each_entry(kpos, &dpos->keys, list) { 13843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx2++ < data->s_idx2) 13853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister continue; 13863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_nl_fill_devkey(data->skb, data->portid, 13883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->nlmsg_seq, 13893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister dpos->hwaddr, kpos, 13903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->dev)) { 13913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc = -EMSGSIZE; 13923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 13933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->s_idx2++; 13953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 13963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 13973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->s_idx++; 13983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 13993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 14013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_dump_devkeys(struct sk_buff *skb, 14043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct netlink_callback *cb) 14053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys); 14073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 14123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterllsec_parse_seclevel(struct genl_info *info, 14133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_seclevel *sl) 14143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister memset(sl, 0, sizeof(*sl)); 14163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE] || 14183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS] || 14193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]) 14203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 14213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->frame_type = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE]); 14233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD) { 14243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID]) 14253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 14263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->cmd_frame_id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID]); 14283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 14293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->sec_levels = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS]); 14313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->device_override = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]); 14323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14333e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 14343e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14353e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14363e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_add_seclevel(struct net_device *dev, struct genl_info *info) 14373e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14383e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 14393e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_seclevel sl; 14403e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14413e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (llsec_parse_seclevel(info, &sl)) 14423e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 14433e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14443e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->add_seclevel(dev, &sl); 14453e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14463e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14473e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_add_seclevel(struct sk_buff *skb, struct genl_info *info) 14483e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14493e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) != 14503e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister (NLM_F_CREATE | NLM_F_EXCL)) 14513e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 14523e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14533e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_add_seclevel); 14543e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14553e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14563e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_del_seclevel(struct net_device *dev, struct genl_info *info) 14573e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14583e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); 14593e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_seclevel sl; 14603e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14613e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (llsec_parse_seclevel(info, &sl)) 14623e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EINVAL; 14633e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14643e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ops->llsec->del_seclevel(dev, &sl); 14653e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14663e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14673e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_del_seclevel(struct sk_buff *skb, struct genl_info *info) 14683e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14693e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_nl_llsec_change(skb, info, llsec_del_seclevel); 14703e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 14713e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14723e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int 14733e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterieee802154_nl_fill_seclevel(struct sk_buff *msg, u32 portid, u32 seq, 14743e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct ieee802154_llsec_seclevel *sl, 14753e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister const struct net_device *dev) 14763e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 14773e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister void *hdr; 14783e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14793e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI, 14803e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister IEEE802154_LLSEC_LIST_SECLEVEL); 14813e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (!hdr) 14823e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto out; 14833e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14843e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || 14853e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || 14863e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_FRAME_TYPE, sl->frame_type) || 14873e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVELS, sl->sec_levels) || 14883e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE, 14893e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->device_override)) 14903e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 14913e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14923e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD && 14933e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister nla_put_u8(msg, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID, 14943e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister sl->cmd_frame_id)) 14953e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister goto nla_put_failure; 14963e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 14973e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_end(msg, hdr); 14983e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return 0; 14993e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15003e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisternla_put_failure: 15013e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister genlmsg_cancel(msg, hdr); 15023e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterout: 15033e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return -EMSGSIZE; 15043e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 15053e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15063e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterstatic int llsec_iter_seclevels(struct llsec_dump_data *data) 15073e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 15083e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct ieee802154_llsec_seclevel *pos; 15093e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister int rc = 0, idx = 0; 15103e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15113e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister list_for_each_entry(pos, &data->table->security_levels, list) { 15123e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (idx++ < data->s_idx) 15133e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister continue; 15143e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15153e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister if (ieee802154_nl_fill_seclevel(data->skb, data->portid, 15163e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->nlmsg_seq, pos, 15173e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->dev)) { 15183e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister rc = -EMSGSIZE; 15193e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister break; 15203e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 15213e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15223e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister data->s_idx++; 15233e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister } 15243e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15253e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return rc; 15263e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 15273e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister 15283e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheisterint ieee802154_llsec_dump_seclevels(struct sk_buff *skb, 15293e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister struct netlink_callback *cb) 15303e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister{ 15313e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister return ieee802154_llsec_dump_table(skb, cb, llsec_iter_seclevels); 15323e9c156e2c210ab67b12b1b692983a6b97c19d3fPhoebe Buckheister} 1533