Linux实现Cisco风格的NAT(2)

iph = ip_hdr(*pskb);
 csum_replace4(&iph->check, iph->daddr, new_addr);
 rawnat4_update_l4(*pskb, iph->daddr, new_addr);
 iph->daddr = new_addr;
 return NF_ACCEPT;
}

//定义数据结构
struct addr_map {
 struct list_head list;
 __be32 addr[2];
 int type;  //0:源地址转换;1:目标地址转换
};
//全局的map list
static LIST_HEAD(map_list);

static unsigned int ipv4_static_nat_pre(unsigned int hooknum,
                    struct sk_buff *skb,
                    const struct net_device *in,
                    const struct net_device *out,
                    int (*okfn)(struct sk_buff *))
{
 __be32 new_daddr = 0x0;
 struct addr_map *map;
 const struct iphdr *iph = ip_hdr(skb);
 if (list_empty(&map_list)) {
  return NF_ACCEPT;
 }
 //查找是否需要做目标地址转换
 list_for_each_entry(map, &map_list, list) {
  if (map->addr[((map->type-1)&0x00000001)] == iph->daddr) {
   new_daddr = map->addr[map->type&0x00000001];
   break;
  }
 }
 if (new_daddr == 0) {
  return NF_ACCEPT;
 }
 return rawdnat(&skb, new_daddr);
}

static unsigned int ipv4_static_nat_post(unsigned int hooknum,
                    struct sk_buff *skb,
                    const struct net_device *in,
                    const struct net_device *out,
                    int (*okfn)(struct sk_buff *))
{
 __be32 new_saddr = 0x0;
 struct addr_map *map;
 const struct iphdr *iph = ip_hdr(skb);
 if (list_empty(&map_list)) {
  return NF_ACCEPT;
 }
 //查找是否做源地址转换
 list_for_each_entry(map, &map_list, list) {
  if (map->addr[map->type&0x00000001] == iph->saddr) {
   new_saddr = map->addr[((map->type-1)&0x00000001)];
   break;
  }
 }
 if (new_saddr == 0) {
  return NF_ACCEPT;
 }
 return rawsnat(&skb, new_saddr);
}

static struct nf_hook_ops ipv4_static_nat[] __read_mostly = {
    {
        .hook        = ipv4_static_nat_pre,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,
        .priority    = NF_IP_PRI_NAT_SRC+1,
    },
    {
        .hook        = ipv4_static_nat_post,
        .owner        = THIS_MODULE,
        .pf        = NFPROTO_IPV4,
        .hooknum    = NF_INET_PRE_ROUTING,
        .priority    = NF_IP_PRI_RAW+1,
    },
};

//以下是定义用户接口
//如果需要添加一条source转换。则:
<strong>//echo +172.16.4.34-128.129.4.34 >/proc/STATIC_Nat/source</strong>
struct proc_dir_entry *nat_entry = NULL;

static ssize_t write_snat(struct file *file, const char __user *buf,
      size_t count, loff_t *ppos)
{
 struct addr_map *am = NULL;
 char addr_temp[20] = {0};
 __be32 addr1 = 0, addr2 = 0;
 int ret = count;
 int i = 1;
 for (; i < 48; i++) {
  if (buf[i] == '-') {
   memcpy(addr_temp, buf+1, i-1);
   break;
  }
 }
 addr1 = in_aton(addr_temp);
 addr2 = in_aton(buf + i + 1);
 
 if (buf[0] == '+') {
  am = kzalloc(sizeof(struct addr_map), GFP_KERNEL);
  INIT_LIST_HEAD(&am->list);
  am->addr[0] = addr1;
  am->addr[1] = addr2;
  am->type = 0;
  list_add(&am->list, &map_list);
 } else if(buf[0] == '-') {
  //Remove TODO
 }
 return ret;
}

static ssize_t write_dnat(struct file *file, const char __user *buf,
      size_t count, loff_t *ppos)
{
 //TODO
 return 0;
}
static ssize_t read_snat(struct file *file, char __user *buf,
      size_t count, loff_t *ppos)
{
 //TODO
 return 0;
}
static ssize_t read_dnat(struct file *file, char __user *buf,
      size_t count, loff_t *ppos)
{
 //TODO
 return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/14d94933d70a141f9d6b32018b7453dd.html