1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Netlink interface for IEEE 802.15.4 stack 4 * 5 * Copyright 2007, 2008 Siemens AG 6 * 7 * Written by: 8 * Sergey Lapin <slapin@ossfans.org> 9 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 10 * Maxim Osipov <maxim.osipov@siemens.com> 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/gfp.h> 15 #include <net/genetlink.h> 16 #include <linux/nl802154.h> 17 18 #include "ieee802154.h" 19 20 static unsigned int ieee802154_seq_num; 21 static DEFINE_SPINLOCK(ieee802154_seq_lock); 22 23 /* Requests to userspace */ 24 struct sk_buff *ieee802154_nl_create(int flags, u8 req) 25 { 26 void *hdr; 27 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 28 unsigned long f; 29 30 if (!msg) 31 return NULL; 32 33 spin_lock_irqsave(&ieee802154_seq_lock, f); 34 hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, 35 &nl802154_family, flags, req); 36 spin_unlock_irqrestore(&ieee802154_seq_lock, f); 37 if (!hdr) { 38 nlmsg_free(msg); 39 return NULL; 40 } 41 42 return msg; 43 } 44 45 int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group) 46 { 47 struct nlmsghdr *nlh = nlmsg_hdr(msg); 48 void *hdr = genlmsg_data(nlmsg_data(nlh)); 49 50 genlmsg_end(msg, hdr); 51 52 return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC); 53 } 54 55 struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, 56 int flags, u8 req) 57 { 58 void *hdr; 59 struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 60 61 if (!msg) 62 return NULL; 63 64 hdr = genlmsg_put_reply(msg, info, 65 &nl802154_family, flags, req); 66 if (!hdr) { 67 nlmsg_free(msg); 68 return NULL; 69 } 70 71 return msg; 72 } 73 74 int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info) 75 { 76 struct nlmsghdr *nlh = nlmsg_hdr(msg); 77 void *hdr = genlmsg_data(nlmsg_data(nlh)); 78 79 genlmsg_end(msg, hdr); 80 81 return genlmsg_reply(msg, info); 82 } 83 84 static const struct genl_small_ops ieee802154_ops[] = { 85 /* see nl-phy.c */ 86 IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy, 87 ieee802154_dump_phy), 88 IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), 89 IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), 90 /* see nl-mac.c */ 91 IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), 92 IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), 93 IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), 94 IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), 95 IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), 96 IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, 97 ieee802154_dump_iface), 98 IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams), 99 IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams), 100 IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams), 101 IEEE802154_DUMP(IEEE802154_LLSEC_LIST_KEY, NULL, 102 ieee802154_llsec_dump_keys), 103 IEEE802154_OP(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key), 104 IEEE802154_OP(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key), 105 IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEV, NULL, 106 ieee802154_llsec_dump_devs), 107 IEEE802154_OP(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev), 108 IEEE802154_OP(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev), 109 IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEVKEY, NULL, 110 ieee802154_llsec_dump_devkeys), 111 IEEE802154_OP(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey), 112 IEEE802154_OP(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey), 113 IEEE802154_DUMP(IEEE802154_LLSEC_LIST_SECLEVEL, NULL, 114 ieee802154_llsec_dump_seclevels), 115 IEEE802154_OP(IEEE802154_LLSEC_ADD_SECLEVEL, 116 ieee802154_llsec_add_seclevel), 117 IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL, 118 ieee802154_llsec_del_seclevel), 119 }; 120 121 static const struct genl_multicast_group ieee802154_mcgrps[] = { 122 [IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, }, 123 [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, }, 124 }; 125 126 struct genl_family nl802154_family __ro_after_init = { 127 .hdrsize = 0, 128 .name = IEEE802154_NL_NAME, 129 .version = 1, 130 .maxattr = IEEE802154_ATTR_MAX, 131 .policy = ieee802154_policy, 132 .module = THIS_MODULE, 133 .small_ops = ieee802154_ops, 134 .n_small_ops = ARRAY_SIZE(ieee802154_ops), 135 .resv_start_op = IEEE802154_LLSEC_DEL_SECLEVEL + 1, 136 .mcgrps = ieee802154_mcgrps, 137 .n_mcgrps = ARRAY_SIZE(ieee802154_mcgrps), 138 }; 139 140 int __init ieee802154_nl_init(void) 141 { 142 return genl_register_family(&nl802154_family); 143 } 144 145 void ieee802154_nl_exit(void) 146 { 147 genl_unregister_family(&nl802154_family); 148 } 149