1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * xfrm4_output.c - Common IPsec encapsulation code for IPv4. 4 * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au> 5 */ 6 7 #include <linux/if_ether.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/skbuff.h> 11 #include <linux/netfilter_ipv4.h> 12 #include <net/dst.h> 13 #include <net/ip.h> 14 #include <net/xfrm.h> 15 #include <net/icmp.h> 16 17 int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) 18 { 19 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 20 21 #ifdef CONFIG_NETFILTER 22 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; 23 #endif 24 25 return xfrm_output(sk, skb); 26 } 27 28 static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) 29 { 30 struct xfrm_state *x = skb_dst(skb)->xfrm; 31 const struct xfrm_state_afinfo *afinfo; 32 int ret = -EAFNOSUPPORT; 33 34 #ifdef CONFIG_NETFILTER 35 if (!x) { 36 IPCB(skb)->flags |= IPSKB_REROUTED; 37 return dst_output(net, sk, skb); 38 } 39 #endif 40 41 rcu_read_lock(); 42 afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); 43 if (likely(afinfo)) 44 ret = afinfo->output_finish(sk, skb); 45 else 46 kfree_skb(skb); 47 rcu_read_unlock(); 48 49 return ret; 50 } 51 52 int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) 53 { 54 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, 55 net, sk, skb, skb->dev, skb_dst(skb)->dev, 56 __xfrm4_output, 57 !(IPCB(skb)->flags & IPSKB_REROUTED)); 58 } 59 60 void xfrm4_local_error(struct sk_buff *skb, u32 mtu) 61 { 62 struct iphdr *hdr; 63 64 hdr = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); 65 ip_local_error(skb->sk, EMSGSIZE, hdr->daddr, 66 inet_sk(skb->sk)->inet_dport, mtu); 67 } 68