免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1757 | 回复: 3
打印 上一主题 下一主题

[内核模块] 请教关于netfilter下给ip包尾添加数据的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-19 13:15 |只看该作者 |倒序浏览
本帖最后由 zhouunix 于 2012-07-19 20:01 编辑

最近开始接触linux和netfilter,希望能在netfilter框架下实现对本机发送出去的ip包尾添加一个标志。现在自己按照网络上的资料编了一个模块程序,可是一加载模块,系统几乎都崩溃,查了网上好多资料,零零散散,没有头绪,请求大神们帮我看看代码,改改错  ps 本菜的电脑是ubuntu11.04 ,内核2.6.38.8
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/tcp.h>
#include <net/udp.h>

MODULE_LICENSE("GPL" ) ;

#define NIPQUAD(addr) \
  ((unsigned char *)&addr)[0], \
  ((unsigned char *)&addr)[1], \
  ((unsigned char *)&addr)[2], \
  ((unsigned char *)&addr)[3]

struct iphdr *iph;            //ip header struct
struct tcphdr *tcph,_otcph;
struct ethhdr *ethdr;
unsigned int tcph_len;
unsigned int iph_len;

typedef struct addpatch{
unsigned long int packetnumber;
}addpatch;
struct addpatch addpatch1;//想添加的标志
struct sk_buff *nskb;

unsigned char   SMAC[ETH_ALEN] = {0x00,0x1d,0x09,0x7e,0x2e,0xec};
unsigned char   DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xFA,0x70,0x2A};

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 *))
{
        unsigned char *put_skb=NULL;
        unsigned int tailroom;
        int ret=0;

        if(ip_hdr(skb)->frag_off & htons(IP_OFFSET))
                    return NF_ACCEPT;
        tcph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_otcph),&_otcph ) ;
        iph =ip_hdr(skb) ;
        if(tcph == NULL)
           return NF_ACCEPT;
        if(nf_ip_checksum(skb,hooknum,ip_hdrlen(skb),IPPROTO_TCP))
            return NF_ACCEPT;
        if(!skb) { return NF_ACCEPT;}

       //下面是扩充skb中tail和end的空间,添加数据12345
        addpatch1.packetnumber=12345;
        if((tailroom=skb_tailroom(skb))>=sizeof(struct addpatch))
        {
             put_skb=skb_put(skb,sizeof(struct addpatch)) ;
             memcpy(put_skb,&addpatch1,sizeof(struct addpatch)) ;
             printk("sequence number size is %d\n",sizeof(struct addpatch)) ;
        }
        else
        {
              printk("the tailroom of skb is less than the struct addpatch's size %d\n ,it is %d\n",sizeof(struct addpatch), tailroom) ;
              nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb)+sizeof(struct addpatch),GFP_ATOMIC) ;
              if(!nskb)
              {
                printk("low memory....\n" ) ;
                dev_kfree_skb(skb) ;
                return -1;
              }
              else
              {
                kfree_skb(skb) ;
                skb = nskb;
               }
              memcpy(skb_put(skb,sizeof(struct addpatch)),&addpatch1,sizeof(struct addpatch)) ;
       }
       // 下面是重新计算校验和
       iph=ip_hdr(skb) ;
       iph_len=iph->ihl<<2;
       iph->tot_len= htons(skb->len) ;

       tcph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_otcph),&_otcph) ;
       if(tcph == NULL)
           return -1;
       tcph_len = tcph->doff<<2;

       iph->check = 0;
       iph->check =ip_fast_csum((unsigned char*)iph,iph->ihl) ;

       skb->csum = 0;
       skb->csum =csum_partial((unsigned char *)(tcph+tcph_len),ntohs(iph->tot_len)-iph_len-tcph_len,0) ;

       tcph->check = 0;
       tcph->check = csum_tcpudp_magic(iph->saddr,iph->daddr,ntohs(iph->tot_len)-iph_len,iph->protocol,csum_partial((unsigned char *)tcph,tcph_len,skb->csum)) ;

       skb->ip_summed = CHECKSUM_NONE;
       skb->pkt_type = PACKET_OTHERHOST;

       skb->dev =dev_get_by_name(&init_net,"eth0" ) ;
       if(skb->dev==NULL)
       {
            printk("%s\n", "dev_get_by_name return NULL" ) ;
            kfree_skb(skb) ;
            return NF_ACCEPT;
        }
       ethdr = (struct ethhdr*)skb_push(skb,14) ;
       memcpy(ethdr->h_dest,DMAC,ETH_ALEN) ;
       memcpy(ethdr->h_source,SMAC,ETH_ALEN) ;
       ethdr->h_proto=__constant_htons(ETH_P_IP) ;

       dev_hold(skb->dev) ;
       printk("%s\n", "dev_hold ok" ) ;

       ret = dev_queue_xmit(skb) ;
       printk("ret:%d\n", ret) ;
       return NF_STOLEN;
}

static struct nf_hook_ops nfho={
   .list =  {NULL,NULL},
   .hook = hook_func,
   .pf = PF_INET,
   .hooknum = NF_INET_LOCAL_OUT,
   .priority = NF_IP_PRI_FILTER
};


static int __init addpatch_init(void)
{
        nf_register_hook(&nfho) ;
        return 0;
}

static void __exit addpatch_exit(void)
{
        nf_unregister_hook(&nfho) ;
}
module_init(addpatch_init) ;
module_exit(addpatch_exit) ;


//参考资料 http://bbs.chinaunix.net/thread-1941060-1-1.html

论坛徽章:
0
2 [报告]
发表于 2012-07-19 13:34 |只看该作者
1.没看懂你是着呢麽判断包是 tcp的,如果udp当作tcp来改就麻烦了。
2. tcp 包,改了长度,只重新计算校验和还是不行的, 因为两边通讯的序号变化了。这个链接上的后续通讯包都要重新计算序号才行,如果后续包无法正常工作。


论坛徽章:
0
3 [报告]
发表于 2012-07-19 13:43 |只看该作者
本帖最后由 zhouunix 于 2012-07-19 15:18 编辑

回复 2# hmsghnh


    谢谢你,判断tcp,我想应该是这几句      
        tcph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_otcph),&_otcph ) ;
        iph =ip_hdr(skb) ;
        if(tcph == NULL)
           return NF_ACCEPT;
       if(nf_ip_checksum(skb,hooknum,ip_hdrlen(skb),IPPROTO_TCP)),这是在ipt_REJECT.c里抄来的。
    其实我是想在IP包的尾部加一个标志,不是在TCP层。类似这样

    |IP Packet |id |

论坛徽章:
0
4 [报告]
发表于 2012-07-19 20:02 |只看该作者
顶,大神们多出现啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP