FILE
nf_dup_ipv4.c
File preview with syntax highlighting.
linux-6.19.14/net/ipv4/netfilter/nf_dup_ipv4.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * (C) 2007 by Sebastian Claßen <sebastian.classen@freenet.ag> 4 * (C) 2007-2010 by Jan Engelhardt <jengelh@medozas.de> 5 * 6 * Extracted from xt_TEE.c 7 */ 8#include <linux/ip.h> 9#include <linux/module.h> 10#include <linux/percpu.h> 11#include <linux/route.h> 12#include <linux/skbuff.h> 13#include <linux/netfilter.h> 14#include <net/checksum.h> 15#include <net/flow.h> 16#include <net/icmp.h> 17#include <net/ip.h> 18#include <net/route.h> 19#include <net/netfilter/ipv4/nf_dup_ipv4.h> 20#if IS_ENABLED(CONFIG_NF_CONNTRACK) 21#include <net/netfilter/nf_conntrack.h> 22#endif 23 24static bool nf_dup_ipv4_route(struct net *net, struct sk_buff *skb, 25 const struct in_addr *gw, int oif) 26{ 27 const struct iphdr *iph = ip_hdr(skb); 28 struct rtable *rt; 29 struct flowi4 fl4; 30 31 memset(&fl4, 0, sizeof(fl4)); 32 if (oif != -1) 33 fl4.flowi4_oif = oif; 34 35 fl4.daddr = gw->s_addr; 36 fl4.flowi4_dscp = ip4h_dscp(iph); 37 fl4.flowi4_scope = RT_SCOPE_UNIVERSE; 38 fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; 39 rt = ip_route_output_key(net, &fl4); 40 if (IS_ERR(rt)) 41 return false; 42 43 skb_dst_drop(skb); 44 skb_dst_set(skb, &rt->dst); 45 skb->dev = rt->dst.dev; 46 skb->protocol = htons(ETH_P_IP); 47 48 return true; 49} 50 51void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, 52 const struct in_addr *gw, int oif) 53{ 54 struct iphdr *iph; 55 56 local_bh_disable(); 57 if (current->in_nf_duplicate) 58 goto out; 59 /* 60 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for 61 * the original skb, which should continue on its way as if nothing has 62 * happened. The copy should be independently delivered to the gateway. 63 */ 64 skb = pskb_copy(skb, GFP_ATOMIC); 65 if (skb == NULL) 66 goto out; 67 68#if IS_ENABLED(CONFIG_NF_CONNTRACK) 69 /* Avoid counting cloned packets towards the original connection. */ 70 nf_reset_ct(skb); 71 nf_ct_set(skb, NULL, IP_CT_UNTRACKED); 72#endif 73 /* 74 * If we are in PREROUTING/INPUT, decrease the TTL to mitigate potential 75 * loops between two hosts. 76 * 77 * Set %IP_DF so that the original source is notified of a potentially 78 * decreased MTU on the clone route. IPv6 does this too. 79 * 80 * IP header checksum will be recalculated at ip_local_out. 81 */ 82 iph = ip_hdr(skb); 83 iph->frag_off |= htons(IP_DF); 84 if (hooknum == NF_INET_PRE_ROUTING || 85 hooknum == NF_INET_LOCAL_IN) 86 --iph->ttl; 87 88 if (nf_dup_ipv4_route(net, skb, gw, oif)) { 89 current->in_nf_duplicate = true; 90 ip_local_out(net, skb->sk, skb); 91 current->in_nf_duplicate = false; 92 } else { 93 kfree_skb(skb); 94 } 95out: 96 local_bh_enable(); 97} 98EXPORT_SYMBOL_GPL(nf_dup_ipv4); 99 100MODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>"); 101MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); 102MODULE_DESCRIPTION("nf_dup_ipv4: Duplicate IPv4 packet"); 103MODULE_LICENSE("GPL");
~/
Read-only file preview.