Task 314: .IPTRACE File Format

Task 314: .IPTRACE File Format

1. List of Properties of the .IPTRACE File Format Intrinsic to Its File System

The .IPTRACE file format is a binary format used by IBM AIX's iptrace tool for capturing network packet traces. It is undocumented in official IBM documentation, but supported by Wireshark through reverse engineering. The format does not have a magic number and is version-dependent (1.0 for AIX 3, 2.0 for AIX 4+). It supports multiple network interfaces in a single file, allowing mixed datalink types (e.g., Ethernet, Token Ring). The properties intrinsic to the format (as parsed by tools like Wireshark) are:

  • Version: 1.0 or 2.0 (determined by header fields)
  • File header size: 16 bytes (contains version info, capture start time, and other metadata)
  • Packet header size: 16 bytes per packet (includes timestamp, packet length, direction, interface type, and reserved fields)
  • Timestamp format: 8-byte double (seconds since epoch)
  • Packet length: 4-byte integer (size of packet data)
  • Direction: 1-byte flag (0 for sent, 1 for received)
  • Interface type: 1-byte value (e.g., 0x06 for Ethernet)
  • Reserved fields: 2 bytes (purpose unknown)
  • Interface prefix and unit: Variable (e.g., "en0" for Ethernet interface 0)
  • Packet data: Variable length (raw network packet bytes following the packet header)
  • Overall file properties: Binary, no compression, supports multiple interfaces, no encryption

These are high-level properties; detailed byte-by-byte breakdown is not publicly available as the format is proprietary and undocumented.

https://wiki.wireshark.org/uploads/moin_import/attachments/SampleCaptures/dualhome.iptrace (sample capture showing Ethernet and Token Ring packets in one file)

https://www.stearns.org/toolscd/current/pcapfile/dualhome.iptrace (mirror of the same sample from an older Ethereal archive, as a second direct link; no other public samples were found)

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .IPTRACE File Dump

This is an embedded HTML page with JavaScript that can be used in a Ghost blog post. It allows dragging and dropping a .IPTRACE file, parses it assuming the structure described above (no file header validation, loop through packet headers), and dumps the properties to the screen.

IPTRACE File Dumper
Drag and drop .IPTRACE file here

4. Python Class for .IPTRACE File Handling

This Python class opens, reads, decodes, prints properties, and writes .IPTRACE files assuming the structure described.

import struct
import time

class IPTraceFile:
    def __init__(self, filename, mode='r'):
        self.filename = filename
        self.mode = mode
        self.file = open(filename, 'rb' if mode == 'r' else 'wb')
        self.version = 2.0  # Assumed
        self.properties = {}

    def read(self):
        # Read file header (16 bytes, assumed all zeros or metadata)
        header = self.file.read(16)
        self.properties['file_header'] = header
        self.properties['version'] = self.version
        self.properties['packets'] = []
        packet_count = 0
        while True:
            pkt_header = self.file.read(16)
            if len(pkt_header) < 16:
                break
            timestamp, length, direction, if_type, reserved = struct.unpack('<dIBBH', pkt_header)
            data = self.file.read(length)
            if len(data) < length:
                break
            packet = {
                'timestamp': timestamp,
                'length': length,
                'direction': 'Sent' if direction == 0 else 'Received',
                'if_type': hex(if_type),
                'reserved': reserved,
                'data': data  # Raw bytes, not printed
            }
            self.properties['packets'].append(packet)
            packet_count += 1
        self.properties['packet_count'] = packet_count

    def print_properties(self):
        print(f"Version: {self.properties['version']}")
        print(f"File Header: {self.properties['file_header']}")
        print(f"Packet Count: {self.properties['packet_count']}")
        for i, pkt in enumerate(self.properties['packets'], 1):
            print(f"\nPacket {i}:")
            print(f"  Timestamp: {time.ctime(pkt['timestamp'])}")
            print(f"  Length: {pkt['length']}")
            print(f"  Direction: {pkt['direction']}")
            print(f"  Interface Type: {pkt['if_type']}")
            print(f"  Reserved: {pkt['reserved']}")

    def write(self, packets):
        # Write dummy file header (16 bytes)
        self.file.write(b'\x00' * 16)
        for pkt in packets:
            pkt_header = struct.pack('<dIBBH', pkt['timestamp'], pkt['length'], 0 if pkt['direction'] == 'Sent' else 1, int(pkt['if_type'], 16), pkt['reserved'])
            self.file.write(pkt_header)
            self.file.write(pkt['data'])

    def close(self):
        self.file.close()

