Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1092081
  • 博文数量: 252
  • 博客积分: 4561
  • 博客等级: 上校
  • 技术积分: 2833
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-15 08:23
文章分类

全部博文(252)

文章存档

2015年(2)

2014年(1)

2013年(1)

2012年(16)

2011年(42)

2010年(67)

2009年(87)

2008年(36)

分类:

2010-09-21 10:56:23

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/in.h>
#include <linux/types.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/sysctl.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <asm/checksum.h>
#include <linux/ip.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <net/net_namespace.h>
#include <net/route.h>
#include <linux/route.h>
#include <linux/stddef.h>
#include <linux/mutex.h>
#include <linux/inet.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/jhash.h>
#include <linux/tcp.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <asm/bitops.h>

static int send_ack(struct sk_buff *skb);

static void err(const char *msg)
{
    printk(KERN_ERR "%s failure\n", msg);
}

static unsigned int packet_in(unsigned int hooknum,
             struct sk_buff *skb,
             const struct net_device *in,
             const struct net_device *out,
             int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;
    struct tcphdr *th;

    iph = ip_hdr(skb);
    th = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb));
    if (!iph || !th)
    {
        err("ip or tcp is NULL");
        goto out;
    }

    if (iph->daddr == in_aton("192.168.10.168") && th->dest == htons(8888))
    {
        printk(KERN_INFO "received server ack packet.\n");
        send_ack(skb);
        return NF_STOLEN;
    }
out:
    return NF_ACCEPT;
}


static struct nf_hook_ops privhook =
{
    .hook    = packet_in,
    .owner    = THIS_MODULE,
    .pf    = PF_INET,
    .hooknum = NF_INET_LOCAL_IN,
};

static void change_addr(struct iphdr *iph)
{
    __be32 addr;

    addr = iph->saddr;
    iph->saddr = iph->daddr;
    iph->daddr = addr;
}

static void change_port(struct tcphdr *th)
{
    __be16 port;

    port = th->source;
    th->source = th->dest;
    th->dest = port;
}

static int send_ack(struct sk_buff *skb)
{
    struct iphdr *iph;
    struct tcphdr *th;
    int l4len;

    iph = ip_hdr(skb);
    th = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb));
    if (!iph || !th)
    {
        err("ip or tcp is NULL");
        goto out;
    }
    
    change_addr(iph);
    change_port(th);

    th->syn = th->fin = th->rst = 0;
    th->ack = 1;
    th->ack_seq = htonl(ntohl(th->seq) + 1);
    th->seq = htonl(12346);

    l4len = skb->len - ip_hdrlen(skb);
    th->check = 0;
    skb->csum = skb_checksum(skb, ip_hdrlen(skb), l4len, 0);
    th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, l4len, iph->protocol, skb->csum);
    skb->ip_summed = CHECKSUM_UNNECESSARY;
    ip_send_check(iph);

    if (ip_route_me_harder(skb, RTN_LOCAL) != 0)
    {
        err("ip_route_me_harder");
        goto out;
    }
    if (dst_output(skb) != 0)
        err("dst_output");
    printk(KERN_INFO "send ack packet success.\n");
    return NF_STOLEN;
out:
    kfree_skb(skb);
    return NF_STOLEN;
}

static int send_syn(void)
{
    struct sk_buff *skb;
    struct tcphdr *th;
    struct iphdr *iph;
    struct rtable *rt;
    struct flowi fl = {};
    int l4len;

    if ((skb = alloc_skb(MAX_TCP_HEADER + 128, GFP_ATOMIC | __GFP_ZERO)) == NULL)
    {
        err("alloc_skb");
        goto out;
    }
    
    skb_reserve(skb, MAX_TCP_HEADER);
    
    th = (struct tcphdr *)skb_push(skb, sizeof(struct tcphdr));
    th->source    = htons(8888);
    th->dest    = htons(7777);
    th->doff    = sizeof(struct tcphdr) >> 2;
    th->seq        = htonl(12345);
    th->syn = 1;
    th->window    = htons(0xFFFF);
    skb_reset_transport_header(skb);

    iph = (struct iphdr *)skb_push(skb, sizeof(struct iphdr));
    iph->ihl    = sizeof(struct iphdr) >> 2;
    iph->version    = 4;
    iph->tot_len    = htons(skb->len);
    iph->ttl    = 64;
    iph->protocol    = IPPROTO_TCP;
    iph->saddr    = in_aton("192.168.10.168");
    iph->daddr    = in_aton("192.168.10.220");
    ip_send_check(iph);
    skb_reset_network_header(skb);

    l4len = skb->len - sizeof(struct iphdr);
    th->check = 0;
    skb->csum = skb_checksum(skb, sizeof(struct iphdr), l4len, 0);
    th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, l4len, iph->protocol, skb->csum);
    skb->ip_summed = CHECKSUM_UNNECESSARY;

    fl.nl_u.ip4_u.daddr = iph->daddr;
    if (ip_route_output_key(&init_net, &rt, &fl) != 0)
    {
        err("ip_route_output_key");
        goto err;
    }
    
    skb_dst_set(skb, &rt->u.dst);
    ip_local_out(skb);
    printk(KERN_INFO "send syn packet success.\n");
    return 0;
err:
    kfree_skb(skb);
out:
    return -ENOMEM;
}

static int main_init(void)
{
    if (nf_register_hook(&privhook) != 0)
    {
        err("nf_register_hook");
        goto out;
    }

    send_syn();
    return 0;
out:
    return -1;
}

static void main_exit(void)
{
    nf_unregister_hook(&privhook);
}

module_init(main_init);
module_exit(main_exit);
MODULE_LICENSE("GPL");


阅读(957) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~