linux/net/netlink/genetlink.c

// SPDX-License-Identifier: GPL-2.0
/*
 * NETLINK      Generic Netlink Family
 *
 * 		Authors:	Jamal Hadi Salim
 * 				Thomas Graf <[email protected]>
 *				Johannes Berg <[email protected]>
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/string_helpers.h>
#include <linux/skbuff.h>
#include <linux/mutex.h>
#include <linux/bitmap.h>
#include <linux/rwsem.h>
#include <linux/idr.h>
#include <net/sock.h>
#include <net/genetlink.h>

#include "genetlink.h"

static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
static DECLARE_RWSEM(cb_lock);

atomic_t genl_sk_destructing_cnt =;
DECLARE_WAIT_QUEUE_HEAD();

void genl_lock(void)
{}
EXPORT_SYMBOL();

void genl_unlock(void)
{}
EXPORT_SYMBOL();

static void genl_lock_all(void)
{}

static void genl_unlock_all(void)
{}

static void genl_op_lock(const struct genl_family *family)
{}

static void genl_op_unlock(const struct genl_family *family)
{}

static DEFINE_IDR(genl_fam_idr);

/*
 * Bitmap of multicast groups that are currently in use.
 *
 * To avoid an allocation at boot of just one unsigned long,
 * declare it global instead.
 * Bit 0 is marked as already used since group 0 is invalid.
 * Bit 1 is marked as already used since the drop-monitor code
 * abuses the API and thinks it can statically use group 1.
 * That group will typically conflict with other groups that
 * any proper users use.
 * Bit 16 is marked as used since it's used for generic netlink
 * and the code no longer marks pre-reserved IDs as used.
 * Bit 17 is marked as already used since the VFS quota code
 * also abused this API and relied on family == group ID, we
 * cater to that by giving it a static family and group ID.
 * Bit 18 is marked as already used since the PMCRAID driver
 * did the same thing as the VFS quota code (maybe copied?)
 */
static unsigned long mc_group_start =;
static unsigned long *mc_groups =;
static unsigned long mc_groups_longs =;

/* We need the last attribute with non-zero ID therefore a 2-entry array */
static struct nla_policy genl_policy_reject_all[] =;

static int genl_ctrl_event(int event, const struct genl_family *family,
			   const struct genl_multicast_group *grp,
			   int grp_id);

static void
genl_op_fill_in_reject_policy(const struct genl_family *family,
			      struct genl_ops *op)
{}

static void
genl_op_fill_in_reject_policy_split(const struct genl_family *family,
				    struct genl_split_ops *op)
{}

static const struct genl_family *genl_family_find_byid(unsigned int id)
{}

static const struct genl_family *genl_family_find_byname(char *name)
{}

struct genl_op_iter {};

static void genl_op_from_full(const struct genl_family *family,
			      unsigned int i, struct genl_ops *op)
{}

static int genl_get_cmd_full(u32 cmd, const struct genl_family *family,
			     struct genl_ops *op)
{}

static void genl_op_from_small(const struct genl_family *family,
			       unsigned int i, struct genl_ops *op)
{}

static int genl_get_cmd_small(u32 cmd, const struct genl_family *family,
			      struct genl_ops *op)
{}

static void genl_op_from_split(struct genl_op_iter *iter)
{}

static int
genl_get_cmd_split(u32 cmd, u8 flag, const struct genl_family *family,
		   struct genl_split_ops *op)
{}

static int
genl_cmd_full_to_split(struct genl_split_ops *op,
		       const struct genl_family *family,
		       const struct genl_ops *full, u8 flags)
{}

/* Must make sure that op is initialized to 0 on failure */
static int
genl_get_cmd(u32 cmd, u8 flags, const struct genl_family *family,
	     struct genl_split_ops *op)
{}

/* For policy dumping only, get ops of both do and dump.
 * Fail if both are missing, genl_get_cmd() will zero-init in case of failure.
 */
static int
genl_get_cmd_both(u32 cmd, const struct genl_family *family,
		  struct genl_split_ops *doit, struct genl_split_ops *dumpit)
{}

static bool
genl_op_iter_init(const struct genl_family *family, struct genl_op_iter *iter)
{}

static bool genl_op_iter_next(struct genl_op_iter *iter)
{}

static void
genl_op_iter_copy(struct genl_op_iter *dst, struct genl_op_iter *src)
{}

static unsigned int genl_op_iter_idx(struct genl_op_iter *iter)
{}

static int genl_allocate_reserve_groups(int n_groups, int *first_id)
{}

static struct genl_family genl_ctrl;

static int genl_validate_assign_mc_groups(struct genl_family *family)
{}

static void genl_unregister_mc_groups(const struct genl_family *family)
{}

static bool genl_split_op_check(const struct genl_split_ops *op)
{}

static int genl_validate_ops(const struct genl_family *family)
{}

static void *genl_sk_priv_alloc(struct genl_family *family)
{}

static void genl_sk_priv_free(const struct genl_family *family, void *priv)
{}

static int genl_sk_privs_alloc(struct genl_family *family)
{}

static void genl_sk_privs_free(const struct genl_family *family)
{}

static void genl_sk_priv_free_by_sock(struct genl_family *family,
				      struct sock *sk)
{}

static void genl_release(struct sock *sk, unsigned long *groups)
{}

/**
 * __genl_sk_priv_get - Get family private pointer for socket, if exists
 *
 * @family: family
 * @sk: socket
 *
 * Lookup a private memory for a Generic netlink family and specified socket.
 *
 * Caller should make sure this is called in RCU read locked section.
 *
 * Return: valid pointer on success, otherwise negative error value
 * encoded by ERR_PTR(), NULL in case priv does not exist.
 */