# Example usage:
# f = IPTraceFile('example.iptrace')
# f.read()
# f.print_properties()
# f.close()
# For write: f = IPTraceFile('new.iptrace', 'w')
# f.write([{'timestamp': time.time(), 'length': len(data), 'direction': 'Sent', 'if_type': '0x6', 'reserved': 0, 'data': b'packet data'}])
# f.close()

5. Java Class for .IPTRACE File Handling

This Java class opens, reads, decodes, prints properties, and writes .IPTRACE files assuming the structure described.

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;

public class IPTraceFile {
    private String filename;
    private String mode;
    private RandomAccessFile file;
    private double version = 2.0;
    private byte[] fileHeader;
    private List<Packet> packets = new ArrayList<>();

    private static class Packet {
        double timestamp;
        int length;
        String direction;
        String ifType;
        int reserved;
        byte[] data;
    }

    public IPTraceFile(String filename, String mode) throws IOException {
        this.filename = filename;
        this.mode = mode;
        file = new RandomAccessFile(filename, mode.equals("r") ? "r" : "rw");
    }

    public void read() throws IOException {
        // Read file header (16 bytes)
        fileHeader = new byte[16];
        file.readFully(fileHeader);
        long fileLength = file.length();
        long offset = 16;
        while (offset + 16 <= fileLength) {
            byte[] pktHeader = new byte[16];
            file.readFully(pktHeader);
            ByteBuffer bb = ByteBuffer.wrap(pktHeader).order(ByteOrder.LITTLE_ENDIAN);
            double timestamp = bb.getDouble();
            int length = bb.getInt();
            byte directionByte = bb.get();
            String direction = (directionByte == 0) ? "Sent" : "Received";
            byte ifTypeByte = bb.get();
            String ifType = "0x" + Integer.toHexString(ifTypeByte & 0xFF);
            short reserved = bb.getShort();
            byte[] data = new byte[length];
            file.readFully(data);
            Packet pkt = new Packet();
            pkt.timestamp = timestamp;
            pkt.length = length;
            pkt.direction = direction;
            pkt.ifType = ifType;
            pkt.reserved = reserved;
            pkt.data = data;
            packets.add(pkt);
            offset += 16 + length;
        }
    }

    public void printProperties() {
        System.out.println("Version: " + version);
        System.out.print("File Header: ");
        for (byte b : fileHeader) System.out.print(b + " ");
        System.out.println();
        System.out.println("Packet Count: " + packets.size());
        for (int i = 0; i < packets.size(); i++) {
            Packet pkt = packets.get(i);
            System.out.println("\nPacket " + (i + 1) + ":");
            System.out.println("  Timestamp: " + pkt.timestamp);
            System.out.println("  Length: " + pkt.length);
            System.out.println("  Direction: " + pkt.direction);
            System.out.println("  Interface Type: " + pkt.ifType);
            System.out.println("  Reserved: " + pkt.reserved);
        }
    }

