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 | static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
18 | { |
19 | #ifdef CONFIG_NETFILTER |
20 | struct xfrm_state *x = skb_dst(skb)->xfrm; |
21 | |
22 | if (!x) { |
23 | IPCB(skb)->flags |= IPSKB_REROUTED; |
24 | return dst_output(net, sk, skb); |
25 | } |
26 | #endif |
27 | |
28 | return xfrm_output(sk, skb); |
29 | } |
30 | |
31 | int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
32 | { |
33 | return NF_HOOK_COND(pf: NFPROTO_IPV4, hook: NF_INET_POST_ROUTING, |
34 | net, sk, skb, in: skb->dev, out: skb_dst(skb)->dev, |
35 | okfn: __xfrm4_output, |
36 | cond: !(IPCB(skb)->flags & IPSKB_REROUTED)); |
37 | } |
38 | |
39 | void xfrm4_local_error(struct sk_buff *skb, u32 mtu) |
40 | { |
41 | struct iphdr *hdr; |
42 | |
43 | hdr = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); |
44 | ip_local_error(sk: skb->sk, EMSGSIZE, daddr: hdr->daddr, |
45 | inet_sk(skb->sk)->inet_dport, info: mtu); |
46 | } |
47 | |