18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  UDPLITEv6   An implementation of the UDP-Lite protocol over IPv6.
48c2ecf20Sopenharmony_ci *              See also net/ipv4/udplite.c
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *  Authors:    Gerrit Renker       <gerrit@erg.abdn.ac.uk>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Changes:
98c2ecf20Sopenharmony_ci *  Fixes:
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#include <linux/export.h>
128c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
138c2ecf20Sopenharmony_ci#include "udp_impl.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic int udplitev6_sk_init(struct sock *sk)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	udpv6_init_sock(sk);
188c2ecf20Sopenharmony_ci	udp_sk(sk)->pcflag = UDPLITE_BIT;
198c2ecf20Sopenharmony_ci	return 0;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic int udplitev6_rcv(struct sk_buff *skb)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic int udplitev6_err(struct sk_buff *skb,
288c2ecf20Sopenharmony_ci			  struct inet6_skb_parm *opt,
298c2ecf20Sopenharmony_ci			  u8 type, u8 code, int offset, __be32 info)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	return __udp6_lib_err(skb, opt, type, code, offset, info,
328c2ecf20Sopenharmony_ci			      &udplite_table);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic const struct inet6_protocol udplitev6_protocol = {
368c2ecf20Sopenharmony_ci	.handler	=	udplitev6_rcv,
378c2ecf20Sopenharmony_ci	.err_handler	=	udplitev6_err,
388c2ecf20Sopenharmony_ci	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
398c2ecf20Sopenharmony_ci};
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistruct proto udplitev6_prot = {
428c2ecf20Sopenharmony_ci	.name		   = "UDPLITEv6",
438c2ecf20Sopenharmony_ci	.owner		   = THIS_MODULE,
448c2ecf20Sopenharmony_ci	.close		   = udp_lib_close,
458c2ecf20Sopenharmony_ci	.connect	   = ip6_datagram_connect,
468c2ecf20Sopenharmony_ci	.disconnect	   = udp_disconnect,
478c2ecf20Sopenharmony_ci	.ioctl		   = udp_ioctl,
488c2ecf20Sopenharmony_ci	.init		   = udplitev6_sk_init,
498c2ecf20Sopenharmony_ci	.destroy	   = udpv6_destroy_sock,
508c2ecf20Sopenharmony_ci	.setsockopt	   = udpv6_setsockopt,
518c2ecf20Sopenharmony_ci	.getsockopt	   = udpv6_getsockopt,
528c2ecf20Sopenharmony_ci	.sendmsg	   = udpv6_sendmsg,
538c2ecf20Sopenharmony_ci	.recvmsg	   = udpv6_recvmsg,
548c2ecf20Sopenharmony_ci	.hash		   = udp_lib_hash,
558c2ecf20Sopenharmony_ci	.unhash		   = udp_lib_unhash,
568c2ecf20Sopenharmony_ci	.rehash		   = udp_v6_rehash,
578c2ecf20Sopenharmony_ci	.get_port	   = udp_v6_get_port,
588c2ecf20Sopenharmony_ci	.memory_allocated  = &udp_memory_allocated,
598c2ecf20Sopenharmony_ci	.sysctl_mem	   = sysctl_udp_mem,
608c2ecf20Sopenharmony_ci	.sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
618c2ecf20Sopenharmony_ci	.sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
628c2ecf20Sopenharmony_ci	.obj_size	   = sizeof(struct udp6_sock),
638c2ecf20Sopenharmony_ci	.h.udp_table	   = &udplite_table,
648c2ecf20Sopenharmony_ci};
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic struct inet_protosw udplite6_protosw = {
678c2ecf20Sopenharmony_ci	.type		= SOCK_DGRAM,
688c2ecf20Sopenharmony_ci	.protocol	= IPPROTO_UDPLITE,
698c2ecf20Sopenharmony_ci	.prot		= &udplitev6_prot,
708c2ecf20Sopenharmony_ci	.ops		= &inet6_dgram_ops,
718c2ecf20Sopenharmony_ci	.flags		= INET_PROTOSW_PERMANENT,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciint __init udplitev6_init(void)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	int ret;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
798c2ecf20Sopenharmony_ci	if (ret)
808c2ecf20Sopenharmony_ci		goto out;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	ret = inet6_register_protosw(&udplite6_protosw);
838c2ecf20Sopenharmony_ci	if (ret)
848c2ecf20Sopenharmony_ci		goto out_udplitev6_protocol;
858c2ecf20Sopenharmony_ciout:
868c2ecf20Sopenharmony_ci	return ret;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ciout_udplitev6_protocol:
898c2ecf20Sopenharmony_ci	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
908c2ecf20Sopenharmony_ci	goto out;
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_civoid udplitev6_exit(void)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	inet6_unregister_protosw(&udplite6_protosw);
968c2ecf20Sopenharmony_ci	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
1008c2ecf20Sopenharmony_cistatic struct udp_seq_afinfo udplite6_seq_afinfo = {
1018c2ecf20Sopenharmony_ci	.family		= AF_INET6,
1028c2ecf20Sopenharmony_ci	.udp_table	= &udplite_table,
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic int __net_init udplite6_proc_init_net(struct net *net)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	if (!proc_create_net_data("udplite6", 0444, net->proc_net,
1088c2ecf20Sopenharmony_ci			&udp6_seq_ops, sizeof(struct udp_iter_state),
1098c2ecf20Sopenharmony_ci			&udplite6_seq_afinfo))
1108c2ecf20Sopenharmony_ci		return -ENOMEM;
1118c2ecf20Sopenharmony_ci	return 0;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic void __net_exit udplite6_proc_exit_net(struct net *net)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	remove_proc_entry("udplite6", net->proc_net);
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic struct pernet_operations udplite6_net_ops = {
1208c2ecf20Sopenharmony_ci	.init = udplite6_proc_init_net,
1218c2ecf20Sopenharmony_ci	.exit = udplite6_proc_exit_net,
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ciint __init udplite6_proc_init(void)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	return register_pernet_subsys(&udplite6_net_ops);
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_civoid udplite6_proc_exit(void)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	unregister_pernet_subsys(&udplite6_net_ops);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci#endif
134