免费注册 查看新帖 |

Chinaunix

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

linux packet filter [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-08 18:59 |只看该作者 |倒序浏览
/*
   这个函数主要是linux下的packet模块来捕获数据(pcap的功能太少了。)。但是我碰到的问题就是当进程执行到读取数据的时候,也就是recv的时候就会  一直暂停,根本就读取不到数据。
   生成的lsf为 tcpdump -dd ip dst host 192.168.1.214(214是我自己的ip地址。)

   大家帮我看看怎么解决问题。谢谢了
   下面是代码:
*/
#include <string.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <netdb.h>
#include <pcap.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <sys/ioctl.h>
#include <linux/filter.h>
#include <linux/if.h>





char packet_cache[24];

int main (int argc, char **argv)
{
  struct ifreq  request_if;


  //tcpdump -dd ip dst host angel.
  struct sock_filter fprog[] =  \
    {
      { 0x28, 0, 0, 0x0000000c },
      { 0x15, 0, 3, 0x00000800 },
      { 0x20, 0, 0, 0x0000001e },
      { 0x15, 0, 1, 0xc0a801d6 },
      { 0x6, 0, 0, 0x00000060 },
      { 0x6, 0, 0, 0x00000000 }
    };
  
  struct sock_fprog fprog_info;
  
  int fd_packet_sniffer;

  /*
    create packet sniffer.
   */
  fd_packet_sniffer = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_IP));
  if (-1 == fd_packet_sniffer)
    {
      perror ("create packet socket failure");
      return EXIT_FAILURE;
    }

   
  /*
    set promisc mode.
   */
  strcpy (request_if.ifr_name, "eth0");
  if (0 != ioctl (fd_packet_sniffer, SIOCGIFFLAGS, &request_if))
    {
      perror ("get information of interface failure");
      goto __FUNCTION__close_packet_sniffer;
    }

  request_if.ifr_flags |= IFF_PROMISC;
  if (0 != ioctl (fd_packet_sniffer, SIOCSIFFLAGS, &request_if))
    {
      perror ("set promisc mode failure");
      goto __FUNCTION__close_packet_sniffer;
    }

  
  /*
    setup filter.
   */
  fprog_info.len = sizeof (fprog) / sizeof (struct sock_fprog);
  fprog_info.filter = fprog;

  
  /*
    insert packet filter.
   */
  if (-1 == (setsockopt (fd_packet_sniffer, SOL_SOCKET,                        \
                         SO_ATTACH_FILTER, &fprog_info,                \
                         sizeof (struct sock_fprog))))
    {
      perror ("insert packet filter failure");
      goto __FUNCTION__close_packet_sniffer;
    }


   
  while (1)
    {
      if (-1 == recv (fd_packet_sniffer, packet_cache, sizeof (packet_cache), 0))
        {
          perror ("capture packet failure");
          goto __FUNCTION__close_packet_sniffer;
        }
      fprintf (stdout, "IP Version: %d.\n", (short) ntohs (packet_cache[0]));
      break;
    }

__FUNCTION__close_packet_sniffer:
  close (fd_packet_sniffer);
  
  return 0;
}

论坛徽章:
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
2 [报告]
发表于 2009-03-08 20:19 |只看该作者
LZ先大致介绍一下你的代码。

论坛徽章:
0
3 [报告]
发表于 2009-03-08 22:59 |只看该作者

回复 #2 Godbach 的帖子

这个程序大概的意思就是用来捕获发给192.168.1.214机器的所有的ip包。
但是当程序执行到recv那个函数的时候就会读取不出来数据。
请给看看到底哪里除了问题。
TQ

论坛徽章:
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 [报告]
发表于 2009-03-09 11:20 |只看该作者
revc读不出来东西是返回了,还是阻塞了?

论坛徽章:
0
5 [报告]
发表于 2009-03-09 12:48 |只看该作者

回复 #4 Godbach 的帖子

是阻塞了。根本读取不出来东西。
我觉得应该是生成的bpf有问题。但是就是不知道该怎么解决。
谢谢了 。

论坛徽章:
0
6 [报告]
发表于 2009-03-09 12:55 |只看该作者
你没有bind到网卡

论坛徽章:
0
7 [报告]
发表于 2009-03-09 20:41 |只看该作者

回复 #6 qtdszws 的帖子

绝对不会是绑定网卡的问题。因为tcp服务器也同样不需要绑定网卡,绑定只意味着在某一个特定的网卡来捕获数据啊 。

论坛徽章:
0
8 [报告]
发表于 2009-03-10 21:16 |只看该作者
嗯,测试了一下,确实不需要bind网卡,你需要做的是
要么将SOCK_DGRAM改成SOCK_RAW,将packet_cache[0]改成packet_cache[14]
要么改变fprog中的指令值(具体原理还没弄明白)

另外set promisc mode.那几行代码是废代码,可以去掉

[ 本帖最后由 qtdszws 于 2009-3-11 08:44 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2009-03-11 09:28 |只看该作者

回复 #8 qtdszws 的帖子

要么改变fprog中的指令值(具体原理现在明白了)为
      { 0x28, 0, 0, 0xfffff000 },
      { 0x15, 0, 3, 0x00000800 },
      { 0x20, 0, 0, 0x00000010 },
      { 0x15, 0, 1, 0xc0a801d6 },
      { 0x6, 0, 0, 0x00000060 },
      { 0x6, 0, 0, 0x00000000 }

其中的原理查看内核代码就可以明白,简单指出
v2.4.0

在调用packet_rcv之前,skb->data指向网络层
static int packet_rcv(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt)
{
..

//tcpdump -i any -nnn ip,使用SOCK_DGRAM
//tcpdump -i eth0 -nnn ip,使用SOCK_RAW

        if (dev->hard_header) {//<<<
                /* The device has an explicit notion of ll header,
                   exported to higher levels.

                   Otherwise, the device hides datails of it frame
                   隐藏帧结构
                   structure, so that corresponding packet head
                   相应的包头不发送给用户
                   never delivered to user.

                   SOCK_DGRAM,也不发送
                 */
                 //本skb是clone过的,所以不需要恢复下面的操作
                if (sk->type != SOCK_DGRAM)
                        skb_push(skb, skb->data - skb->mac.raw);//SOCK_RAW,data从网络层拉回链路层
                else if (skb->pkt_type == PACKET_OUTGOING) {//捕获的外出包
                        /* Special case: outgoing packets have ll header at head */
                        skb_pull(skb, skb->nh.raw - skb->data);//略过链路层
                }
        }
...
}

也即SOCK_RAW,相对于链路头偏移寻址
SOCK_DGRAM,相对于网络头偏移寻址
因此SOCK_DGRAM下,
      { 0x28, 0, 0, 0x0000000c },//c为协议域相对于链路头偏移
需要改成
      { 0x28, 0, 0, 0xfffff000 },//0xfffff000指示从skb->protocol中取协议值
      { 0x20, 0, 0, 0x0000001e },//1e为目的ip地址相对于链路头偏移
需改成
      { 0x20, 0, 0, 0x00000010 },//10为目的ip地址相对于网络头偏移
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP