免费注册 查看新帖 |

Chinaunix

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

[内核模块] 收到Vxlan隧道报文,怎么去掉隧道之后发送给协议栈?小白求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-11-06 09:58 |只看该作者 |倒序浏览
如下图所示,设备收到该报文,如何去掉隧道头部,将原报文发送给协议栈列?
我在LCAOL_IN加了一个钩子函数,做了如下动作
代码中用到的结构体:
typedef struct st_Ether
{
    uint8_t dest[6];
    uint8_t src[6];
    uint16_t proto;
    uint8_t data[0];
} tEther;


struct vxlan_header {
    uint32_t flags;
    uint32_t vni;
    uint8_t  data[0];
};


typedef  struct  st_Ip
{
    uint8_t  hlen;
    uint8_t  tos;
    uint16_t  len;
    uint16_t  ipid;
    uint16_t  fragoff;
    uint8_t  ttl;
    uint8_t  proto;
    uint16_t  cksum;
    union {
    uint32_t  src;
    uint8_t  src1[4];
    };
    union {
    uint32_t  dest;
    uint8_t  dest1[4];
    };
    uint8_t  data[0];
} tIp;


typedef struct st_Udp
{
    uint16_t sport;
    uint16_t dport;
    uint16_t len;
    uint16_t cksum;
    char  data[0];
} tUdp;

typedef  struct  st_Tcp
{
    uint16_t  sport;
    uint16_t  dport;
    uint32_t  seq;
    uint32_t  ack;

    uint8_t  offset;
    uint8_t  code;
    uint16_t  window;
    uint16_t  cksum;
    uint16_t  urg;
    char   data[0];
} tTcp;

代码如下:
static int del_tunnel_vxlan(struct sk_buff *skb)
{

        UINT1 buff[1514] ={0};
        tEther* peth =NULL;
        tIp* pIp=(tIp*)ip_hdr(skb);
        tUdp* pudp = (tUdp*)pIp->data;
        struct vxlan_header* pvxlan = (struct vxlan_header*)pudp->data;
        UINT1 *p;

        int pkt_len = skb->len - 50+14;//原报文长度(74)
        int data_len = pkt_len-sizeof(struct iphdr)-sizeof(struct ethhdr);
        int ip_len   = data_len + sizeof(struct iphdr);

        printk(KERN_ALERT "skb->len:%d,pkt_len:%d;data_len:%d\n",skb->len,pkt_len,data_len);


        memcpy(buff,pvxlan->data,data_len); 将原报文拷贝到buff中
        peth = (tEther*)buff;
        if(peth->proto != ntohs(ETH_P_IP))
                return 1;
        pIp = (tIp*)peth->data;

        skb_reserve(skb,skb->len +2);
       
        p = skb_push(skb,data_len);
        memcpy(p,pIp->data,data_len);
        skb_reset_transport_header(skb);

        p = skb_push(skb,sizeof(struct iphdr));
        memcpy(p,peth->data,sizeof(struct iphdr));
        skb_reset_network_header(skb);

        p = skb_push(skb,sizeof(struct ethhdr));
        memcpy(p,buff,sizeof(struct ethhdr));
        skb_reset_mac_header(skb);
               
        return 0;
}


static unsigned int nf_hook_in(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;
    struct tcphdr *tcph = NULL;
    tIp* pIp = (tIp*)ip_hdr(sb);
    tTcp* ptcp = NULL;
    unsigned int src_ip = pIp->src;


    switch(pIp->proto)
    {
        case IPPROTO_UDP:
        {
            tUdp* pudp =(tUdp*)pIp->data;

            if(pIp->src == in_aton("172.16.3.40") && pIp->dest == in_aton("172.16.3.38"))
            {
                                if(pudp->sport == ntohs(4789)&& pudp->dport == ntohs(4789))
                    {
                            del_tunnel_vxlan(skb);
                        printk(KERN_ALERT "del_tunnel_vxlan ok\n");
                            return NF_ACCEPT;
                    }
                 }
        }
        break;
        default:
            break;
    }
    return NF_ACCEPT; //í
}

但是并没有抓到去隧道之后的报文或者回复报文;

论坛徽章:
0
2 [报告]
发表于 2015-11-06 17:28 |只看该作者
static int del_tunnel_vxlan(struct sk_buff *skb)
{

        UINT1 buff[1514] ={0};
        tEther* peth =NULL;
        tIp* pIp=(tIp*)ip_hdr(skb);
        tUdp* pudp = (tUdp*)pIp->data;
        struct vxlan_header* pvxlan = (struct vxlan_header*)pudp->data;
        UINT1 *p;
        int ret =0;

        int pkt_len = skb->len - 50+14;
        int data_len = pkt_len-sizeof(struct iphdr)-sizeof(struct ethhdr);
        int ip_len   = data_len + sizeof(struct iphdr);

        memcpy(buff,pvxlan->data,pkt_len); //±¨
        peth = (tEther*)buff;
        if(peth->proto != ntohs(ETH_P_IP))
                return 1;

        skb->len = 0;
        skb->data_len = 0;
        skb->protocol = htons(ETH_P_IP);
        skb->pkt_type = PACKET_HOST;

        pIp = (tIp*)peth->data;
       
        skb_reserve(skb,pkt_len+2);
       
        p = skb_push(skb,data_len);
        memcpy(p,pIp->data,data_len);
        skb_reset_transport_header(skb);

        p = skb_push(skb,sizeof(struct iphdr));
        memcpy(p,peth->data,sizeof(struct iphdr));
        skb_reset_network_header(skb);

        p = skb_push(skb,sizeof(struct ethhdr));
        memcpy(p,buff,sizeof(struct ethhdr));
        skb_reset_mac_header(skb);


        /*ret = dev_queue_xmit(skb);
        if(ret <0)
        {
             printk("dev_queue_xmit() error\n");
             return 1;
        }*/
        return 0;
}

static unsigned int nf_hook_in(unsigned int hooknum,struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff*))
{
.....
            if(pIp->src == in_aton("172.16.3.40") && pIp->dest == in_aton("172.16.3.38"))
            {
                                if(pudp->sport == ntohs(4789)&& pudp->dport == ntohs(4789))
                    {
                            del_tunnel_vxlan(skb);
                        printk(KERN_ALERT "del_tunnel_vxlan ok\n");
                            return NF_ACCEPT;
                    }
                 }
        }
........
}

改成如上代码,通过打印skb->data里面的内容,确实是原报文内容,但是没有抓到该报文或者其回复报文;若将调用dev_queue_xmit注释打开则可以收到原报文和其回复报文,但是运行3分钟左右系统句挂了(1s发一次封装的报文)。请问知道该怎么定位问题么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP