システムコールでstrace recvを解析する方法は?

システムコールでstrace recvを解析する方法は?

カールコマンドを追跡しました。

strace -s 2000 -f curl google.com

2つのDNSクエリを参照してください。

recvfrom(3, "\302\325\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\6google\3com\0\0\34\0\1\0\0\0\362\0\20*\0\24P@\t\10\v\0\0\0\0\0\0 \16", 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.65.7")}, [28->16]) = 66
recvfrom(3, "X\320\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\6google\3com\0\0\1\0\1\0\0\1)\0\4\216\372\263\356", 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.65.7")}, [28->16]) = 54

次に、GoogleのIPである142.250.179.238へのconnect()システムコールを表示します。

connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("142.250.179.238")}, 16) = 0

私は2つのrecvfrom呼び出しのうちの1つにIP "142.250.179.238"が含まれていると思います。それ以外の場合、カールはどのIPに接続するかを知ることができません。

私の質問:2つのrecvfrom文字列の形式は何ですか?そして、IPアドレスを取得するためにこれを解析する方法は?

"\302\325\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\6google\3com\0\0\34\0\1\0\0\0\362\0\20*\0\24P@\t\10\v\0\0\0\0\0\0 \16"
"X\320\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\6google\3com\0\0\1\0\1\0\0\1)\0\4\216\372\263\356"

答え1

recvfrom(2)次のように文書化されています(以下のLinuxのマニュアルページを使用)。

  ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len,
                   int flags,
                   struct sockaddr *_Nullable restrict src_addr,
                   socklen_t *_Nullable restrict addrlen);

またはもっと簡単にPOSIX定義:

  ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
      int flags, struct sockaddr *restrict address,
      socklen_t *restrict address_len);

出力を理解するには、strace各システムコールのマニュアルページを読んでください。

バッファ/バッファは、システムコールの成功後に受信したデータを提供する空間で、straceCと同様の方法でその内容を再表示します。

バッファスペースは、Cのようにエンコードされたバイトシーケンスで表され、で表示されるバッファまたは文字列と同じですstrace。その後に\3桁の数字が来ると8進数数値は、単純なASCII文字またはC言語で定義されている事前定義された特殊デフォルト表示形式(\n以下の2番目のコマンドで使用されるような特殊文字の一部)では表示できないバイト値を表します。printf例を見るウィキペディアリファレンスこれで:

\nnn その値はnnn与えられたバイトとして解釈されます。8進数

私たちが探しているものが何であるかを知っているので(8進数):

$ printf '\\%o' 142 250 179 238; printf '\n'
\216\372\263\356

これは2番目のデータの終わりにありますrecvfrom()

もちろん、これはもはやシステムコールに関するものではなく、DNSプロトコルに関するものです。 DNS応答の詳細については、特にこれについて説明するRFCをお読みください。RFC 1035:ドメイン名 - 実装と仕様セクション4.1.3。リソースレコード形式:

Each resource record has the following format:
                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                                               /
    /                      NAME                     /
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     CLASS                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      TTL                      |
    |                                               |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   RDLENGTH                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
    /                     RDATA                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

各部分はこのRFCで説明されています(ここではRDLENGTH = 4で、RDATAは4バイトのIPv4アドレスを保持しています)。

FWIW、受信した最初の応答はIPv6応答です。ここで\034、28はAAAAIPv6レコード(RFC 3596 - 2.1 AAAAレコードタイプA)IPv4レコードの場合1の代わりに。

関連情報