📄 cap_module.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 + -