void *__genl_sk_priv_get(struct genl_family *family, struct sock *sk)
{}

/**
 * genl_sk_priv_get - Get family private pointer for socket
 *
 * @family: family
 * @sk: socket
 *
 * Lookup a private memory for a Generic netlink family and specified socket.
 * Allocate the private memory in case it was not already done.
 *
 * Return: valid pointer on success, otherwise negative error value
 * encoded by ERR_PTR().
 */
void *genl_sk_priv_get(struct genl_family *family, struct sock *sk)
{}

/**
 * genl_register_family - register a generic netlink family
 * @family: generic netlink family
 *
 * Registers the specified family after validating it first. Only one
 * family may be registered with the same family name or identifier.
 *
 * The family's ops, multicast groups and module pointer must already
 * be assigned.
 *
 * Return 0 on success or a negative error code.
 */
int genl_register_family(struct genl_family *family)
{}
EXPORT_SYMBOL();

/**
 * genl_unregister_family - unregister generic netlink family
 * @family: generic netlink family
 *
 * Unregisters the specified family.
 *
 * Returns 0 on success or a negative error code.
 */
int genl_unregister_family(const struct genl_family *family)
{}
EXPORT_SYMBOL();

/**
 * genlmsg_put - Add generic netlink header to netlink message
 * @skb: socket buffer holding the message
 * @portid: netlink portid the message is addressed to
 * @seq: sequence number (usually the one of the sender)
 * @family: generic netlink family
 * @flags: netlink message flags
 * @cmd: generic netlink command
 *
 * Returns pointer to user specific header
 */
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
		  const struct genl_family *family, int flags, u8 cmd)
{}
EXPORT_SYMBOL();

static struct genl_dumpit_info *genl_dumpit_info_alloc(void)
{}

static void genl_dumpit_info_free(const struct genl_dumpit_info *info)
{}

static struct nlattr **
genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
				struct nlmsghdr *nlh,
				struct netlink_ext_ack *extack,
				const struct genl_split_ops *ops,
				int hdrlen,
				enum genl_validate_flags no_strict_flag)
{}

static void genl_family_rcv_msg_attrs_free(struct nlattr **attrbuf)
{}

struct genl_start_context {};

static int genl_start(struct netlink_callback *cb)
{}

static int genl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{}

static int genl_done(struct netlink_callback *cb)
{}

static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
				      struct sk_buff *skb,
				      struct nlmsghdr *nlh,
				      struct netlink_ext_ack *extack,
				      const struct genl_split_ops *ops,
				      int hdrlen, struct net *net)
{}

static int genl_family_rcv_msg_doit(const struct genl_family *family,
				    struct sk_buff *skb,
				    struct nlmsghdr *nlh,
				    struct netlink_ext_ack *extack,
				    const struct genl_split_ops *ops,
				    int hdrlen, struct net *net)
{}

static int genl_header_check(const struct genl_family *family,
			     struct nlmsghdr *nlh, struct genlmsghdr *hdr,
			     struct netlink_ext_ack *extack)
{}

static int genl_family_rcv_msg(const struct genl_family *family,
			       struct sk_buff *skb,
			       struct nlmsghdr *nlh,
			       struct netlink_ext_ack *extack)
{}

static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{}

static void genl_rcv(struct sk_buff *skb)
{}

/**************************************************************************
 * Controller
 **************************************************************************/

static struct genl_family genl_ctrl;

static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq,
			  u32 flags, struct sk_buff *skb, u8 cmd)
{}

static int ctrl_fill_mcgrp_info(const struct genl_family *family,
				const struct genl_multicast_group *grp,
				int grp_id, u32 portid, u32 seq, u32 flags,
				struct sk_buff *skb, u8 cmd)
{}

static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
{}

static struct sk_buff *ctrl_build_family_msg(const struct genl_family *family,
					     u32 portid, int seq, u8 cmd)
{}

static struct sk_buff *
ctrl_build_mcgrp_msg(const struct genl_family *family,
		     const struct genl_multicast_group *grp,
		     int grp_id, u32 portid, int seq, u8 cmd)
{}

static const struct nla_policy ctrl_policy_family[] =;

static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
{}

static int genl_ctrl_event(int event, const struct genl_family *family,
			   const struct genl_multicast_group *grp,
			   int grp_id)
{}

struct ctrl_dump_policy_ctx {};

static const struct nla_policy ctrl_policy_policy[] =;

static int ctrl_dumppolicy_start(struct netlink_callback *cb)
{}

static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
				  struct netlink_callback *cb)
{}

static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
				  struct netlink_callback *cb,
				  struct genl_split_ops *doit,
				  struct genl_split_ops *dumpit)
{}

static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
{}

static int ctrl_dumppolicy_done(struct netlink_callback *cb)
{}

static const struct genl_split_ops genl_ctrl_ops[] =;

static const struct genl_multicast_group genl_ctrl_groups[] =;

static struct genl_family genl_ctrl __ro_after_init =;

static int genl_bind(struct net *net, int group)
{}

static void genl_unbind(struct net *net, int group)
{}

static int __net_init genl_pernet_init(struct net *net)
{}

static void __net_exit genl_pernet_exit(struct net *net)
{}

static struct pernet_operations genl_pernet_ops =;

static int __init genl_init(void)
{}

core_initcall(genl_init);

static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
			 gfp_t flags)
{}

int genlmsg_multicast_allns(const struct genl_family *family,
			    struct sk_buff *skb, u32 portid,
			    unsigned int group, gfp_t flags)
{}
EXPORT_SYMBOL();

void genl_notify(const struct genl_family *family, struct sk_buff *skb,
		 struct genl_info *info, u32 group, gfp_t flags)
{}
EXPORT_SYMBOL();