用法
tcpdump -s len
原理
tcpdump会把这个长度值编译到ebpf代码中。 ebpf代码执行完后,如果filter成功,则作为返回值(return)返回给调用方(内核协议栈),内核协议栈根据返回值,修改 skb报文到指定的长度,并借助 af socket 返回给用户空间。
tcpdump命令解析
1 | 151 #define MAXIMUM_SNAPLEN 262144 |
代码分析
TCPDUMP代码
- tcpdump 解析’s’参数,并把长度值存放到 ndo 变量中,并最终存放到 pcap_t的句柄中。
- 编译 ebpf 指令时候, 根据pcap——中的报文长度值, 在 bpf 程序最尾部增加一个 RET 指令,并将长度值作为返回值。
- ebpf 在内核协议栈中执行, 如果报文不满足 filter 条件, 则返回负值。如果满足 filter 条件,则返回指定的长度值
- 内核协议栈,根据返回的长度值,对 skb 报文进行截断。
调用栈
1 | ==> tcpdump main 函数解析:ndo->ndo_snaplen = (int)strtol(optarg, &end, 0); |
tcpdump解析
- step1:tcpdump main函数,解析snaplen参数,获取长度值,存放ndo 里。创建句柄时候,再赋值到句柄里。
1
2
3
4
5
61846 case 's':
1847 ndo->ndo_snaplen = (int)strtol(optarg, &end, 0);
...
2229 pd = open_interface(device, ndo, ebuf);
...
2347 if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
1 | 1259 static pcap_t * |
1 | 2591 int |
1 | 3490 int |
1 | 861 int |
kernel 代码
1 | 2219 snaplen = skb_frags_readable(skb) ? skb->len : skb_headlen(skb); |