Blame view

net/netfilter/nf_conntrack_proto_udp.c 8.4 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
2
3
  /* (C) 1999-2001 Paul `Rusty' Russell
   * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
f229f6ce4   Patrick McHardy   netfilter: add my...
4
   * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
5
6
7
   */
  
  #include <linux/types.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
8
9
  #include <linux/timer.h>
  #include <linux/module.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
10
11
12
13
14
15
  #include <linux/udp.h>
  #include <linux/seq_file.h>
  #include <linux/skbuff.h>
  #include <linux/ipv6.h>
  #include <net/ip6_checksum.h>
  #include <net/checksum.h>
f61801218   Martin Josefsson   [NETFILTER]: nf_c...
16

9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
17
18
19
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv6.h>
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
20
  #include <net/netfilter/nf_conntrack_l4proto.h>
f61801218   Martin Josefsson   [NETFILTER]: nf_c...
21
  #include <net/netfilter/nf_conntrack_ecache.h>
c779e8496   Florian Westphal   netfilter: conntr...
22
  #include <net/netfilter/nf_conntrack_timeout.h>
f01ffbd6e   Patrick McHardy   [NETFILTER]: nf_l...
23
  #include <net/netfilter/nf_log.h>
9d2493f88   Christoph Paasch   netfilter: remove...
24
25
  #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
  #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
26

2c9e8637e   Florian Westphal   netfilter: conntr...
27
  static const unsigned int udp_timeouts[UDP_CT_MAX] = {
5a41db94c   Pablo Neira Ayuso   netfilter: nf_ct_...
28
  	[UDP_CT_UNREPLIED]	= 30*HZ,
294304e4c   Florian Westphal   netfilter: conntr...
29
  	[UDP_CT_REPLIED]	= 120*HZ,
5a41db94c   Pablo Neira Ayuso   netfilter: nf_ct_...
30
  };
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
31

2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
32
33
  static unsigned int *udp_get_timeouts(struct net *net)
  {
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
34
  	return nf_udp_pernet(net)->timeouts;
2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
35
  }
83d213fd9   Florian Westphal   netfilter: conntr...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  static void udp_error_log(const struct sk_buff *skb,
  			  const struct nf_hook_state *state,
  			  const char *msg)
  {
  	nf_l4proto_log_invalid(skb, state->net, state->pf,
  			       IPPROTO_UDP, "%s", msg);
  }
  
  static bool udp_error(struct sk_buff *skb,
  		      unsigned int dataoff,
  		      const struct nf_hook_state *state)
  {
  	unsigned int udplen = skb->len - dataoff;
  	const struct udphdr *hdr;
  	struct udphdr _hdr;
  
  	/* Header is too small? */
  	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  	if (!hdr) {
  		udp_error_log(skb, state, "short packet");
  		return true;
  	}
  
  	/* Truncated/malformed packets */
  	if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
  		udp_error_log(skb, state, "truncated/malformed packet");
  		return true;
  	}
  
  	/* Packet with no checksum */
  	if (!hdr->check)
  		return false;
  
  	/* Checksum invalid? Ignore.
  	 * We skip checking packets on the outgoing path
  	 * because the checksum is assumed to be correct.
  	 * FIXME: Source route IP option packets --RR */
  	if (state->hook == NF_INET_PRE_ROUTING &&
  	    state->net->ct.sysctl_checksum &&
  	    nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) {
  		udp_error_log(skb, state, "bad checksum");
  		return true;
  	}
  
  	return false;
  }
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
82
  /* Returns verdict for packet, and may modify conntracktype */
a47c54048   Florian Westphal   netfilter: conntr...
83
84
85
86
87
  int nf_conntrack_udp_packet(struct nf_conn *ct,
  			    struct sk_buff *skb,
  			    unsigned int dataoff,
  			    enum ip_conntrack_info ctinfo,
  			    const struct nf_hook_state *state)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
