| 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_dev(skb), | 
|---|
| 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 |  | 
|---|