2014-12-04 2 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:

Благодаря Art для фиксации наиболее е проблемы. Я редактировал мои tcp_hdr и ip_hdr, поэтому скобки теперь правильные!

у меня еще есть 2 проблемы:

  • Первые 10 байт полезной нагрузки имеет странные символы (так что я думаю, что не назначили полезной нагрузки правильно).
  • Я до сих пор не знаю, когда использовать nthos/nthol. Я знаю, что u_int16_t - это ntohs, а u_int32_t - ntohl. Но как насчет вещей, которые подписали int или unisgned short int. Например, я не использовал ntohs или nthol для ip_v, чтобы он работал. Почему нет? Является ли «ip_hdr-> ip_hl» nthol? и т.д ...

EDIT2

Я установил, почему моя полезная нагрузка не выводя правильно (это потому, что я вычислил размер TCP_header неправильно).

Хотя я все еще смущен, когда использовать nthos, я поставил это как отдельный вопрос, так как я думаю, что я задал слишком много вопросов на этом 1 сообщении!

When to use ntohs and ntohl in C?

+0

Вы знаете, что такие вещи, как номера портов в сетевом порядке * * байт? Используйте 'ntohs' для преобразования короткого (16-разрядного) значения из сетевого байтового порядка в хост-порядок байтов. –

+0

Я попробовал оба, но получил странные цифры для eitehr. Обновление кода в любом случае! –

+0

Есть ли другие поля, которые выглядят правильно? Как адреса источника/назначения? Заголовок ethernet? Как это выглядит по сравнению с одним и тем же пакетом, например. Wireshark? И вы * делаете * получаете это на сырой розетке? И получите * все * пакета? –

ответ

5

Скорее всего, ваша проблема здесь:

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

Ведение (struct ip*) data + sizeof(struct ether_header) первых данных слепков к struct ip *, а затем добавляет 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

Thats исправлено, как почти все мои проблемы. Не возражаете, если вы также ответите на вторую часть моего вопроса, как когда использовать ntohs. Мое текущее правило, которое я составил, для любого типа u_int16_t - это ntohs, а u_int32_t - ntohl. Но как насчет вещей, которые подписали int или unisgned short int. Например, я не использовал ntohs для ip_v, чтобы он работал. Почему нет? Спасибо –

+0

Посмотрите на заголовок ip и определение. Основное правило: вы не конвертируете значения 1B или более короткие (ip_v, ip_hl). Вы используете ntohs для значений 2B (ip_len, ip_p). Вы используете ntohl для значений 4B. «Но что относительно вещей, которые были подписаны int или unisgned short int»: на самом деле не имеет значения, подписан ли он или нет (и я не думаю, что есть какие-либо подписанные значения в ip hdr), поэтому подписанный int является всего лишь значением 4B и unsigned short - значение 2B. Вы можете увидеть IP-заголовок здесь: http://en.wikipedia.org/wiki/IPv4#Header – davak

+0

, поэтому подождите, «ip_hdr-> ip_hl» использует htol, тогда как он имеет тип «unsigned int ip_hl: 4;» Когда я добавил htol, программа прекращает работу даже перед чтением заголовка TCP (возможно, это означает, что чтение части памяти не предполагается). Однако, когда я оставил его без ntohl или ntohs, он работал нормально! –

Смежные вопросы