C - Запись структур в файл (.pcap) - PullRequest
10 голосов
/ 05 сентября 2011

Я пытаюсь написать файл .pcap, который можно использовать в Wireshark. Для этого у меня есть пара структур с различными типами данных, которые мне нужно записать в файл. (см. код)

Итак, я создаю экземпляры структуры, заполняю данные, использую FILE * fp = fopen ("test.pcap", "w"), а затем не уверен, как правильно записать его в файл. Я считаю, что я должен использовать memcpy, но я не уверен, что это лучший способ сделать это. В прошлом я в основном прибегал к библиотекам C ++, чтобы сделать это. Есть предложения?

typedef struct pcap_hdr_s {
        uint32_t magic_number;   /* magic number */
        uint16_t version_major;  /* major version number */
        uint16_t version_minor;  /* minor version number */
        int32_t  thiszone;       /* GMT to local correction */
        uint32_t sigfigs;        /* accuracy of timestamps */
        uint32_t snaplen;        /* max length of captured packets, in octets */
        uint32_t network;        /* data link type */
} pcap_hdr_t;

typedef struct pcaprec_hdr_s {
   uint32_t ts_sec;         /* timestamp seconds */
   uint32_t ts_usec;        /* timestamp microseconds */
   uint32_t incl_len;       /* number of octets of packet saved in file */
   uint32_t orig_len;       /* actual length of packet */
} pcaprec_hdr_t;

typedef struct ethernet_hdr_s {
   uint8_t dst[6];    /* destination host address */
   uint8_t src[6];    /* source host address */
   uint16_t type;     /* IP? ARP? RARP? etc */
} ethernet_hdr_t;

typedef struct ip_hdr_s {
   uint8_t  ip_hl:4, /* both fields are 4 bits */
            ip_v:4;
   uint8_t        ip_tos;
   uint16_t       ip_len;
   uint16_t       ip_id;
   uint16_t       ip_off;
   uint8_t        ip_ttl;
   uint8_t        ip_p;
   uint16_t       ip_sum;
   uint32_t ip_src;
   uint32_t ip_dst;
}ip_hdr_t;

typedef struct udp_header
{
  uint16_t src;
  uint16_t dst;
  uint16_t length;
  uint16_t checksum;
} udp_header_t;

Ответы [ 3 ]

16 голосов
/ 17 февраля 2012

Используйте libpcap или WinPcap - pcap_open_dead(), чтобы получить «подделку» pcap_t для использования с pcap_dump_open(), чтобы указать тип заголовка канального уровня (для Ethernet используйте DLT_EN10MB) и длину снимка (используйте 65535), pcap_dump_open(), чтобы открыть файл для записи, pcap_dump(), чтобы выписать пакет, и pcap_dump_close(), чтобы закрыть файл. НАМНОГО проще, чем напрямую с помощью fopen(), fwrite() и fclose() (именно это libpcap / WinPcap использует "под капотом").

И да, у вас естьчтобы получить порядок байтов в пакетах правильно.Порядок байтов зависит от протокола;для поля type в заголовке Ethernet и для всех многобайтовых полей в заголовках IP, TCP и UDP они должны быть в порядке с прямым порядком байтов.(Магическое число в файле pcap не имеет к этому отношения - оно указывает только порядок байтов полей в заголовке файла и заголовке записи для пакета, NOT порядок байтов полей в пакетеКроме того, благодаря тому, как это реализовано в Linux, метаданные в начале пакетов в Linux USB перехватывают. Предполагается, что пакетные данные будут выглядеть точно так же, как и «по проводам».)

4 голосов
/ 05 сентября 2011

Используйте fwrite () . Вам нужно проверить эту информацию, но я думаю, что .pcap файлы записаны в режиме binary .

Пример:

pcaprec_hdr_t pcaprec_hdr;
// fill pcaprec_hdr with valid info

FILE* pFile = NULL;
pFile = fopen ("myfile.pcap" , "wb"); // open for writing in binary mode

fwrite (&pcaprec_hdr, 1, sizeof(pcaprec_hdr_t) , pFile);

fclose(pFile);
2 голосов
/ 31 июля 2015

Вот мое понимание того, что предлагает Гай Харрис. Итак, по запросу Кислика имеем:

#include <libpcap/pcap.h>

/* Ethernet/IP/SCTP INIT chunk */
static const unsigned char pkt1[82] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, /* ......E. */
  0x00, 0x44, 0x55, 0xb1, 0x00, 0x00, 0x40, 0x84, /* .DU...@. */
  0x26, 0x83, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, /* &....... */
  0x00, 0x01, 0x00, 0x01, 0x1f, 0x90, 0x00, 0x00, /* ........ */
  0x00, 0x00, 0x68, 0xe5, 0x88, 0x1b, 0x01, 0x00, /* ..h..... */
  0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, /* .$...... */
  0xa0, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x00, /* ........ */
  0x16, 0x2e, 0x80, 0x00, 0x00, 0x04, 0xc0, 0x00, /* ........ */
  0x00, 0x04, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x05, /* ........ */
  0x00, 0x00                                      /* .. */
};


int main(int argc, char *argv[]) {

  pcap_t *handle = pcap_open_dead(DLT_EN10MB, 1 << 16);
  pcap_dumper_t *dumper = pcap_dump_open(handle, "/tmp/pktcap/cap.pcap");

  struct pcap_pkthdr pcap_hdr;
  pcap_hdr.caplen = sizeof(pkt1);
  pcap_hdr.len = pcap_hdr.caplen;

  pcap_dump((u_char *)dumper, &pcap_hdr, pkt1);
  pcap_dump_close(dumper);

  return 0;
}
...