162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _AF_NETLINK_H
362306a36Sopenharmony_ci#define _AF_NETLINK_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/rhashtable.h>
662306a36Sopenharmony_ci#include <linux/atomic.h>
762306a36Sopenharmony_ci#include <linux/workqueue.h>
862306a36Sopenharmony_ci#include <net/sock.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* flags */
1162306a36Sopenharmony_cienum {
1262306a36Sopenharmony_ci	NETLINK_F_KERNEL_SOCKET,
1362306a36Sopenharmony_ci	NETLINK_F_RECV_PKTINFO,
1462306a36Sopenharmony_ci	NETLINK_F_BROADCAST_SEND_ERROR,
1562306a36Sopenharmony_ci	NETLINK_F_RECV_NO_ENOBUFS,
1662306a36Sopenharmony_ci	NETLINK_F_LISTEN_ALL_NSID,
1762306a36Sopenharmony_ci	NETLINK_F_CAP_ACK,
1862306a36Sopenharmony_ci	NETLINK_F_EXT_ACK,
1962306a36Sopenharmony_ci	NETLINK_F_STRICT_CHK,
2062306a36Sopenharmony_ci};
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
2362306a36Sopenharmony_ci#define NLGRPLONGS(x)	(NLGRPSZ(x)/sizeof(unsigned long))
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct netlink_sock {
2662306a36Sopenharmony_ci	/* struct sock has to be the first member of netlink_sock */
2762306a36Sopenharmony_ci	struct sock		sk;
2862306a36Sopenharmony_ci	unsigned long		flags;
2962306a36Sopenharmony_ci	u32			portid;
3062306a36Sopenharmony_ci	u32			dst_portid;
3162306a36Sopenharmony_ci	u32			dst_group;
3262306a36Sopenharmony_ci	u32			subscriptions;
3362306a36Sopenharmony_ci	u32			ngroups;
3462306a36Sopenharmony_ci	unsigned long		*groups;
3562306a36Sopenharmony_ci	unsigned long		state;
3662306a36Sopenharmony_ci	size_t			max_recvmsg_len;
3762306a36Sopenharmony_ci	wait_queue_head_t	wait;
3862306a36Sopenharmony_ci	bool			bound;
3962306a36Sopenharmony_ci	bool			cb_running;
4062306a36Sopenharmony_ci	int			dump_done_errno;
4162306a36Sopenharmony_ci	struct netlink_callback	cb;
4262306a36Sopenharmony_ci	struct mutex		*cb_mutex;
4362306a36Sopenharmony_ci	struct mutex		cb_def_mutex;
4462306a36Sopenharmony_ci	void			(*netlink_rcv)(struct sk_buff *skb);
4562306a36Sopenharmony_ci	int			(*netlink_bind)(struct net *net, int group);
4662306a36Sopenharmony_ci	void			(*netlink_unbind)(struct net *net, int group);
4762306a36Sopenharmony_ci	void			(*netlink_release)(struct sock *sk,
4862306a36Sopenharmony_ci						   unsigned long *groups);
4962306a36Sopenharmony_ci	struct module		*module;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	struct rhash_head	node;
5262306a36Sopenharmony_ci	struct rcu_head		rcu;
5362306a36Sopenharmony_ci	struct work_struct	work;
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic inline struct netlink_sock *nlk_sk(struct sock *sk)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	return container_of(sk, struct netlink_sock, sk);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define nlk_test_bit(nr, sk) test_bit(NETLINK_F_##nr, &nlk_sk(sk)->flags)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct netlink_table {
6462306a36Sopenharmony_ci	struct rhashtable	hash;
6562306a36Sopenharmony_ci	struct hlist_head	mc_list;
6662306a36Sopenharmony_ci	struct listeners __rcu	*listeners;
6762306a36Sopenharmony_ci	unsigned int		flags;
6862306a36Sopenharmony_ci	unsigned int		groups;
6962306a36Sopenharmony_ci	struct mutex		*cb_mutex;
7062306a36Sopenharmony_ci	struct module		*module;
7162306a36Sopenharmony_ci	int			(*bind)(struct net *net, int group);
7262306a36Sopenharmony_ci	void			(*unbind)(struct net *net, int group);
7362306a36Sopenharmony_ci	void                    (*release)(struct sock *sk,
7462306a36Sopenharmony_ci					   unsigned long *groups);
7562306a36Sopenharmony_ci	int			registered;
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciextern struct netlink_table *nl_table;
7962306a36Sopenharmony_ciextern rwlock_t nl_table_lock;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#endif
82