Blame view

net/netfilter/nf_conntrack_proto_icmpv6.c 8.14 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
2
3
4
  /*
   * Copyright (C)2003,2004 USAGI/WIDE Project
   *
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
5
6
   * Author:
   *	Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
7
8
9
   */
  
  #include <linux/types.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
10
11
12
13
14
15
16
17
18
19
20
  #include <linux/timer.h>
  #include <linux/module.h>
  #include <linux/netfilter.h>
  #include <linux/in6.h>
  #include <linux/icmpv6.h>
  #include <linux/ipv6.h>
  #include <net/ipv6.h>
  #include <net/ip6_checksum.h>
  #include <linux/seq_file.h>
  #include <linux/netfilter_ipv6.h>
  #include <net/netfilter/nf_conntrack_tuple.h>
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
21
  #include <net/netfilter/nf_conntrack_l4proto.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
22
  #include <net/netfilter/nf_conntrack_core.h>
c779e8496   Florian Westphal   netfilter: conntr...
23
  #include <net/netfilter/nf_conntrack_timeout.h>
5d0aa2ccd   Patrick McHardy   netfilter: nf_con...
24
  #include <net/netfilter/nf_conntrack_zones.h>
f01ffbd6e   Patrick McHardy   [NETFILTER]: nf_l...
25
  #include <net/netfilter/nf_log.h>
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
26

cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
27
  #include "nf_internals.h"
2c9e8637e   Florian Westphal   netfilter: conntr...
28
  static const unsigned int nf_ct_icmpv6_timeout = 30*HZ;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
29

e2e48b471   Florian Westphal   netfilter: conntr...
30
31
32
33
  bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
  			 unsigned int dataoff,
  			 struct net *net,
  			 struct nf_conntrack_tuple *tuple)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
