Допустим, у нас есть файл XML с информацией о пакете
<packet>
<frame_type>Ethernet</frame_type>
<local_mac_address>00-21-85-11-29-1b</local_mac_address>
<remote_mac_address>ff-ff-ff-ff-ff</remote_mac_address>
<protocol>IP</protocol>
<version>4</version>
<local_address>147.175.106.141</local_address>
<remote_address>255.255.255.255</remote_address>
<protocol_type>UDP</protocol_type>
<protocol>UDP</protocol>
<local_port>17500</local_port>
<remote_port>17500</remote_port>
<service_name></service_name>
<packets>8</packets>
</packet>
Я могу разобрать это легко с pugiXML или другим анализатором XML.
Каков подход для генерации такого пакета с использованием чистого C ++ (получить информацию о пакете в правильном порядке) и сохранить его в файле, который можно прочитать с помощью wireshark, используя функцию, объявленную в pcap.h?
pcap_dump(dumpfile, header, pkt_data);
u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data;
Как я полагаю заполнить pkt_data
а также header
используя чистый C ++?
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
Есть ли пример данных, которые я должен установить в ts
, caplen
, len
?
РЕДАКТИРОВАТЬ
Итак, после некоторого времени поиска в Google я узнал это нить на ТАК.
Поэтому я использую эти структуры, чтобы заполнить мой пакет Ethernet -> IP -> TCP следующим образом
Я не знаком с такими типами, как uint16_t, uint8_t и т. Д.
pcap_hdr_t pcaphdr;
pcaphdr.magic_number = 0xd4c3b2a1; //0xa1b2c3d4 || 0xd4c3b2a1 <- i am on winwows (Little endian)
pcaphdr.sigfigs = 0;
pcaphdr.version_major = 2;
pcaphdr.version_minor = 4;
pcaphdr.snaplen = 65536;
pcaphdr.thiszone = 0;
pcaphdr.network = DLT_EN10MB;
ethernet_hdr_t ethernethdr;
ethernethdr.dst = ??; // I have no clue how to fill this either ...dst[0] = 0xFF? type is uint8_t.
ethernethdr.src = ??;//same as above
ethernethdr.type = 2048; //? //(I want to use IP = 0x800), it is uint16_t
//and for IP
ip_hdr_t ipp;
ipp.ip_dst = parseIPV4string(ipAddressString); //this function converts string into uint32_t
ipp.ip_src = parseIPV4string(ipAddressString);
ipp.ip_v = 4; //version
ipp.ip_hl = 20; //header length
ipp.ip_id = 12758; //id whatever id
ipp.ip_ttl = 125; //time to live
ipp.ip_p = 6; //protocol 6 = TCP
ipp.ip_off = 0;
ipp.ip_tos = 0;
//and save all this by
FILE *ptr_myfile;
ptr_myfile=fopen("test.pcap", "wb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
fwrite(&pcaphdr, 1, sizeof(pcap_hdr_t), ptr_myfile);
fwrite(ðernethdr, 1, sizeof(ethernet_hdr_t), ptr_myfile);
fwrite(&ipp, 1, sizeof(ip_hdr_t), ptr_myfile);
fclose(ptr_myfile);
Я не собираюсь создавать пакет с полезной нагрузкой (данными), я пытаюсь подойти к чистому пакету без его данных + проверить этот пакет в wireshark.
Вам не нужен pcap_dump, вы можете просто открыть файл и написать в него.
Пример заголовка файла pcap, один раз на файл в начале файла
struct pcap_file_header fh;
fh.magic = TCPDUMP_MAGIC;
fh.sigfigs = 0;
fh.version_major = 2;
fh.version_minor = 4;
fh.snaplen = USHRT_MAX;
fh.thiszone = 0;
fh.linktype = LINKTYPE_ETHERNET;
fwrite(&fh, sizeof(fh), 1, file);
Пример заголовка пакета pcap, один раз на пакет данных
Повторите это для каждого пакета, который вы хотите написать
struct pcap_pkthdr pkhdr;
pkhdr.len = pkhdr.caplen = your_content_length;
pkhdr.ts.tv_sec = 1396306094; // Some unix timestamp
fwrite(&pkhdr, sizeof(pkhdr), 1, file);
fwrite(your_binary_packet, your_content_length, 1, file)
Если вы хотите использовать pcap_dump, первый аргумент — это значение, возвращаемое pcap_dump_open, заголовок такой же, как pkhdr выше, pkt_data — ваши двоичные данные, и длина этих данных должна соответствовать той, которую вы указали как pkhdr.len. Чтобы pkt_data указывала на что-то значимое, конвертируйте любые данные в двоичный.
РЕДАКТИРОВАТЬ:
Похоже, вы нигде не пишете заголовок файла pcap в вашем примере. Кроме того, вам нужно прочитать немного больше о протоколах, которые вы используете. Я предполагаю, что у вас есть причина для использования DLT_EN10MB, а не LINKTYPE_ETHERNET. Я не знаком с первым.
Для ethernet dst / src просто заполните 0 для тестирования. Я предполагаю, что вы позже захотите преобразовать то, что у вас есть в ваш XML.
ip_hl — это число 32-битных слов, а не байтов, поэтому 20 = 5. Вы также не указали ip_len — общее количество байтов заголовка IP + данные. Если вы хотите начать с простого заголовка ethernet + IP и отсутствия дополнительных данных для целей тестирования, вы можете оставить это на 20. Используйте функции htons (). Для правильности вы в конечном итоге захотите также рассчитать контрольную сумму IP.
для x86 подумайте о uint16_t = unsigned short, uint8_t = unsigned char
Других решений пока нет …