162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __NET_GENERIC_NETLINK_H
362306a36Sopenharmony_ci#define __NET_GENERIC_NETLINK_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/genetlink.h>
662306a36Sopenharmony_ci#include <net/netlink.h>
762306a36Sopenharmony_ci#include <net/net_namespace.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/**
1262306a36Sopenharmony_ci * struct genl_multicast_group - generic netlink multicast group
1362306a36Sopenharmony_ci * @name: name of the multicast group, names are per-family
1462306a36Sopenharmony_ci * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
1562306a36Sopenharmony_ci * @cap_sys_admin: whether %CAP_SYS_ADMIN is required for binding
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_cistruct genl_multicast_group {
1862306a36Sopenharmony_ci	char			name[GENL_NAMSIZ];
1962306a36Sopenharmony_ci	u8			flags;
2062306a36Sopenharmony_ci	u8			cap_sys_admin:1;
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct genl_split_ops;
2462306a36Sopenharmony_cistruct genl_info;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/**
2762306a36Sopenharmony_ci * struct genl_family - generic netlink family
2862306a36Sopenharmony_ci * @hdrsize: length of user specific header in bytes
2962306a36Sopenharmony_ci * @name: name of family
3062306a36Sopenharmony_ci * @version: protocol version
3162306a36Sopenharmony_ci * @maxattr: maximum number of attributes supported
3262306a36Sopenharmony_ci * @policy: netlink policy
3362306a36Sopenharmony_ci * @netnsok: set to true if the family can handle network
3462306a36Sopenharmony_ci *	namespaces and should be presented in all of them
3562306a36Sopenharmony_ci * @parallel_ops: operations can be called in parallel and aren't
3662306a36Sopenharmony_ci *	synchronized by the core genetlink code
3762306a36Sopenharmony_ci * @pre_doit: called before an operation's doit callback, it may
3862306a36Sopenharmony_ci *	do additional, common, filtering and return an error
3962306a36Sopenharmony_ci * @post_doit: called after an operation's doit callback, it may
4062306a36Sopenharmony_ci *	undo operations done by pre_doit, for example release locks
4162306a36Sopenharmony_ci * @module: pointer to the owning module (set to THIS_MODULE)
4262306a36Sopenharmony_ci * @mcgrps: multicast groups used by this family
4362306a36Sopenharmony_ci * @n_mcgrps: number of multicast groups
4462306a36Sopenharmony_ci * @resv_start_op: first operation for which reserved fields of the header
4562306a36Sopenharmony_ci *	can be validated and policies are required (see below);
4662306a36Sopenharmony_ci *	new families should leave this field at zero
4762306a36Sopenharmony_ci * @ops: the operations supported by this family
4862306a36Sopenharmony_ci * @n_ops: number of operations supported by this family
4962306a36Sopenharmony_ci * @small_ops: the small-struct operations supported by this family
5062306a36Sopenharmony_ci * @n_small_ops: number of small-struct operations supported by this family
5162306a36Sopenharmony_ci * @split_ops: the split do/dump form of operation definition
5262306a36Sopenharmony_ci * @n_split_ops: number of entries in @split_ops, not that with split do/dump
5362306a36Sopenharmony_ci *	ops the number of entries is not the same as number of commands
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * Attribute policies (the combination of @policy and @maxattr fields)
5662306a36Sopenharmony_ci * can be attached at the family level or at the operation level.
5762306a36Sopenharmony_ci * If both are present the per-operation policy takes precedence.
5862306a36Sopenharmony_ci * For operations before @resv_start_op lack of policy means that the core
5962306a36Sopenharmony_ci * will perform no attribute parsing or validation. For newer operations
6062306a36Sopenharmony_ci * if policy is not provided core will reject all TLV attributes.
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistruct genl_family {
6362306a36Sopenharmony_ci	unsigned int		hdrsize;
6462306a36Sopenharmony_ci	char			name[GENL_NAMSIZ];
6562306a36Sopenharmony_ci	unsigned int		version;
6662306a36Sopenharmony_ci	unsigned int		maxattr;
6762306a36Sopenharmony_ci	u8			netnsok:1;
6862306a36Sopenharmony_ci	u8			parallel_ops:1;
6962306a36Sopenharmony_ci	u8			n_ops;
7062306a36Sopenharmony_ci	u8			n_small_ops;
7162306a36Sopenharmony_ci	u8			n_split_ops;
7262306a36Sopenharmony_ci	u8			n_mcgrps;
7362306a36Sopenharmony_ci	u8			resv_start_op;
7462306a36Sopenharmony_ci	const struct nla_policy *policy;
7562306a36Sopenharmony_ci	int			(*pre_doit)(const struct genl_split_ops *ops,
7662306a36Sopenharmony_ci					    struct sk_buff *skb,
7762306a36Sopenharmony_ci					    struct genl_info *info);
7862306a36Sopenharmony_ci	void			(*post_doit)(const struct genl_split_ops *ops,
7962306a36Sopenharmony_ci					     struct sk_buff *skb,
8062306a36Sopenharmony_ci					     struct genl_info *info);
8162306a36Sopenharmony_ci	const struct genl_ops *	ops;
8262306a36Sopenharmony_ci	const struct genl_small_ops *small_ops;
8362306a36Sopenharmony_ci	const struct genl_split_ops *split_ops;
8462306a36Sopenharmony_ci	const struct genl_multicast_group *mcgrps;
8562306a36Sopenharmony_ci	struct module		*module;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/* private: internal use only */
8862306a36Sopenharmony_ci	/* protocol family identifier */
8962306a36Sopenharmony_ci	int			id;
9062306a36Sopenharmony_ci	/* starting number of multicast group IDs in this family */
9162306a36Sopenharmony_ci	unsigned int		mcgrp_offset;
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/**
9562306a36Sopenharmony_ci * struct genl_info - receiving information
9662306a36Sopenharmony_ci * @snd_seq: sending sequence number
9762306a36Sopenharmony_ci * @snd_portid: netlink portid of sender
9862306a36Sopenharmony_ci * @family: generic netlink family
9962306a36Sopenharmony_ci * @nlhdr: netlink message header
10062306a36Sopenharmony_ci * @genlhdr: generic netlink message header
10162306a36Sopenharmony_ci * @attrs: netlink attributes
10262306a36Sopenharmony_ci * @_net: network namespace
10362306a36Sopenharmony_ci * @user_ptr: user pointers
10462306a36Sopenharmony_ci * @extack: extended ACK report struct
10562306a36Sopenharmony_ci */
10662306a36Sopenharmony_cistruct genl_info {
10762306a36Sopenharmony_ci	u32			snd_seq;
10862306a36Sopenharmony_ci	u32			snd_portid;
10962306a36Sopenharmony_ci	const struct genl_family *family;
11062306a36Sopenharmony_ci	const struct nlmsghdr *	nlhdr;
11162306a36Sopenharmony_ci	struct genlmsghdr *	genlhdr;
11262306a36Sopenharmony_ci	struct nlattr **	attrs;
11362306a36Sopenharmony_ci	possible_net_t		_net;
11462306a36Sopenharmony_ci	void *			user_ptr[2];
11562306a36Sopenharmony_ci	struct netlink_ext_ack *extack;
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic inline struct net *genl_info_net(const struct genl_info *info)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	return read_pnet(&info->_net);
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline void genl_info_net_set(struct genl_info *info, struct net *net)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	write_pnet(&info->_net, net);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline void *genl_info_userhdr(const struct genl_info *info)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	return (u8 *)info->genlhdr + GENL_HDRLEN;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci#define GENL_SET_ERR_MSG_FMT(info, msg, args...) \
13662306a36Sopenharmony_ci	NL_SET_ERR_MSG_FMT((info)->extack, msg, ##args)
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/* Report that a root attribute is missing */
13962306a36Sopenharmony_ci#define GENL_REQ_ATTR_CHECK(info, attr) ({				\
14062306a36Sopenharmony_ci	struct genl_info *__info = (info);				\
14162306a36Sopenharmony_ci									\
14262306a36Sopenharmony_ci	NL_REQ_ATTR_CHECK(__info->extack, NULL, __info->attrs, (attr)); \
14362306a36Sopenharmony_ci})
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cienum genl_validate_flags {
14662306a36Sopenharmony_ci	GENL_DONT_VALIDATE_STRICT		= BIT(0),
14762306a36Sopenharmony_ci	GENL_DONT_VALIDATE_DUMP			= BIT(1),
14862306a36Sopenharmony_ci	GENL_DONT_VALIDATE_DUMP_STRICT		= BIT(2),
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/**
15262306a36Sopenharmony_ci * struct genl_small_ops - generic netlink operations (small version)
15362306a36Sopenharmony_ci * @cmd: command identifier
15462306a36Sopenharmony_ci * @internal_flags: flags used by the family
15562306a36Sopenharmony_ci * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
15662306a36Sopenharmony_ci * @validate: validation flags from enum genl_validate_flags
15762306a36Sopenharmony_ci * @doit: standard command callback
15862306a36Sopenharmony_ci * @dumpit: callback for dumpers
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * This is a cut-down version of struct genl_ops for users who don't need
16162306a36Sopenharmony_ci * most of the ancillary infra and want to save space.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_cistruct genl_small_ops {
16462306a36Sopenharmony_ci	int	(*doit)(struct sk_buff *skb, struct genl_info *info);
16562306a36Sopenharmony_ci	int	(*dumpit)(struct sk_buff *skb, struct netlink_callback *cb);
16662306a36Sopenharmony_ci	u8	cmd;
16762306a36Sopenharmony_ci	u8	internal_flags;
16862306a36Sopenharmony_ci	u8	flags;
16962306a36Sopenharmony_ci	u8	validate;
17062306a36Sopenharmony_ci};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/**
17362306a36Sopenharmony_ci * struct genl_ops - generic netlink operations
17462306a36Sopenharmony_ci * @cmd: command identifier
17562306a36Sopenharmony_ci * @internal_flags: flags used by the family
17662306a36Sopenharmony_ci * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
17762306a36Sopenharmony_ci * @maxattr: maximum number of attributes supported
17862306a36Sopenharmony_ci * @policy: netlink policy (takes precedence over family policy)
17962306a36Sopenharmony_ci * @validate: validation flags from enum genl_validate_flags
18062306a36Sopenharmony_ci * @doit: standard command callback
18162306a36Sopenharmony_ci * @start: start callback for dumps
18262306a36Sopenharmony_ci * @dumpit: callback for dumpers
18362306a36Sopenharmony_ci * @done: completion callback for dumps
18462306a36Sopenharmony_ci */
18562306a36Sopenharmony_cistruct genl_ops {
18662306a36Sopenharmony_ci	int		       (*doit)(struct sk_buff *skb,
18762306a36Sopenharmony_ci				       struct genl_info *info);
18862306a36Sopenharmony_ci	int		       (*start)(struct netlink_callback *cb);
18962306a36Sopenharmony_ci	int		       (*dumpit)(struct sk_buff *skb,
19062306a36Sopenharmony_ci					 struct netlink_callback *cb);
19162306a36Sopenharmony_ci	int		       (*done)(struct netlink_callback *cb);
19262306a36Sopenharmony_ci	const struct nla_policy *policy;
19362306a36Sopenharmony_ci	unsigned int		maxattr;
19462306a36Sopenharmony_ci	u8			cmd;
19562306a36Sopenharmony_ci	u8			internal_flags;
19662306a36Sopenharmony_ci	u8			flags;
19762306a36Sopenharmony_ci	u8			validate;
19862306a36Sopenharmony_ci};
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/**
20162306a36Sopenharmony_ci * struct genl_split_ops - generic netlink operations (do/dump split version)
20262306a36Sopenharmony_ci * @cmd: command identifier
20362306a36Sopenharmony_ci * @internal_flags: flags used by the family
20462306a36Sopenharmony_ci * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM)
20562306a36Sopenharmony_ci * @validate: validation flags from enum genl_validate_flags
20662306a36Sopenharmony_ci * @policy: netlink policy (takes precedence over family policy)
20762306a36Sopenharmony_ci * @maxattr: maximum number of attributes supported
20862306a36Sopenharmony_ci *
20962306a36Sopenharmony_ci * Do callbacks:
21062306a36Sopenharmony_ci * @pre_doit: called before an operation's @doit callback, it may
21162306a36Sopenharmony_ci *	do additional, common, filtering and return an error
21262306a36Sopenharmony_ci * @doit: standard command callback
21362306a36Sopenharmony_ci * @post_doit: called after an operation's @doit callback, it may
21462306a36Sopenharmony_ci *	undo operations done by pre_doit, for example release locks
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Dump callbacks:
21762306a36Sopenharmony_ci * @start: start callback for dumps
21862306a36Sopenharmony_ci * @dumpit: callback for dumpers
21962306a36Sopenharmony_ci * @done: completion callback for dumps
22062306a36Sopenharmony_ci *
22162306a36Sopenharmony_ci * Do callbacks can be used if %GENL_CMD_CAP_DO is set in @flags.
22262306a36Sopenharmony_ci * Dump callbacks can be used if %GENL_CMD_CAP_DUMP is set in @flags.
22362306a36Sopenharmony_ci * Exactly one of those flags must be set.
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_cistruct genl_split_ops {
22662306a36Sopenharmony_ci	union {
22762306a36Sopenharmony_ci		struct {
22862306a36Sopenharmony_ci			int (*pre_doit)(const struct genl_split_ops *ops,
22962306a36Sopenharmony_ci					struct sk_buff *skb,
23062306a36Sopenharmony_ci					struct genl_info *info);
23162306a36Sopenharmony_ci			int (*doit)(struct sk_buff *skb,
23262306a36Sopenharmony_ci				    struct genl_info *info);
23362306a36Sopenharmony_ci			void (*post_doit)(const struct genl_split_ops *ops,
23462306a36Sopenharmony_ci					  struct sk_buff *skb,
23562306a36Sopenharmony_ci					  struct genl_info *info);
23662306a36Sopenharmony_ci		};
23762306a36Sopenharmony_ci		struct {
23862306a36Sopenharmony_ci			int (*start)(struct netlink_callback *cb);
23962306a36Sopenharmony_ci			int (*dumpit)(struct sk_buff *skb,
24062306a36Sopenharmony_ci				      struct netlink_callback *cb);
24162306a36Sopenharmony_ci			int (*done)(struct netlink_callback *cb);
24262306a36Sopenharmony_ci		};
24362306a36Sopenharmony_ci	};
24462306a36Sopenharmony_ci	const struct nla_policy *policy;
24562306a36Sopenharmony_ci	unsigned int		maxattr;
24662306a36Sopenharmony_ci	u8			cmd;
24762306a36Sopenharmony_ci	u8			internal_flags;
24862306a36Sopenharmony_ci	u8			flags;
24962306a36Sopenharmony_ci	u8			validate;
25062306a36Sopenharmony_ci};
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/**
25362306a36Sopenharmony_ci * struct genl_dumpit_info - info that is available during dumpit op call
25462306a36Sopenharmony_ci * @op: generic netlink ops - for internal genl code usage
25562306a36Sopenharmony_ci * @attrs: netlink attributes
25662306a36Sopenharmony_ci * @info: struct genl_info describing the request
25762306a36Sopenharmony_ci */
25862306a36Sopenharmony_cistruct genl_dumpit_info {
25962306a36Sopenharmony_ci	struct genl_split_ops op;
26062306a36Sopenharmony_ci	struct genl_info info;
26162306a36Sopenharmony_ci};
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic inline const struct genl_dumpit_info *
26462306a36Sopenharmony_cigenl_dumpit_info(struct netlink_callback *cb)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	return cb->data;
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic inline const struct genl_info *
27062306a36Sopenharmony_cigenl_info_dump(struct netlink_callback *cb)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	return &genl_dumpit_info(cb)->info;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/**
27662306a36Sopenharmony_ci * genl_info_init_ntf() - initialize genl_info for notifications
27762306a36Sopenharmony_ci * @info:   genl_info struct to set up
27862306a36Sopenharmony_ci * @family: pointer to the genetlink family
27962306a36Sopenharmony_ci * @cmd:    command to be used in the notification
28062306a36Sopenharmony_ci *
28162306a36Sopenharmony_ci * Initialize a locally declared struct genl_info to pass to various APIs.
28262306a36Sopenharmony_ci * Intended to be used when creating notifications.
28362306a36Sopenharmony_ci */
28462306a36Sopenharmony_cistatic inline void
28562306a36Sopenharmony_cigenl_info_init_ntf(struct genl_info *info, const struct genl_family *family,
28662306a36Sopenharmony_ci		   u8 cmd)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	struct genlmsghdr *hdr = (void *) &info->user_ptr[0];
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	memset(info, 0, sizeof(*info));
29162306a36Sopenharmony_ci	info->family = family;
29262306a36Sopenharmony_ci	info->genlhdr = hdr;
29362306a36Sopenharmony_ci	hdr->cmd = cmd;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic inline bool genl_info_is_ntf(const struct genl_info *info)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	return !info->nlhdr;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ciint genl_register_family(struct genl_family *family);
30262306a36Sopenharmony_ciint genl_unregister_family(const struct genl_family *family);
30362306a36Sopenharmony_civoid genl_notify(const struct genl_family *family, struct sk_buff *skb,
30462306a36Sopenharmony_ci		 struct genl_info *info, u32 group, gfp_t flags);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_civoid *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
30762306a36Sopenharmony_ci		  const struct genl_family *family, int flags, u8 cmd);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic inline void *
31062306a36Sopenharmony_ci__genlmsg_iput(struct sk_buff *skb, const struct genl_info *info, int flags)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	return genlmsg_put(skb, info->snd_portid, info->snd_seq, info->family,
31362306a36Sopenharmony_ci			   flags, info->genlhdr->cmd);
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci/**
31762306a36Sopenharmony_ci * genlmsg_iput - start genetlink message based on genl_info
31862306a36Sopenharmony_ci * @skb: skb in which message header will be placed
31962306a36Sopenharmony_ci * @info: genl_info as provided to do/dump handlers
32062306a36Sopenharmony_ci *
32162306a36Sopenharmony_ci * Convenience wrapper which starts a genetlink message based on
32262306a36Sopenharmony_ci * information in user request. @info should be either the struct passed
32362306a36Sopenharmony_ci * by genetlink core to do/dump handlers (when constructing replies to
32462306a36Sopenharmony_ci * such requests) or a struct initialized by genl_info_init_ntf()
32562306a36Sopenharmony_ci * when constructing notifications.
32662306a36Sopenharmony_ci *
32762306a36Sopenharmony_ci * Returns pointer to new genetlink header.
32862306a36Sopenharmony_ci */
32962306a36Sopenharmony_cistatic inline void *
33062306a36Sopenharmony_cigenlmsg_iput(struct sk_buff *skb, const struct genl_info *info)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	return __genlmsg_iput(skb, info, 0);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci/**
33662306a36Sopenharmony_ci * genlmsg_nlhdr - Obtain netlink header from user specified header
33762306a36Sopenharmony_ci * @user_hdr: user header as returned from genlmsg_put()
33862306a36Sopenharmony_ci *
33962306a36Sopenharmony_ci * Returns pointer to netlink header.
34062306a36Sopenharmony_ci */
34162306a36Sopenharmony_cistatic inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	return (struct nlmsghdr *)((char *)user_hdr -
34462306a36Sopenharmony_ci				   GENL_HDRLEN -
34562306a36Sopenharmony_ci				   NLMSG_HDRLEN);
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci/**
34962306a36Sopenharmony_ci * genlmsg_parse_deprecated - parse attributes of a genetlink message
35062306a36Sopenharmony_ci * @nlh: netlink message header
35162306a36Sopenharmony_ci * @family: genetlink message family
35262306a36Sopenharmony_ci * @tb: destination array with maxtype+1 elements
35362306a36Sopenharmony_ci * @maxtype: maximum attribute type to be expected
35462306a36Sopenharmony_ci * @policy: validation policy
35562306a36Sopenharmony_ci * @extack: extended ACK report struct
35662306a36Sopenharmony_ci */
35762306a36Sopenharmony_cistatic inline int genlmsg_parse_deprecated(const struct nlmsghdr *nlh,
35862306a36Sopenharmony_ci					   const struct genl_family *family,
35962306a36Sopenharmony_ci					   struct nlattr *tb[], int maxtype,
36062306a36Sopenharmony_ci					   const struct nla_policy *policy,
36162306a36Sopenharmony_ci					   struct netlink_ext_ack *extack)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	return __nlmsg_parse(nlh, family->hdrsize + GENL_HDRLEN, tb, maxtype,
36462306a36Sopenharmony_ci			     policy, NL_VALIDATE_LIBERAL, extack);
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci/**
36862306a36Sopenharmony_ci * genlmsg_parse - parse attributes of a genetlink message
36962306a36Sopenharmony_ci * @nlh: netlink message header
37062306a36Sopenharmony_ci * @family: genetlink message family
37162306a36Sopenharmony_ci * @tb: destination array with maxtype+1 elements
37262306a36Sopenharmony_ci * @maxtype: maximum attribute type to be expected
37362306a36Sopenharmony_ci * @policy: validation policy
37462306a36Sopenharmony_ci * @extack: extended ACK report struct
37562306a36Sopenharmony_ci */
37662306a36Sopenharmony_cistatic inline int genlmsg_parse(const struct nlmsghdr *nlh,
37762306a36Sopenharmony_ci				const struct genl_family *family,
37862306a36Sopenharmony_ci				struct nlattr *tb[], int maxtype,
37962306a36Sopenharmony_ci				const struct nla_policy *policy,
38062306a36Sopenharmony_ci				struct netlink_ext_ack *extack)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	return __nlmsg_parse(nlh, family->hdrsize + GENL_HDRLEN, tb, maxtype,
38362306a36Sopenharmony_ci			     policy, NL_VALIDATE_STRICT, extack);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci/**
38762306a36Sopenharmony_ci * genl_dump_check_consistent - check if sequence is consistent and advertise if not
38862306a36Sopenharmony_ci * @cb: netlink callback structure that stores the sequence number
38962306a36Sopenharmony_ci * @user_hdr: user header as returned from genlmsg_put()
39062306a36Sopenharmony_ci *
39162306a36Sopenharmony_ci * Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
39262306a36Sopenharmony_ci * simpler to use with generic netlink.
39362306a36Sopenharmony_ci */
39462306a36Sopenharmony_cistatic inline void genl_dump_check_consistent(struct netlink_callback *cb,
39562306a36Sopenharmony_ci					      void *user_hdr)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr));
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci/**
40162306a36Sopenharmony_ci * genlmsg_put_reply - Add generic netlink header to a reply message
40262306a36Sopenharmony_ci * @skb: socket buffer holding the message
40362306a36Sopenharmony_ci * @info: receiver info
40462306a36Sopenharmony_ci * @family: generic netlink family
40562306a36Sopenharmony_ci * @flags: netlink message flags
40662306a36Sopenharmony_ci * @cmd: generic netlink command
40762306a36Sopenharmony_ci *
40862306a36Sopenharmony_ci * Returns pointer to user specific header
40962306a36Sopenharmony_ci */
41062306a36Sopenharmony_cistatic inline void *genlmsg_put_reply(struct sk_buff *skb,
41162306a36Sopenharmony_ci				      struct genl_info *info,
41262306a36Sopenharmony_ci				      const struct genl_family *family,
41362306a36Sopenharmony_ci				      int flags, u8 cmd)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
41662306a36Sopenharmony_ci			   flags, cmd);
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci/**
42062306a36Sopenharmony_ci * genlmsg_end - Finalize a generic netlink message
42162306a36Sopenharmony_ci * @skb: socket buffer the message is stored in
42262306a36Sopenharmony_ci * @hdr: user specific header
42362306a36Sopenharmony_ci */
42462306a36Sopenharmony_cistatic inline void genlmsg_end(struct sk_buff *skb, void *hdr)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	nlmsg_end(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci/**
43062306a36Sopenharmony_ci * genlmsg_cancel - Cancel construction of a generic netlink message
43162306a36Sopenharmony_ci * @skb: socket buffer the message is stored in
43262306a36Sopenharmony_ci * @hdr: generic netlink message header
43362306a36Sopenharmony_ci */
43462306a36Sopenharmony_cistatic inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	if (hdr)
43762306a36Sopenharmony_ci		nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci/**
44162306a36Sopenharmony_ci * genlmsg_multicast_netns - multicast a netlink message to a specific netns
44262306a36Sopenharmony_ci * @family: the generic netlink family
44362306a36Sopenharmony_ci * @net: the net namespace
44462306a36Sopenharmony_ci * @skb: netlink message as socket buffer
44562306a36Sopenharmony_ci * @portid: own netlink portid to avoid sending to yourself
44662306a36Sopenharmony_ci * @group: offset of multicast group in groups array
44762306a36Sopenharmony_ci * @flags: allocation flags
44862306a36Sopenharmony_ci */
44962306a36Sopenharmony_cistatic inline int genlmsg_multicast_netns(const struct genl_family *family,
45062306a36Sopenharmony_ci					  struct net *net, struct sk_buff *skb,
45162306a36Sopenharmony_ci					  u32 portid, unsigned int group, gfp_t flags)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	if (WARN_ON_ONCE(group >= family->n_mcgrps))
45462306a36Sopenharmony_ci		return -EINVAL;
45562306a36Sopenharmony_ci	group = family->mcgrp_offset + group;
45662306a36Sopenharmony_ci	return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
45762306a36Sopenharmony_ci}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci/**
46062306a36Sopenharmony_ci * genlmsg_multicast - multicast a netlink message to the default netns
46162306a36Sopenharmony_ci * @family: the generic netlink family
46262306a36Sopenharmony_ci * @skb: netlink message as socket buffer
46362306a36Sopenharmony_ci * @portid: own netlink portid to avoid sending to yourself
46462306a36Sopenharmony_ci * @group: offset of multicast group in groups array
46562306a36Sopenharmony_ci * @flags: allocation flags
46662306a36Sopenharmony_ci */
46762306a36Sopenharmony_cistatic inline int genlmsg_multicast(const struct genl_family *family,
46862306a36Sopenharmony_ci				    struct sk_buff *skb, u32 portid,
46962306a36Sopenharmony_ci				    unsigned int group, gfp_t flags)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	return genlmsg_multicast_netns(family, &init_net, skb,
47262306a36Sopenharmony_ci				       portid, group, flags);
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/**
47662306a36Sopenharmony_ci * genlmsg_multicast_allns - multicast a netlink message to all net namespaces
47762306a36Sopenharmony_ci * @family: the generic netlink family
47862306a36Sopenharmony_ci * @skb: netlink message as socket buffer
47962306a36Sopenharmony_ci * @portid: own netlink portid to avoid sending to yourself
48062306a36Sopenharmony_ci * @group: offset of multicast group in groups array
48162306a36Sopenharmony_ci * @flags: allocation flags
48262306a36Sopenharmony_ci *
48362306a36Sopenharmony_ci * This function must hold the RTNL or rcu_read_lock().
48462306a36Sopenharmony_ci */
48562306a36Sopenharmony_ciint genlmsg_multicast_allns(const struct genl_family *family,
48662306a36Sopenharmony_ci			    struct sk_buff *skb, u32 portid,
48762306a36Sopenharmony_ci			    unsigned int group, gfp_t flags);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci/**
49062306a36Sopenharmony_ci * genlmsg_unicast - unicast a netlink message
49162306a36Sopenharmony_ci * @net: network namespace to look up @portid in
49262306a36Sopenharmony_ci * @skb: netlink message as socket buffer
49362306a36Sopenharmony_ci * @portid: netlink portid of the destination socket
49462306a36Sopenharmony_ci */
49562306a36Sopenharmony_cistatic inline int genlmsg_unicast(struct net *net, struct sk_buff *skb, u32 portid)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	return nlmsg_unicast(net->genl_sock, skb, portid);
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci/**
50162306a36Sopenharmony_ci * genlmsg_reply - reply to a request
50262306a36Sopenharmony_ci * @skb: netlink message to be sent back
50362306a36Sopenharmony_ci * @info: receiver information
50462306a36Sopenharmony_ci */
50562306a36Sopenharmony_cistatic inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	return genlmsg_unicast(genl_info_net(info), skb, info->snd_portid);
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci/**
51162306a36Sopenharmony_ci * genlmsg_data - head of message payload
51262306a36Sopenharmony_ci * @gnlh: genetlink message header
51362306a36Sopenharmony_ci */
51462306a36Sopenharmony_cistatic inline void *genlmsg_data(const struct genlmsghdr *gnlh)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	return ((unsigned char *) gnlh + GENL_HDRLEN);
51762306a36Sopenharmony_ci}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci/**
52062306a36Sopenharmony_ci * genlmsg_len - length of message payload
52162306a36Sopenharmony_ci * @gnlh: genetlink message header
52262306a36Sopenharmony_ci */
52362306a36Sopenharmony_cistatic inline int genlmsg_len(const struct genlmsghdr *gnlh)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh -
52662306a36Sopenharmony_ci							NLMSG_HDRLEN);
52762306a36Sopenharmony_ci	return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN);
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci/**
53162306a36Sopenharmony_ci * genlmsg_msg_size - length of genetlink message not including padding
53262306a36Sopenharmony_ci * @payload: length of message payload
53362306a36Sopenharmony_ci */
53462306a36Sopenharmony_cistatic inline int genlmsg_msg_size(int payload)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	return GENL_HDRLEN + payload;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci/**
54062306a36Sopenharmony_ci * genlmsg_total_size - length of genetlink message including padding
54162306a36Sopenharmony_ci * @payload: length of message payload
54262306a36Sopenharmony_ci */
54362306a36Sopenharmony_cistatic inline int genlmsg_total_size(int payload)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	return NLMSG_ALIGN(genlmsg_msg_size(payload));
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci/**
54962306a36Sopenharmony_ci * genlmsg_new - Allocate a new generic netlink message
55062306a36Sopenharmony_ci * @payload: size of the message payload
55162306a36Sopenharmony_ci * @flags: the type of memory to allocate.
55262306a36Sopenharmony_ci */
55362306a36Sopenharmony_cistatic inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	return nlmsg_new(genlmsg_total_size(payload), flags);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci/**
55962306a36Sopenharmony_ci * genl_set_err - report error to genetlink broadcast listeners
56062306a36Sopenharmony_ci * @family: the generic netlink family
56162306a36Sopenharmony_ci * @net: the network namespace to report the error to
56262306a36Sopenharmony_ci * @portid: the PORTID of a process that we want to skip (if any)
56362306a36Sopenharmony_ci * @group: the broadcast group that will notice the error
56462306a36Sopenharmony_ci * 	(this is the offset of the multicast group in the groups array)
56562306a36Sopenharmony_ci * @code: error code, must be negative (as usual in kernelspace)
56662306a36Sopenharmony_ci *
56762306a36Sopenharmony_ci * This function returns the number of broadcast listeners that have set the
56862306a36Sopenharmony_ci * NETLINK_RECV_NO_ENOBUFS socket option.
56962306a36Sopenharmony_ci */
57062306a36Sopenharmony_cistatic inline int genl_set_err(const struct genl_family *family,
57162306a36Sopenharmony_ci			       struct net *net, u32 portid,
57262306a36Sopenharmony_ci			       u32 group, int code)
57362306a36Sopenharmony_ci{
57462306a36Sopenharmony_ci	if (WARN_ON_ONCE(group >= family->n_mcgrps))
57562306a36Sopenharmony_ci		return -EINVAL;
57662306a36Sopenharmony_ci	group = family->mcgrp_offset + group;
57762306a36Sopenharmony_ci	return netlink_set_err(net->genl_sock, portid, group, code);
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic inline int genl_has_listeners(const struct genl_family *family,
58162306a36Sopenharmony_ci				     struct net *net, unsigned int group)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	if (WARN_ON_ONCE(group >= family->n_mcgrps))
58462306a36Sopenharmony_ci		return -EINVAL;
58562306a36Sopenharmony_ci	group = family->mcgrp_offset + group;
58662306a36Sopenharmony_ci	return netlink_has_listeners(net->genl_sock, group);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci#endif	/* __NET_GENERIC_NETLINK_H */
589