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
nat_keepalive_init(struct nat_keepalive * ka,struct xfrm_state * x)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
nat_keepalive_send_ipv4(struct sk_buff * skb,struct nat_keepalive * ka)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)
nat_keepalive_send_ipv6(struct sk_buff * skb,struct nat_keepalive * ka,struct udphdr * uh)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
nat_keepalive_send(struct nat_keepalive * ka)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
nat_keepalive_work_collect(struct xfrm_state * x,int count,void * ptr)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
nat_keepalive_work_single(struct xfrm_state * x,struct nat_keepalive_work_ctx * ctx)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
nat_keepalive_work(struct work_struct * work)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
nat_keepalive_sk_init(struct sock_bh_locked __percpu * socks,unsigned short family)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
nat_keepalive_sk_fini(struct sock_bh_locked __percpu * socks)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
xfrm_nat_keepalive_state_updated(struct xfrm_state * x)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
xfrm_nat_keepalive_net_init(struct net * net)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
xfrm_nat_keepalive_net_fini(struct net * net)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
xfrm_nat_keepalive_init(unsigned short family)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
xfrm_nat_keepalive_fini(unsigned short family)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