88
  {
c779e8496   Florian Westphal   netfilter: conntr...
89
  	unsigned int *timeouts;
83d213fd9   Florian Westphal   netfilter: conntr...
90
91
  	if (udp_error(skb, dataoff, state))
  		return -NF_ACCEPT;
c779e8496   Florian Westphal   netfilter: conntr...
92
93
94
  	timeouts = nf_ct_timeout_lookup(ct);
  	if (!timeouts)
  		timeouts = udp_get_timeouts(nf_ct_net(ct));
d535c8a69   Florian Westphal   netfilter: conntr...
95
96
  	if (!nf_ct_is_confirmed(ct))
  		ct->proto.udp.stream_ts = 2 * HZ + jiffies;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
97
  	/* If we've seen traffic both ways, this is some kind of UDP
d535c8a69   Florian Westphal   netfilter: conntr...
98
99
  	 * stream. Set Assured.
  	 */
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
100
  	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
d535c8a69   Florian Westphal   netfilter: conntr...
101
102
103
104
105
106
107
  		unsigned long extra = timeouts[UDP_CT_UNREPLIED];
  
  		/* Still active after two seconds? Extend timeout. */
  		if (time_after(jiffies, ct->proto.udp.stream_ts))
  			extra = timeouts[UDP_CT_REPLIED];
  
  		nf_ct_refresh_acct(ct, ctinfo, skb, extra);
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
108
  		/* Also, more likely to be important, and not a probe */
c88130bcd   Patrick McHardy   [NETFILTER]: nf_c...
109
  		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
858b31330   Patrick McHardy   netfilter: nf_con...
110
  			nf_conntrack_event_cache(IPCT_ASSURED, ct);
5a41db94c   Pablo Neira Ayuso   netfilter: nf_ct_...
111
112
  	} else {
  		nf_ct_refresh_acct(ct, ctinfo, skb,
2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
113
  				   timeouts[UDP_CT_UNREPLIED]);
5a41db94c   Pablo Neira Ayuso   netfilter: nf_ct_...
114
  	}
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
115
116
  	return NF_ACCEPT;
  }
e4781421e   Florian Westphal   netfilter: merge ...
117
  #ifdef CONFIG_NF_CT_PROTO_UDPLITE
93e66024b   Florian Westphal   netfilter: conntr...
118
119
120
  static void udplite_error_log(const struct sk_buff *skb,
  			      const struct nf_hook_state *state,
  			      const char *msg)
c4f3db159   Florian Westphal   netfilter: conntr...
121
  {
93e66024b   Florian Westphal   netfilter: conntr...
122
123
  	nf_l4proto_log_invalid(skb, state->net, state->pf,
  			       IPPROTO_UDPLITE, "%s", msg);
c4f3db159   Florian Westphal   netfilter: conntr...
124
  }
83d213fd9   Florian Westphal   netfilter: conntr...
125
126
127
  static bool udplite_error(struct sk_buff *skb,
  			  unsigned int dataoff,
  			  const struct nf_hook_state *state)
e4781421e   Florian Westphal   netfilter: merge ...
128
129
130
131
132
133
134
135
136
  {
  	unsigned int udplen = skb->len - dataoff;
  	const struct udphdr *hdr;
  	struct udphdr _hdr;
  	unsigned int cscov;
  
  	/* Header is too small? */
  	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  	if (!hdr) {
93e66024b   Florian Westphal   netfilter: conntr...
137
  		udplite_error_log(skb, state, "short packet");
83d213fd9   Florian Westphal   netfilter: conntr...
138
  		return true;
e4781421e   Florian Westphal   netfilter: merge ...
139
140
141
142
143
144
  	}
  
  	cscov = ntohs(hdr->len);
  	if (cscov == 0) {
  		cscov = udplen;
  	} else if (cscov < sizeof(*hdr) || cscov > udplen) {
93e66024b   Florian Westphal   netfilter: conntr...
145
  		udplite_error_log(skb, state, "invalid checksum coverage");
83d213fd9   Florian Westphal   netfilter: conntr...
146
  		return true;
e4781421e   Florian Westphal   netfilter: merge ...
147
148
149
150
  	}
  
  	/* UDPLITE mandates checksums */
  	if (!hdr->check) {
93e66024b   Florian Westphal   netfilter: conntr...
151
  		udplite_error_log(skb, state, "checksum missing");
83d213fd9   Florian Westphal   netfilter: conntr...
152
  		return true;
e4781421e   Florian Westphal   netfilter: merge ...
153
154
155
  	}
  
  	/* Checksum invalid? Ignore. */
93e66024b   Florian Westphal   netfilter: conntr...
156
157
158
159
160
  	if (state->hook == NF_INET_PRE_ROUTING &&
  	    state->net->ct.sysctl_checksum &&
  	    nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP,
  				state->pf)) {
  		udplite_error_log(skb, state, "bad checksum");
83d213fd9   Florian Westphal   netfilter: conntr...
161
  		return true;
e4781421e   Florian Westphal   netfilter: merge ...
162
  	}
