заголовок и флаги tcp - PullRequest
       46

заголовок и флаги tcp

0 голосов
/ 29 марта 2012

Я недавно начал писать анализатор пакетов, используя библиотеки и заголовочные файлы libpcap & linux, такие как netinet / tcp.h. Проблема заключается в следующем: когда я получаю заголовок tcp, используя TH_OFF (tcp) * 4, его значение часто составляет менее 20 байтов. Хорошо, я знаю, это неправильно сформировано, но Wireshark отображает другое значение (20 <). То же самое происходит с флагами. </p>

Вот код:

struct nread_tcp {
    u_short th_sport; /* source port            */
    u_short th_dport; /* destination port       */
    u_short th_seq;   /* sequence number        */
    u_short th_ack;   /* acknowledgement number */
#if BYTE_ORDER == LITTLE_ENDIAN
    u_int th_x2:4,    /* (unused)    */
    th_off:4;         /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
    u_int th_off:4,   /* data offset */
    th_x2:4;          /* (unused)    */
#endif
    u_char th_flags;
#define TH_FIN      0x01
#define TH_SYN      0x02
#define TH_RST      0x04
#define TH_PUSH     0x08
#define TH_ACK      0x10
#define TH_URG      0x20
#define TH_ECE      0x40
#define TH_CWR      0x80

#define TH_NS       0x100
#define TH_RS       0xE00

    u_short th_win; /* window */
    u_short th_sum; /* checksum */
    u_short th_urp; /* urgent pointer */
u_char  th_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
};

const struct nread_tcp* tcp = (struct nread_tcp*)(pachet + sizeof(struct ether_header) + sizeof(struct crt_ip));

...
int hlen = TH_OFF(tcp)*4;

char * tmp = new char[strlen("000000000000")+1];
    strcpy(tmp,"000000000000");

    if (tcp->th_flags & TH_NS){
        tmp[3] = '1';
        }
    else
        tmp[3] = '0';


    if (tcp->th_flags & TH_ECE){
        tmp[4] = '1';
        }
    else
        tmp[4] = '0';

    if (tcp->th_flags & TH_CWR){
        tmp[5] = '1';
        }
    else
        tmp[5] = '0';

    if (tcp->th_flags & TH_URG){
        tmp[6] = '1';
        }
    else
        tmp[6] = '0';

    if (tcp->th_flags & TH_ACK){
        tmp[7] = '1';
        }
    else
        tmp[7] = '0';

    if (tcp->th_flags & TH_PUSH){
        tmp[8] = '1';
        }
    else
        tmp[8] = '0';

    if (tcp->th_flags & TH_RST){
        tmp[9] = '1';
        }
    else
        tmp[9] = '0';

    if (tcp->th_flags & TH_SYN){
        tmp[10] = '1';
        }
    else
        tmp[10] = '0';

    if (tcp->th_flags & TH_FIN){
        tmp[11] = '1';
        }
    else
        tmp[11] = '0';

Я немного погуглил и не нашел ничего полезного. Может быть, это ошибка еще одного новичка, но я не могу понять это. Заранее спасибо.


Еще раз спасибо за советы / идеи.

Все функции обработки pcap, включая обработку заголовков канального уровня, корректны. Мое приложение написано в Qt 4.7.4. Позвольте мне дать вам больше информации о моей логике. Возможно, я m using pointers that are not pointing correctly. I wish to emphasize the fact that tcp is the only protocol with this issue. The others that I m подробно анализирую заголовок кадра Ethernet, заголовок IP, заголовок UDP, заголовок ARP / RARP и заголовок ICMP. Что касается логики, это выглядит так: У меня есть нить, которую слушает ведьма
-pcap_loop (captureHandler, -1, packetHandler, (беззнаковый символ *) дамп-файл); PackageHandler находится в отдельном .cpp с именем "engine.cpp" В этом .cpp у меня есть интерпретатор пакетов, который, в соответствии с типом протокола, создает правильный класс (tcpPacketHandler для протокола tcp). Моя структура tcp объявлена ​​в engine.h (не в заголовке tcpPacketHandler). Структура tcp - та, которая размещена в моем первоначальном вопросе. Конструктор tcpPacketHandler выглядит следующим образом:

