-1

I am writing a pcap file in c++ without using libpcap library. The packet structures are correct. But I see that the length of IP Packet is wrong, and hencec the rest of the protocols are not shown. Error is shown in the attached 'pcap file error image' file. I have searched libpcap format wireshark etc...But I don't see a solution to my problem.

pcap file error image

Here is my code

 int iWritePcapHeader(){  


        pcap_global_header_s.magic_number =  0xa1b2c3d4 ;
        pcap_global_header_s.version_major = PCAP_VERSION_MAJOR ;
        pcap_global_header_s.version_minor = PCAP_VERSION_MINOR;
        pcap_global_header_s.thiszone = 0; // check here if timestamps of packets are not correct
        pcap_global_header_s.sigfigs = 0;
        pcap_global_header_s.snaplen = 65535;
        pcap_global_header_s.network = 1;   //Ethernet          

        return 0;
    }

    uint16_t uiIPHeader_Checksum(void *data, int len)
    {
        uint32_t sum=0;
        size_t i;
        for (i=0; i < len/2; ++i)
            sum += ntohs(((uint16_t*)data)[i]);
        while (sum & 0xFFFF0000)
            sum = (sum & 0xFFFF)+(sum >> 16);
        return ((uint16_t) ~sum);
    }

    int iWrite(
        const CString &rcsSrcAddress, unsigned long ulSrcPort,
        const CString &rcsDestAddress, unsigned long ulDestPort, 
        enum E_PROTOCOL_TYPE eProtocolType,
        const unsigned char *pucBytes, unsigned long ulNofBytes)
    {
        printf("iWrite %ul\n" , ulNofBytes);

        iWritePcapHeader();

        //PCAP header for each data packet  
        SYSTEMTIME timews;
        GetSystemTime(&timews);
        PCAP_PKT_HEADER pcap_pkt_header_s ;
        pcap_pkt_header_s.ts_sec = time(NULL);
        pcap_pkt_header_s.ts_usec =  (timews.wMilliseconds * 1000);
        pcap_pkt_header_s.incl_len = ulNofBytes + sizeof(UDP_HEADER) + sizeof(IP_HEADER) + sizeof(ETHERNET_HEADER);
        pcap_pkt_header_s.orig_len = ulNofBytes + sizeof(UDP_HEADER) + sizeof(IP_HEADER) + sizeof(ETHERNET_HEADER);

        //Ethernet Header
        ETHERNET_HEADER ethernet_header_s;
        unsigned char macAddress[6] = {0x00,0x00,0x00,0x00,0x00,0x00};      // no mac available for now. Hence just fill in dummy data
        memcpy(ethernet_header_s.dst,macAddress,6);
        memcpy(ethernet_header_s.src,macAddress,6);
        ethernet_header_s.type = 0x0800;


        //IP_Header   
        IP_HEADER ip_header_s;
        ip_header_s.ip_v = IPVERSION;
        ip_header_s.ip_hl = 5;
        ip_header_s.ip_tos = 0;
        ip_header_s.ip_len = (uint16_t)(ulNofBytes + sizeof(UDP_HEADER) + sizeof(IP_HEADER));
        ip_header_s.ip_id =   0;
        ip_header_s.ip_off = IP_DF;
        ip_header_s.ip_ttl =  0x40;  // 40(hex) = 64 , 80(hex) = 128
        ip_header_s.ip_p = 0x11;                                                                   
        ip_header_s.ip_src = inet_addr(rcsSrcAddress);
        ip_header_s.ip_dst = inet_addr(rcsDestAddress);        
        ip_header_s.ip_sum = (uint16_t)(uiIPHeader_Checksum(&ip_header_s, sizeof(IP_HEADER)));   

        //UDP Header
        UDP_HEADER udp_header_s; 
        udp_header_s.srcPort = ulSrcPort;
        udp_header_s.dstPort = ulDestPort;
        udp_header_s.length =  (uint16_t)(ulNofBytes + sizeof(UDP_HEADER));

        if (eProtocolType == E_UDP) {
            //UDP Header
            UDP_HEADER udp_header_s;
            udp_header_s.srcPort = ulSrcPort;
            udp_header_s.dstPort = ulDestPort;
            udp_header_s.length = (uint16_t)(ulNofBytes + sizeof(UDP_HEADER));

            //  wiresharkPkt = pcap_pkt_header_s + ethernet_header_s + ip_header_s + udp_header_s + pucBytes ;
            WIRESHARK_UDP_PKT_HEADER wireshark_udp_pkt_header;
            wireshark_udp_pkt_header.pcap_pkt_header = pcap_pkt_header_s;
            wireshark_udp_pkt_header.l2l3UDP_header.ethernet_header = ethernet_header_s;
            wireshark_udp_pkt_header.l2l3UDP_header.ip_header = ip_header_s;
            wireshark_udp_pkt_header.l2l3UDP_header.udp_header = udp_header_s;

            fwrite(&pcap_global_header_s, sizeof(PCAP_GLOBAL_HEADER), 1, mpFile);
            fwrite(&wireshark_udp_pkt_header, sizeof(WIRESHARK_UDP_PKT_HEADER), 1, mpFile);
            fwrite(pucBytes, ulNofBytes, 1, mpFile);
        }
        else if (eProtocolType == E_TCP)
        {
            //TCP Header


        }
AswathyPrasad
  • 353
  • 4
  • 12

1 Answers1

0

Both IP and UDP, just as many other network protocols, utilize big-endian byte order. And since you probably running this code on little-endian machine values written in ip_header_s.ip_len and udp_header_s.length will be incorrect. You should use htons function to convert short value from host to network byte order.

ip_header_s.ip_len = htons((uint16_t)(ulNofBytes + sizeof(UDP_HEADER) + sizeof(IP_HEADER)));

Aside from byte order, you can improve your code by checking actual sizes of structures and getting rid of magic numbers. Also your code is completely written in C, why did you add C++ tag?

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Thanks for the help. Although I had to use ntohs to make it work!! As for the tag, I have omitted the classes etc used in the program and only pasted the method. The design is originally in C++, however, here it doesn't matter :) – AswathyPrasad May 10 '17 at 09:13