34
  {
7cc3864d3   Jan Engelhardt   [NETFILTER]: nf_{...
35
36
  	const struct icmp6hdr *hp;
  	struct icmp6hdr _hdr;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
37
38
39
  
  	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
  	if (hp == NULL)
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
40
  		return false;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
41
42
43
  	tuple->dst.u.icmp.type = hp->icmp6_type;
  	tuple->src.u.icmp.id = hp->icmp6_identifier;
  	tuple->dst.u.icmp.code = hp->icmp6_code;
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
44
  	return true;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
45
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
46
  /* Add 1; spaces filled with 0. */
7cc3864d3   Jan Engelhardt   [NETFILTER]: nf_{...
47
  static const u_int8_t invmap[] = {
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
48
49
  	[ICMPV6_ECHO_REQUEST - 128]	= ICMPV6_ECHO_REPLY + 1,
  	[ICMPV6_ECHO_REPLY - 128]	= ICMPV6_ECHO_REQUEST + 1,
a51f42f3c   Eric Leblond   netfilter: fix tu...
50
  	[ICMPV6_NI_QUERY - 128]		= ICMPV6_NI_REPLY + 1,
f9527ea9b   Ian Morris   netfilter: ipv6: ...
51
  	[ICMPV6_NI_REPLY - 128]		= ICMPV6_NI_QUERY + 1
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
52
  };
3f9007135   Eric Leblond   netfilter: nf_con...
53
54
  static const u_int8_t noct_valid_new[] = {
  	[ICMPV6_MGM_QUERY - 130] = 1,
f9527ea9b   Ian Morris   netfilter: ipv6: ...
55
  	[ICMPV6_MGM_REPORT - 130] = 1,
3f9007135   Eric Leblond   netfilter: nf_con...
56
57
58
59
60
61
62
  	[ICMPV6_MGM_REDUCTION - 130] = 1,
  	[NDISC_ROUTER_SOLICITATION - 130] = 1,
  	[NDISC_ROUTER_ADVERTISEMENT - 130] = 1,
  	[NDISC_NEIGHBOUR_SOLICITATION - 130] = 1,
  	[NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1,
  	[ICMPV6_MLD2_REPORT - 130] = 1
  };
197c4300a   Florian Westphal   netfilter: conntr...
63
64
  bool nf_conntrack_invert_icmpv6_tuple(struct nf_conntrack_tuple *tuple,
  				      const struct nf_conntrack_tuple *orig)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
65
  {
f16c91072   Yasuyuki Kozakai   [NETFILTER]: nf_c...
66
67
  	int type = orig->dst.u.icmp.type - 128;
  	if (type < 0 || type >= sizeof(invmap) || !invmap[type])
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
68
  		return false;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
69
70
71
72
  
  	tuple->src.u.icmp.id   = orig->src.u.icmp.id;
  	tuple->dst.u.icmp.type = invmap[type] - 1;
  	tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
09f263cd3   Jan Engelhardt   [NETFILTER]: nf_c...
73
  	return true;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
74
  }
2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
75
76
  static unsigned int *icmpv6_get_timeouts(struct net *net)
  {
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
77
  	return &nf_icmpv6_pernet(net)->timeout;
2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
78
  }
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
79
  /* Returns verdict for packet, or -1 for invalid. */
a47c54048   Florian Westphal   netfilter: conntr...
80
81
82
83
  int nf_conntrack_icmpv6_packet(struct nf_conn *ct,
  			       struct sk_buff *skb,
  			       enum ip_conntrack_info ctinfo,
  			       const struct nf_hook_state *state)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
84
  {
c779e8496   Florian Westphal   netfilter: conntr...
85
  	unsigned int *timeout = nf_ct_timeout_lookup(ct);
9976fc6e6   Florian Westphal   netfilter: conntr...
86
87
88
89
  	static const u8 valid_new[] = {
  		[ICMPV6_ECHO_REQUEST - 128] = 1,
  		[ICMPV6_NI_QUERY - 128] = 1
  	};
dd2934a95   Florian Westphal   netfilter: conntr...
90
91
  	if (state->pf != NFPROTO_IPV6)
  		return -NF_ACCEPT;
9976fc6e6   Florian Westphal   netfilter: conntr...
92
93
94
95
96
97
98
99
100
101
102
103
  	if (!nf_ct_is_confirmed(ct)) {
  		int type = ct->tuplehash[0].tuple.dst.u.icmp.type - 128;
  
  		if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) {
  			/* Can't create a new ICMPv6 `conn' with this. */
  			pr_debug("icmpv6: can't create new conn with type %u
  ",
  				 type + 128);
  			nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple);
  			return -NF_ACCEPT;
  		}
  	}
c779e8496   Florian Westphal   netfilter: conntr...
104
105
106
  
  	if (!timeout)
  		timeout = icmpv6_get_timeouts(nf_ct_net(ct));
f87fb666b   Jan Kasprzak   netfilter: nf_ct_...
107
108
109
  	/* Do not immediately delete the connection after the first
  	   successful reply to avoid excessive conntrackd traffic
  	   and also to handle correctly ICMP echo reply duplicates. */
2c8503f55   Pablo Neira Ayuso   netfilter: nf_con...
110
  	nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
111
112
113
  
  	return NF_ACCEPT;
  }
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
114

93e66024b   Florian Westphal   netfilter: conntr...
115
116
117
  static void icmpv6_error_log(const struct sk_buff *skb,
  			     const struct nf_hook_state *state,
  			     const char *msg)
c4f3db159   Florian Westphal   netfilter: conntr...
118
  {
93e66024b   Florian Westphal   netfilter: conntr...
119
120
  	nf_l4proto_log_invalid(skb, state->net, state->pf,
  			       IPPROTO_ICMPV6, "%s", msg);
c4f3db159   Florian Westphal   netfilter: conntr...
121
  }
6fe78fa48   Florian Westphal   netfilter: conntr...
122
123
124
125
  int nf_conntrack_icmpv6_error(struct nf_conn *tmpl,
  			      struct sk_buff *skb,
  			      unsigned int dataoff,
  			      const struct nf_hook_state *state)
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
126
  {
1025ce752   Florian Westphal   netfilter: conntr...
127
  	union nf_inet_addr outer_daddr;
7cc3864d3   Jan Engelhardt   [NETFILTER]: nf_{...
128
129
  	const struct icmp6hdr *icmp6h;
  	struct icmp6hdr _ih;
3f9007135   Eric Leblond   netfilter: nf_con...
130
  	int type;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
131
132
133
  
  	icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
  	if (icmp6h == NULL) {
93e66024b   Florian Westphal   netfilter: conntr...
134
  		icmpv6_error_log(skb, state, "short packet");
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
135
136
  		return -NF_ACCEPT;
  	}
93e66024b   Florian Westphal   netfilter: conntr...
137
138
139
140
  	if (state->hook == NF_INET_PRE_ROUTING &&
  	    state->net->ct.sysctl_checksum &&
  	    nf_ip6_checksum(skb, state->hook, dataoff, IPPROTO_ICMPV6)) {
  		icmpv6_error_log(skb, state, "ICMPv6 checksum failed");
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
141
142
  		return -NF_ACCEPT;
  	}
3f9007135   Eric Leblond   netfilter: nf_con...
143
144
145
  	type = icmp6h->icmp6_type - 130;
  	if (type >= 0 && type < sizeof(noct_valid_new) &&
  	    noct_valid_new[type]) {
cc41c84b7   Florian Westphal   netfilter: kill t...
146
  		nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
3f9007135   Eric Leblond   netfilter: nf_con...
147
148
  		return NF_ACCEPT;
  	}
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
149
150
151
  	/* is not error message ? */
  	if (icmp6h->icmp6_type >= 128)
  		return NF_ACCEPT;
1025ce752   Florian Westphal   netfilter: conntr...
152
153
154
155
156
  	memcpy(&outer_daddr.ip6, &ipv6_hdr(skb)->daddr,
  	       sizeof(outer_daddr.ip6));
  	dataoff += sizeof(*icmp6h);
  	return nf_conntrack_inet_error(tmpl, skb, dataoff, state,
  				       IPPROTO_ICMPV6, &outer_daddr);
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
157
  }
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
158
  #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
159
160
161
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_conntrack.h>
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
162
  static int icmpv6_tuple_to_nlattr(struct sk_buff *skb,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
163
164
  				  const struct nf_conntrack_tuple *t)
  {
e549a6b3a   David S. Miller   netfilter: ipv6: ...
165
166
167
168
  	if (nla_put_be16(skb, CTA_PROTO_ICMPV6_ID, t->src.u.icmp.id) ||
  	    nla_put_u8(skb, CTA_PROTO_ICMPV6_TYPE, t->dst.u.icmp.type) ||
  	    nla_put_u8(skb, CTA_PROTO_ICMPV6_CODE, t->dst.u.icmp.code))
  		goto nla_put_failure;
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
169
  	return 0;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
170
  nla_put_failure:
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
171
172
  	return -1;
  }
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
173
174
175
176
  static const struct nla_policy icmpv6_nla_policy[CTA_PROTO_MAX+1] = {
  	[CTA_PROTO_ICMPV6_TYPE]	= { .type = NLA_U8 },
  	[CTA_PROTO_ICMPV6_CODE]	= { .type = NLA_U8 },
  	[CTA_PROTO_ICMPV6_ID]	= { .type = NLA_U16 },
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
177
  };
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
178
  static int icmpv6_nlattr_to_tuple(struct nlattr *tb[],
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
179
180
  				struct nf_conntrack_tuple *tuple,
  				u_int32_t flags)
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
181
  {
cb8aa9a3a   Romain Bellan   netfilter: ctnetl...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  	if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_TYPE)) {
  		if (!tb[CTA_PROTO_ICMPV6_TYPE])
  			return -EINVAL;
  
  		tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]);
  		if (tuple->dst.u.icmp.type < 128 ||
  		    tuple->dst.u.icmp.type - 128 >= sizeof(invmap) ||
  		    !invmap[tuple->dst.u.icmp.type - 128])
  			return -EINVAL;
  	}
  
  	if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_CODE)) {
  		if (!tb[CTA_PROTO_ICMPV6_CODE])
  			return -EINVAL;
  
  		tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]);
  	}
  
  	if (flags & CTA_FILTER_FLAG(CTA_PROTO_ICMPV6_ID)) {
  		if (!tb[CTA_PROTO_ICMPV6_ID])
  			return -EINVAL;
  
  		tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]);
  	}
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
206
207
208
  
  	return 0;
  }
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
209

