2014-12-04 15 views
5

Próbuję parsować pakiet tcp, a następnie przypisać do wskaźnika do początku ładunku.Parsowanie danych pakietu TCP

Używam C, a to jest mój kod do tej pory:

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; 

    } 

Jestem pewien, że nie ma błędów w tym kodzie, ponieważ numery portów są dziwne. Nikt nie przypisuje wartości 80. Wydana wersja IP również może być naprawdę dziwna (podobnie jak wersja 11). Co ja robię źle? Dzięki!

Również nie jestem pewien, kiedy używać nthos, a kiedy nie. Wiem, że nthos jest dla 16-bitowej liczby całkowitej bez znaku i wiem, że nthol jest dla 32-bitowych liczb całkowitych bez znaku, ale jestem świadomy, że nie zamierzałeś używać ich do wszystkiego w tych pakietach (takich jak: tcp_hdr-> fin). Dlaczego niektóre rzeczy, a nie one?

WIELE DZIĘKI!

EDIT:

Dzięki Sztuka ustalania najbardziej f problemów. Edytowałem moje tcp_hdr i ip_hdr, więc nawiasy są teraz poprawne!

nadal mam 2 problemy:

  • Pierwsze 10 bajty payload'u symbole dziwne (tak myślę, że nie zostały prawidłowo przypisane ładunek).
  • Nadal nie jestem pewien, kiedy użyć nthos/nthol. Wiem, że u_int16_t to ntohs, a u_int32_t to ntohl. Ale co z rzeczami, które są podpisane int lub unisgned krótki int. Na przykład nie użyłem ntohs lub nthol dla ip_v, aby działał. Dlaczego nie? Czy "ip_hdr-> ip_hl" nthol? etc ...

EDIT2

Mam ustalone, dlaczego mój ładunek nie został wyprowadzania poprawnie (to dlatego, że obliczona wielkość TCP_header źle).

Chociaż nadal nie rozumiem, kiedy używać nthos, potraktuję to jako osobne pytanie, ponieważ myślę, że zadałem zbyt wiele pytań na temat tego 1 posta!

When to use ntohs and ntohl in C?

+0

Wiesz, że rzeczy takie jak numery portów są w sieci * * kolejności bajtów? Użyj 'ntohs', aby przekonwertować krótką (16-bitową) wartość z bajtów sieciowych na kolejność bajtów hosta. –

+0

Próbowałem obu, ale dostałem dziwne liczby przez eitehr. Aktualizuję kod teraz! –

+0

Czy są inne pola, które wyglądają poprawnie? Podobnie jak adresy źródłowe/docelowe? Nagłówek ethernetowy? Jak wygląda w porównaniu do tego samego pakietu w np. Wireshark? A ty * czy * otrzymujesz to na surowym gnieździe? A otrzymasz * wszystkie * pakietu? –

Odpowiedz

5

Najprawdopodobniej problem jest tutaj:

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

Doing (struct ip*) data + sizeof(struct ether_header) pierwsze dane rzuca do struct ip *, następnie dodaje sizeof(struct ether_header) do niego, które znamy z arytmetyki wskaźnik nie zrobi tego, co można się spodziewać do zrobienia.

Jeśli problem jest nadal niejasne, oto prosty program, który powinien wskazać we właściwym kierunku:

#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

To naprawiono jak prawie wszystkie moje problemy. Czy nie przeszkadza ci, jeśli odpowiesz na drugą część mojego pytania jako na temat używania ntohs. Moja obecna zasada, którą wymyśliłem, dotyczy wszystkiego, co u_int16_t to ntohs, a u_int32_t to ntohl. Ale co z rzeczami, które są podpisane int lub unisgned krótki int. Na przykład nie użyłem ntohs dla ip_v, żeby działał. Dlaczego nie? Dzięki –

+0

Spójrz na nagłówek ip i definicję. Podstawowa zasada: nie konwertuj wartości o wartości 1B lub mniejszej (ip_v, ip_hl). Używasz ntohs dla wartości 2B (ip_len, ip_p). Używasz ntohl dla wartości 4B. "Ale co z rzeczami, które są podpisane int lub unisgned krótki int": Nie ma znaczenia, czy jest podpisane, czy nie (i nie sądzę, że są jakieś podpisane wartości w ip hdr), więc podpis int jest tylko wartość 4B a unsigned short to wartość 2B. Możesz zobaczyć nagłówek ip tutaj: http://en.wikipedia.org/wiki/IPv4#Header – davak

+0

, więc czekaj "ip_hdr-> ip_hl" użyj htol, ponieważ jest typu "unsigned int ip_hl: 4;" Po dodaniu htola program kończy się przed odczytaniem nagłówka TCP (prawdopodobnie oznaczając, że jego część pamięci nie jest do odczytu). Jednak gdy opuściłem go bez ntohl lub ntohs działało dobrze! –

Powiązane problemy