xref: /openbmc/linux/net/ieee802154/netlink.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22c21d115SSergey Lapin /*
369bb631eSVarka Bhadram  * Netlink interface for IEEE 802.15.4 stack
42c21d115SSergey Lapin  *
52c21d115SSergey Lapin  * Copyright 2007, 2008 Siemens AG
62c21d115SSergey Lapin  *
72c21d115SSergey Lapin  * Written by:
82c21d115SSergey Lapin  * Sergey Lapin <slapin@ossfans.org>
92c21d115SSergey Lapin  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
108e753dd0SDmitry Baryshkov  * Maxim Osipov <maxim.osipov@siemens.com>
112c21d115SSergey Lapin  */
122c21d115SSergey Lapin 
132c21d115SSergey Lapin #include <linux/kernel.h>
145a0e3ad6STejun Heo #include <linux/gfp.h>
152c21d115SSergey Lapin #include <net/genetlink.h>
162c21d115SSergey Lapin #include <linux/nl802154.h>
1778fe738dSDmitry Eremin-Solenikov 
1878fe738dSDmitry Eremin-Solenikov #include "ieee802154.h"
192c21d115SSergey Lapin 
202c21d115SSergey Lapin static unsigned int ieee802154_seq_num;
21c4835d81SDmitry Eremin-Solenikov static DEFINE_SPINLOCK(ieee802154_seq_lock);
222c21d115SSergey Lapin 
232c21d115SSergey Lapin /* Requests to userspace */
ieee802154_nl_create(int flags,u8 req)2478fe738dSDmitry Eremin-Solenikov struct sk_buff *ieee802154_nl_create(int flags, u8 req)
252c21d115SSergey Lapin {
262c21d115SSergey Lapin 	void *hdr;
2758050fceSThomas Graf 	struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
28c4835d81SDmitry Eremin-Solenikov 	unsigned long f;
292c21d115SSergey Lapin 
302c21d115SSergey Lapin 	if (!msg)
312c21d115SSergey Lapin 		return NULL;
322c21d115SSergey Lapin 
33c4835d81SDmitry Eremin-Solenikov 	spin_lock_irqsave(&ieee802154_seq_lock, f);
342c21d115SSergey Lapin 	hdr = genlmsg_put(msg, 0, ieee802154_seq_num++,
3578fe738dSDmitry Eremin-Solenikov 			  &nl802154_family, flags, req);
36c4835d81SDmitry Eremin-Solenikov 	spin_unlock_irqrestore(&ieee802154_seq_lock, f);
372c21d115SSergey Lapin 	if (!hdr) {
382c21d115SSergey Lapin 		nlmsg_free(msg);
392c21d115SSergey Lapin 		return NULL;
402c21d115SSergey Lapin 	}
412c21d115SSergey Lapin 
422c21d115SSergey Lapin 	return msg;
432c21d115SSergey Lapin }
442c21d115SSergey Lapin 
ieee802154_nl_mcast(struct sk_buff * msg,unsigned int group)4578fe738dSDmitry Eremin-Solenikov int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
462c21d115SSergey Lapin {
4710c9cbb1SHong zhi guo 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
4810c9cbb1SHong zhi guo 	void *hdr = genlmsg_data(nlmsg_data(nlh));
492c21d115SSergey Lapin 
50053c095aSJohannes Berg 	genlmsg_end(msg, hdr);
512c21d115SSergey Lapin 
5268eb5503SJohannes Berg 	return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC);
532c21d115SSergey Lapin }
542c21d115SSergey Lapin 
ieee802154_nl_new_reply(struct genl_info * info,int flags,u8 req)55339b4ca5SDmitry Eremin-Solenikov struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
56339b4ca5SDmitry Eremin-Solenikov 					int flags, u8 req)
57339b4ca5SDmitry Eremin-Solenikov {
58339b4ca5SDmitry Eremin-Solenikov 	void *hdr;
5958050fceSThomas Graf 	struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
60339b4ca5SDmitry Eremin-Solenikov 
61339b4ca5SDmitry Eremin-Solenikov 	if (!msg)
62339b4ca5SDmitry Eremin-Solenikov 		return NULL;
63339b4ca5SDmitry Eremin-Solenikov 
64339b4ca5SDmitry Eremin-Solenikov 	hdr = genlmsg_put_reply(msg, info,
65339b4ca5SDmitry Eremin-Solenikov 				&nl802154_family, flags, req);
66339b4ca5SDmitry Eremin-Solenikov 	if (!hdr) {
67339b4ca5SDmitry Eremin-Solenikov 		nlmsg_free(msg);
68339b4ca5SDmitry Eremin-Solenikov 		return NULL;
69339b4ca5SDmitry Eremin-Solenikov 	}
70339b4ca5SDmitry Eremin-Solenikov 
71339b4ca5SDmitry Eremin-Solenikov 	return msg;
72339b4ca5SDmitry Eremin-Solenikov }
73339b4ca5SDmitry Eremin-Solenikov 
ieee802154_nl_reply(struct sk_buff * msg,struct genl_info * info)74339b4ca5SDmitry Eremin-Solenikov int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info)
75339b4ca5SDmitry Eremin-Solenikov {
7610c9cbb1SHong zhi guo 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
7710c9cbb1SHong zhi guo 	void *hdr = genlmsg_data(nlmsg_data(nlh));
78339b4ca5SDmitry Eremin-Solenikov 
79053c095aSJohannes Berg 	genlmsg_end(msg, hdr);
80339b4ca5SDmitry Eremin-Solenikov 
81339b4ca5SDmitry Eremin-Solenikov 	return genlmsg_reply(msg, info);
82339b4ca5SDmitry Eremin-Solenikov }
83339b4ca5SDmitry Eremin-Solenikov 
8466a9b928SJakub Kicinski static const struct genl_small_ops ieee802154_ops[] = {
851c582d91SJohannes Berg 	/* see nl-phy.c */
861c582d91SJohannes Berg 	IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy,
871c582d91SJohannes Berg 			ieee802154_dump_phy),
881c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
891c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
901c582d91SJohannes Berg 	/* see nl-mac.c */
911c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
921c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
931c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req),
941c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req),
951c582d91SJohannes Berg 	IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
961c582d91SJohannes Berg 	IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
971c582d91SJohannes Berg 			ieee802154_dump_iface),
98e462ded6SPhoebe Buckheister 	IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
993e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams),
1003e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams),
1013e9c156eSPhoebe Buckheister 	IEEE802154_DUMP(IEEE802154_LLSEC_LIST_KEY, NULL,
1023e9c156eSPhoebe Buckheister 			ieee802154_llsec_dump_keys),
1033e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
1043e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
1053e9c156eSPhoebe Buckheister 	IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEV, NULL,
1063e9c156eSPhoebe Buckheister 			ieee802154_llsec_dump_devs),
1073e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
1083e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
1093e9c156eSPhoebe Buckheister 	IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
1103e9c156eSPhoebe Buckheister 			ieee802154_llsec_dump_devkeys),
1113e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
1123e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
1133e9c156eSPhoebe Buckheister 	IEEE802154_DUMP(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
1143e9c156eSPhoebe Buckheister 			ieee802154_llsec_dump_seclevels),
1153e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_ADD_SECLEVEL,
1163e9c156eSPhoebe Buckheister 		      ieee802154_llsec_add_seclevel),
1173e9c156eSPhoebe Buckheister 	IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL,
1183e9c156eSPhoebe Buckheister 		      ieee802154_llsec_del_seclevel),
1191c582d91SJohannes Berg };
1201c582d91SJohannes Berg 
1212a94fe48SJohannes Berg static const struct genl_multicast_group ieee802154_mcgrps[] = {
1222a94fe48SJohannes Berg 	[IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, },
1232a94fe48SJohannes Berg 	[IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
1242a94fe48SJohannes Berg };
1252a94fe48SJohannes Berg 
12656989f6dSJohannes Berg struct genl_family nl802154_family __ro_after_init = {
127489111e5SJohannes Berg 	.hdrsize	= 0,
128489111e5SJohannes Berg 	.name		= IEEE802154_NL_NAME,
129489111e5SJohannes Berg 	.version	= 1,
130489111e5SJohannes Berg 	.maxattr	= IEEE802154_ATTR_MAX,
1313b0f31f2SJohannes Berg 	.policy		= ieee802154_policy,
132489111e5SJohannes Berg 	.module		= THIS_MODULE,
13366a9b928SJakub Kicinski 	.small_ops	= ieee802154_ops,
13466a9b928SJakub Kicinski 	.n_small_ops	= ARRAY_SIZE(ieee802154_ops),
135*9c5d03d3SJakub Kicinski 	.resv_start_op	= IEEE802154_LLSEC_DEL_SECLEVEL + 1,
136489111e5SJohannes Berg 	.mcgrps		= ieee802154_mcgrps,
137489111e5SJohannes Berg 	.n_mcgrps	= ARRAY_SIZE(ieee802154_mcgrps),
138489111e5SJohannes Berg };
139489111e5SJohannes Berg 
ieee802154_nl_init(void)140cb6b3763SDmitry Eremin-Solenikov int __init ieee802154_nl_init(void)
1412c21d115SSergey Lapin {
142489111e5SJohannes Berg 	return genl_register_family(&nl802154_family);
1432c21d115SSergey Lapin }
1442c21d115SSergey Lapin 
ieee802154_nl_exit(void)14579fe1a2aSAlexander Aring void ieee802154_nl_exit(void)
1462c21d115SSergey Lapin {
14778fe738dSDmitry Eremin-Solenikov 	genl_unregister_family(&nl802154_family);
1482c21d115SSergey Lapin }
149