2014-12-04 5 views
5

tcp 패킷을 구문 분석하고 페이로드 시작 포인터를 할당하려고합니다.TCP 패킷 데이터 구문 분석

나는 C를 사용하고이 지금까지 내 코드입니다 :

void dump(const unsigned char *data, int length) { //*data contains the raw packet data 
    unsigned int i; 
    static unsigned long pcount = 0; 

    // Decode Packet Header 
    struct ether_header *eth_header = (struct ether_header *) data; 

    printf("\n\n === PACKET %ld HEADER ===\n", pcount); 

    printf("\nSource MAC: "); 
    for (i = 0; i < 6; ++i) { 
     printf("%02x", eth_header->ether_shost[i]); //? Why don't i use nthos here? 
     if (i < 5) printf(":"); 
    } 

    unsigned short ethernet_type = ntohs(eth_header->ether_type); 
    printf("\nType: %hu\n", ethernet_type); 

    if (ethernet_type == ETHERTYPE_IP) { //IP Header 
     printf("\n == IP HEADER ==\n"); 
     struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header); 
     unsigned int size_ip = ip_hdr->ip_hl * 4; 
     printf("\nIP Version: %u", ip_hdr->ip_v); //? Nthos or no nthos 
     printf("\nHeader Length: %u", ip_hdr->ip_hl); //? Nthos or no nthos 
     printf("\nTotal Length: %hu", ntohs(ip_hdr->ip_len)); //? Nthos or no nthos 

     // TCP Header 
     printf("\n== TCP HEADER ==\n"); 
     struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip; 
     printf("\n Source Port: %" PRIu16, nthos(tcp_hdr->th_sport)); 
     printf("\n Destination Port: %" PRIu16, nthos(tcp_hdr->th_dport)); 
     printf("\n fin: %" PRIu16, tcp_hdr->fin); 
     printf("\n urg: %" PRIu16, tcp_hdr->urg); 
     printf("\n ack_seq: %" PRIu32, ntohl(tcp_hdr->ack_seq)); 

     //Transport payload! i.e. rest of the data 
     const unsigned char *payload = data + ETH_HLEN + size_ip + sizeof(struct tcphdr) + tcp_hdr->doff; 

    } 

내가 포트 번호가 모두 이상한 때문에이 코드에서 실수가 확신합니다. 단 하나도 80에 배정되지 않습니다. 출력 된 IP 버전은 (버전 11과 같이) 정말 이상 할 수도 있습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 감사!

또한 nthos를 사용할 때와 사용하지 않을 때 나는 확신이 없습니다. nthos는 16 비트 부호없는 정수이고 nthol은 32 비트 부호없는 정수임을 알고 있습니다. 그러나이 패킷 (tcp_hdr-> fin과 같은)에있는 모든 것에 사용할 필요는 없습니다. 왜 특정 것들이 아닌가?

많은 감사!

EDIT :

감사 아트 문제점 F 최대한 고정. 내 tcp_hdr 및 ip_hdr을 편집하여 대괄호가 올바르게되었습니다!

  • 페이로드의 처음 10 바이트 (그래서 내가 제대로 페이로드를 지정하지 않은 생각) 이상한 문자가 있습니다

    나는 여전히이 문제가있다.

  • nthos/nthol을 사용할 때는 여전히 확실하지 않습니다. 나는 u_int16_t가 ntohs이고 u_int32_t가 ntohl이라는 것을 알고 있습니다. 그러나 int intis 또는 unisgned short int에 사인되는 것은 어떨까요? 예를 들어, ip_v에 ntohs 나 nthol을 사용하지 않았습니다. 왜 안돼? "ip_hdr-> ip_hl"이 (가) nthol입니까? 등 ... 내 페이로드 (필자는 TCP_header 크기가 잘못 계산하기 때문에 그것의)가 제대로 출력되지 않은 이유를 내가 해결 한 EDIT2

.

나는 nthos를 언제 사용하는지 혼란 스럽지만 나는 이것을 1 개의 게시물에 대해 너무 많은 질문을했다.

When to use ntohs and ntohl in C?

+0

당신은 알고 포트 번호와 같은 일이 * 네트워크 * 바이트 순서에 있는지가? 네트워크 바이트 순서에서 호스트 바이트 순서로 짧은 (16 비트) 값을 변환하려면'ntohs '를 사용하십시오. –

+0

나는 둘 다 시도했지만 eitehr에 이상한 번호를 얻었다. 이제 코드를 업데이트하는 중! –

+0

다른 모양이 올바른가요? 출발지/목적지 주소와 비슷합니까? 이더넷 헤더? 예를 들어, 동일한 패킷과 비교하여 어떻게 보입니까? 와이 샤크? 그리고 원시 소켓에서 이것을 받습니까? 그리고 패킷의 * all *을 받습니까? –

답변

5

는 대부분의 경우 문제가 여기에 있습니다 : struct ip *(struct ip*) data + sizeof(struct ether_header) 첫번째 캐스트 데이터를 수행

struct ip *ip_hdr = (struct ip*) data + sizeof(struct ether_header); 
struct tcphdr *tcp_hdr = (struct tcphdr*) data + sizeof(struct ether_header) + size_ip; 

, 당신이 그것을 기대하지 않을 것이다 우리가 포인터를 arithmetics 알고 그것에 sizeof(struct ether_header)을 추가 할 것.

문제가 여전히 불분명, 여기에 올바른 방향을 가리켜 야하는 간단한 프로그램입니다 :

#include <stdio.h> 

struct foo { 
    int a, b; 
}; 

int 
main(int argc, char **argv) 
{ 
    char *x = NULL; 

    printf("%p\n", x); 
    printf("%p\n", (struct foo *)x + 4); 
    printf("%p\n", (struct foo *)(x + 4)); 

    return 0; 
} 
+0

그게 전부 내 문제처럼 고정. ntohs를 사용할 때와 같이 제 질문의 두 번째 부분에 대해서도 대답 해 주시겠습니까? 내가 만든 현재 규칙은 u_int16_t 유형의 모든 것이 ntohs이고 u_int32_t가 ntohl입니다. 그러나 int intis 또는 unisgned short int에 사인되는 것은 어떨까요? 예를 들어, ip_v를 작동시키기 위해 ntohs를 사용하지 않았습니다. 왜 안돼? 감사합니다 –

+0

IP 헤더와 정의를보십시오. 기본 규칙 : 1B 이하의 값 (ip_v, ip_hl)은 변환하지 않습니다. 2B 값 (ip_len, ip_p)에 ntohs를 사용합니다. 4B 값에는 ntohl을 사용합니다. "하지만 int 또는 unisgned short int에 서명하는 것은 어떨까요?": 서명 여부에 상관없이 (서명 된 값이 IP hdr에 있다고 생각하지 않습니다.) 서명 된 int는 단지 4B 값입니다. 부호없는 short는 2B 값입니다. 여기서 ip 헤더를 볼 수 있습니다 : http://en.wikipedia.org/wiki/IPv4#Header – davak

+0

그래서 "ip_hdr-> ip_hl"은 "unsigned int ip_hl : 4;"유형이므로 htol을 사용합니다. htol을 추가하면 프로그램이 TCP 헤더를 읽지 않고도 종료됩니다. 아마도 TCP 헤더를 읽는 것입니다. 그러나 내가 그것을 ntohl 또는 ntohs없이 남겨 두었을 때 그것은 잘 움직였다! –