5caaed151   Florian Westphal   netfilter: conntr...
210
  static unsigned int icmpv6_nlattr_tuple_size(void)
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
211
  {
5caaed151   Florian Westphal   netfilter: conntr...
212
213
214
215
216
217
  	static unsigned int size __read_mostly;
  
  	if (!size)
  		size = nla_policy_len(icmpv6_nla_policy, CTA_PROTO_MAX + 1);
  
  	return size;
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
218
  }
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
219
  #endif
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
220
  #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
509784623   Pablo Neira Ayuso   netfilter: add ct...
221
222
223
  
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_cttimeout.h>
8264deb81   Gao feng   netfilter: nf_con...
224
225
  static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[],
  					struct net *net, void *data)
509784623   Pablo Neira Ayuso   netfilter: add ct...
226
227
  {
  	unsigned int *timeout = data;
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
228
  	struct nf_icmp_net *in = nf_icmpv6_pernet(net);
509784623   Pablo Neira Ayuso   netfilter: add ct...
229

c779e8496   Florian Westphal   netfilter: conntr...
230
231
  	if (!timeout)
  		timeout = icmpv6_get_timeouts(net);
509784623   Pablo Neira Ayuso   netfilter: add ct...
232
233
234
235
236
  	if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) {
  		*timeout =
  		    ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ;
  	} else {
  		/* Set default ICMPv6 timeout. */
8264deb81   Gao feng   netfilter: nf_con...
237
  		*timeout = in->timeout;
509784623   Pablo Neira Ayuso   netfilter: add ct...
238
239
240
241
242
243
244
245
  	}
  	return 0;
  }
  
  static int
  icmpv6_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
  {
  	const unsigned int *timeout = data;
e549a6b3a   David S. Miller   netfilter: ipv6: ...
246
247
  	if (nla_put_be32(skb, CTA_TIMEOUT_ICMPV6_TIMEOUT, htonl(*timeout / HZ)))
  		goto nla_put_failure;
509784623   Pablo Neira Ayuso   netfilter: add ct...
248
249
250
251
252
253
254
255
256
257
  	return 0;
  
  nla_put_failure:
  	return -ENOSPC;
  }
  
  static const struct nla_policy
  icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
  	[CTA_TIMEOUT_ICMPV6_TIMEOUT]	= { .type = NLA_U32 },
  };
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
258
  #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
