⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cap_module.c

📁 将来自eth0的数据包截获并修改其目的地址之后在NF_PRO_ROUTING处解包
💻 C
字号:
#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif

#include <linux/kernel.h>
#include <asm/types.h>
#include <linux/module.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ctype.h>
#include <linux/ip.h>


#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/in_route.h>
#include <linux/net.h>

#include <linux/netfilter.h>

#include <linux/net.h>
#include <net/route.h>
#include <net/checksum.h>

#include <asm/byteorder.h>

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>

#include <linux/skbuff.h>
#include <linux/ctype.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/net.h>
#include <net/route.h>
#include <net/checksum.h>


#include <linux/netfilter_ipv4.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/time.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/fs.h>
#include <linux/wireless.h>
#include <linux/if_arp.h>
#include <linux/sockios.h>
#include <linux/ioctl.h>
#include <asm/div64.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <netinet/in.h>
#define IPPROTO_MIPE 55


/*ina.sin_addr.s_addr=inet_addr("192.168.2.13");*/


struct min_ipenc_hdr {
    u_int8_t protocol;
#if defined(__LITTLE_ENDIAN)
    u_int8_t res:7;
    u_int8_t s:1;
#elif defined(__BIG_ENDIAN)
    u_int8_t s:1;
    u_int8_t res:7;
#else 
#error  "Adjust your <asm/byteorder.h> defines"
#endif
    u_int16_t check;
    u_int32_t daddr;
 };
struct sockaddr_in ina mysockaddr



/*全局变量定义*/
struct nf_hook_ops encap_filter; //封包hook
struct nf_hook_ops decap_filter; //解包hookstruct nf_hook_ops localout_filter;

   u_int32_t   aodv_ip; //aodv接口的ip
u_int32_t wlan_ip;        char * aodvip,*wlanip;

MODULE_PARM(aodvip, "s"); //使用命令行传入参数

MODULE_PARM(wlanip, "s"); 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Somebody");
MODULE_DESCRIPTION("IP encapsulate & decapsulate working with ad-hoc routing kernel module");


/****************************************************

   inet_aton
----------------------------------------------------
Converts a string into a 32-bit unsigned int
****************************************************/
int inet_aton(const char *cp, __u32 *addr)
{
    unsigned int val;
    int                     base,
    n;
    char            c;
    u_int           parts[4];
    u_int      *pp = parts;

    for (;;)
    {

        //Collect number up to ``.''. Values are specified as for C:
        // 0x=hex, 0=octal, other=decimal.

        val = 0;
        base = 10;
        if (*cp == '0')
        {
            if (*++cp == 'x' || *cp == 'X')
                base = 16, cp++;
            else
                base = 8;
        }
        while ((c = *cp) != '\0')
        {
            if (isascii(c) && isdigit(c))
            {
                val = (val * base) + (c - '0');
                cp++;
                continue;

            }
            if (base == 16 && isascii(c) && isxdigit(c))
            {
                val = (val << 4) +
                      (c + 10 - (islower(c) ? 'a' : 'A'));
                cp++;
                continue;
            }
            break;
        }
        if (*cp == '.')
        {
            // Internet format: a.b.c.d a.b.c       (with c treated as
            // 16-bits) a.b         (with b treated as 24 bits)

            if (pp >= parts + 3 || val > 0xff)
                return (0);
            *pp++ = val, cp++;
        }
        else
            break;
    }

    // Check for trailing characters.

    if (*cp && (!isascii(*cp) || !isspace(*cp)))
        return (0);


    // Concoct the address according to the number of parts specified.

    n = pp - parts + 1;
    switch (n)
    {

    case 1:                 // a -- 32 bits
        break;

    case 2:                 //a.b -- 8.24 bits
        if (val > 0xffffff)
            return (0);
        val |= parts[0] << 24;
        break;

    case 3:                 //a.b.c -- 8.8.16 bits
        if (val > 0xffff)
            return (0);
        val |= (parts[0] << 24) | (parts[1] << 16);
        break;

    case 4:                 // a.b.c.d -- 8.8.8.8 bits
        if (val > 0xff)
            return (0);
        val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
        break;
    }
    if (addr)
        *addr= htonl(val);
    return (1);
}


