1
2
3
4
5
6
7#include <linux/types.h>
8#include <linux/timer.h>
9#include <linux/netfilter.h>
10#include <linux/in.h>
11#include <linux/icmp.h>
12#include <linux/seq_file.h>
13#include <net/ip.h>
14#include <net/checksum.h>
15#include <linux/netfilter_ipv4.h>
16#include <net/netfilter/nf_conntrack_tuple.h>
17#include <net/netfilter/nf_conntrack_l4proto.h>
18#include <net/netfilter/nf_conntrack_core.h>
19#include <net/netfilter/nf_conntrack_timeout.h>
20#include <net/netfilter/nf_conntrack_zones.h>
21#include <net/netfilter/nf_log.h>
22
23#include "nf_internals.h"
24
25static const unsigned int nf_ct_icmp_timeout = 30*HZ;
26
27bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
28 struct net *net, struct nf_conntrack_tuple *tuple)
29{
30 const struct icmphdr *hp;
31 struct icmphdr _hdr;
32
33 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
34 if (hp == NULL)
35 return false;
36
37 tuple->dst.u.icmp.type = hp->type;
38 tuple->src.u.icmp.id = hp->un.echo.id;
39 tuple->dst.u.icmp.code = hp->code;
40
41 return true;
42}
43
44
45static const u_int8_t invmap[] = {
46 [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
47 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
48 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
49 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
50 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
51 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
52 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
53 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
54};
55
56bool nf_conntrack_invert_icmp_tuple(struct nf_conntrack_tuple *tuple,
57 const struct nf_conntrack_tuple *orig)
58{
59 if (orig->dst.u.icmp.type >= sizeof(invmap) ||
60 !invmap[orig->dst.u.icmp.type])
61 return false;
62
63 tuple->src.u.icmp.id = orig->src.u.icmp.id;
64 tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
65 tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
66 return true;
67}
68
69
70int nf_conntrack_icmp_packet(struct nf_conn *ct,
71 struct sk_buff *skb,
72 enum ip_conntrack_info ctinfo,
73 const struct nf_hook_state *state)
74{
75
76
77
78 unsigned int *timeout = nf_ct_timeout_lookup(ct);
79 static const u_int8_t valid_new[] = {
80 [ICMP_ECHO] = 1,
81 [ICMP_TIMESTAMP] = 1,
82 [ICMP_INFO_REQUEST] = 1,
83 [ICMP_ADDRESS] = 1
84 };
85
86 if (state->pf != NFPROTO_IPV4)
87 return -NF_ACCEPT;
88
89 if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) ||
90 !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) {
91
92 pr_debug("icmp: can't create new conn with type %u\n",
93 ct->tuplehash[0].tuple.dst.u.icmp.type);
94 nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
95 return -NF_ACCEPT;
96 }
97
98 if (!timeout)
99 timeout = &nf_icmp_pernet(nf_ct_net(ct))->timeout;
100
101 nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
102 return NF_ACCEPT;
103}
104
105
106int nf_conntrack_inet_error(struct nf_conn *tmpl, struct sk_buff *skb,
107 unsigned int dataoff,
108 const struct nf_hook_state *state,
109 u8 l4proto, union nf_inet_addr *outer_daddr)
110{
111 struct nf_conntrack_tuple innertuple, origtuple;
112 const struct nf_conntrack_tuple_hash *h;
113 const struct nf_conntrack_zone *zone;
114 enum ip_conntrack_info ctinfo;
115 struct nf_conntrack_zone tmp;
116 union nf_inet_addr *ct_daddr;
117 enum ip_conntrack_dir dir;
118 struct nf_conn *ct;
119
120 WARN_ON(skb_nfct(skb));
121 zone = nf_ct_zone_tmpl(tmpl, skb, &tmp);
122
123
124 if (!nf_ct_get_tuplepr(skb, dataoff,
125 state->pf, state->net, &origtuple))
126 return -NF_ACCEPT;
127
128
129
130 if (!nf_ct_invert_tuple(&innertuple, &origtuple))
131 return -NF_ACCEPT;
132
133 h = nf_conntrack_find_get(state->net, zone, &innertuple);
134 if (!h)
135 return -NF_ACCEPT;
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 ct = nf_ct_tuplehash_to_ctrack(h);
169 dir = NF_CT_DIRECTION(h);
170 ct_daddr = &ct->tuplehash[dir].tuple.dst.u3;
171 if (!nf_inet_addr_cmp(outer_daddr, ct_daddr)) {
172 if (state->pf == AF_INET) {
173 nf_l4proto_log_invalid(skb, state,
174 l4proto,
175 "outer daddr %pI4 != inner %pI4",
176 &outer_daddr->ip, &ct_daddr->ip);
177 } else if (state->pf == AF_INET6) {
178 nf_l4proto_log_invalid(skb, state,
179 l4proto,
180 "outer daddr %pI6 != inner %pI6",
181 &outer_daddr->ip6, &ct_daddr->ip6);
182 }
183 nf_ct_put(ct);
184 return -NF_ACCEPT;
185 }
186
187 ctinfo = IP_CT_RELATED;
188 if (dir == IP_CT_DIR_REPLY)
189 ctinfo += IP_CT_IS_REPLY;
190
191
192 nf_ct_set(skb, ct, ctinfo);
193 return NF_ACCEPT;
194}
195
196static void icmp_error_log(const struct sk_buff *skb,
197 const struct nf_hook_state *state,
198 const char *msg)
199{
200 nf_l4proto_log_invalid(skb, state, IPPROTO_ICMP, "%s", msg);
201}
202
203
204int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
205 struct sk_buff *skb, unsigned int dataoff,
206 const struct nf_hook_state *state)
207{
208 union nf_inet_addr outer_daddr;
209 const struct icmphdr *icmph;
210 struct icmphdr _ih;
211
212
213 icmph = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
214 if (icmph == NULL) {
215 icmp_error_log(skb, state, "short packet");
216 return -NF_ACCEPT;
217 }
218
219
220 if (state->net->ct.sysctl_checksum &&
221 state->hook == NF_INET_PRE_ROUTING &&
222 nf_ip_checksum(skb, state->hook, dataoff, IPPROTO_ICMP)) {
223 icmp_error_log(skb, state, "bad hw icmp checksum");
224 return -NF_ACCEPT;
225 }
226
227
228
229
230
231
232
233 if (icmph->type > NR_ICMP_TYPES) {
234 icmp_error_log(skb, state, "invalid icmp type");
235 return -NF_ACCEPT;
236 }
237
238
239 if (!icmp_is_err(icmph->type))
240 return NF_ACCEPT;
241
242 memset(&outer_daddr, 0, sizeof(outer_daddr));
243 outer_daddr.ip = ip_hdr(skb)->daddr;
244
245 dataoff += sizeof(*icmph);
246 return nf_conntrack_inet_error(tmpl, skb, dataoff, state,
247 IPPROTO_ICMP, &outer_daddr);
248}
249
250#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
251
252#include <linux/netfilter/nfnetlink.h>
253#include <linux/netfilter/nfnetlink_conntrack.h>
254
255static int icmp_tuple_to_nlattr(struct sk_buff *skb,
256 const struct nf_conntrack_tuple *t)
257{
258 if (nla_put_be16(skb, CTA_PROTO_ICMP_ID, t->src.u.icmp.id) ||
259 nla_put_u8(skb, CTA_PROTO_ICMP_TYPE, t->dst.u.icmp.type) ||
260 nla_put_u8(skb, CTA_PROTO_ICMP_CODE, t->dst.u.icmp.code))
261 goto nla_put_failure;
262 return 0;
263
264nla_put_failure:
265 return -1;
266}
267
268static const struct nla_policy icmp_nla_policy[CTA_PROTO_MAX+1] = {
269 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
270 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
271 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
272};
273
274static int icmp_nlattr_to_tuple(struct nlattr *tb[],
275 struct nf_conntrack_tuple *tuple,
276 u_int32_t flags)
277{
278 if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_TYPE)) {
279 if (!tb[CTA_PROTO_ICMP_TYPE])
280 return -EINVAL;
281
282 tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
283 if (tuple->dst.u.icmp.type >= sizeof(invmap) ||
284 !invmap[tuple->dst.u.icmp.type])
285 return -EINVAL;
286 }
287
288 if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_CODE)) {
289 if (!tb[CTA_PROTO_ICMP_CODE])
290 return -EINVAL;
291
292 tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
293 }
294
295 if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMP_ID)) {
296 if (!tb[CTA_PROTO_ICMP_ID])
297 return -EINVAL;
298
299 tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMP_ID]);
300 }
301
302 return 0;
303}
304
305static unsigned int icmp_nlattr_tuple_size(void)
306{
307 static unsigned int size __read_mostly;
308
309 if (!size)
310 size = nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1);
311
312 return size;
313}
314#endif
315
316#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
317
318#include <linux/netfilter/nfnetlink.h>
319#include <linux/netfilter/nfnetlink_cttimeout.h>
320
321static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[],
322 struct net *net, void *data)
323{
324 unsigned int *timeout = data;
325 struct nf_icmp_net *in = nf_icmp_pernet(net);
326
327 if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) {
328 if (!timeout)
329 timeout = &in->timeout;
330 *timeout =
331 ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ;
332 } else if (timeout) {
333
334 *timeout = in->timeout;
335 }
336 return 0;
337}
338
339static int
340icmp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
341{
342 const unsigned int *timeout = data;
343
344 if (nla_put_be32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ)))
345 goto nla_put_failure;
346 return 0;
347
348nla_put_failure:
349 return -ENOSPC;
350}
351
352static const struct nla_policy
353icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = {
354 [CTA_TIMEOUT_ICMP_TIMEOUT] = { .type = NLA_U32 },
355};
356#endif
357
358void nf_conntrack_icmp_init_net(struct net *net)
359{
360 struct nf_icmp_net *in = nf_icmp_pernet(net);
361
362 in->timeout = nf_ct_icmp_timeout;
363}
364
365const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
366{
367 .l4proto = IPPROTO_ICMP,
368#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
369 .tuple_to_nlattr = icmp_tuple_to_nlattr,
370 .nlattr_tuple_size = icmp_nlattr_tuple_size,
371 .nlattr_to_tuple = icmp_nlattr_to_tuple,
372 .nla_policy = icmp_nla_policy,
373#endif
374#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
375 .ctnl_timeout = {
376 .nlattr_to_obj = icmp_timeout_nlattr_to_obj,
377 .obj_to_nlattr = icmp_timeout_obj_to_nlattr,
378 .nlattr_max = CTA_TIMEOUT_ICMP_MAX,
379 .obj_size = sizeof(unsigned int),
380 .nla_policy = icmp_timeout_nla_policy,
381 },
382#endif
383};
384