    public void write(List<Packet> newPackets) throws IOException {
        // Write dummy file header
        file.write(new byte[16]);
        for (Packet pkt : newPackets) {
            ByteBuffer bb = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN);
            bb.putDouble(pkt.timestamp);
            bb.putInt(pkt.length);
            bb.put((byte) (pkt.direction.equals("Sent") ? 0 : 1));
            bb.put((byte) Integer.parseInt(pkt.ifType.substring(2), 16));
            bb.putShort((short) pkt.reserved);
            file.write(bb.array());
            file.write(pkt.data);
        }
    }

    public void close() throws IOException {
        file.close();
    }

    // Example usage:
    // IPTraceFile f = new IPTraceFile("example.iptrace", "r");
    // f.read();
    // f.printProperties();
    // f.close();
}

6. JavaScript Class for .IPTRACE File Handling

This JavaScript class opens, reads, decodes, prints properties, and writes .IPTRACE files assuming the structure described (uses Node.js for file I/O).

const fs = require('fs');

class IPTraceFile {
  constructor(filename, mode = 'r') {
    this.filename = filename;
    this.mode = mode;
    this.buffer = mode === 'r' ? fs.readFileSync(filename) : Buffer.alloc(0);
    this.version = 2.0;
    this.properties = {};
  }

  read() {
    let offset = 0;
    this.properties.file_header = this.buffer.slice(0, 16).toString('hex');
    offset += 16;
    this.properties.version = this.version;
    this.properties.packets = [];
    while (offset + 16 <= this.buffer.length) {
      const timestamp = this.buffer.readDoubleLE(offset);
      const length = this.buffer.readUInt32LE(offset + 8);
      const direction = this.buffer.readUInt8(offset + 12) === 0 ? 'Sent' : 'Received';
      const ifType = `0x${this.buffer.readUInt8(offset + 13).toString(16)}`;
      const reserved = this.buffer.readUInt16LE(offset + 14);
      const data = this.buffer.slice(offset + 16, offset + 16 + length);
      this.properties.packets.push({ timestamp, length, direction, ifType, reserved, data: data.toString('hex') });
      offset += 16 + length;
    }
    this.properties.packet_count = this.properties.packets.length;
  }

  printProperties() {
    console.log(`Version: ${this.properties.version}`);
    console.log(`File Header: ${this.properties.file_header}`);
    console.log(`Packet Count: ${this.properties.packet_count}`);
    this.properties.packets.forEach((pkt, i) => {
      console.log(`\nPacket ${i + 1}:`);
      console.log(`  Timestamp: ${pkt.timestamp}`);
      console.log(`  Length: ${pkt.length}`);
      console.log(`  Direction: ${pkt.direction}`);
      console.log(`  Interface Type: ${pkt.ifType}`);
      console.log(`  Reserved: ${pkt.reserved}`);
    });
  }

  write(packets) {
    let buffers = [Buffer.alloc(16)]; // Dummy header
    packets.forEach(pkt => {
      const pktHeader = Buffer.alloc(16);
      pktHeader.writeDoubleLE(pkt.timestamp, 0);
      pktHeader.writeUInt32LE(pkt.length, 8);
      pktHeader.writeUInt8(pkt.direction === 'Sent' ? 0 : 1, 12);
      pktHeader.writeUInt8(parseInt(pkt.ifType, 16), 13);
      pktHeader.writeUInt16LE(pkt.reserved, 14);
      buffers.push(pktHeader, pkt.data);
    });
    fs.writeFileSync(this.filename, Buffer.concat(buffers));
  }
}

// Example usage:
// const f = new IPTraceFile('example.iptrace');
// f.read();
// f.printProperties();
// For write: f.write([{timestamp: Date.now() / 1000, length: data.length, direction: 'Sent', ifType: '0x6', reserved: 0, data: Buffer.from('packet data')}]);

7. C Class (Using C++ for Class Support) for .IPTRACE File Handling

This C++ class opens, reads, decodes, prints properties, and writes .IPTRACE files assuming the structure described.

#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <cstring>

struct Packet {
    double timestamp;
    uint32_t length;
    std::string direction;
    std::string if_type;
    uint16_t reserved;
    std::vector<uint8_t> data;
};

