- 论坛徽章:
- 0
|
本帖最后由 令人愉悦的忧伤 于 2010-11-02 14:12 编辑
两台主机(A,B)通信,A->B发送数据报。
A,B都加载模块。A发时,对数据报进行“包裹”;B收时,进行“解包”。我所说的“包裹”,就是在ip包头和四层数据之间,添加一个数据结构(保存一些信息);“解包”时恢复原数据。
基本思路是:仿照aodv-uu网关功能的实现。在A(192.168.3.3)的NF_IP_LOCAL_OUT,对源为192.168.3.3的skb_buff进行重新封装(申请一个新的skb_buff,把原始报的所有数据复制进新skb_buff,并在ip包头和四层数据之间添加一个数据结构,然后释放原始skb_buff),然后然后让新的skb_buff沿netfiter继续流动;在B(192.168.3.4)的NF_IP_PRE_ROUTING,对源为192.168.3.3的sk_buff,进行恢复。
但是,我测试发现在A的NF_IP_LOCAL_OUT对192.168.3.3的skb_buff做任何修改都会引起内核崩溃,不知缘故,特来求救。
测试所用的内核版本是2.6.28.10
代码如下- /*#define _KERNEL_ */
- /*#define _KERNEL_ */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/netfilter.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/netdevice.h>
- #include <linux/if_ether.h>
- #include <linux/if_packet.h>
- #include <net/tcp.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/timer.h>
- #include <net/xfrm.h>
- #include <linux/netdevice.h>
- #include <linux/inet.h>
- #define NF_IP_PRE_ROUTING 0
- #define NF_IP_LOCAL_IN 1
- #define NF_IP_FORWARD 2
- #define NF_IP_LOCAL_OUT 3
- #define NF_IP_POST_ROUTING 4
- /*定义新的四层协议*/
- #define IPPROTO_MIPE 55
- /*在ip包头和四层数据之间添加数据结构*/
- struct ip_add_hdr
- {
- u_int8_t protocol;
- u_int8_t res:7;
- u_int8_t s:1;
- u_int16_t check;
- u_int32_t saddr;
- };
- u_int16_t
- my_re_check (u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
- {
- u_int32_t diffs[] = { oldvalinv, newval };
- return
- csum_fold (csum_partial
- ((char *) diffs, sizeof (diffs), oldcheck ^ 0xFFFF));
- }
- /* Simple function (based on R. Stevens) to calculate IP header checksum */
- 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_mpkt_encapsulate (struct sk_buff *skb, __u32 src)
- {
- struct ip_add_hdr *ipahr;
- struct sk_buff *nskb;
- struct iphdr *iph;
- /*复制原始数据到新sk_buff*/
- nskb = skb_copy_expand (skb, skb_headroom (skb),
- skb_tailroom (skb) + sizeof (struct ip_add_hdr),
- GFP_ATOMIC);
- if (nskb == NULL)
- {
- printk ("Could not allocate new skb\n");
- kfree_skb (skb);
- return NULL;
- }
- if (skb->sk != NULL)
- skb_set_owner_w (nskb, skb->sk);
- iph = (struct iphdr *) skb->network_header;
- skb_put (nskb, sizeof (struct ip_add_hdr));
- memcpy (nskb->data, skb->data, (iph->ihl << 2));
- memcpy (nskb->data + (iph->ihl << 2) + sizeof (struct ip_add_hdr),
- skb->data + (iph->ihl << 2), skb->len - (iph->ihl << 2));
-
- memcpy (nskb->data + (iph->ihl << 2),
- skb->data + (iph->ihl << 2), skb->len - (iph->ihl << 2));
-
- kfree_skb (skb);
- skb = nskb;
- iph = (struct iphdr *) skb->data;
- skb->network_header = skb->data;
- /*对添加的数据结构进行赋值*/
- ipahr = (struct ip_add_hdr *) (skb->data + (iph->ihl << 2));
- ipahr->protocol = iph->protocol;
- ipahr->s = 0;
- ipahr->res = 0;
- ipahr->check = 0;
- ipahr->saddr = iph->saddr;
- /*修改ip包头*/
- iph->saddr = src;
- iph->protocol = IPPROTO_MIPE;
- iph->tot_len = htons (ntohs (iph->tot_len) + sizeof (struct ip_add_hdr));
- ipahr->check = ip_csum ((unsigned short *) ipahr, 4);
-
- ip_send_check (iph);
- if (iph->id == 0)
- {
- if (skb->dst)
- ip_select_ident (iph, skb->dst, NULL);
- }
- return skb;
- }
- /*解包*/
- struct sk_buff *
- ip_mpkt_decapsulate (struct sk_buff *skb)
- {
- struct ip_add_hdr *ipahdr;
- struct iphdr *iph = (struct iphdr *) skb->network_header;
- ipahdr = (struct ip_add_hdr *) ((char *) iph + (iph->ihl << 2));
- iph->protocol = ipahdr->protocol;
- iph->saddr = ipahdr->saddr;
- memmove (skb->data + (iph->ihl << 2),
- skb->data + (iph->ihl << 2) + sizeof (struct ip_add_hdr),
- skb->len - (iph->ihl << 2) - sizeof (struct ip_add_hdr));
- skb_trim (skb, skb->len - sizeof (struct ip_add_hdr));
- iph = (struct iphdr *) skb->data;
- skb->network_header = skb->data;
- iph->tot_len = htons (ntohs (iph->tot_len) - sizeof (struct ip_add_hdr));
- ip_send_check (iph);
- return skb;
- }
- unsigned int
- hook_func (unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out, int (*okfn) (struct sk_buff *))
- {
- struct sk_buff *sb = skb;
- __u32 src_ip_n; /* _n 代表网络字节序 */
- __u32 des_ip_n; /* _n 代表网络字节序 */
- struct iphdr *iph =ip_hdr (sb);
- if (iph == NULL)
- return NF_ACCEPT;
- src_ip_n =iph->saddr;
- des_ip_n = iph->daddr;
- switch (hooknum)
- {
- /*NF_IP_PRE_ROUTING解包处理*/
- case NF_IP_PRE_ROUTING:
- if (iph->protocol == IPPROTO_MIPE && src_ip_n == in_aton("192.168.3.3"))
- {
- ip_mpkt_decapsulate(skb);
- return NF_ACCEPT;
- }
- break;
- /*NF_IP_LOCAL_OUT重新封包处理*/
- case NF_IP_LOCAL_OUT:
- if (src_ip_n == in_aton("192.168.3.3"))
- {
- skb = ip_mpkt_encapsulate (skb, iph->saddr);
-
- if (!skb)
- return NF_STOLEN;
- ip_route_me_harder(skb,RTN_LOCAL);
- }
- }
- return NF_ACCEPT;
- }
- static struct nf_hook_ops hook_ops[] = {
- {
- .hook = hook_func,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRI_FIRST,
- },
- {
- .hook = hook_func,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_LOCAL_OUT,
- .priority = NF_IP_PRI_FIRST,
- },
- };
- static int __init nat_init (void)
- {
- int ret;
- ret = nf_register_hook (&hook_ops[0]);
- if (ret < 0)
- goto cleanup_hook0;
- ret = nf_register_hook (&hook_ops[1]);
- if (ret < 0)
- goto cleanup_hook1;
- return ret;
- cleanup_hook1:
- nf_unregister_hook (&hook_ops[1]);
- cleanup_hook0:
- nf_unregister_hook (&hook_ops[0]);
- return ret;
- }
- void __exit nat_exit (void)
- {
- nf_unregister_hook (&hook_ops[1]);
- nf_unregister_hook (&hook_ops[0]);
- }
- module_init(nat_init);
- module_exit(nat_exit);
复制代码 |
|