// SPDX-License-Identifier: GPL-2.0-only
/*
 *  Shared Memory Communications over RDMA (SMC-R) and RoCE
 *
 *  Definitions for the IPPROTO_SMC (socket related)
 *
 *  Copyright IBM Corp. 2016, 2018
 *  Copyright (c) 2024, Alibaba Inc.
 *
 *  Author: D. Wythe <alibuda@linux.alibaba.com>
 */

#include <net/protocol.h>
#include <net/sock.h>

#include "smc_inet.h"
#include "smc.h"

static int smc_inet_init_sock(struct sock *sk);

static struct proto smc_inet_prot = {
	.name		= "INET_SMC",
	.owner		= THIS_MODULE,
	.init		= smc_inet_init_sock,
	.hash		= smc_hash_sk,
	.unhash		= smc_unhash_sk,
	.release_cb	= smc_release_cb,
	.obj_size	= sizeof(struct smc_sock),
	.h.smc_hash	= &smc_v4_hashinfo,
	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
};

static const struct proto_ops smc_inet_stream_ops = {
	.family		= PF_INET,
	.owner		= THIS_MODULE,
	.release	= smc_release,
	.bind		= smc_bind,
	.connect	= smc_connect,
	.socketpair	= sock_no_socketpair,
	.accept		= smc_accept,
	.getname	= smc_getname,
	.poll		= smc_poll,
	.ioctl		= smc_ioctl,
	.listen		= smc_listen,
	.shutdown	= smc_shutdown,
	.setsockopt	= smc_setsockopt,
	.getsockopt	= smc_getsockopt,
	.sendmsg	= smc_sendmsg,
	.recvmsg	= smc_recvmsg,
	.mmap		= sock_no_mmap,
	.splice_read	= smc_splice_read,
};

static struct inet_protosw smc_inet_protosw = {
	.type		= SOCK_STREAM,
	.protocol	= IPPROTO_SMC,
	.prot		= &smc_inet_prot,
	.ops		= &smc_inet_stream_ops,
	.flags		= INET_PROTOSW_ICSK,
};

#if IS_ENABLED(CONFIG_IPV6)
struct smc6_sock {
	struct smc_sock		smc;
	struct ipv6_pinfo	inet6;
};

static struct proto smc_inet6_prot = {
	.name		= "INET6_SMC",
	.owner		= THIS_MODULE,
	.init		= smc_inet_init_sock,
	.hash		= smc_hash_sk,
	.unhash		= smc_unhash_sk,
	.release_cb	= smc_release_cb,
	.obj_size	= sizeof(struct smc6_sock),
	.h.smc_hash	= &smc_v6_hashinfo,
	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
	.ipv6_pinfo_offset	= offsetof(struct smc6_sock, inet6),
};

static const struct proto_ops smc_inet6_stream_ops = {
	.family		= PF_INET6,
	.owner		= THIS_MODULE,
	.release	= smc_release,
	.bind		= smc_bind,
	.connect	= smc_connect,
	.socketpair	= sock_no_socketpair,
	.accept		= smc_accept,
	.getname	= smc_getname,
	.poll		= smc_poll,
	.ioctl		= smc_ioctl,
	.listen		= smc_listen,
	.shutdown	= smc_shutdown,
	.setsockopt	= smc_setsockopt,
	.getsockopt	= smc_getsockopt,
	.sendmsg	= smc_sendmsg,
	.recvmsg	= smc_recvmsg,
	.mmap		= sock_no_mmap,
	.splice_read	= smc_splice_read,
};

static struct inet_protosw smc_inet6_protosw = {
	.type		= SOCK_STREAM,
	.protocol	= IPPROTO_SMC,
	.prot		= &smc_inet6_prot,
	.ops		= &smc_inet6_stream_ops,
	.flags		= INET_PROTOSW_ICSK,
};
#endif /* CONFIG_IPV6 */

static unsigned int smc_sync_mss(struct sock *sk, u32 pmtu)
{
	/* No need pass it through to clcsock, mss can always be set by
	 * sock_create_kern or smc_setsockopt.
	 */
	return 0;
}

static int smc_inet_init_sock(struct sock *sk)
{
	struct net *net = sock_net(sk);

	/* init common smc sock */
	smc_sk_init(net, sk, IPPROTO_SMC);

	inet_csk(sk)->icsk_sync_mss = smc_sync_mss;

	/* create clcsock */
	return smc_create_clcsk(net, sk, sk->sk_family);
}

int __init smc_inet_init(void)
{
	int rc;

	rc = proto_register(&smc_inet_prot, 1);
	if (rc) {
		pr_err("%s: proto_register smc_inet_prot fails with %d\n",
		       __func__, rc);
		return rc;
	}
	/* no return value */
	inet_register_protosw(&smc_inet_protosw);

#if IS_ENABLED(CONFIG_IPV6)
	rc = proto_register(&smc_inet6_prot, 1);
	if (rc) {
		pr_err("%s: proto_register smc_inet6_prot fails with %d\n",
		       __func__, rc);
		goto out_inet6_prot;
	}
	rc = inet6_register_protosw(&smc_inet6_protosw);
	if (rc) {
		pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n",
		       __func__, rc);
		goto out_inet6_protosw;
	}
	return rc;
out_inet6_protosw:
	proto_unregister(&smc_inet6_prot);
out_inet6_prot:
	inet_unregister_protosw(&smc_inet_protosw);
	proto_unregister(&smc_inet_prot);
#endif /* CONFIG_IPV6 */
	return rc;
}

void smc_inet_exit(void)
{
#if IS_ENABLED(CONFIG_IPV6)
	inet6_unregister_protosw(&smc_inet6_protosw);
	proto_unregister(&smc_inet6_prot);
#endif /* CONFIG_IPV6 */
	inet_unregister_protosw(&smc_inet_protosw);
	proto_unregister(&smc_inet_prot);
}
