root/net/ipv4/netfilter/nf_dup_ipv4.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nf_dup_ipv4_route
  2. nf_dup_ipv4

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

/* [<][>][^][v][top][bottom][index][help] */