509784623   Pablo Neira Ayuso   netfilter: add ct...
259

2a389de86   Florian Westphal   netfilter: conntr...
260
  void nf_conntrack_icmpv6_init_net(struct net *net)
8fc027816   Gao feng   netfilter: nf_ct_...
261
  {
a95a7774d   Pablo Neira Ayuso   netfilter: conntr...
262
  	struct nf_icmp_net *in = nf_icmpv6_pernet(net);
8fc027816   Gao feng   netfilter: nf_ct_...
263
264
  
  	in->timeout = nf_ct_icmpv6_timeout;
08911475d   Pablo Neira Ayuso   netfilter: nf_con...
265
  }
9dae47aba   Florian Westphal   netfilter: conntr...
266
  const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
267
  {
605dcad6c   Martin Josefsson   [NETFILTER]: nf_c...
268
  	.l4proto		= IPPROTO_ICMPV6,
07a936260   Amerigo Wang   ipv6: use IS_ENAB...
269
  #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
270
  	.tuple_to_nlattr	= icmpv6_tuple_to_nlattr,
a400c30ed   Holger Eitzenberger   netfilter: nf_con...
271
  	.nlattr_tuple_size	= icmpv6_nlattr_tuple_size,
fdf708322   Patrick McHardy   [NETFILTER]: nfne...
272
  	.nlattr_to_tuple	= icmpv6_nlattr_to_tuple,
f73e924cd   Patrick McHardy   [NETFILTER]: ctne...
273
  	.nla_policy		= icmpv6_nla_policy,
c1d10adb4   Pablo Neira Ayuso   [NETFILTER]: Add ...
274
  #endif
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
275
  #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
509784623   Pablo Neira Ayuso   netfilter: add ct...
276
277
278
279
280
281
282
  	.ctnl_timeout		= {
  		.nlattr_to_obj	= icmpv6_timeout_nlattr_to_obj,
  		.obj_to_nlattr	= icmpv6_timeout_obj_to_nlattr,
  		.nlattr_max	= CTA_TIMEOUT_ICMP_MAX,
  		.obj_size	= sizeof(unsigned int),
  		.nla_policy	= icmpv6_timeout_nla_policy,
  	},
a874752a1   Pablo Neira Ayuso   netfilter: conntr...
283
  #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
284
  };