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