1

Lets say we have an XML file with packet information

<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>

I can parse this easy with pugiXML or some other XML parser.

What is the approach to generate such packet using pure C++ (get the packet information in the right order) and save it in to a file that is readable by wireshark using function declared in pcap.h?

pcap_dump(dumpfile, header, pkt_data);

u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data;

How am I suppose to fill pkt_data and header using pure 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) */
};

Is there an example of data I am supposed to set in to ts, caplen, len?


EDIT

So after a while of googling I found out this thread on SO.

So I am using those structs to fill my Ethernet -> IP -> TCP packet as following

I am not familiar with types like uint16_t, uint8_t etc.

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(&ethernethdr, 1, sizeof(ethernet_hdr_t), ptr_myfile);
fwrite(&ipp, 1, sizeof(ip_hdr_t), ptr_myfile);
fclose(ptr_myfile);

I am not looking to create packet with payload (data), I am trying to approach pure packet without its data + inspect this packet in wireshark.

Community
  • 1
  • 1
Kyslik
  • 8,217
  • 5
  • 54
  • 87
  • You want to convert the XML packet to a pcap packet? Unless you have the entire binary data/hex dump somewhere not shown in your example, then there's really not enough information to do so. You can create synthetic headers for Ethernet/IP/UDP with the information you got, but there's no data to put in the UDP portion so it's kinda pointless. – imbtfab Mar 31 '14 at 22:35
  • I know there is no data, I am trying to understand how to put packet data into u_char variable (more C thing), but in over all I am trying to understand concept of pcap_pkthdr structure (I know there is a manual file but it is no clear from that) winpcap.org/docs/docs_41b5/html/structpcap__pkthdr.html – Kyslik Mar 31 '14 at 22:48
  • "Ethernet2" If each packet has a different frame type, you can't use pcap, you'd have to use pcap-ng. –  Apr 01 '14 at 00:54
  • it can be either Ethernet or 802.3 – Kyslik Apr 01 '14 at 01:01

1 Answers1

2

You don't really need pcap_dump, you can just open the file yourself and write to it.

sample pcap file header, once per file at the beginning of the file 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);

Sample pcap packet header, once per packet of data 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) Repeat this for every packet you want to write

If you want to use pcap_dump, the first argument is the value returned by pcap_dump_open, the header is the same as pkhdr above, pkt_data is your binary data and the length of that data should match what you specified as pkhdr.len. To have pkt_data point to something meaningful, convert whatever data you have to binary.

EDIT: You don't appear to write the pcap file header anywhere in your example. In addition, you need to read a little bit more about the protocols you're using. I assume you have a reason for using DLT_EN10MB and not LINKTYPE_ETHERNET. I'm not familiar with the former.

For ethernet dst/src, just fill with 0 for testing. I assume you later on want to convert what you have in your XML.

ip_hl is the number of 32 bit words, not bytes, so 20=5. You also didn't specify ip_len which is total number of bytes of IP header+data. If you want to start off by just having an ethernet+IP header and no additional data for testing purpose, you can leave this at 20. Use the htons() functions. For correctness, you'd eventually want to calculate the IP checksum as well.

for x86 think of uint16_t=unsigned short, uint8_t=unsigned char

imbtfab
  • 493
  • 4
  • 10
  • This is what I was looking for, (now I dropped idea of using `pcap_dump()`). Could you also please provide "your_binary_packet" example? – Kyslik Mar 31 '14 at 23:25
  • Lets say I saved file into test.bin (using `fwrite(&pkhdr...)`), I am unable to open the file via wireshark (so I can debug). Any hints? – Kyslik Apr 01 '14 at 00:09
  • creation of your_binary_packet depends entirely of how you have the binary data available and since you show no example of that, I really can't show to convert it. Your failed file, did you also write the pcap file header? How did you provide your data? – imbtfab Apr 01 '14 at 08:57
  • See edit. It's not hard to do, just requires you to be precise in what you're doing. – imbtfab Apr 01 '14 at 15:14
  • I am using DLT_EN10MB because LINKTYPE_ETHERNET is "undefined" I dont know why, so I googled around and this is equivalent http://www.tcpdump.org/linktypes.html . But please inspect again I am writing `pcap_hdr_t pcaphdr;` into file which is by inspection "pcap file header" didnt you mean "pcap packet header"? As for macaddress src | dsc I tried filling it as 0, but whenever I open my test.pcap file I get errors: File is corrupted, network type 16777216 unknown or unsupported... I never managed to open file correctly in wireshark, I can not debug correctly. I am not C man. – Kyslik Apr 01 '14 at 18:05
  • You need to use htons/htonl functions before setting the variables. It's using network/big endian byte order. `ethernethdr.type = htons(0x800);` You write pcaphdr which is supposed to be one per file, but your code lacks writing of the header per packet, called pkhdr in my post. – imbtfab Apr 01 '14 at 20:07
  • Alright, so in order I have to write in to file in order "pcap file header" => header packet => frame (ethernet) => IP protocol => TCP? When I open up wireshark and capture few TCP packets it is in order as I wrote. htons(0x800) doesnt changes a thing same error `network type 16777216 unknown or unsupported`, but I think I am writing in to file some bytes I dont need or in bad order or so therefore there is that error. – Kyslik Apr 01 '14 at 20:44
  • Correct. If you can upload your result file somewhere, like dropbox or filebin I can have a look at it. I already have code reading pcap files and decoding the protocol data. – imbtfab Apr 01 '14 at 21:27
  • Ill upload it somewhere. The file itself is not valid I guess https://www.dropbox.com/sh/8g997ugxejushjq/akGlhtgmnT – Kyslik Apr 01 '14 at 21:32
  • 1
    I'm not sure where to begin, fh.magic needs to be 0xa1b2c3d4, otherwise all other members must be swapped as well. It doesn't matter if you're on windows or not, wireshark supports both, it just needs to be consistent. The file header appears otherwise ok. There doesn't appear to be a valid packet header in the file, or if you wrote one, you didn't set caplen=len, but even reading caplen bytes doesn't work, so it's probably missing since there's only 12 bytes left in the file after reading the headers. LINKTYPE_ETHERNET is defined as 1 btw. – imbtfab Apr 01 '14 at 22:08
  • Perhaps if you go about this a little bit differently. Use wireshark to generate a pcap file with just one message in it, then write a short program to read the file header, then packet header, then the data. Then you can inspect what the headers look like in a proper file, and having the code to read that should make it easier to write the same. – imbtfab Apr 01 '14 at 22:11
  • Thank you for input I will do that, yes LINKTYPE_ETHERNET is 1 as same as DLT_EN10MB. – Kyslik Apr 01 '14 at 23:54