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