libpcap
399円で dual display
結局、399円でレンタルCD屋からHDMIなケーブル(2M)を仕入れてきた。これ1種類しか無いので迷う事無し。ホームセンターには1500円平均ぐらいのやつが何種類か置いてあった。どれを選んでいいやらである。HDMIはどこかの特許になってて、ケーブルにも特許料が課せられる。お墨付きって言うみかじめ代だ。
399円品は、どこかからの輸入品。価格から言って中華だろう。無事に映ったよ。画面を横に並べるより、縦にする方が、カーソルの移動が楽。カーソルが移動していって、画面を超えると、別画面ににゅーと出て来るのは、慣れが必要だな。
本体のLCDとTVの解像度は同一。TVの方でWindows Terminalを使ってる。Ctl+-, Ctl+= で、動的にフォントサイズを変更出来るのが便利。Rows 50 ぐらいまで、目に負担なく使えるので、なかなか良い。
ちょいと贅沢な悩み。2画面あると目移りしちゃう。思い切ってTV画面だけにしちゃって、TVに集中するか(Win+pで切り替え)。そして、Windows Terminalを全面に拡げる。複数の画面を作って、TABで切り替え(Ctl+Alt+1,2,3..)。
emacsを立ち上げる。Ctl-x 2 なり、Ctl-x 3 で、emacs画面を分割。画面間の移動はどうする? そんなの先人の知恵を借りればOk。 Emacsの分割ウィンドウを←↓↑→で移動
TVの前に、どっかりと胡坐をかいた状態だと、腰痛に襲われそう。さて、どうする? それと、女房とのTV取り合い戦争は、どうやって回避する? こういう問題が難しいんだよな。
調子こいて Thinkpad SL510のdebianで試そうと思ったら、何故かHDMIコネクターの口が合わない。マニュアル調べたら、HDMIかDisplay Portですって書かれていた。ひょっとしてHDMIとは違うの? なんでもDisplay Portの方は、任意団体が規格化したもののようで、みかじめ代は不要らしい。
ああ、思い出した。仙台の銘酒と言えば、浦霞。でも、昔仙台市民だった時は、 一ノ蔵、無監査二級酒なんてのを愛飲してた。国税庁の監査を受けると酒税が高くなる(可能性がある)。そこで、あえて監査を受けずに、二級酒として安く販売するんだそうな。その心意気気に入った、ってんで、ずっとこればかりでしたね。懐かしいな、たまには飲んでみたいぞ。
nmapのあれ
nmap方面で、OSの検出はどうなってるか、確認してみる。
OS DETECTION One of Nmap's best-known features is remote OS detection using TCP/IP stack fingerprinting. Nmap sends a series of TCP and UDP packets to the remote host and examines practically every bit in the responses. After performing dozens of tests such as TCP ISN sampling, TCP options support and ordering, IP ID sampling, and the initial window size check, Nmap compares the results to its nmap-os-db database of more than 2,600 known OS fingerprints and prints out the OS details if there is a match. -O (Enable OS detection) Enables OS detection, as discussed above. Alternatively, you can use -A to enable OS detection along with other things.
10万行を超えるnma-os-dbってファイルの一部
# OpenBSD 6.1 GENERIC.MP#20 amd64 Fingerprint OpenBSD 6.1 Class OpenBSD | OpenBSD | 6.X | general purpose CPE cpe:/o:openbsd:openbsd:6.1 auto SEQ(SP=F7-101%GCD=1-6%ISR=FD-115%TI=RD%CI=RI%II=RI%TS=20|21) OPS(O1=M5B4NNSNW6NNT11%O2=M5B4NNSNW6NNT11%O3=M5B4NW6NNT11%O4=M5B4NNSNW6NNT11%O5\ =M5B4NNSNW6NNT11%O6=M5B4NNSNNT11) :
見ていてもしょうがないので、検証開始。
debian:~$ sudo nmap -O localhost Starting Nmap 7.80 ( https://nmap.org ) at 2021-06-14 06:32 JST Nmap scan report for localhost (127.0.0.1) Host is up (0.000026s latency). Other addresses for localhost (not scanned): ::1 Not shown: 999 closed ports PORT STATE SERVICE 22/tcp open ssh No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.80%E=4%D=6/14%OT=22%CT=1%CU=34197%PV=N%DS=0%DC=L%G=Y%TM=60C6797 OS:6%P=i686-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O :
知らないんで、下記のデータと共に、投稿してよとお願いされたよ。そんじゃ、推測してみてくれって指示。
debian:~$ sudo nmap -O --osscan-guess localhost : Aggressive OS guesses: Linux 2.6.32 (96%), Linux 3.8 - 4.14 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.7 - 3.11 (93%), Linux 3.10 (93%), Linux 3.8 - 3.9 (93%), Linux 3.7 - 3.10 (93%), ASUS RT-N56U WAP (Linux 3.4) (93%)
確率論的な結果を返してきましたなあ。ネットワークカメラも、最近はリナの範疇なのか。NetBSDは、こういう分野得意だったのに、お株を奪われつつあるのね。
libpcap
libpcapを使っているアプリとして真っ先に思い付くのはtcpdumpそれに、上でやったnmapとかもそうだ。libpcapはしっかりと組み込まれてしまっていて、どんな風に動いているか知るのは、容易ではない。みんなこう思っているみたいで、偉大な先人達は、libpcapを裸で使おうと努力なされている。
パケットキャプチャツールのつくり方【C言語】 〜IPヘッダー解析〜
これらが、その例だ。コピペして動かしてgdbしてみるって簡単コースだな。OpenBSDなら、libpcapに分け入って行くのも自然だし。。。こういう事は誰もやってないみたい。
車のエンジンを解体屋から買ってきて、自分仕様の車を作ってみるって事だ。でも、エンジンがどう動いているかまでは踏み込んでいないって事だ。まあ、エンジン(libpcap)は、部品として扱えば良い訳で、深入りしても意味ないよって所だろう。でも、あえてそこに踏み込むもの一興かと。そんな訳で、libpcapを解剖台に載せるべく、頑張ってみる。
http.server
で、tcpdumpの雛型なんだけど、パケット発生をさせないと、どうにもならない。今まではsshした時のパケットを観察した。それにも秋田ので、今流行りのWebでやってみるか。
ええ、どこでもpythonで、どこでもWebサーバーです。オイラーのpythonの使い道と言ったら、これぐらいしかありません(きっぱり)。
alias server='python3 -m http.server 8080'
早速起動して、w3mからアクセス。
sakae@pen:/tmp$ server Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ... aa.bb.cc.129 - - [15/Jun/2021 07:27:17] "GET / HTTP/1.0" 200 -
それを、キャプチャ出来るか、本物で確認。
sakae@pen:/tmp$ sudo tcpdump port 8080 [sudo] password for sakae: tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
あろう事か、tcpdumpは無反応。でも、serverは、リクエストをちゃんと受け付けているし、w3mもちゃんと表示した。変なの、理解に苦しむぞ。気を取り直して、loなデバイスを監視。
sakae@pen:/tmp$ sudo tcpdump -i lo port 8080 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes : 07:58:02.771377 IP aa.bb.cc.129.36762 > aa.bb.cc.129.http-alt: Flags [.], ack 1, win 512, options [nop,nop,TS val 1440373251 ecr 1440373251], length 0 07:58:02.772029 IP aa.bb.cc.129.36762 > aa.bb.cc.129.http-alt: Flags [P.], seq 1:289, ack 1, win 512, options [nop,nop,TS val 1440373251 ecr 1440373251], length 288: HTTP: GET / HTTP/1.0 07:58:02.772067 IP aa.bb.cc.129.http-alt > aa.bb.cc.129.36762: Flags [.], ack 289, win 510, options [nop,nop,TS val 1440373251 ecr 1440373251], length 0 07:58:02.773226 IP aa.bb.cc.129.http-alt > aa.bb.cc.129.36762: Flags [P.], seq 1:156, ack 289, win 512, options [nop,nop,TS val 1440373253 ecr 1440373251], length 155: HTTP: HTTP/1.0 200 OK
127.0.0.1なIPにも、グローバルなIPパケットが流れるのか? ちょいとオイラーのの理解の範疇を越えているな。まあ、兎も角、今後はlocalhostでアクセスする事にしよう。
原型なtcpdump
今度は、コードを寄せ集めて、loなデバイスでport 8080をキャプチャするもどきを作ってみた(先人に感謝です)。設計図は、巻末に掲載。
sakae@pen:/tmp$ sudo ./a.out device = lo packet size = 94 00 00 00 00 00 00 00 00 00 00 00 00 86 dd 60 00| ..............`. : packet size = 348 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00| ..............E. 01 4e 1a 8f 40 00 40 06 21 19 7f 00 00 01 7f 00| .N..@.@.!....... 00 01 80 76 1f 90 28 4d f3 1b eb cf 6d 7a 80 18| ...v..(M....mz.. 02 00 ff 42 00 00 01 01 08 0a 34 fb ba b2 34 fb| ...B......4...4. ba b2 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 30| ..GET / HTTP/1.0 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 77 33| ..User-Agent: w3 6d 2f 30 2e 35 2e 33 2b 67 69 74 32 30 31 39 30| m/0.5.3+git20190 31 30 35 0d 0a 41 63 63 65 70 74 3a 20 74 65 78| 105..Accept: tex : packet size = 221 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00| ..............E. 00 cf 6b 77 40 00 40 06 d0 af 7f 00 00 01 7f 00| ..kw@.@......... 00 01 1f 90 80 76 eb cf 6d 7a 28 4d f4 35 80 18| .....v..mz(M.5.. 02 00 fe c3 00 00 01 01 08 0a 34 fb ba b3 34 fb| ..........4...4. ba b2 48 54 54 50 2f 31 2e 30 20 32 30 30 20 4f| ..HTTP/1.0 200 O 4b 0d 0a 53 65 72 76 65 72 3a 20 53 69 6d 70 6c| K..Server: Simpl 65 48 54 54 50 2f 30 2e 36 20 50 79 74 68 6f 6e| eHTTP/0.6 Python 2f 33 2e 37 2e 33 0d 0a 44 61 74 65 3a 20 4d 6f| /3.7.3..Date: Mo : packet size = 1181 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00| ..............E. 04 8f 6b 78 40 00 40 06 cc ee 7f 00 00 01 7f 00| ..kx@.@......... 00 01 1f 90 80 76 eb cf 6e 15 28 4d f4 35 80 18| .....v..n.(M.5.. 02 00 02 84 00 00 01 01 08 0a 34 fb ba b4 34 fb| ..........4...4. ba b3 3c 21 44 4f 43 54 59 50 45 20 48 54 4d 4c| ..<!DOCTYPE HTML 20 50 55 42 4c 49 43 20 22 2d 2f 2f 57 33 43 2f| PUBLIC "-//W3C/ 2f 44 54 44 20 48 54 4d 4c 20 34 2e 30 31 2f 2f| /DTD HTML 4.01// 45 4e 22 20 22 68 74 74 70 3a 2f 2f 77 77 77 2e| EN" "http://www. 77 33 2e 6f 72 67 2f 54 52 2f 68 74 6d 6c 34 2f| w3.org/TR/html4/ 73 74 72 69 63 74 2e 64 74 64 22 3e 0a 3c 68 74| strict.dtd">.<ht 6d 6c 3e 0a 3c 68 65 61 64 3e 0a 3c 6d 65 74 61| ml>.<head>.<meta :
リクエストが出て、返事が有って、やがてコンテンツが流れてきた。以上構築終了。
at OpenBSD
Debianではpcapの中へ潜っていけないので(自前で何とかするのめんどい)、OpenBSDでやってみる。loなデバイスなんてOpenBSDには無いので、忘れずにlo0に変更。
vbox$ cc -g mypc.c -lpcap vbox$ doas ./a.out doas (sakae@vbox.local.jp) password: device = lo0 packet size = 44 Segmentation fault (core dumped)
なんと、まあ、行くてを阻むのはセグフォ也。何でさ? こういう予期せぬトラップが仕掛けられているんだな。
vbox# gdb -q a.out a.out.core Reading symbols from a.out...done. [New process 263199] warning: Unexpected size of section `.reg2/263199' in core file. #0 0x1860688f in dump (data_buffer=0x0, length=44) at mypc.c:10 10 byte = data_buffer[i];
0番地から読みだそうとしたら、怒られるわな。
u_char * pcap_next(pcap_t *p, struct pcap_pkthdr *h);
manにはこう定義されてた。この関数からの返値をそのまま使うなって事かな。パケットが到着しなくてタイムアウトした場合も、この関数が終了するんだろうから、その場合は無効って判断を、ユーザーの責任でしろ、だろうね。
vbox# gdb -q a.out Reading symbols from a.out...done. (gdb) b pcap_next Function "pcap_next" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (pcap_next) pending. (gdb) r Starting program: /tmp/a.out device = lo0 Breakpoint 1, pcap_next (p=0x5090ae00, h=0xcf7c40e8) at /usr/src/lib/libpcap/pcap.c:108 108 s.hdr = h; (gdb) l 103 const u_char * 104 pcap_next(pcap_t *p, struct pcap_pkthdr *h) 105 { 106 struct singleton s; 107 108 s.hdr = h; 109 if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) 110 return (0); 111 return (s.pkt); 112 }
if文を満たしてしまっているんだな。ユーザープログラムで対処するか。元のfor文の所を下記のように改造。
i = 10; while (i>0) { packet = pcap_next(pcap_handle, &header); if (packet == NULL) continue; printf("packet size = %d\n", header.len); dump(packet, header.len); i--; }
10パケで十分か? 接続時のネゴシエーションの3パケ、それからgetが来て、okが来てって具合になるんで、まあ、頭の方は取れるだろう。
packet size = 255 00 00 00 02 45 00 00 fb 68 0f 40 00 40 06 d3 eb| ....E...h.@.@... 7f 00 00 01 7f 00 00 01 19 c2 1f 90 70 20 fe a6| ............p .. d0 68 ce 54 80 18 01 00 7a 54 00 00 01 01 08 0a| .h.T....zT...... 73 2a 2d c9 14 7b a9 81 47 45 54 20 2f 20 48 54| s*-..{..GET / HT 54 50 2f 31 2e 30 0d 0a 55 73 65 72 2d 41 67 65| TP/1.0..User-Age 6e 74 3a 20 77 33 6d 2f 30 2e 35 2e 33 2b 67 69| nt: w3m/0.5.3+gi : packet size = 210 00 00 00 02 45 00 00 ce d4 92 40 00 40 06 67 95| ....E.....@.@.g. 7f 00 00 01 7f 00 00 01 1f 90 19 c2 d0 68 ce 54| .............h.T 70 20 ff 6d 80 18 01 00 76 ac 00 00 01 01 08 0a| p .m....v....... 14 7b a9 81 73 2a 2d c9 48 54 54 50 2f 31 2e 30| .{..s*-.HTTP/1.0 20 32 30 30 20 4f 4b 0d 0a 53 65 72 76 65 72 3a| 200 OK..Server: 20 53 69 6d 70 6c 65 48 54 54 50 2f 30 2e 36 20| SimpleHTTP/0.6 50 79 74 68 6f 6e 2f 33 2e 38 2e 38 0d 0a 44 61| Python/3.8.8..Da :
ちゃんとキャプチャ出来てる。物はついでなんで、dump関数を既存のhexdumpに任せてみるかな。 ソースの冒頭に #include <unistd.h> を追加。元のdump呼び出しを write(1, packet, header.len); に変更。システムコールですよ。
vbox# ./a.out | hexdump -C 00000000 00 00 00 02 45 00 00 40 c7 aa 40 00 40 06 75 0b |....E..@..@.@.u.| 00000010 7f 00 00 01 7f 00 00 01 10 61 1f 90 f4 2b 70 df |.........a...+p.| 00000020 00 00 00 00 b0 02 40 00 d3 19 00 00 02 04 7f d8 |......@.........| 00000030 01 01 04 02 01 03 03 06 01 01 08 0a 59 a8 bc 15 |............Y...| 00000040 00 00 00 00 00 00 00 02 45 00 00 40 68 f3 40 00 |........E..@h.@.| 00000050 40 06 d3 c2 7f 00 00 01 7f 00 00 01 1f 90 10 61 |@..............a| 00000060 1d 56 f4 77 f4 2b 70 e0 b0 12 40 00 6e bd 00 00 |.V.w.+p...@.n...| :
もろにバイナリーデータが出てきて、それをhexdumpに喰わせてみた。これが、unix流のプログラミングだよ。まて、そんなバイナリーデータは始末に困るぞ。そんな事もあろうかと、erlangが控えているのさ。バイナリーも得意だそうですから。
それにしても、ひょひょいとコピペしたコードが何故リナでは普通に動いてしまったのだろう? そうか、リナはスクリプト・キディに優しい仕様になってるんだな。正統派ならBSDを使えって事だ(多分)。
at linux
やっぱり気になるよう。OpenBSDでは、改造しなければ動かなかったやつが、リナでは普通に動いちゃうのが。ひょっとしてlibpcapの仕様が違うのではなかろうか? スクリプト・キディ用になってる疑惑。疑惑を正すのが刑事の務めです。
まずは、自前でlibpcapをインストールだな。取ってきて、入れた。configure –prefix=/home/sakae/MINE って指定。コンパイルの報告を見てたら、-g -O2 だったから佳しとしよう。
次は、これをリンクだな。
debian:tmp$ ls -l /home/sakae/MINE/lib -rw-r--r-- 1 sakae sakae 1447800 Jun 18 07:37 libpcap.a lrwxrwxrwx 1 sakae sakae 12 Jun 18 07:37 libpcap.so -> libpcap.so.1* lrwxrwxrwx 1 sakae sakae 17 Jun 18 07:37 libpcap.so.1 -> libpcap.so.1.10.1* -rwxr-xr-x 1 sakae sakae 987080 Jun 18 07:37 libpcap.so.1.10.1* drwxr-xr-x 2 sakae sakae 4096 Jun 18 07:37 pkgconfig/
debian:tmp$ cc -g mypc.c -L/home/sakae/MINE/lib -lpcap debian:tmp$ ldd a.out linux-gate.so.1 (0xb7fbe000) libpcap.so.1 => not found libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7da8000) /lib/ld-linux.so.2 (0xb7fc0000)
新たなlibpcapをリンクするように指示。んが、見つからんぞ。
debian:tmp$ export LD_LIBRARY_PATH=/home/sakae/MINE/lib debian:tmp$ ldd a.out linux-gate.so.1 (0xb7f59000) libpcap.so.1 => /home/sakae/MINE/lib/libpcap.so.1 (0xb7f03000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7cf7000) libibverbs.so.1 => /usr/lib/i386-linux-gnu/libibverbs.so.1 (0xb7cdb000) libdbus-1.so.3 => /lib/i386-linux-gnu/libdbus-1.so.3 (0xb7c7c000) /lib/ld-linux.so.2 (0xb7f5b000) libnl-route-3.so.200 => /usr/lib/i386-linux-gnu/libnl-route-3.so.200 (0xb7bfa000) libnl-3.so.200 => /lib/i386-linux-gnu/libnl-3.so.200 (0xb7bd6000) libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb7bb5000) libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7baf000) libsystemd.so.0 => /lib/i386-linux-gnu/libsystemd.so.0 (0xb7b04000) librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xb7af9000) liblzma.so.5 => /lib/i386-linux-gnu/liblzma.so.5 (0xb7acb000) liblz4.so.1 => /usr/lib/i386-linux-gnu/liblz4.so.1 (0xb7aab000) libgcrypt.so.20 => /lib/i386-linux-gnu/libgcrypt.so.20 (0xb79c8000) libgpg-error.so.0 => /lib/i386-linux-gnu/libgpg-error.so.0 (0xb79a3000)
昔のSolaris時代を思い出して、伝家の宝刀をを抜く。そしたら、余計なものまで見えてきた。 けど、気にしない。気にしなくちゃいけないのは、このアプリはrootでの実行になるんで、rootにも伝家の宝刀を抜いて貰うと言う、危ない橋を渡ってもらうって事。
root@debian:/tmp# gdb -q a.out Reading symbols from a.out... (gdb) b pcap_next Breakpoint 1 at 0x10e0 (gdb) r Starting program: /tmp/a.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1". device = lo Breakpoint 1, pcap_next (p=0x4059a0, h=0xbffff694) at ./pcap.c:593 593 s.hdr = h; (gdb) l 588 pcap_next(pcap_t *p, struct pcap_pkthdr *h) 589 { 590 struct oneshot_userdata s; 591 const u_char *pkt; 592 593 s.hdr = h; 594 s.pkt = &pkt; 595 s.pd = p; 596 if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0) 597 return (0); (gdb) n 594 s.pkt = &pkt; (gdb) 595 s.pd = p; (gdb) 596 if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0) (gdb)
ざっと見、OpenBSDのそれと同一のコードっぽい。が、決定的に違うのは、パケットが到着するまで。 pcap_dispatch
で、ブロック(待たされて)しまうと言う事。
(gdb) main () at mypc.c:67 67 printf("packet size = %d\n", header.len); (gdb) n packet size = 94 68 dump(packet, header.len); (gdb) s dump (data_buffer=0x405c30 "", length=94) at mypc.c:9 9 for (i = 0; i < length; i++) {
w3m http://localhost:8080 で、パケットを発生させると、ブロックが解除されて、メインに復帰してくる。その時は、バッファーに有効なパケットが充填されてる。 だから、メイン側で気を回す必要無し。
じゃ、パケットが到着するまでのタイムアウトうんぬんはどうなった。それは無視ですよ。便利なら、それでいいじゃない、何か文句ある? 世の中の仕組みを捻じ曲げてる、矛盾した仕様は、混乱の元。だからリナ系ときたら、、、、、、これ以上は言うまえ。
なお、FreeBSDはちゃんと、矛盾なく実装されてたよ。
(gdb) bt #0 0xb7fd4d31 in __kernel_vsyscall () #1 0xb7e66b37 in poll () from /lib/i386-linux-gnu/libc.so.6 #2 0xb7f87caf in pcap_wait_for_frames_mmap (handle=handle@entry=0x4059a0) at ./pcap-linux.c:3493 #3 0xb7f88827 in pcap_read_linux_mmap_v3 (handle=<optimized out>, max_packets=<optimized out>, callback=<optimized out>, user=<optimized out>) at ./pcap-linux.c:4085 #4 0xb7f90778 in pcap_next (p=0x4059a0, h=0xbffff694) at ./pcap.c:596 #5 0x00401544 in main () at mypc.c:66
リナは、特別扱いされてるな。コードをちょい見したら、kernelの特殊性を吸収するため、リングバッファを導入してるよーーなんて事が、解説されてた。深入りはよしときましょ。
sniffex.c
tcpdumpな本家が、libpcapを使った見本を提供してる。これは、有無を言わさず見て桶。 sniffex.c
vbox$ doas ./a.out lo0 doas (sakae@vbox.local.jp) password: sniffex - Sniffer example using libpcap Copyright (c) 2005 The Tcpdump Group THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM. Device: lo0 Number of packets: 10 Filter expression: tcp port 8080 lo0 is not an Ethernet
loなデバイスはEthernetとは認められないのか。ならば、
root@debian:/tmp# ./a.out : Device: wlp5s0 Number of packets: 10 Filter expression: tcp port 8080 : Packet number 4: From: aa.bb.cc.5 To: aa.bb.cc.6 Protocol: TCP Src port: 59556 Dst port: 8080 Payload (194 bytes): 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 30 0d 0a GET / HTTP/1.0.. 00016 55 73 65 72 2d 41 67 65 6e 74 3a 20 77 33 6d 2f User-Agent: w3m/ :
code
これがdebianで動いた、tcpdumpの原型。コンパイルは、
cc mypc.c -lpcap
mypc.c
#include <stdlib.h> #include<pcap.h> void dump(const unsigned char *data_buffer, const unsigned int length) { unsigned char byte; unsigned int i, j; for (i = 0; i < length; i++) { byte = data_buffer[i]; printf(" %02x", data_buffer[i]); if ((i % 16 == 15) || (i == length - 1)) { for (j = 0; j < 15 - (i % 16); j++) { printf(" "); } printf("| "); for (j = (i - (i % 16)); j <= i; j++) { byte = data_buffer[j]; if ((byte > 31) && (byte < 127)) printf("%c", byte); else printf("."); } printf("\n"); } } } int main() { struct pcap_pkthdr header; const u_char *packet; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t *pcap_handle; int i; char device[] = "lo"; struct bpf_program fp; char filter_exp[] = "port 8080"; bpf_u_int32 mask; bpf_u_int32 net; printf("device = %s\n", device); if (pcap_lookupnet(device, &net, &mask, errbuf) == -1) { fprintf(stderr, "dev: %s netmask: %s\n", device, errbuf); net = 0; mask = 0; } pcap_handle = pcap_open_live(device, 4096, 1, 1000, errbuf); if (pcap_handle == NULL) { printf("error\n"); return 1; } if (pcap_compile(pcap_handle, &fp, filter_exp, 0, net) == -1) { fprintf(stderr, "%s can not analyze: %s\n", filter_exp, pcap_geterr(pcap_handle)); exit(1); } if (pcap_setfilter(pcap_handle, &fp) == -1) { fprintf(stderr, "%s can not inst: %s\n", filter_exp, pcap_geterr(pcap_handle)); exit(1); } for (int i = 0; i < 20; i++) { packet = pcap_next(pcap_handle, &header); printf("packet size = %d\n", header.len); dump(packet, header.len); } pcap_close(pcap_handle); return 0; }