tcpPacketHandler::tcpPacketHandler(u_char *arg, const pcap_pkthdr * header,const u_char * pachet)
{

    (void)arg;
    (void)header;

    const struct nread_tcp* tcp = (struct nread_tcp*)(pachet + sizeof(struct ether_header) + sizeof(struct crt_ip));
    //fprintf(stdout,"\nSEQUENCE NUMBER %u \nACK %u \nWINDOW %u\nURGENT POINTER %u\n", tcp->th_seq, tcp->th_ack, tcp->th_win,tcp->th_urp);

    //qDebug() <<sizeof(struct ether_header)<< "  "<< sizeof(struct crt_ip);
    this->seqNr                 = ntohs(tcp->th_seq);
    this->ackNr                 = ntohs(tcp->th_ack);
    this->window                = ntohs(tcp->th_win);
    this->urgentPointer         = ntohs(tcp->th_urp);
    this->portSursa             = ntohs(tcp->th_sport);
    this->portDestinatie        = ntohs(tcp->th_dport);
    this->checksum              = ntohs(tcp->th_sum);


    char * tmp = new char[strlen("000000000000")+1];
    strcpy(tmp,"000000000000");

    if (tcp->th_flags & TH_NS){
        tmp[3] = '1';
        }
    else
        tmp[3] = '0';


    if (tcp->th_flags & TH_ECE){
        tmp[4] = '1';
        }
    else
        tmp[4] = '0';

    if (tcp->th_flags & TH_CWR){
        tmp[5] = '1';
        }
    else
        tmp[5] = '0';

    if (tcp->th_flags & TH_URG){
        tmp[6] = '1';
        }
    else
        tmp[6] = '0';

    if (tcp->th_flags & TH_ACK){
        tmp[7] = '1';
        }
    else
        tmp[7] = '0';

    if (tcp->th_flags & TH_PUSH){
        tmp[8] = '1';
        }
    else
        tmp[8] = '0';

    if (tcp->th_flags & TH_RST){
        tmp[9] = '1';
        }
    else
        tmp[9] = '0';

    if (tcp->th_flags & TH_SYN){
        tmp[10] = '1';
        }
    else
        tmp[10] = '0';

    if (tcp->th_flags & TH_FIN){
        tmp[11] = '1';
        }
    else
        tmp[11] = '0';

    this->hdrLen = TH_OFF(tcp)*4;
   // qDebug() << this->hdrLen;

    this->flags = new char[13];
    strcpy(this->flags,tmp);

    if(tmp)
    {
        delete [] tmp;
        tmp = NULL;
    }


}

Все поля заголовка tcp отображаются правильно, пока я не нажму "поле смещения данных"

#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)

С этого момента оставшиеся данные заголовка tcp не соответствуют результату Wireshark (Смещение данных, Флаги и Полезная нагрузка).

Возможно, проблема в том, что структура nread_tcp объявлена ​​в файле, который используется несколькими пакетами, и указатель работает неправильно при захвате большого количества пакетов за короткий промежуток времени. Я действительно понятия не имею. Все, что я нашел в Google, использует эту структуру, но у меня нет проблемы в моем коде. И в качестве второго вопроса: может ли функция packetHandler (из функции pcap_loop) быть объявлена ​​членом класса? (потому что я заметил, что у него нет типа, и когда я попытался сделать его членом класса, компилятор выдал мне ошибку).

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 15 июня 2016

Вот что у меня сработало.

u_short th_seq;   /* sequence number        */
u_short th_ack;   /* acknowledgement number */

Изменено на:

u_int th_seq;   /* sequence number        */
u_int th_ack;   /* acknowledgement number */
0 голосов
/ 29 марта 2012

Нет поля смещения данных в заголовке TCP после указателя срочности; заголовок TCP имеет опции после указателя срочности.Вместо этого удалите

#if BYTE_ORDER == LITTLE_ENDIAN
    u_int th_x2:4,    /* (unused)    */
    th_off:4;         /* data offset */
#endif
#if BYTE_ORDER == BIG_ENDIAN
    u_int th_off:4,   /* data offset */
    th_x2:4;          /* (unused)    */
#endif

из вашей структуры и переместите

u_char  th_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)

вверх, чтобы заменить его, чтобы структура выглядела как

struct nread_tcp {
    u_short th_sport; /* source port            */
    u_short th_dport; /* destination port       */
    u_short th_seq;   /* sequence number        */
    u_short th_ack;   /* acknowledgement number */
    u_char  th_offx2; /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
    u_char  th_flags;
#define TH_FIN      0x01
#define TH_SYN      0x02
#define TH_RST      0x04
#define TH_PUSH     0x08
#define TH_ACK      0x10
#define TH_URG      0x20
#define TH_ECE      0x40
#define TH_CWR      0x80

#define TH_NS       0x100
#define TH_RS       0xE00

    u_short th_win; /* window */
    u_short th_sum; /* checksum */
    u_short th_urp; /* urgent pointer */
};

и перекомпилируйте вашу программуи посмотрите, работает ли это.

...