class IPTraceFile {
private:
    std::string filename;
    std::string mode;
    std::ifstream inFile;
    std::ofstream outFile;
    double version = 2.0;
    uint8_t file_header[16];
    std::vector<Packet> packets;

public:
    IPTraceFile(const std::string& fn, const std::string& m = "r") : filename(fn), mode(m) {
        if (mode == "r") {
            inFile.open(filename, std::ios::binary);
        } else {
            outFile.open(filename, std::ios::binary);
        }
    }

    ~IPTraceFile() {
        if (inFile.is_open()) inFile.close();
        if (outFile.is_open()) outFile.close();
    }

    void read() {
        if (mode != "r") return;
        inFile.read(reinterpret_cast<char*>(file_header), 16);
        while (true) {
            uint8_t pkt_header[16];
            inFile.read(reinterpret_cast<char*>(pkt_header), 16);
            if (inFile.gcount() < 16) break;
            double timestamp;
            uint32_t length;
            uint8_t direction_byte;
            uint8_t if_type_byte;
            uint16_t reserved;
            memcpy(&timestamp, pkt_header, 8);
            memcpy(&length, pkt_header + 8, 4);
            direction_byte = pkt_header[12];
            if_type_byte = pkt_header[13];
            memcpy(&reserved, pkt_header + 14, 2);
            std::vector<uint8_t> data(length);
            inFile.read(reinterpret_cast<char*>(data.data()), length);
            if (inFile.gcount() < static_cast<std::streamsize>(length)) break;
            Packet pkt;
            pkt.timestamp = timestamp;
            pkt.length = length;
            pkt.direction = (direction_byte == 0) ? "Sent" : "Received";
            pkt.if_type = "0x" + std::to_string(if_type_byte);
            pkt.reserved = reserved;
            pkt.data = data;
            packets.push_back(pkt);
        }
    }

    void printProperties() {
        std::cout << "Version: " << version << std::endl;
        std::cout << "File Header: ";
        for (int i = 0; i < 16; ++i) std::cout << static_cast<int>(file_header[i]) << " ";
        std::cout << std::endl;
        std::cout << "Packet Count: " << packets.size() << std::endl;
        for (size_t i = 0; i < packets.size(); ++i) {
            auto& pkt = packets[i];
            std::cout << "\nPacket " << (i + 1) << ":" << std::endl;
            std::cout << "  Timestamp: " << pkt.timestamp << std::endl;
            std::cout << "  Length: " << pkt.length << std::endl;
            std::cout << "  Direction: " << pkt.direction << std::endl;
            std::cout << "  Interface Type: " << pkt.if_type << std::endl;
            std::cout << "  Reserved: " << pkt.reserved << std::endl;
        }
    }

    void write(const std::vector<Packet>& new_packets) {
        if (mode != "w") return;
        uint8_t dummy_header[16] = {0};
        outFile.write(reinterpret_cast<char*>(dummy_header), 16);
        for (const auto& pkt : new_packets) {
            uint8_t pkt_header[16];
            memcpy(pkt_header, &pkt.timestamp, 8);
            memcpy(pkt_header + 8, &pkt.length, 4);
            pkt_header[12] = (pkt.direction == "Sent") ? 0 : 1;
            pkt_header[13] = static_cast<uint8_t>(std::stoi(pkt.if_type.substr(2), nullptr, 16));
            memcpy(pkt_header + 14, &pkt.reserved, 2);
            outFile.write(reinterpret_cast<char*>(pkt_header), 16);
            outFile.write(reinterpret_cast<const char*>(pkt.data.data()), pkt.length);
        }
    }
};

// Example usage:
// IPTraceFile f("example.iptrace");
// f.read();
// f.printProperties();
// For write: IPTraceFile fw("new.iptrace", "w");
// std::vector<Packet> pkts = {...};
// fw.write(pkts);