背景
在linux下编写网络包过滤程序的时候,希望内核只投递指定规则的报文。
概要
主要是记录如何分析bpf filter的规则码。
tcpdump 生成bpf code
tcpdump -i lo ip and udp and dst port 65500 -d 
如下:
(000) ldh      [12]                             # 加载第12字节的word
(001) jeq      #0x800           jt 2	jf 10   # 判断是否是ipv4, 分别跳转到2 或 10
(002) ldb      [23]                             # 加载23字节
(003) jeq      #0x11            jt 4	jf 10   # 判断是否是udp(17), 分别跳转
(004) ldh      [20]                             # 加载第20字节的word
(005) jset     #0x1fff          jt 10	jf 6    # 分析是否出现了 frament(分包)
(006) ldxb     4*([14]&0xf)                     # 计算ip头部长度
(007) ldh      [x + 16]                         # 取ip后的第16字节(word), udp源端口
(008) jeq      #0xffdc          jt 9	jf 10   # 判断源端口是否是65500
(009) ret      #262144                          # match
(010) ret      #0                               # discard
通过 -dd 参数产生具体的struct sock_filter结构的数据:
tcpdump -i lo ip and udp and dst port 65500 -dd
注意点
创建raw socket的时候需要指定收包是从数据链路层开始,还是从ip开始。
使用上述的规则码的时候,必须是从数据链路层开始,即:
int fd = ::socket(PF_PACKET, SOCK_RAW , htons(ETH_P_IP));
如果
int fd = ::socket(PF_PACKET, SOCK_DGRAM , htons(ETH_P_IP));
那么就需要自行修改这个规则码,将所有的”地址” 减去 14(一般来说是以太网,以太网帧头部长14字节).
知道了上述规则后,就具备了修改code的能力。