83d213fd9   Florian Westphal   netfilter: conntr...
163
  	return false;
e4781421e   Florian Westphal   netfilter: merge ...
164
  }
e4781421e   Florian Westphal   netfilter: merge ...
165

83d213fd9   Florian Westphal   netfilter: conntr...
166
  /* Returns verdict for packet, and may modify conntracktype */
a47c54048   Florian Westphal   netfilter: conntr...
167
168
169
170
171
  int nf_conntrack_udplite_packet(struct nf_conn *ct,
  				struct sk_buff *skb,
  				unsigned int dataoff,
  				enum ip_conntrack_info ctinfo,
  				const struct nf_hook_state *state)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
172
  {
83d213fd9   Florian Westphal   netfilter: conntr...
173
  	unsigned int *timeouts;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
174

83d213fd9   Florian Westphal   netfilter: conntr...
175
  	if (udplite_error(skb, dataoff, state))
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
176
  		return -NF_ACCEPT;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
177

83d213fd9   Florian Westphal   netfilter: conntr...
178
179
180
  	timeouts = nf_ct_timeout_lookup(ct);
  	if (!timeouts)
  		timeouts = udp_get_timeouts(nf_ct_net(ct));
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
181

83d213fd9   Florian Westphal   netfilter: conntr...
182
183
184
185
186
187
188
189
190
191
192
  	/* If we've seen traffic both ways, this is some kind of UDP
  	   stream.  Extend timeout. */
  	if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  		nf_ct_refresh_acct(ct, ctinfo, skb,
  				   timeouts[UDP_CT_REPLIED]);
  		/* Also, more likely to be important, and not a probe */
  		if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
  			nf_conntrack_event_cache(IPCT_ASSURED, ct);
  	} else {
  		nf_ct_refresh_acct(ct, ctinfo, skb,
  				   timeouts[UDP_CT_UNREPLIED]);
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
193
  	}
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
194
195
  	return NF_ACCEPT;
  }
83d213fd9   Florian Westphal   netfilter: conntr...
196
  #endif
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
197

a874752a1   Pablo Neira Ayuso   netfilter: conntr...
198
  #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
509784623   Pablo Neira Ayuso   netfilter: add ct...
199
200
201
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_cttimeout.h>
8264deb81   Gao feng   netfilter: nf_con...
202
203
  static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
  				     struct net *net, void *data)
509784623   Pablo Neira Ayuso   netfilter: add ct...
204
205
  {
  	unsigned int *timeouts = data;
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
206
  	struct nf_udp_net *un = nf_udp_pernet(net);
509784623   Pablo Neira Ayuso   netfilter: add ct...
207

c779e8496   Florian Westphal   netfilter: conntr...
208
209
  	if (!timeouts)
  		timeouts = un->timeouts;
509784623   Pablo Neira Ayuso   netfilter: add ct...
210
  	/* set default timeouts for UDP. */
8264deb81   Gao feng   netfilter: nf_con...
211
212
  	timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
  	timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
509784623   Pablo Neira Ayuso   netfilter: add ct...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  
  	if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
  		timeouts[UDP_CT_UNREPLIED] =
  			ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_UNREPLIED])) * HZ;
  	}
  	if (tb[CTA_TIMEOUT_UDP_REPLIED]) {
  		timeouts[UDP_CT_REPLIED] =
  			ntohl(nla_get_be32(tb[CTA_TIMEOUT_UDP_REPLIED])) * HZ;
  	}
  	return 0;
  }
  
  static int
  udp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
  {
  	const unsigned int *timeouts = data;
3c60a17b1   David S. Miller   nf_conntrack_prot...
229
230
231
232
233
  	if (nla_put_be32(skb, CTA_TIMEOUT_UDP_UNREPLIED,
  			 htonl(timeouts[UDP_CT_UNREPLIED] / HZ)) ||
  	    nla_put_be32(skb, CTA_TIMEOUT_UDP_REPLIED,
  			 htonl(timeouts[UDP_CT_REPLIED] / HZ)))
  		goto nla_put_failure;
509784623   Pablo Neira Ayuso   netfilter: add ct...
234
235
236
237
238
239
240
241
242
243
244
  	return 0;
  
  nla_put_failure:
  	return -ENOSPC;
  }
  
  static const struct nla_policy
  udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
         [CTA_TIMEOUT_UDP_UNREPLIED]	= { .type = NLA_U32 },
         [CTA_TIMEOUT_UDP_REPLIED]	= { .type = NLA_U32 },
  };
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
245
  #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
509784623   Pablo Neira Ayuso   netfilter: add ct...
246

2a389de86   Florian Westphal   netfilter: conntr...
247
  void nf_conntrack_udp_init_net(struct net *net)
0ce490ad4   Gao feng   netfilter: nf_ct_...
248
  {
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
249
  	struct nf_udp_net *un = nf_udp_pernet(net);
2a389de86   Florian Westphal   netfilter: conntr...
250
  	int i;
0ce490ad4   Gao feng   netfilter: nf_ct_...
251

2a389de86   Florian Westphal   netfilter: conntr...
252
253
  	for (i = 0; i < UDP_CT_MAX; i++)
  		un->timeouts[i] = udp_timeouts[i];
08911475d   Pablo Neira Ayuso   netfilter: nf_con...
254
  }
dd2934a95   Florian Westphal   netfilter: conntr...
255
  const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
256
  {
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
257
  	.l4proto		= IPPROTO_UDP,
71d8c47fc   Pablo Neira Ayuso   netfilter: conntr...
258
  	.allow_clash		= true,
c0cd11566   Igor Maravić   net:netfilter: us...
259
  #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
260
261
  	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
  	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
262
  	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
263
  	.nla_policy		= nf_ct_port_nla_policy,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
264
  #endif
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
265
  #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
509784623   Pablo Neira Ayuso   netfilter: add ct...
266
267
268
269
270
271
272
  	.ctnl_timeout		= {
  		.nlattr_to_obj	= udp_timeout_nlattr_to_obj,
  		.obj_to_nlattr	= udp_timeout_obj_to_nlattr,
  		.nlattr_max	= CTA_TIMEOUT_UDP_MAX,
  		.obj_size	= sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
  		.nla_policy	= udp_timeout_nla_policy,
  	},
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
273
  #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
274
  };
e4781421e   Florian Westphal   netfilter: merge ...
275
  #ifdef CONFIG_NF_CT_PROTO_UDPLITE
dd2934a95   Florian Westphal   netfilter: conntr...
276
  const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite =
e4781421e   Florian Westphal   netfilter: merge ...
277
  {
e4781421e   Florian Westphal   netfilter: merge ...
278
  	.l4proto		= IPPROTO_UDPLITE,
e4781421e   Florian Westphal   netfilter: merge ...
279
  	.allow_clash		= true,
e4781421e   Florian Westphal   netfilter: merge ...
280
281
282
283
284
285
  #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
  	.tuple_to_nlattr	= nf_ct_port_tuple_to_nlattr,
  	.nlattr_to_tuple	= nf_ct_port_nlattr_to_tuple,
  	.nlattr_tuple_size	= nf_ct_port_nlattr_tuple_size,
  	.nla_policy		= nf_ct_port_nla_policy,
  #endif
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
286
  #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
e4781421e   Florian Westphal   netfilter: merge ...
287
288
289
290
291
292
293
  	.ctnl_timeout		= {
  		.nlattr_to_obj	= udp_timeout_nlattr_to_obj,
  		.obj_to_nlattr	= udp_timeout_obj_to_nlattr,
  		.nlattr_max	= CTA_TIMEOUT_UDP_MAX,
  		.obj_size	= sizeof(unsigned int) * CTA_TIMEOUT_UDP_MAX,
  		.nla_policy	= udp_timeout_nla_policy,
  	},
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
294
  #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
e4781421e   Florian Westphal   netfilter: merge ...
295
  };
e4781421e   Florian Westphal   netfilter: merge ...
296
  #endif