/*cap函数*/
static u_int16_t ip_csum(unsigned short *buf, int nshorts)
{
    u_int32_t sum;
    
    for (sum = 0; nshorts > 0; nshorts--) {
        sum += *buf++;
    }
    
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    
    return ~sum;
}

struct sk_buff *ip_pkt_encapsulate(struct sk_buff *skb, u_int32_t dest)
{


    struct min_ipenc_hdr *ipe;    
    struct sk_buff *nskb;
    struct iphdr *iph;//ip头结构指针
    
    /* Allocate new data space at head */
    nskb = skb_copy_expand(skb, skb_headroom(skb),     //这是一个对skb进行操作的函数,产生一个skb拷贝,包含分组数据,和指定大小的头、尾空间
			   skb_tailroom(skb) +            //skb_headroom返回skb头部空闲空间的字节数
			   sizeof(struct min_ipenc_hdr), 
			   GFP_ATOMIC);

    if (nskb == NULL) {
	printk("Could not allocate new skb\n");
	kfree_skb(skb);
	return NULL;	
    }

    /* Set old owner */
    if (skb->sk != NULL)//这是一个指向拥有这个sk_buff的sock结构的指针。这个指针在网络包由本机发出或者由本机进程接收时有效
	skb_set_owner_w(nskb, skb->sk);//sock的转移
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    iph = skb->nh.iph;//原包的ip头指针
#else
    iph = (struct iphdr *)skb->network_header;
#endif

    skb_put(nskb, sizeof(struct min_ipenc_hdr));//扩展缓冲区中数据区域的大小
    
    /* Move the IP header */
    memcpy(nskb->data, skb->data, (iph->ihl << 2));//data指向实际数据头,<<是左移的意思
    //ihl首部长度(4位):首部长度指的是IP层头部占32 bit字的数目(也就是IP层头部包含多少个4字节 -- 32位),包括任何选项。
    /* Move the data */
    memcpy(nskb->data + (iph->ihl << 2) + sizeof(struct min_ipenc_hdr), 
	   skb->data + (iph->ihl << 2), skb->len - (iph->ihl << 2));
    
    kfree_skb(skb);
    skb = nskb;
    
    /* Update pointers */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    iph = skb->nh.iph = (struct iphdr *)skb->data;//新包的ip头指针
#else
    iph = (struct iphdr *)skb->data;
    skb->network_header = skb->data;
#endif

    ipe = (struct min_ipenc_hdr *)(skb->data + (iph->ihl << 2));//用来保存旧的ip头的信息
    
    /* Save the old ip header information in the encapsulation header */
    ipe->protocol = iph->protocol;//复制协议域
    ipe->s = 0; /* No source address field in the encapsulation header 源ip*/
    ipe->res = 0;
    ipe->check = 0;
    ipe->daddr = iph->daddr;//复制目的ip

    /* Update the IP header */
    iph->daddr = ina.sin_addr.s_addr;//新包的目的ip
    iph->protocol = IPPROTO_MIPE;//新包的协议域
    iph->tot_len = htons(ntohs(iph->tot_len) + sizeof(struct min_ipenc_hdr));//总长度字段(16位)是指整个IP数据报的长度,以字节为单位。
    
    /* Recalculate checksums */
    ipe->check = ip_csum((unsigned short *)ipe, 4);//计算校验和

    ip_send_check(iph); //计算外发数据包的IP校验和

    if (iph->id == 0)//id标识字段(16位)唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1。
	ip_select_ident(iph, skb->dst, NULL);//为IP包分配标识号, 禁止分片的IP包标识为零
        
    return skb;
}

struct sk_buff *ip_pkt_decapsulate(struct sk_buff *skb) //何时解压参见mod.c
{
    struct min_ipenc_hdr *ipe;
    /* skb->nh.iph is probably not set yet */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    struct iphdr *iph = skb->nh.iph;//ip包头指针
#else
    struct iphdr *iph = (struct iphdr *)skb->network_header; 
#endif

    ipe = (struct min_ipenc_hdr *)((char *)iph + (iph->ihl << 2));//指针指向新包中保存旧包信息的部分

    iph->protocol = ipe->protocol;//复制协议域
    iph->daddr = ipe->daddr;//复制目的ip
    
