免费注册 查看新帖 |

Chinaunix

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

bpf and netfiter [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-11 14:31 |只看该作者 |倒序浏览
今天看libpcap代码,文章说bpf(bsd packet filter)不错,自己写了个sniff,不过pcap那一套毕竟要copy数据包,就算是mmap pcap也要copy一次,而netfilter不用copy数据包...

   我想能不能把bpf搞到netfilter呢??如果是应用层的话可以实用setsockopt来做
if ( (sock=socket(PF_PACKET, SOCK_RAW,
                    htons(ETH_P_IP)))<0) {
    perror("socket");
    exit(1);
  }


  /* Attach the filter to the socket */
  if(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
                &Filter, sizeof(Filter))<0){
    perror("setsockopt");
    close(sock);
    exit(1);
  }


   内核态呢???   不解...    由于对bpf也不是很熟悉,欢迎讨论

论坛徽章:
0
2 [报告]
发表于 2010-01-11 15:46 |只看该作者
内核态的实现在 <kernel>/net/core/filter.c 中

  1. /**
  2. *      sk_run_filter - run a filter on a socket
  3. *      @skb: buffer to run the filter on
  4. *      @filter: filter to apply
  5. *      @flen: length of filter
  6. *
  7. * Decode and apply filter instructions to the skb->data.
  8. * Return length to keep, 0 for none. skb is the data we are
  9. * filtering, filter is the array of filter instructions, and
  10. * len is the number of filter blocks in the array.
  11. */
  12. unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
  13. {
  14.         struct sock_filter *fentry;     /* We walk down these */
  15.         void *ptr;
  16.         u32 A = 0;                      /* Accumulator */
  17.         u32 X = 0;                      /* Index Register */
  18.         u32 mem[BPF_MEMWORDS];          /* Scratch Memory Store */
  19.         u32 tmp;
  20.         int k;
  21.         int pc;

  22.         /*
  23.          * Process array of filter instructions.
  24.          */
  25.         for (pc = 0; pc < flen; pc++) {
  26.                 fentry = &filter[pc];

  27.                 switch (fentry->code) {
  28.                 case BPF_ALU|BPF_ADD|BPF_X:
  29.                         A += X;
  30.                         continue;
  31.                 case BPF_ALU|BPF_ADD|BPF_K:
  32.                         A += fentry->k;
  33.                         continue;
  34.                 case BPF_ALU|BPF_SUB|BPF_X:
  35.                         A -= X;
  36.                         continue;
  37.                 case BPF_ALU|BPF_SUB|BPF_K:
  38.                         A -= fentry->k;
  39.                         continue;
  40.                 case BPF_ALU|BPF_MUL|BPF_X:
  41.                         A *= X;
  42.                         continue;
  43.                 case BPF_ALU|BPF_MUL|BPF_K:
  44.                         A *= fentry->k;
  45.                         continue;
  46.                 case BPF_ALU|BPF_DIV|BPF_X:
  47.                         if (X == 0)
  48.                                 return 0;
  49.                         A /= X;
  50.                         continue;
  51.                 case BPF_ALU|BPF_DIV|BPF_K:
  52.                         A /= fentry->k;
  53.                         continue;
  54.                 case BPF_ALU|BPF_AND|BPF_X:
  55.                         A &= X;
  56.                         continue;
  57.                 case BPF_ALU|BPF_AND|BPF_K:
  58.                         A &= fentry->k;
  59.                         continue;
  60.                 case BPF_ALU|BPF_OR|BPF_X:
  61.                         A |= X;
  62.                         continue;
  63.                 case BPF_ALU|BPF_OR|BPF_K:
  64.                         A |= fentry->k;
  65.                         continue;
  66.                 case BPF_ALU|BPF_LSH|BPF_X:
  67.                         A <<= X;
  68.                         continue;
  69.                 case BPF_ALU|BPF_LSH|BPF_K:
  70.                         A <<= fentry->k;
  71.                         continue;
  72.                 case BPF_ALU|BPF_RSH|BPF_X:
  73.                         A >>= X;
  74.                         continue;
  75.                 case BPF_ALU|BPF_RSH|BPF_K:
  76.                         A >>= fentry->k;
  77.                         continue;
  78.                 case BPF_ALU|BPF_NEG:
  79.                         A = -A;
  80.                         continue;
  81.                 case BPF_JMP|BPF_JA:
  82.                         pc += fentry->k;
  83.                         continue;
  84.                 case BPF_JMP|BPF_JGT|BPF_K:
  85.                         pc += (A > fentry->k) ? fentry->jt : fentry->jf;
  86.                         continue;
  87.                 case BPF_JMP|BPF_JGE|BPF_K:
  88.                         pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
  89.                         continue;
  90.                 case BPF_JMP|BPF_JEQ|BPF_K:
  91.                         pc += (A == fentry->k) ? fentry->jt : fentry->jf;
  92.                         continue;
  93.                 case BPF_JMP|BPF_JSET|BPF_K:
  94.                         pc += (A & fentry->k) ? fentry->jt : fentry->jf;
  95.                         continue;
  96.                 case BPF_JMP|BPF_JGT|BPF_X:
  97.                         pc += (A > X) ? fentry->jt : fentry->jf;
  98.                         continue;
  99.                 case BPF_JMP|BPF_JGE|BPF_X:
  100.                         pc += (A >= X) ? fentry->jt : fentry->jf;
  101.                         continue;
  102.                 case BPF_JMP|BPF_JEQ|BPF_X:
  103.                         pc += (A == X) ? fentry->jt : fentry->jf;
  104.                         continue;
  105.                 case BPF_JMP|BPF_JSET|BPF_X:
  106.                         pc += (A & X) ? fentry->jt : fentry->jf;
  107.                         continue;
  108.                 case BPF_LD|BPF_W|BPF_ABS:
  109.                         k = fentry->k;
  110. load_w:
  111.                         ptr = load_pointer(skb, k, 4, &tmp);
  112.                         if (ptr != NULL) {
  113.                                 A = ntohl(get_unaligned((__be32 *)ptr));
  114.                                 continue;
  115.                         }
  116.                         break;
  117.                 case BPF_LD|BPF_H|BPF_ABS:
  118.                         k = fentry->k;
  119. load_h:
  120.                         ptr = load_pointer(skb, k, 2, &tmp);
  121.                         if (ptr != NULL) {
  122.                                 A = ntohs(get_unaligned((__be16 *)ptr));
  123.                                 continue;
  124.                         }
  125.                         break;
  126.                 case BPF_LD|BPF_B|BPF_ABS:
  127.                         k = fentry->k;
  128. load_b:
  129.                         ptr = load_pointer(skb, k, 1, &tmp);
  130.                         if (ptr != NULL) {
  131.                                 A = *(u8 *)ptr;
  132.                                 continue;
  133.                         }
  134.                         break;
  135.                 case BPF_LD|BPF_W|BPF_LEN:
  136.                         A = skb->len;
  137.                         continue;
  138.                 case BPF_LDX|BPF_W|BPF_LEN:
  139.                         X = skb->len;
  140.                         continue;
  141.                 case BPF_LD|BPF_W|BPF_IND:
  142.                         k = X + fentry->k;
  143.                         goto load_w;
  144.                 case BPF_LD|BPF_H|BPF_IND:
  145.                         k = X + fentry->k;
  146.                         goto load_h;
  147.                 case BPF_LD|BPF_B|BPF_IND:
  148.                         k = X + fentry->k;
  149.                         goto load_b;
  150.                 case BPF_LDX|BPF_B|BPF_MSH:
  151.                         ptr = load_pointer(skb, fentry->k, 1, &tmp);
  152.                         if (ptr != NULL) {
  153.                                 X = (*(u8 *)ptr & 0xf) << 2;
  154.                                 continue;
  155.                         }
  156.                         return 0;
  157.                 case BPF_LD|BPF_IMM:
  158.                         A = fentry->k;
  159.                         continue;
  160.                 case BPF_LDX|BPF_IMM:
  161.                         X = fentry->k;
  162.                         continue;
  163.                 case BPF_LD|BPF_MEM:
  164.                         A = mem[fentry->k];
  165.                         continue;
  166.                 case BPF_LDX|BPF_MEM:
  167.                         X = mem[fentry->k];
  168.                         continue;
  169.                 case BPF_MISC|BPF_TAX:
  170.                         X = A;
  171.                         continue;
  172.                 case BPF_MISC|BPF_TXA:
  173.                         A = X;
  174.                         continue;
  175.                 case BPF_RET|BPF_K:
  176.                         return fentry->k;
  177.                 case BPF_RET|BPF_A:
  178.                         return A;
  179.                 case BPF_ST:
  180.                         mem[fentry->k] = A;
  181.                         continue;
  182.                 case BPF_STX:
  183.                         mem[fentry->k] = X;
  184.                         continue;
  185.                 default:
  186.                         WARN_ON(1);
  187.                         return 0;
  188.                 }

  189.                 /*
  190.                  * Handle ancillary data, which are impossible
  191.                  * (or very difficult) to get parsing packet contents.
  192.                  */
  193.                 switch (k-SKF_AD_OFF) {
  194.                 case SKF_AD_PROTOCOL:
  195.                         A = ntohs(skb->protocol);
  196.                         continue;
  197.                 case SKF_AD_PKTTYPE:
  198.                         A = skb->pkt_type;
  199.                         continue;
  200.                 case SKF_AD_IFINDEX:
  201.                         A = skb->dev->ifindex;
  202.                         continue;
  203.                 default:
  204.                         return 0;
  205.                 }
  206.         }

  207.         return 0;
  208. }
复制代码

这是一个类似有穷状态机的实现方式
个人认为如果 filter 的书写比较单一的话,还是有很高提升空间的
上上周刚结束一个 case,改写了 filter,实现自己的抓包过滤机制,由于规则模式很单一,所以改用 hash 实现,效率比 bpf 高出不少

论坛徽章:
0
3 [报告]
发表于 2010-01-11 15:48 |只看该作者
另外,bpf 本身就是在 kernel 实现的,他把,且仅把你要的数据 copy 到用户空间
所以你的理解可能存在错误,误以为是所有数据都 copy 到用户空间然后才选择性丢弃的

论坛徽章:
0
4 [报告]
发表于 2010-01-11 16:52 |只看该作者
原帖由 platinum 于 2010-1-11 15:48 发表
另外,bpf 本身就是在 kernel 实现的,他把,且仅把你要的数据 copy 到用户空间
所以你的理解可能存在错误,误以为是所有数据都 copy 到用户空间然后才选择性丢弃的

呵呵 理解是没错的   可能我上面的描述有误^_^   
谢谢指点  我看看filter.c

论坛徽章:
0
5 [报告]
发表于 2010-01-11 21:18 |只看该作者
bpf就是在内核态过滤。
tcpdump就是用pcap实现的。

速度已经不错了,要是抓包软件无论如何都是要把抓得包copy到用户层的。

如果只是过滤的话,五元组匹配可以通过hash表。不过没测试过bpf的效率

论坛徽章:
0
6 [报告]
发表于 2012-06-04 16:25 |只看该作者
回复 1# ubuntuer


   你好,我最近在学习libpcap中的bpf,我的开发环境是CentOS5.5,使用的是libpcap1.2.1
   我一直有个问题很困惑,是不是所有的linux都支持bpf?我在安装libpcap的源码时,看了一下make的输出,
   并没有使用pcap-bpf.c这个文件,当然libpcap是完全可以运行的,也可以抓到数据包,但我不知道是不是使用的bpf的机制?
   您能把您的sniff 的源码发给我一份吗,十分感谢,邮箱rogge321@163.com
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP