参考文章:https://blog.csdn.net/jin787730090/article/details/117993915
可以使用以下命令生成bpf code
tcpdump -dd -i lo port 6172
输出如下结果
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 8, 0x000086dd },
{ 0x30, 0, 0, 0x00000014 },
{ 0x15, 2, 0, 0x00000084 },
{ 0x15, 1, 0, 0x00000006 },
{ 0x15, 0, 17, 0x00000011 },
{ 0x28, 0, 0, 0x00000036 },
{ 0x15, 14, 0, 0x0000181c },
{ 0x28, 0, 0, 0x00000038 },
{ 0x15, 12, 13, 0x0000181c },
{ 0x15, 0, 12, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 2, 0, 0x00000084 },
{ 0x15, 1, 0, 0x00000006 },
{ 0x15, 0, 8, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 6, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 2, 0, 0x0000181c },
{ 0x48, 0, 0, 0x00000010 },
{ 0x15, 0, 1, 0x0000181c },
{ 0x6, 0, 0, 0x00040000 },
{ 0x6, 0, 0, 0x00000000 },
tcpdump 提供了 -d 选项来阐述这段数字的意义
tcpdump -d -i lo port 6172
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 10
(002) ldb [20]
(003) jeq #0x84 jt 6 jf 4
(004) jeq #0x6 jt 6 jf 5
(005) jeq #0x11 jt 6 jf 23
(006) ldh [54]
(007) jeq #0x181c jt 22 jf 8
(008) ldh [56]
(009) jeq #0x181c jt 22 jf 23
(010) jeq #0x800 jt 11 jf 23
(011) ldb [23]
(012) jeq #0x84 jt 15 jf 13
(013) jeq #0x6 jt 15 jf 14
(014) jeq #0x11 jt 15 jf 23
(015) ldh [20]
(016) jset #0x1fff jt 23 jf 17
(017) ldxb 4*([14]&0xf)
(018) ldh [x + 14]
(019) jeq #0x181c jt 22 jf 20
(020) ldh [x + 16]
(021) jeq #0x181c jt 22 jf 23
(022) ret #262144
(023) ret #0
其中 ld是加载某位的数据,jeq是做相等比较
(000) ldh [12] // 加载数据包的第12个字节
(001) jeq #0x86dd jt 2 jf 10 // 判断是否为IPv6数据包,如果是,跳转到第2行,否则跳转到第10行
(002) ldb [20] // 加载数据包的第20个字节
(003) jeq #0x84 jt 6 jf 4 // 判断是否为ICMPv6数据包,如果是,跳转到第6行,否则跳转到第4行
(004) jeq #0x6 jt 6 jf 5 // 判断是否为TCP数据包,如果是,跳转到第6行,否则跳转到第5行
(005) jeq #0x11 jt 6 jf 23 // 判断是否为UDP数据包,如果是,跳转到第6行,否则跳转到第23行
(006) ldh [54] // 加载数据包的第54个字节,即TCP或UDP源端口
(007) jeq #0x181c jt 22 jf 8 // 判断源端口是否为6172,如果是,跳转到第22行,否则跳转到第8行
(008) ldh [56] // 加载数据包的第56个字节,即TCP或UDP目标端口
(009) jeq #0x181c jt 22 jf 23 // 判断目标端口是否为6172,如果是,跳转到第22行,否则跳转到第23行
(010) jeq #0x800 jt 11 jf 23 // 判断是否为IPv4数据包,如果是,跳转到第11行,否则跳转到第23行
(011) ldb [23] // 加载数据包的第23个字节,即IPv4或IPv6协议版本号
(012) jeq #0x84 jt 15 jf 13 // 判断是否为ICMPv6数据包,如果是,跳转到第15行,否则跳转到第13行
(013) jeq #0x6 jt 15 jf 14 // 判断是否为TCP数据包,如果是,跳转到第15行,否则跳转到第14行
(014) jeq #0x11 jt 15 jf 23 // 判断是否为UDP数据包,如果是,跳转到第15行,否则跳转到第23行
(015) ldh [20] // 加载数据包的第20个字节,即IP协议字段
(016) jset #0x1fff jt 23 jf 17 // 判断IP协议字段的值是否满足条件,如果满足,跳转到第23行,否则跳转到第17行
(017) ldxb 4*([14]&0xf) // 根据数据包的第14个字节计算偏移量
(018) ldh [x + 14] // 加载偏移量位置的字节
(019) jeq #0x181c jt 22 jf 20 // 判断该字节是否为6172,如果是,跳转到第22行,否则跳转到第20行
(020) ldh [x + 16] // 加载偏移量+16位置的字节
(021) jeq #0x181c jt 22 jf 23 // 判断该字节是否为6172,如果是,跳转到第22行,否则跳转到第23行
(022) ret #262144 // 匹配成功,返回262144
(023) ret #0 // 匹配失败,返回0