    /* Shift the data to the left, overwriting the encap header */
    memmove(skb->data + (iph->ihl << 2), 
	    skb->data + (iph->ihl << 2) + sizeof(struct min_ipenc_hdr), 
	    skb->len - (iph->ihl << 2) - sizeof(struct min_ipenc_hdr));//由src所指内存区域复制count个字节到dest所指内存区域。
/*memcpy(skb->data + (iph->ihl << 2),(void*)&ina.sin_addr.s_addr,sizeof(ina.sin_addr.s_addr));*/
    
    skb_trim(skb, skb->len - sizeof(struct min_ipenc_hdr));//将包体截断为len字节
    
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    skb->nh.iph = iph = (struct iphdr *)skb->data;//旧的ip包头
#else
    iph = (struct iphdr *)skb->data;
    skb->network_header = skb->data;
#endif

    iph->tot_len = htons((ntohs(iph->tot_len) - sizeof(struct min_ipenc_hdr))); //总长度字段
    ip_send_check(iph); //计算外发数据包的IP校验和

   
    return skb;
}

/*handler函数*/


/****************************************************

   encap_handler
----------------------------------------------------

****************************************************/
unsigned int encap_handler(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
 struct iphdr *ip;
 u_int32_t mask;

 inet_aton("255.255.255.0",&mask);
 ip  = (*skb)->nh.iph;
 
 if((ip->daddr&mask)==(wlan_ip&mask))
  {
   *skb = ip_pkt_encapsulate(*skb,aodv_ip);
    if (!(*skb))
     return NF_STOLEN;
   }
 return NF_ACCEPT; 
 }

/****************************************************

   dncap_handler
----------------------------------------------------

****************************************************/

unsigned int decap_handler(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
 struct iphdr *ip;
 ip  = (*skb)->nh.iph;

 if (ip->protocol == IPPROTO_MIPE ) 
    ip_pkt_decapsulate(*skb);

 return NF_ACCEPT;
}



/*加载卸载*/
/****************************************************

   module
----------------------------------------------------

****************************************************/



/****************************************************

	init_module
----------------------------------------------------
This is called by insmod when things get
started up!
****************************************************/

int init_module(void)
{
 int result;
 if (wlanip==NULL||aodvip==NULL) 
 {
  printk("Lack of aodv interface's ip!\n");
  return -1; //返回负值表示载入模块失败
  }
 else
 {
  inet_aton(wlanip, &wlan_ip);
  inet_aton(aodvip, &aodv_ip);
  }
 
 //以下填充钩子注册结构
 encap_filter.list.next = NULL;
 encap_filter.list.prev = NULL;
 encap_filter.hook = encap_handler;//处理函数
 encap_filter.pf = PF_INET; // IPv4
 encap_filter.priority = NF_IP_PRI_FIRST;//在forward点这个函数将被最先执行
 /*encap_filter.hooknum = NF_IP_FORWARD;*/
 encap_filter.hooknum=NF_IP_PREROUTING;

 decap_filter.list.next = NULL;
 decap_filter.list.prev = NULL;
 decap_filter.hook = decap_handler;//处理函数
 decap_filter.pf = PF_INET; // IPv4
 decap_filter.priority = NF_IP_PRI_LAST;//此处如果错误可尝试将此值直接赋为50或99
 decap_filter.hooknum = NF_IP_POST_ROUTING; localout_filter.list.next = NULL;
 localout_filter.list.prev = NULL;
 localout_filter.hook = encap_handler;//处理函数
 localout_filter.pf = PF_INET; // IPv4
 localout_filter.priority = NF_IP_PRI_FIRST;
 localout_filter.hooknum = NF_IP_LOCAL_OUT;
 
 result = nf_register_hook(&encap_filter);
    if (result)
      return -1;
 
 result = nf_register_hook(&decap_filter);
    if (result)
      return -1;
 result = nf_register_hook(&localout_filter);
    if (result)
      return -1;
 return 0;
}


/****************************************************

   cleanup_module
----------------------------------------------------
cleans up the module. called by rmmod
****************************************************/
void cleanup_module(void)
{
 nf_unregister_hook(&encap_filter);
 nf_unregister_hook(&decap_filter); nf_unregister_hook(&localout_filter);
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -