免费注册 查看新帖 |

Chinaunix

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

[内核入门] 新版本内核构造包发送问题 [复制链接]

论坛徽章:
2
程序设计版块每日发帖之星
日期:2016-02-12 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-10-14 00:42 |只看该作者 |倒序浏览
我在工作中和家中运行的ubuntu系统是12.04,发现内核版本已经是至少是3.11版本了,其中struct sk_buff的结构相较于以前变化了不少,下面是我摘取的
一个功能模块,主要是调用dev_queue_xmit发送自己构造的包
  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/ip.h>
  5. #include <linux/tcp.h>
  6. #include <net/ip.h>
  7. #include <net/checksum.h>


  8. int cp_dev_xmit_tcp (const char *dev_name,
  9.                 const u_char * smac, const u_char * dmac,
  10.                 u_char * pkt, int pkt_len,
  11.                 __be32 sip, __be32 dip,
  12.                 __be16 sport, __be16 dport,
  13.                 __be32 seq, __be32 ack_seq, u_char psh, u_char fin)

  14. {
  15.         struct sk_buff * skb = NULL;
  16.         struct net_device * dev = NULL;
  17.         struct ethhdr * ethdr = NULL;
  18.         struct iphdr * iph = NULL;
  19.         struct tcphdr * tcph = NULL;
  20.         u_char * pdata = NULL;
  21.         int nret = 1;


  22.         if (NULL == smac || NULL == dmac || !dev_name)
  23.                 goto out;

  24.         dev = dev_get_by_name(&init_net,dev_name);

  25.         if (NULL == dev)
  26.         {
  27.                 pr_info("dev is NULL!!!!\n");
  28.                 goto out;
  29.         }

  30.         pr_info("dev->name[%s],mtd[%d]\n",dev->name,dev->mtu);
  31.         skb = alloc_skb (pkt_len + sizeof (struct iphdr) + sizeof (struct tcphdr) + LL_RESERVED_SPACE (dev), GFP_ATOMIC);

  32.         if (NULL == skb)
  33.         {
  34.                 dev_put (dev);
  35.                 pr_info("alloc skb is  NULL!!!!\n");
  36.                 goto out;
  37.         }

  38.         memset(skb,0,pkt_len + sizeof (struct iphdr) + sizeof (struct tcphdr) + LL_RESERVED_SPACE (dev));
  39.         pr_info(" skb is start!!\n");
  40.         skb_reserve (skb, LL_RESERVED_SPACE (dev));
  41.         skb->dev = dev;
  42.         skb->pkt_type = PACKET_OTHERHOST;
  43.         skb->protocol = __constant_htons(ETH_P_IP);
  44.         skb->ip_summed = CHECKSUM_NONE;

  45.         skb->priority = 0;
  46.         skb_put(skb, sizeof (struct iphdr));
  47.         skb_put(skb, sizeof (struct tcphdr));
  48.         skb->network_header = (U8 *)ip_hdr(skb) - skb->head;
  49.         skb->transport_header = (U8 *)tcp_hdr(skb) - skb->head;
  50.         pdata = skb_put (skb, pkt_len);
  51.         {
  52.                 if (NULL != pkt)
  53.                         memcpy (pdata, pkt, pkt_len);

  54.         }

  55.         pr_info("tcphdr is start!!\n");
  56.         {
  57.                 tcph = tcp_hdr(skb);
  58.                 pr_info("tcphdr is start!!1\n");
  59.                 memset (tcph, 0, sizeof (struct tcphdr));
  60.                 pr_info("tcphdr is start!!2\n");
  61.                 pr_info("tcphdr is start!!2\n");
  62.                 tcph->source = sport;
  63.                 pr_info("tcphdr is start!!3\n");
  64.                 tcph->dest = dport;
  65.                 pr_info("tcphdr is start!!4\n");
  66.                 if(seq)
  67.                         tcph->seq = seq;
  68.                 if(ack_seq)
  69.                         tcph->ack_seq = ack_seq;
  70.                 pr_info("tcphdr is start!!5\n");
  71.                 tcph->doff = 5;
  72.                 pr_info("tcphdr is start!!6\n");
  73.                 tcph->psh = psh;
  74.                 pr_info("tcphdr is start!!7\n");
  75.                 tcph->fin = fin;
  76.                 pr_info("tcphdr is start!!8\n");
  77.                 tcph->ack = 1;
  78.                 pr_info("tcphdr is start!!9\n");
  79.                 tcph->window = __constant_htons (65535);
  80.                 pr_info("tcphdr is start!!10\n");
  81.                 skb->csum = 0;
  82.                 pr_info("tcphdr is start!!11\n");
  83.                 tcph->check = 0;
  84.                 pr_info("tcphdr is start!!12\n");
  85.         }

  86.         pr_info("iphdr is start!!13\n");
  87.         {
  88.                 iph = ip_hdr(skb);
  89.                 iph->version = 4;
  90.                 iph->ihl = sizeof(struct iphdr)>>2;
  91.                 iph->frag_off = 0;
  92.                 iph->protocol = IPPROTO_TCP;
  93.                 iph->tos = 0;
  94.                 iph->daddr = dip;
  95.                 iph->saddr = sip;
  96.                 iph->ttl = 0x40;
  97.                 iph->tot_len = __constant_htons(skb->len);
  98.                 iph->check = 0;
  99.         }

  100.         skb->csum = skb_checksum (skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);
  101.         tcph->check = csum_tcpudp_magic (sip, dip, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
  102.         ip_send_check(iph);

  103.         skb_push (skb, 14);
  104.         { //eth header
  105.                 ethdr = (struct ethhdr *) skb->data;
  106.                 memcpy (ethdr->h_dest, dmac, ETH_ALEN);
  107.                 memcpy (ethdr->h_source, smac, ETH_ALEN);
  108.                 ethdr->h_proto = __constant_htons (ETH_P_IP);
  109.         }
  110.         pr_info("fasong is start!!\n");
  111.         if (0 > dev_queue_xmit(skb))
  112.                 goto out;
  113.         nret = 0;
  114. out:
  115.         if (0 != nret && NULL != skb) {
  116.                 dev_put (dev);
  117.                 kfree_skb (skb);
  118.         }
  119.         return (nret);

  120. }

  121. static int __init hello_kernel(void)
  122. {
  123.         cp_dev_queue_xmit(.......);
  124.         return 0;
  125. }
复制代码
结果使用dmesg后查看发现内核打印“protocol 0x0800 is buggy, dev eth0” (eth0是我在调用cp_dev_queue_xmit函数时传递的参数)

请教各位神牛,新版本的内核下,我这个程序有啥问题啊?
谢谢了

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
2 [报告]
发表于 2015-10-14 12:19 |只看该作者
这是xmit上抓包接口打印的信息,从很早的版本就有了,并不是新内核才有的。
原因是skb->nh设置的不对,参见net/dev/core.c里的dev_queue_xmit_nit。

        skb->network_header = (U8 *)ip_hdr(skb) - skb->head;
ip_hdr本来就是从skb->nh推导出来的,这里却用来设置skb->nh,有啥意义呢?

论坛徽章:
2
程序设计版块每日发帖之星
日期:2016-02-12 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
3 [报告]
发表于 2015-10-15 00:24 |只看该作者
这个功能我已经调出来了,还有,新版本内核的sk_buff中没有nh这个成员变量。回复 2# nswcfd


   

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
4 [报告]
发表于 2015-10-15 16:22 |只看该作者
回复 1# 买单老
  1. skb->protocol = __constant_htons(ETH_P_IP);
复制代码
请确认一下,skb->protocol 是否需需要使用网络字节序。

结果使用dmesg后查看发现内核打印“protocol 0x0800 is buggy, dev eth0” (eth0是我在调用cp_dev_queue_xmit函数时传递的参数)


从你的报错结果,应该是 protocol 协议号设置的不对,系统不认识。

   

论坛徽章:
2
程序设计版块每日发帖之星
日期:2016-02-12 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
5 [报告]
发表于 2015-10-16 00:00 |只看该作者
  1. skb->protocol = __constant_htons(ETH_P_IP);
复制代码
上面这段语句是正确的,我参照的cu置顶的文章里面就是这么写的。

我是这么修改的
  1. 执行skb_put(skb, sizeof (struct iphdr));后
  2. 调用skb_reset_network_header(skb);
  3. 执行skb_put(skb, sizeof (struct tcphdr));后
  4. 调用skb_reset_transport_header(skb);
  5. 执行skb_push (skb, 14);后
  6. skb_reset_mac_header(skb);
复制代码
添加了上面三个reset函数后就能发送UDP数据了。

现在有新的问题了,我使用原来的上面的代码,把
  1. dev_queue_xmit(skb);
复制代码
替换成
  1. netif_receive_skb(skb);
复制代码
想实现在pre routing这个钩子点之前发送数据,然后希望数据稍后流进这个钩子点,钩子函数触发。
但是,钩子函数没有被触发,不过tcpdump 命令却输出了这个UDP报文数据。

想请问一下,如果使用netif_receive_skb(skb);发送数据,还需要注意哪些参数设置啊?

麻烦了


回复 4# Godbach


   

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
6 [报告]
发表于 2015-10-16 01:58 |只看该作者
回复 5# 买单老

想请问一下,如果使用netif_receive_skb(skb);发送数据,还需要注意哪些参数设置啊


这个是从网卡驱动中读取 skb 的。你要发送数据,为什么用这个函数?


   

论坛徽章:
2
程序设计版块每日发帖之星
日期:2016-02-12 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
7 [报告]
发表于 2015-10-16 23:40 |只看该作者
我想让自己构造的包流进协议栈。
现在有个疑问啊,调用ip_local_deliver这个函数,结果在内核模块编译的时候提示undefined,怎么解决呢?


回复 6# Godbach


   

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
8 [报告]
发表于 2015-10-18 22:59 |只看该作者
回复 7# 买单老

意味着这个函数并未 export 出来,你没办法调用。你可尝试把这个函数 export 出来,然后重新编译 kernel。


   

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
9 [报告]
发表于 2015-10-19 11:54 |只看该作者
想发送自己,把dev换成lo,调用xmit接口。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2016-02-12 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
10 [报告]
发表于 2015-10-19 20:58 |只看该作者
好的,我看看去,谢谢持续支持啊回复 9# nswcfd


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP