Linux カーネルには、BPF (バークレー パケット フィルター) と呼ばれる同様のメカニズムがあります。アプリケーションから BPF フィルターをカーネルに登録します。フィルタに一致するパケットがキャプチャされ、登録されたフック関数に転送されます。
以下は、インターネットで見つけた例のコードです。( https://gist.github.com/939154 ) 基本的に、オープンを作成し、それを BPF フィルターにバインドしてから、パケットを受信するためにこの FD を選択する必要がありました。set_filter(int fd) { struct bpf_program fcode = {0};
/* dump ssh packets only */
struct bpf_insn insns[] = {
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 10),
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 8),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 6, 0),
BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 2, 0),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 22, 0, 1),
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
BPF_STMT(BPF_RET+BPF_K, 0),
};
/* Set the filter */
fcode.bf_len = sizeof(insns) / sizeof(struct bpf_insn);
fcode.bf_insns = &insns[0];
if(ioctl(fd, BIOCSETF, &fcode) < 0)
return -1;
return 0;
}
bpf_inst は奇妙に見えます。ただし、手動で記述する必要はありません。tcp-dump を使用して、これらのスクリプトを自動生成できます。
例えば:
sudo tcpdump 'tcp[13]=18' -i eth0 -dd
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 8, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 6, 0x00000006 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 4, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x50, 0, 0, 0x0000001b },
{ 0x15, 0, 1, 0x00000012 },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 },