1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* (C) 1999-2001 Paul `Rusty' Russell |
3 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> |
4 | * (C) 2006-2012 Patrick McHardy <kaber@trash.net> |
5 | */ |
6 | |
7 | #include <linux/types.h> |
8 | #include <linux/timer.h> |
9 | #include <linux/module.h> |
10 | #include <linux/udp.h> |
11 | #include <linux/seq_file.h> |
12 | #include <linux/skbuff.h> |
13 | #include <linux/ipv6.h> |
14 | #include <net/ip6_checksum.h> |
15 | #include <net/checksum.h> |
16 | |
17 | #include <linux/netfilter.h> |
18 | #include <linux/netfilter_ipv4.h> |
19 | #include <linux/netfilter_ipv6.h> |
20 | #include <net/netfilter/nf_conntrack_l4proto.h> |
21 | #include <net/netfilter/nf_conntrack_ecache.h> |
22 | #include <net/netfilter/nf_conntrack_timeout.h> |
23 | #include <net/netfilter/nf_log.h> |
24 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
25 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
26 | |
27 | static const unsigned int udp_timeouts[UDP_CT_MAX] = { |
28 | [UDP_CT_UNREPLIED] = 30*HZ, |
29 | [UDP_CT_REPLIED] = 120*HZ, |
30 | }; |
31 | |
32 | static unsigned int *udp_get_timeouts(struct net *net) |
33 | { |
34 | return nf_udp_pernet(net)->timeouts; |
35 | } |
36 | |
37 | static void udp_error_log(const struct sk_buff *skb, |
38 | const struct nf_hook_state *state, |
39 | const char *msg) |
40 | { |
41 | nf_l4proto_log_invalid(skb, state, IPPROTO_UDP, fmt: "%s" , msg); |
42 | } |
43 | |
44 | static bool udp_error(struct sk_buff *skb, |
45 | unsigned int dataoff, |
46 | const struct nf_hook_state *state) |
47 | { |
48 | unsigned int udplen = skb->len - dataoff; |
49 | const struct udphdr *hdr; |
50 | struct udphdr _hdr; |
51 | |
52 | /* Header is too small? */ |
53 | hdr = skb_header_pointer(skb, offset: dataoff, len: sizeof(_hdr), buffer: &_hdr); |
54 | if (!hdr) { |
55 | udp_error_log(skb, state, msg: "short packet" ); |
56 | return true; |
57 | } |
58 | |
59 | /* Truncated/malformed packets */ |
60 | if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { |
61 | udp_error_log(skb, state, msg: "truncated/malformed packet" ); |
62 | return true; |
63 | } |
64 | |
65 | /* Packet with no checksum */ |
66 | if (!hdr->check) |
67 | return false; |
68 | |
69 | /* Checksum invalid? Ignore. |
70 | * We skip checking packets on the outgoing path |
71 | * because the checksum is assumed to be correct. |
72 | * FIXME: Source route IP option packets --RR */ |
73 | if (state->hook == NF_INET_PRE_ROUTING && |
74 | state->net->ct.sysctl_checksum && |
75 | nf_checksum(skb, hook: state->hook, dataoff, IPPROTO_UDP, family: state->pf)) { |
76 | udp_error_log(skb, state, msg: "bad checksum" ); |
77 | return true; |
78 | } |
79 | |
80 | return false; |
81 | } |
82 | |
83 | /* Returns verdict for packet, and may modify conntracktype */ |
84 | int nf_conntrack_udp_packet(struct nf_conn *ct, |
85 | struct sk_buff *skb, |
86 | unsigned int dataoff, |
87 | enum ip_conntrack_info ctinfo, |
88 | const struct nf_hook_state *state) |
89 | { |
90 | unsigned int *timeouts; |
91 | unsigned long status; |
92 | |
93 | if (udp_error(skb, dataoff, state)) |
94 | return -NF_ACCEPT; |
95 | |
96 | timeouts = nf_ct_timeout_lookup(ct); |
97 | if (!timeouts) |
98 | timeouts = udp_get_timeouts(net: nf_ct_net(ct)); |
99 | |
100 | status = READ_ONCE(ct->status); |
101 | if ((status & IPS_CONFIRMED) == 0) |
102 | ct->proto.udp.stream_ts = 2 * HZ + jiffies; |
103 | |
104 | /* If we've seen traffic both ways, this is some kind of UDP |
105 | * stream. Set Assured. |
106 | */ |
107 | if (status & IPS_SEEN_REPLY) { |
108 | unsigned long = timeouts[UDP_CT_UNREPLIED]; |
109 | bool stream = false; |
110 | |
111 | /* Still active after two seconds? Extend timeout. */ |
112 | if (time_after(jiffies, ct->proto.udp.stream_ts)) { |
113 | extra = timeouts[UDP_CT_REPLIED]; |
114 | stream = (status & IPS_ASSURED) == 0; |
115 | } |
116 | |
117 | nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies: extra); |
118 | |
119 | /* never set ASSURED for IPS_NAT_CLASH, they time out soon */ |
120 | if (unlikely((status & IPS_NAT_CLASH))) |
121 | return NF_ACCEPT; |
122 | |
123 | /* Also, more likely to be important, and not a probe */ |
124 | if (stream && !test_and_set_bit(nr: IPS_ASSURED_BIT, addr: &ct->status)) |
125 | nf_conntrack_event_cache(event: IPCT_ASSURED, ct); |
126 | } else { |
127 | nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies: timeouts[UDP_CT_UNREPLIED]); |
128 | } |
129 | return NF_ACCEPT; |
130 | } |
131 | |
132 | #ifdef CONFIG_NF_CT_PROTO_UDPLITE |
133 | static void udplite_error_log(const struct sk_buff *skb, |
134 | const struct nf_hook_state *state, |
135 | const char *msg) |
136 | { |
137 | nf_l4proto_log_invalid(skb, state, IPPROTO_UDPLITE, fmt: "%s" , msg); |
138 | } |
139 | |
140 | static bool udplite_error(struct sk_buff *skb, |
141 | unsigned int dataoff, |
142 | const struct nf_hook_state *state) |
143 | { |
144 | unsigned int udplen = skb->len - dataoff; |
145 | const struct udphdr *hdr; |
146 | struct udphdr _hdr; |
147 | unsigned int cscov; |
148 | |
149 | /* Header is too small? */ |
150 | hdr = skb_header_pointer(skb, offset: dataoff, len: sizeof(_hdr), buffer: &_hdr); |
151 | if (!hdr) { |
152 | udplite_error_log(skb, state, msg: "short packet" ); |
153 | return true; |
154 | } |
155 | |
156 | cscov = ntohs(hdr->len); |
157 | if (cscov == 0) { |
158 | cscov = udplen; |
159 | } else if (cscov < sizeof(*hdr) || cscov > udplen) { |
160 | udplite_error_log(skb, state, msg: "invalid checksum coverage" ); |
161 | return true; |
162 | } |
163 | |
164 | /* UDPLITE mandates checksums */ |
165 | if (!hdr->check) { |
166 | udplite_error_log(skb, state, msg: "checksum missing" ); |
167 | return true; |
168 | } |
169 | |
170 | /* Checksum invalid? Ignore. */ |
171 | if (state->hook == NF_INET_PRE_ROUTING && |
172 | state->net->ct.sysctl_checksum && |
173 | nf_checksum_partial(skb, hook: state->hook, dataoff, len: cscov, IPPROTO_UDP, |
174 | family: state->pf)) { |
175 | udplite_error_log(skb, state, msg: "bad checksum" ); |
176 | return true; |
177 | } |
178 | |
179 | return false; |
180 | } |
181 | |
182 | /* Returns verdict for packet, and may modify conntracktype */ |
183 | int nf_conntrack_udplite_packet(struct nf_conn *ct, |
184 | struct sk_buff *skb, |
185 | unsigned int dataoff, |
186 | enum ip_conntrack_info ctinfo, |
187 | const struct nf_hook_state *state) |
188 | { |
189 | unsigned int *timeouts; |
190 | |
191 | if (udplite_error(skb, dataoff, state)) |
192 | return -NF_ACCEPT; |
193 | |
194 | timeouts = nf_ct_timeout_lookup(ct); |
195 | if (!timeouts) |
196 | timeouts = udp_get_timeouts(net: nf_ct_net(ct)); |
197 | |
198 | /* If we've seen traffic both ways, this is some kind of UDP |
199 | stream. Extend timeout. */ |
200 | if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { |
201 | nf_ct_refresh_acct(ct, ctinfo, skb, |
202 | extra_jiffies: timeouts[UDP_CT_REPLIED]); |
203 | |
204 | if (unlikely((ct->status & IPS_NAT_CLASH))) |
205 | return NF_ACCEPT; |
206 | |
207 | /* Also, more likely to be important, and not a probe */ |
208 | if (!test_and_set_bit(nr: IPS_ASSURED_BIT, addr: &ct->status)) |
209 | nf_conntrack_event_cache(event: IPCT_ASSURED, ct); |
210 | } else { |
211 | nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies: timeouts[UDP_CT_UNREPLIED]); |
212 | } |
213 | return NF_ACCEPT; |
214 | } |
215 | #endif |
216 | |
217 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
218 | |
219 | #include <linux/netfilter/nfnetlink.h> |
220 | #include <linux/netfilter/nfnetlink_cttimeout.h> |
221 | |
222 | static int udp_timeout_nlattr_to_obj(struct nlattr *tb[], |
223 | struct net *net, void *data) |
224 | { |
225 | unsigned int *timeouts = data; |
226 | struct nf_udp_net *un = nf_udp_pernet(net); |
227 | |
228 | if (!timeouts) |
229 | timeouts = un->timeouts; |
230 | |
231 | /* set default timeouts for UDP. */ |
232 | timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED]; |
233 | timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED]; |
234 | |
235 | if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) { |
236 | timeouts[UDP_CT_UNREPLIED] = |
237 | ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ; |
238 | } |
239 | if (tb[CTA_TIMEOUT_UDP_REPLIED]) { |
240 | timeouts[UDP_CT_REPLIED] = |
241 | ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ; |
242 | } |
243 | return 0; |
244 | } |
245 | |
246 | static int |
247 | udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) |
248 | { |
249 | const unsigned int *timeouts = data; |
250 | |
251 | if (nla_put_be32(skb, attrtype: CTA_TIMEOUT_UDP_UNREPLIED, |
252 | htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) || |
253 | nla_put_be32(skb, attrtype: CTA_TIMEOUT_UDP_REPLIED, |
254 | htonl(timeouts[UDP_CT_REPLIED] / HZ))) |
255 | goto nla_put_failure; |
256 | return 0; |
257 | |
258 | nla_put_failure: |
259 | return -ENOSPC; |
260 | } |
261 | |
262 | static const struct nla_policy |
263 | udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = { |
264 | [CTA_TIMEOUT_UDP_UNREPLIED] = { .type = NLA_U32 }, |
265 | [CTA_TIMEOUT_UDP_REPLIED] = { .type = NLA_U32 }, |
266 | }; |
267 | #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ |
268 | |
269 | void nf_conntrack_udp_init_net(struct net *net) |
270 | { |
271 | struct nf_udp_net *un = nf_udp_pernet(net); |
272 | int i; |
273 | |
274 | for (i = 0; i < UDP_CT_MAX; i++) |
275 | un->timeouts[i] = udp_timeouts[i]; |
276 | |
277 | #if IS_ENABLED(CONFIG_NF_FLOW_TABLE) |
278 | un->offload_timeout = 30 * HZ; |
279 | #endif |
280 | } |
281 | |
282 | const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp = |
283 | { |
284 | .l4proto = IPPROTO_UDP, |
285 | .allow_clash = true, |
286 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
287 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
288 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
289 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, |
290 | .nla_policy = nf_ct_port_nla_policy, |
291 | #endif |
292 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
293 | .ctnl_timeout = { |
294 | .nlattr_to_obj = udp_timeout_nlattr_to_obj, |
295 | .obj_to_nlattr = udp_timeout_obj_to_nlattr, |
296 | .nlattr_max = CTA_TIMEOUT_UDP_MAX, |
297 | .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX, |
298 | .nla_policy = udp_timeout_nla_policy, |
299 | }, |
300 | #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ |
301 | }; |
302 | |
303 | #ifdef CONFIG_NF_CT_PROTO_UDPLITE |
304 | const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite = |
305 | { |
306 | .l4proto = IPPROTO_UDPLITE, |
307 | .allow_clash = true, |
308 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
309 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
310 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
311 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, |
312 | .nla_policy = nf_ct_port_nla_policy, |
313 | #endif |
314 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
315 | .ctnl_timeout = { |
316 | .nlattr_to_obj = udp_timeout_nlattr_to_obj, |
317 | .obj_to_nlattr = udp_timeout_obj_to_nlattr, |
318 | .nlattr_max = CTA_TIMEOUT_UDP_MAX, |
319 | .obj_size = sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX, |
320 | .nla_policy = udp_timeout_nla_policy, |
321 | }, |
322 | #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ |
323 | }; |
324 | #endif |
325 | |