시스템 호출에서 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 호출 중 하나에 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아래 두 번째 명령에 사용되는 것과 같은 일부 특수 문자의 경우)으로 표시할 수 없는 바이트 값을 나타냅니다. printf예시 보기위키피디아 참조이에:

\nnn 그 값은 nnn주어진 바이트로 해석 됩니다.8진수

우리가 찾고 있는 것이 무엇인지 알고 있으므로(8진수):

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

이는 두 번째 데이터의 끝 부분에서 볼 수 있습니다 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 응답입니다. 여기서 \03428은 AAAAIPv6 레코드(RFC 3596 - 2.1 AAAA 레코드 유형A) IPv4 레코드의 경우 1 대신 .

관련 정보