1 /* Masquerade.  Simple mapping which alters range to a local IP address
 
   2    (depending on route). */
 
   4 /* (C) 1999-2001 Paul `Rusty' Russell
 
   5  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
 
   7  * This program is free software; you can redistribute it and/or modify
 
   8  * it under the terms of the GNU General Public License version 2 as
 
   9  * published by the Free Software Foundation.
 
  12 #include <linux/config.h>
 
  13 #include <linux/types.h>
 
  14 #include <linux/inetdevice.h>
 
  16 #include <linux/timer.h>
 
  17 #include <linux/module.h>
 
  18 #include <linux/netfilter.h>
 
  19 #include <net/protocol.h>
 
  21 #include <net/checksum.h>
 
  22 #include <net/route.h>
 
  23 #include <linux/netfilter_ipv4.h>
 
  24 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 
  25 #include <linux/netfilter_ipv4/ip_tables.h>
 
  27 MODULE_LICENSE("GPL");
 
  28 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 
  29 MODULE_DESCRIPTION("iptables MASQUERADE target module");
 
  34 #define DEBUGP(format, args...)
 
  37 /* Lock protects masq region inside conntrack */
 
  38 static DEFINE_RWLOCK(masq_lock);
 
  40 /* FIXME: Multiple targets. --RR */
 
  42 masquerade_check(const char *tablename,
 
  44                  const struct xt_target *target,
 
  46                  unsigned int targinfosize,
 
  47                  unsigned int hook_mask)
 
  49         const struct ip_nat_multi_range_compat *mr = targinfo;
 
  51         if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
 
  52                 DEBUGP("masquerade_check: bad MAP_IPS.\n");
 
  55         if (mr->rangesize != 1) {
 
  56                 DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize);
 
  63 masquerade_target(struct sk_buff **pskb,
 
  64                   const struct net_device *in,
 
  65                   const struct net_device *out,
 
  67                   const struct xt_target *target,
 
  71         struct ip_conntrack *ct;
 
  72         enum ip_conntrack_info ctinfo;
 
  73         const struct ip_nat_multi_range_compat *mr;
 
  74         struct ip_nat_range newrange;
 
  78         IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
 
  80         ct = ip_conntrack_get(*pskb, &ctinfo);
 
  81         IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
 
  82                             || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
  84         /* Source address is 0.0.0.0 - locally generated packet that is
 
  85          * probably not supposed to be masqueraded.
 
  87         if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
 
  91         rt = (struct rtable *)(*pskb)->dst;
 
  92         newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
 
  94                 printk("MASQUERADE: %s ate my IP address\n", out->name);
 
  98         write_lock_bh(&masq_lock);
 
  99         ct->nat.masq_index = out->ifindex;
 
 100         write_unlock_bh(&masq_lock);
 
 102         /* Transfer from original range. */
 
 103         newrange = ((struct ip_nat_range)
 
 104                 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
 
 106                   mr->range[0].min, mr->range[0].max });
 
 108         /* Hand modified range to generic setup. */
 
 109         return ip_nat_setup_info(ct, &newrange, hooknum);
 
 113 device_cmp(struct ip_conntrack *i, void *ifindex)
 
 117         read_lock_bh(&masq_lock);
 
 118         ret = (i->nat.masq_index == (int)(long)ifindex);
 
 119         read_unlock_bh(&masq_lock);
 
 124 static int masq_device_event(struct notifier_block *this,
 
 128         struct net_device *dev = ptr;
 
 130         if (event == NETDEV_DOWN) {
 
 131                 /* Device was downed.  Search entire table for
 
 132                    conntracks which were associated with that device,
 
 134                 IP_NF_ASSERT(dev->ifindex != 0);
 
 136                 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
 
 142 static int masq_inet_event(struct notifier_block *this,
 
 146         struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
 
 148         if (event == NETDEV_DOWN) {
 
 149                 /* IP address was deleted.  Search entire table for
 
 150                    conntracks which were associated with that device,
 
 152                 IP_NF_ASSERT(dev->ifindex != 0);
 
 154                 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
 
 160 static struct notifier_block masq_dev_notifier = {
 
 161         .notifier_call  = masq_device_event,
 
 164 static struct notifier_block masq_inet_notifier = {
 
 165         .notifier_call  = masq_inet_event,
 
 168 static struct ipt_target masquerade = {
 
 169         .name           = "MASQUERADE",
 
 170         .target         = masquerade_target,
 
 171         .targetsize     = sizeof(struct ip_nat_multi_range_compat),
 
 173         .hooks          = 1 << NF_IP_POST_ROUTING,
 
 174         .checkentry     = masquerade_check,
 
 178 static int __init ipt_masquerade_init(void)
 
 182         ret = ipt_register_target(&masquerade);
 
 185                 /* Register for device down reports */
 
 186                 register_netdevice_notifier(&masq_dev_notifier);
 
 187                 /* Register IP address change reports */
 
 188                 register_inetaddr_notifier(&masq_inet_notifier);
 
 194 static void __exit ipt_masquerade_fini(void)
 
 196         ipt_unregister_target(&masquerade);
 
 197         unregister_netdevice_notifier(&masq_dev_notifier);
 
 198         unregister_inetaddr_notifier(&masq_inet_notifier);      
 
 201 module_init(ipt_masquerade_init);
 
 202 module_exit(ipt_masquerade_fini);