GNU Linux-libre 4.19.314-gnu1
[releases.git] / net / ipv6 / udplite.c
1 /*
2  *  UDPLITEv6   An implementation of the UDP-Lite protocol over IPv6.
3  *              See also net/ipv4/udplite.c
4  *
5  *  Authors:    Gerrit Renker       <gerrit@erg.abdn.ac.uk>
6  *
7  *  Changes:
8  *  Fixes:
9  *              This program is free software; you can redistribute it and/or
10  *              modify it under the terms of the GNU General Public License
11  *              as published by the Free Software Foundation; either version
12  *              2 of the License, or (at your option) any later version.
13  */
14 #include <linux/export.h>
15 #include <linux/proc_fs.h>
16 #include "udp_impl.h"
17
18 static int udplitev6_sk_init(struct sock *sk)
19 {
20         udpv6_init_sock(sk);
21         udp_sk(sk)->pcflag = UDPLITE_BIT;
22         return 0;
23 }
24
25 static int udplitev6_rcv(struct sk_buff *skb)
26 {
27         return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
28 }
29
30 static void udplitev6_err(struct sk_buff *skb,
31                           struct inet6_skb_parm *opt,
32                           u8 type, u8 code, int offset, __be32 info)
33 {
34         __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table);
35 }
36
37 static const struct inet6_protocol udplitev6_protocol = {
38         .handler        =       udplitev6_rcv,
39         .err_handler    =       udplitev6_err,
40         .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
41 };
42
43 struct proto udplitev6_prot = {
44         .name              = "UDPLITEv6",
45         .owner             = THIS_MODULE,
46         .close             = udp_lib_close,
47         .connect           = ip6_datagram_connect,
48         .disconnect        = udp_disconnect,
49         .ioctl             = udp_ioctl,
50         .init              = udplitev6_sk_init,
51         .destroy           = udpv6_destroy_sock,
52         .setsockopt        = udpv6_setsockopt,
53         .getsockopt        = udpv6_getsockopt,
54         .sendmsg           = udpv6_sendmsg,
55         .recvmsg           = udpv6_recvmsg,
56         .hash              = udp_lib_hash,
57         .unhash            = udp_lib_unhash,
58         .get_port          = udp_v6_get_port,
59         .memory_allocated  = &udp_memory_allocated,
60         .sysctl_mem        = sysctl_udp_mem,
61         .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
62         .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
63         .obj_size          = sizeof(struct udp6_sock),
64         .h.udp_table       = &udplite_table,
65 #ifdef CONFIG_COMPAT
66         .compat_setsockopt = compat_udpv6_setsockopt,
67         .compat_getsockopt = compat_udpv6_getsockopt,
68 #endif
69 };
70
71 static struct inet_protosw udplite6_protosw = {
72         .type           = SOCK_DGRAM,
73         .protocol       = IPPROTO_UDPLITE,
74         .prot           = &udplitev6_prot,
75         .ops            = &inet6_dgram_ops,
76         .flags          = INET_PROTOSW_PERMANENT,
77 };
78
79 int __init udplitev6_init(void)
80 {
81         int ret;
82
83         ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
84         if (ret)
85                 goto out;
86
87         ret = inet6_register_protosw(&udplite6_protosw);
88         if (ret)
89                 goto out_udplitev6_protocol;
90 out:
91         return ret;
92
93 out_udplitev6_protocol:
94         inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
95         goto out;
96 }
97
98 void udplitev6_exit(void)
99 {
100         inet6_unregister_protosw(&udplite6_protosw);
101         inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
102 }
103
104 #ifdef CONFIG_PROC_FS
105 static struct udp_seq_afinfo udplite6_seq_afinfo = {
106         .family         = AF_INET6,
107         .udp_table      = &udplite_table,
108 };
109
110 static int __net_init udplite6_proc_init_net(struct net *net)
111 {
112         if (!proc_create_net_data("udplite6", 0444, net->proc_net,
113                         &udp6_seq_ops, sizeof(struct udp_iter_state),
114                         &udplite6_seq_afinfo))
115                 return -ENOMEM;
116         return 0;
117 }
118
119 static void __net_exit udplite6_proc_exit_net(struct net *net)
120 {
121         remove_proc_entry("udplite6", net->proc_net);
122 }
123
124 static struct pernet_operations udplite6_net_ops = {
125         .init = udplite6_proc_init_net,
126         .exit = udplite6_proc_exit_net,
127 };
128
129 int __init udplite6_proc_init(void)
130 {
131         return register_pernet_subsys(&udplite6_net_ops);
132 }
133
134 void udplite6_proc_exit(void)
135 {
136         unregister_pernet_subsys(&udplite6_net_ops);
137 }
138 #endif