xref: /linux/net/xfrm/xfrm_nat_keepalive.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * xfrm_nat_keepalive.c
4  *
5  * (c) 2024 Eyal Birger <eyal.birger@gmail.com>
6  */
7 
8 #include <net/inet_common.h>
9 #include <net/ip6_checksum.h>
10 #include <net/xfrm.h>
11 
12 static DEFINE_PER_CPU(struct sock_bh_locked, nat_keepalive_sk_ipv4) = {
13 	.bh_lock = INIT_LOCAL_LOCK(bh_lock),
14 };
15 #if IS_ENABLED(CONFIG_IPV6)
16 static DEFINE_PER_CPU(struct sock_bh_locked, nat_keepalive_sk_ipv6) = {
17 	.bh_lock = INIT_LOCAL_LOCK(bh_lock),
18 };
19 #endif
20 
21 struct nat_keepalive {
22 	struct net *net;
23 	u16 family;
24 	xfrm_address_t saddr;
25 	xfrm_address_t daddr;
26 	__be16 encap_sport;
27 	__be16 encap_dport;
28 	__u32 smark;
29 };
30 
31 static void nat_keepalive_init(struct nat_keepalive *ka, struct xfrm_state *x)
32 {
33 	ka->net = xs_net(x);
34 	ka->family = x->props.family;
35 	ka->saddr = x->props.saddr;
36 	ka->daddr = x->id.daddr;
37 	ka->encap_sport = x->encap->encap_sport;
38 	ka->encap_dport = x->encap->encap_dport;
39 	ka->smark = xfrm_smark_get(0, x);
40 }
41 
42 static int nat_keepalive_send_ipv4(struct sk_buff *skb,
43 				   struct nat_keepalive *ka)
44 {
45 	struct net *net = ka->net;
46 	struct flowi4 fl4;
47 	struct rtable *rt;
48 	struct sock *sk;
49 	__u8 tos = 0;
50 	int err;
51 
52 	flowi4_init_output(&fl4, 0 /* oif */, skb->mark, tos,
53 			   RT_SCOPE_UNIVERSE, IPPROTO_UDP, 0,
54 			   ka->daddr.a4, ka->saddr.a4, ka->encap_dport,
55 			   ka->encap_sport, sock_net_uid(net, NULL));
56 
57 	rt = ip_route_output_key(net, &fl4);
58 	if (IS_ERR(rt)) {
59 		kfree_skb(skb);
60 		return PTR_ERR(rt);
61 	}
62 
63 	skb_dst_set(skb, &rt->dst);
64 
65 	local_lock_nested_bh(&nat_keepalive_sk_ipv4.bh_lock);
66 	sk = this_cpu_read(nat_keepalive_sk_ipv4.sock);
67 	sock_net_set(sk, net);
68 	err = ip_build_and_send_pkt(skb, sk, fl4.saddr, fl4.daddr, NULL, tos);
69 	sock_net_set(sk, &init_net);
70 	local_unlock_nested_bh(&nat_keepalive_sk_ipv4.bh_lock);
71 	return err;
72 }
73 
74 #if IS_ENABLED(CONFIG_IPV6)
75 static int nat_keepalive_send_ipv6(struct sk_buff *skb,
76 				   struct nat_keepalive *ka,
77 				   struct udphdr *uh)
78 {
79 	struct net *net = ka->net;
80 	struct dst_entry *dst;
81 	struct flowi6 fl6;
82 	struct sock *sk;
83 	__wsum csum;
84 	int err;
85 
86 	csum = skb_checksum(skb, 0, skb->len, 0);
87 	uh->check = csum_ipv6_magic(&ka->saddr.in6, &ka->daddr.in6,
88 				    skb->len, IPPROTO_UDP, csum);
89 	if (uh->check == 0)
90 		uh->check = CSUM_MANGLED_0;
91 
92 	memset(&fl6, 0, sizeof(fl6));
93 	fl6.flowi6_mark = skb->mark;
94 	fl6.saddr = ka->saddr.in6;
95 	fl6.daddr = ka->daddr.in6;
96 	fl6.flowi6_proto = IPPROTO_UDP;
97 	fl6.fl6_sport = ka->encap_sport;
98 	fl6.fl6_dport = ka->encap_dport;
99 
100 	local_lock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
101 	sk = this_cpu_read(nat_keepalive_sk_ipv6.sock);
102 	sock_net_set(sk, net);
103 	dst = ip6_dst_lookup_flow(net, sk, &fl6, NULL);
104 	if (IS_ERR(dst)) {
105 		local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
106 		kfree_skb(skb);
107 		return PTR_ERR(dst);
108 	}
109 
110 	skb_dst_set(skb, dst);
111 	err = ip6_xmit(sk, skb, &fl6, skb->mark, NULL, 0, 0);
112 	sock_net_set(sk, &init_net);
113 	local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
114 	return err;
115 }
116 #endif
117 
118 static void nat_keepalive_send(struct nat_keepalive *ka)
119 {
120 	const int nat_ka_hdrs_len = max(sizeof(struct iphdr),
121 					sizeof(struct ipv6hdr)) +
122 				    sizeof(struct udphdr);
123 	const u8 nat_ka_payload = 0xFF;
124 	struct sk_buff *skb;
125 	struct udphdr *uh;
126 
127 	skb = alloc_skb(nat_ka_hdrs_len + sizeof(nat_ka_payload), GFP_ATOMIC);
128 	if (unlikely(!skb))
129 		return;
130 
131 	skb_reserve(skb, nat_ka_hdrs_len);
132 
133 	skb_put_u8(skb, nat_ka_payload);
134 
135 	uh = skb_push(skb, sizeof(*uh));
136 	uh->source = ka->encap_sport;
137 	uh->dest = ka->encap_dport;
138 	udp_set_len_short(uh, skb->len);
139 	uh->check = 0;
140 
141 	skb->mark = ka->smark;
142 
143 	switch (ka->family) {
144 	case AF_INET:
145 		nat_keepalive_send_ipv4(skb, ka);
146 		break;
147 #if IS_ENABLED(CONFIG_IPV6)
148 	case AF_INET6:
149 		nat_keepalive_send_ipv6(skb, ka, uh);
150 		break;
151 #endif
152 	default:
153 		kfree_skb(skb);
154 		break;
155 	}
156 }
157 
158 enum {
159 	NAT_KEEPALIVE_BATCH_SIZE = 16,
160 	NAT_KEEPALIVE_BATCH_FULL = 1,
161 };
162 
163 struct nat_keepalive_work_ctx {
164 	struct xfrm_state *batch[NAT_KEEPALIVE_BATCH_SIZE];
165 	unsigned int nr;
166 	time64_t next_run;
167 	time64_t now;
168 };
169 
170 static int nat_keepalive_work_collect(struct xfrm_state *x, int count, void *ptr)
171 {
172 	struct nat_keepalive_work_ctx *ctx = ptr;
173 
174 	if (!READ_ONCE(x->nat_keepalive_interval))
175 		return 0;
176 
177 	if (ctx->nr == ARRAY_SIZE(ctx->batch))
178 		return NAT_KEEPALIVE_BATCH_FULL;
179 
180 	xfrm_state_hold(x);
181 	ctx->batch[ctx->nr++] = x;
182 	return 0;
183 }
184 
185 static void nat_keepalive_work_single(struct xfrm_state *x,
186 				      struct nat_keepalive_work_ctx *ctx)
187 {
188 	bool send_keepalive = false;
189 	struct nat_keepalive ka;
190 	time64_t next_run = 0;
191 	u32 interval;
192 	int delta;
193 
194 	spin_lock_bh(&x->lock);
195 
196 	if (x->km.state == XFRM_STATE_DEAD)
197 		goto out;
198 
199 	interval = x->nat_keepalive_interval;
200 	if (!interval)
201 		goto out;
202 
203 	delta = (int)(ctx->now - x->lastused);
204 	if (delta < interval) {
205 		x->nat_keepalive_expiration = ctx->now + interval - delta;
206 		next_run = x->nat_keepalive_expiration;
207 	} else if (x->nat_keepalive_expiration > ctx->now) {
208 		next_run = x->nat_keepalive_expiration;
209 	} else {
210 		next_run = ctx->now + interval;
211 		nat_keepalive_init(&ka, x);
212 		send_keepalive = true;
213 	}
214 
215 out:
216 	spin_unlock_bh(&x->lock);
217 
218 	if (send_keepalive)
219 		nat_keepalive_send(&ka);
220 
221 	if (next_run && (!ctx->next_run || next_run < ctx->next_run))
222 		ctx->next_run = next_run;
223 }
224 
225 static void nat_keepalive_work(struct work_struct *work)
226 {
227 	struct nat_keepalive_work_ctx ctx;
228 	struct xfrm_state_walk walk;
229 	struct net *net;
230 	int err, i;
231 
232 	ctx.next_run = 0;
233 	ctx.now = ktime_get_real_seconds();
234 
235 	net = container_of(work, struct net, xfrm.nat_keepalive_work.work);
236 	xfrm_state_walk_init(&walk, IPPROTO_ESP, NULL);
237 	do {
238 		ctx.nr = 0;
239 		err = xfrm_state_walk(net, &walk, nat_keepalive_work_collect, &ctx);
240 		local_bh_disable();
241 		for (i = 0; i < ctx.nr; i++) {
242 			nat_keepalive_work_single(ctx.batch[i], &ctx);
243 			xfrm_state_put(ctx.batch[i]);
244 		}
245 		local_bh_enable();
246 	} while (err == NAT_KEEPALIVE_BATCH_FULL);
247 	xfrm_state_walk_done(&walk, net);
248 	if (ctx.next_run)
249 		schedule_delayed_work(&net->xfrm.nat_keepalive_work,
250 				      (ctx.next_run - ctx.now) * HZ);
251 }
252 
253 static int nat_keepalive_sk_init(struct sock_bh_locked __percpu *socks,
254 				 unsigned short family)
255 {
256 	struct sock *sk;
257 	int err, i;
258 
259 	for_each_possible_cpu(i) {
260 		err = inet_ctl_sock_create(&sk, family, SOCK_RAW, IPPROTO_UDP,
261 					   &init_net);
262 		if (err < 0)
263 			goto err;
264 
265 		per_cpu_ptr(socks, i)->sock = sk;
266 	}
267 
268 	return 0;
269 err:
270 	for_each_possible_cpu(i)
271 		inet_ctl_sock_destroy(per_cpu_ptr(socks, i)->sock);
272 	return err;
273 }
274 
275 static void nat_keepalive_sk_fini(struct sock_bh_locked __percpu *socks)
276 {
277 	int i;
278 
279 	for_each_possible_cpu(i)
280 		inet_ctl_sock_destroy(per_cpu_ptr(socks, i)->sock);
281 }
282 
283 void xfrm_nat_keepalive_state_updated(struct xfrm_state *x)
284 {
285 	struct net *net;
286 
287 	if (!x->nat_keepalive_interval)
288 		return;
289 
290 	net = xs_net(x);
291 	schedule_delayed_work(&net->xfrm.nat_keepalive_work, 0);
292 }
293 
294 int __net_init xfrm_nat_keepalive_net_init(struct net *net)
295 {
296 	INIT_DELAYED_WORK(&net->xfrm.nat_keepalive_work, nat_keepalive_work);
297 	return 0;
298 }
299 
300 int xfrm_nat_keepalive_net_fini(struct net *net)
301 {
302 	disable_delayed_work_sync(&net->xfrm.nat_keepalive_work);
303 	return 0;
304 }
305 
306 int xfrm_nat_keepalive_init(unsigned short family)
307 {
308 	int err = -EAFNOSUPPORT;
309 
310 	switch (family) {
311 	case AF_INET:
312 		err = nat_keepalive_sk_init(&nat_keepalive_sk_ipv4, PF_INET);
313 		break;
314 #if IS_ENABLED(CONFIG_IPV6)
315 	case AF_INET6:
316 		err = nat_keepalive_sk_init(&nat_keepalive_sk_ipv6, PF_INET6);
317 		break;
318 #endif
319 	}
320 
321 	if (err)
322 		pr_err("xfrm nat keepalive init: failed to init err:%d\n", err);
323 	return err;
324 }
325 EXPORT_SYMBOL_GPL(xfrm_nat_keepalive_init);
326 
327 void xfrm_nat_keepalive_fini(unsigned short family)
328 {
329 	switch (family) {
330 	case AF_INET:
331 		nat_keepalive_sk_fini(&nat_keepalive_sk_ipv4);
332 		break;
333 #if IS_ENABLED(CONFIG_IPV6)
334 	case AF_INET6:
335 		nat_keepalive_sk_fini(&nat_keepalive_sk_ipv6);
336 		break;
337 #endif
338 	}
339 }
340 EXPORT_SYMBOL_GPL(xfrm_nat_keepalive_fini);
341