Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Netlink interface for IEEE 802.15.4 stack
0004  *
0005  * Copyright 2007, 2008 Siemens AG
0006  *
0007  * Written by:
0008  * Sergey Lapin <slapin@ossfans.org>
0009  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
0010  * Maxim Osipov <maxim.osipov@siemens.com>
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/gfp.h>
0015 #include <net/genetlink.h>
0016 #include <linux/nl802154.h>
0017 
0018 #include "ieee802154.h"
0019 
0020 static unsigned int ieee802154_seq_num;
0021 static DEFINE_SPINLOCK(ieee802154_seq_lock);
0022 
0023 /* Requests to userspace */
0024 struct sk_buff *ieee802154_nl_create(int flags, u8 req)
0025 {
0026     void *hdr;
0027     struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
0028     unsigned long f;
0029 
0030     if (!msg)
0031         return NULL;
0032 
0033     spin_lock_irqsave(&ieee802154_seq_lock, f);
0034     hdr = genlmsg_put(msg, 0, ieee802154_seq_num++,
0035               &nl802154_family, flags, req);
0036     spin_unlock_irqrestore(&ieee802154_seq_lock, f);
0037     if (!hdr) {
0038         nlmsg_free(msg);
0039         return NULL;
0040     }
0041 
0042     return msg;
0043 }
0044 
0045 int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
0046 {
0047     struct nlmsghdr *nlh = nlmsg_hdr(msg);
0048     void *hdr = genlmsg_data(nlmsg_data(nlh));
0049 
0050     genlmsg_end(msg, hdr);
0051 
0052     return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC);
0053 }
0054 
0055 struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
0056                     int flags, u8 req)
0057 {
0058     void *hdr;
0059     struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
0060 
0061     if (!msg)
0062         return NULL;
0063 
0064     hdr = genlmsg_put_reply(msg, info,
0065                 &nl802154_family, flags, req);
0066     if (!hdr) {
0067         nlmsg_free(msg);
0068         return NULL;
0069     }
0070 
0071     return msg;
0072 }
0073 
0074 int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info)
0075 {
0076     struct nlmsghdr *nlh = nlmsg_hdr(msg);
0077     void *hdr = genlmsg_data(nlmsg_data(nlh));
0078 
0079     genlmsg_end(msg, hdr);
0080 
0081     return genlmsg_reply(msg, info);
0082 }
0083 
0084 static const struct genl_small_ops ieee802154_ops[] = {
0085     /* see nl-phy.c */
0086     IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy,
0087             ieee802154_dump_phy),
0088     IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
0089     IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
0090     /* see nl-mac.c */
0091     IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
0092     IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
0093     IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req),
0094     IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req),
0095     IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
0096     IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
0097             ieee802154_dump_iface),
0098     IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
0099     IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams),
0100     IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams),
0101     IEEE802154_DUMP(IEEE802154_LLSEC_LIST_KEY, NULL,
0102             ieee802154_llsec_dump_keys),
0103     IEEE802154_OP(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
0104     IEEE802154_OP(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
0105     IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEV, NULL,
0106             ieee802154_llsec_dump_devs),
0107     IEEE802154_OP(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
0108     IEEE802154_OP(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
0109     IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
0110             ieee802154_llsec_dump_devkeys),
0111     IEEE802154_OP(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
0112     IEEE802154_OP(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
0113     IEEE802154_DUMP(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
0114             ieee802154_llsec_dump_seclevels),
0115     IEEE802154_OP(IEEE802154_LLSEC_ADD_SECLEVEL,
0116               ieee802154_llsec_add_seclevel),
0117     IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL,
0118               ieee802154_llsec_del_seclevel),
0119 };
0120 
0121 static const struct genl_multicast_group ieee802154_mcgrps[] = {
0122     [IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, },
0123     [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
0124 };
0125 
0126 struct genl_family nl802154_family __ro_after_init = {
0127     .hdrsize    = 0,
0128     .name       = IEEE802154_NL_NAME,
0129     .version    = 1,
0130     .maxattr    = IEEE802154_ATTR_MAX,
0131     .policy     = ieee802154_policy,
0132     .module     = THIS_MODULE,
0133     .small_ops  = ieee802154_ops,
0134     .n_small_ops    = ARRAY_SIZE(ieee802154_ops),
0135     .mcgrps     = ieee802154_mcgrps,
0136     .n_mcgrps   = ARRAY_SIZE(ieee802154_mcgrps),
0137 };
0138 
0139 int __init ieee802154_nl_init(void)
0140 {
0141     return genl_register_family(&nl802154_family);
0142 }
0143 
0144 void ieee802154_nl_exit(void)
0145 {
0146     genl_unregister_family(&nl802154_family);
0147 }