162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Generic netlink handshake service
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Chuck Lever <chuck.lever@oracle.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2023, Oracle and/or its affiliates.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef _INTERNAL_HANDSHAKE_H
1162306a36Sopenharmony_ci#define _INTERNAL_HANDSHAKE_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/* Per-net namespace context */
1462306a36Sopenharmony_cistruct handshake_net {
1562306a36Sopenharmony_ci	spinlock_t		hn_lock;	/* protects next 3 fields */
1662306a36Sopenharmony_ci	int			hn_pending;
1762306a36Sopenharmony_ci	int			hn_pending_max;
1862306a36Sopenharmony_ci	struct list_head	hn_requests;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	unsigned long		hn_flags;
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cienum hn_flags_bits {
2462306a36Sopenharmony_ci	HANDSHAKE_F_NET_DRAINING,
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistruct handshake_proto;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* One handshake request */
3062306a36Sopenharmony_cistruct handshake_req {
3162306a36Sopenharmony_ci	struct list_head		hr_list;
3262306a36Sopenharmony_ci	struct rhash_head		hr_rhash;
3362306a36Sopenharmony_ci	unsigned long			hr_flags;
3462306a36Sopenharmony_ci	const struct handshake_proto	*hr_proto;
3562306a36Sopenharmony_ci	struct sock			*hr_sk;
3662306a36Sopenharmony_ci	void				(*hr_odestruct)(struct sock *sk);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* Always the last field */
3962306a36Sopenharmony_ci	char				hr_priv[];
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cienum hr_flags_bits {
4362306a36Sopenharmony_ci	HANDSHAKE_F_REQ_COMPLETED,
4462306a36Sopenharmony_ci	HANDSHAKE_F_REQ_SESSION,
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct genl_info;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Invariants for all handshake requests for one transport layer
5062306a36Sopenharmony_ci * security protocol
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_cistruct handshake_proto {
5362306a36Sopenharmony_ci	int			hp_handler_class;
5462306a36Sopenharmony_ci	size_t			hp_privsize;
5562306a36Sopenharmony_ci	unsigned long		hp_flags;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	int			(*hp_accept)(struct handshake_req *req,
5862306a36Sopenharmony_ci					     struct genl_info *info, int fd);
5962306a36Sopenharmony_ci	void			(*hp_done)(struct handshake_req *req,
6062306a36Sopenharmony_ci					   unsigned int status,
6162306a36Sopenharmony_ci					   struct genl_info *info);
6262306a36Sopenharmony_ci	void			(*hp_destroy)(struct handshake_req *req);
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cienum hp_flags_bits {
6662306a36Sopenharmony_ci	HANDSHAKE_F_PROTO_NOTIFY,
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/* alert.c */
7062306a36Sopenharmony_ciint tls_alert_send(struct socket *sock, u8 level, u8 description);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* netlink.c */
7362306a36Sopenharmony_ciint handshake_genl_notify(struct net *net, const struct handshake_proto *proto,
7462306a36Sopenharmony_ci			  gfp_t flags);
7562306a36Sopenharmony_cistruct nlmsghdr *handshake_genl_put(struct sk_buff *msg,
7662306a36Sopenharmony_ci				    struct genl_info *info);
7762306a36Sopenharmony_cistruct handshake_net *handshake_pernet(struct net *net);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* request.c */
8062306a36Sopenharmony_cistruct handshake_req *handshake_req_alloc(const struct handshake_proto *proto,
8162306a36Sopenharmony_ci					  gfp_t flags);
8262306a36Sopenharmony_ciint handshake_req_hash_init(void);
8362306a36Sopenharmony_civoid handshake_req_hash_destroy(void);
8462306a36Sopenharmony_civoid *handshake_req_private(struct handshake_req *req);
8562306a36Sopenharmony_cistruct handshake_req *handshake_req_hash_lookup(struct sock *sk);
8662306a36Sopenharmony_cistruct handshake_req *handshake_req_next(struct handshake_net *hn, int class);
8762306a36Sopenharmony_ciint handshake_req_submit(struct socket *sock, struct handshake_req *req,
8862306a36Sopenharmony_ci			 gfp_t flags);
8962306a36Sopenharmony_civoid handshake_complete(struct handshake_req *req, unsigned int status,
9062306a36Sopenharmony_ci			struct genl_info *info);
9162306a36Sopenharmony_cibool handshake_req_cancel(struct sock *sk);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci#endif /* _INTERNAL_HANDSHAKE_H */
94