162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  UDPLITEv6   An implementation of the UDP-Lite protocol over IPv6.
462306a36Sopenharmony_ci *              See also net/ipv4/udplite.c
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Authors:    Gerrit Renker       <gerrit@erg.abdn.ac.uk>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  Changes:
962306a36Sopenharmony_ci *  Fixes:
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#define pr_fmt(fmt) "UDPLite6: " fmt
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/export.h>
1462306a36Sopenharmony_ci#include <linux/proc_fs.h>
1562306a36Sopenharmony_ci#include "udp_impl.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic int udplitev6_sk_init(struct sock *sk)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	udpv6_init_sock(sk);
2062306a36Sopenharmony_ci	pr_warn_once("UDP-Lite is deprecated and scheduled to be removed in 2025, "
2162306a36Sopenharmony_ci		     "please contact the netdev mailing list\n");
2262306a36Sopenharmony_ci	return 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int udplitev6_rcv(struct sk_buff *skb)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int udplitev6_err(struct sk_buff *skb,
3162306a36Sopenharmony_ci			  struct inet6_skb_parm *opt,
3262306a36Sopenharmony_ci			  u8 type, u8 code, int offset, __be32 info)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	return __udp6_lib_err(skb, opt, type, code, offset, info,
3562306a36Sopenharmony_ci			      &udplite_table);
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic const struct inet6_protocol udplitev6_protocol = {
3962306a36Sopenharmony_ci	.handler	=	udplitev6_rcv,
4062306a36Sopenharmony_ci	.err_handler	=	udplitev6_err,
4162306a36Sopenharmony_ci	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct proto udplitev6_prot = {
4562306a36Sopenharmony_ci	.name		   = "UDPLITEv6",
4662306a36Sopenharmony_ci	.owner		   = THIS_MODULE,
4762306a36Sopenharmony_ci	.close		   = udp_lib_close,
4862306a36Sopenharmony_ci	.connect	   = ip6_datagram_connect,
4962306a36Sopenharmony_ci	.disconnect	   = udp_disconnect,
5062306a36Sopenharmony_ci	.ioctl		   = udp_ioctl,
5162306a36Sopenharmony_ci	.init		   = udplitev6_sk_init,
5262306a36Sopenharmony_ci	.destroy	   = udpv6_destroy_sock,
5362306a36Sopenharmony_ci	.setsockopt	   = udpv6_setsockopt,
5462306a36Sopenharmony_ci	.getsockopt	   = udpv6_getsockopt,
5562306a36Sopenharmony_ci	.sendmsg	   = udpv6_sendmsg,
5662306a36Sopenharmony_ci	.recvmsg	   = udpv6_recvmsg,
5762306a36Sopenharmony_ci	.hash		   = udp_lib_hash,
5862306a36Sopenharmony_ci	.unhash		   = udp_lib_unhash,
5962306a36Sopenharmony_ci	.rehash		   = udp_v6_rehash,
6062306a36Sopenharmony_ci	.get_port	   = udp_v6_get_port,
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	.memory_allocated  = &udp_memory_allocated,
6362306a36Sopenharmony_ci	.per_cpu_fw_alloc  = &udp_memory_per_cpu_fw_alloc,
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	.sysctl_mem	   = sysctl_udp_mem,
6662306a36Sopenharmony_ci	.sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
6762306a36Sopenharmony_ci	.sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
6862306a36Sopenharmony_ci	.obj_size	   = sizeof(struct udp6_sock),
6962306a36Sopenharmony_ci	.ipv6_pinfo_offset = offsetof(struct udp6_sock, inet6),
7062306a36Sopenharmony_ci	.h.udp_table	   = &udplite_table,
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic struct inet_protosw udplite6_protosw = {
7462306a36Sopenharmony_ci	.type		= SOCK_DGRAM,
7562306a36Sopenharmony_ci	.protocol	= IPPROTO_UDPLITE,
7662306a36Sopenharmony_ci	.prot		= &udplitev6_prot,
7762306a36Sopenharmony_ci	.ops		= &inet6_dgram_ops,
7862306a36Sopenharmony_ci	.flags		= INET_PROTOSW_PERMANENT,
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciint __init udplitev6_init(void)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	int ret;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
8662306a36Sopenharmony_ci	if (ret)
8762306a36Sopenharmony_ci		goto out;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	ret = inet6_register_protosw(&udplite6_protosw);
9062306a36Sopenharmony_ci	if (ret)
9162306a36Sopenharmony_ci		goto out_udplitev6_protocol;
9262306a36Sopenharmony_ciout:
9362306a36Sopenharmony_ci	return ret;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciout_udplitev6_protocol:
9662306a36Sopenharmony_ci	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
9762306a36Sopenharmony_ci	goto out;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_civoid udplitev6_exit(void)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	inet6_unregister_protosw(&udplite6_protosw);
10362306a36Sopenharmony_ci	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
10762306a36Sopenharmony_cistatic struct udp_seq_afinfo udplite6_seq_afinfo = {
10862306a36Sopenharmony_ci	.family		= AF_INET6,
10962306a36Sopenharmony_ci	.udp_table	= &udplite_table,
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic int __net_init udplite6_proc_init_net(struct net *net)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	if (!proc_create_net_data("udplite6", 0444, net->proc_net,
11562306a36Sopenharmony_ci			&udp6_seq_ops, sizeof(struct udp_iter_state),
11662306a36Sopenharmony_ci			&udplite6_seq_afinfo))
11762306a36Sopenharmony_ci		return -ENOMEM;
11862306a36Sopenharmony_ci	return 0;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic void __net_exit udplite6_proc_exit_net(struct net *net)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	remove_proc_entry("udplite6", net->proc_net);
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic struct pernet_operations udplite6_net_ops = {
12762306a36Sopenharmony_ci	.init = udplite6_proc_init_net,
12862306a36Sopenharmony_ci	.exit = udplite6_proc_exit_net,
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciint __init udplite6_proc_init(void)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	return register_pernet_subsys(&udplite6_net_ops);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_civoid udplite6_proc_exit(void)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	unregister_pernet_subsys(&udplite6_net_ops);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci#endif
141