Skip to content

2. Getting Started

Mark Bednarczyk edited this page Oct 22, 2024 · 11 revisions

Getting Started with Protocol Packs in jnetpcap

Table of Contents

  1. Introduction
  2. Protocol Pack Overview
  3. Packet and Memory Binding
  4. Protocol Pack Management
  5. Header Options Handling
  6. Reassembly Support

Introduction

For basic jnetpcap installation and setup, please refer to the jnetpcap GitHub Wiki. This guide focuses on working with protocol packs and understanding core jnetpcap concepts.

Protocol Pack Overview

jnetpcap organizes protocols into specialized protocol packs:

public enum ProtocolPackTable implements PackId {
    CORE("core"),           // Core networking protocols
    OPTS("options"),        // Protocol options support
    MEDIA("media"),         // Media protocols
    WEB("web"),            // Web protocols
    TELCO("telco"),        // Telecom protocols
    LTE("lte"),            // LTE protocols
    DB("database"),        // Database protocols
    MS("microsoft"),       // Microsoft protocols
    AAA("authentication"), // Authentication protocols
    IOT("IoT"),            // Internet of Things protocols
    VOIP("VoIP"),          // Voice over IP protocols
    TELCO_3G("3G"),        // 3G protocols
    IM("Realtime IM")      // Instant messaging protocols
}

Loading Protocol Packs

Protocol packs are loaded automatically when they're available on the module path:

// Example of checking available protocol packs
ProtocolPackManager manager = ProtocolPackManager.getDefault();
for (ProtocolPack pack : manager.getAvailablePacks()) {
    System.out.println("Found pack: " + pack.getName());
}

Packet and Memory Binding

jnetpcap uses a unique binding mechanism to efficiently process packets:

// Create reusable packet instance
Packet packet = new Packet();

// Create reusable header instances outside the loop
Ip4 ip4 = new Ip4();
Tcp tcp = new Tcp();

// WARNING: Header bindings are only valid within the packet processing loop
//          and within their respective hasHeader() validation blocks.
//          Accessing header data outside these scopes may throw exceptions
//          or result in undefined behavior as the underlying packet memory
//          may have been invalidated or reused.

// Packet binding to native or buffer memory
while (pcap.nextEx(packet)) {  // Binds packet to next capture buffer
    if (packet.hasHeader(ip4)) {  // Binds ip4 to packet memory if header exists
        // SAFE: Access ip4 header fields here within the hasHeader(ip4) block
        System.out.println("Source IP: " + FormatUtils.ip(ip4.source()));
        
        if (packet.hasHeader(tcp)) {  // Binds tcp to packet memory if header exists
            // SAFE: Access tcp header fields here within the hasHeader(tcp) block
            System.out.println("TCP ports: " + tcp.source() + " -> " + tcp.destination());
        }
    }
}

// Note: To store packet or header instances for later use:
// - Packets and headers must be cloned
// - Memory management is handled through JDK 22's Foreign Function and Memory API
// - Arena and MemorySegment are used for scope management
// - Refer to the Memory Management guide for detailed information about
//   working with Arena scopes and MemorySegment in jnetpcap

Packet Descriptors

Descriptors provide metadata about headers within packets:

// Different types of descriptors provide different capabilities
PacketDescriptor basicDescriptor = packet.descriptor();
IpfDescriptor ipfDescriptor = packet.descriptor(IpfDescriptor.class);  // IP fragment info
PcapDescriptor pcapDescriptor = packet.descriptor(PcapDescriptor.class);  // PCAP specific info

Header Options Handling

Many protocols support options through the HasOption interface:

// IP options example
Ip4 ip4 = new Ip4();
if (packet.hasHeader(ip4)) {
    
    // Create reusable option instances
    Ip4RouterAlertOption routerAlert = new Ip4RouterAlertOption();
    Ip4TimestampOption timestamp = new Ip4TimestampOption();
    
    // Check and bind options
    if (ip4.hasOption(routerAlert)) {
        System.out.println("Router Alert option found");
    }
    
    if (ip4.hasOption(timestamp)) {
        System.out.println("Timestamp option found");
    }
}

// TCP options example
Tcp tcp = new Tcp();
if (packet.hasHeader(tcp)) {
    TcpTimestampOption timestamp = new TcpTimestampOption();
    TcpWindowScaleOption windowScale = new TcpWindowScaleOption();
    
    if (tcp.hasOption(timestamp)) {
        System.out.println("TCP timestamp: " + timestamp.timestamp());
    }
}

Reassembly Support

jnetpcap provides a consistent approach to packet reassembly across protocols:

General Reassembly Pattern

// Generic pattern for protocol reassembly
public class ProtocolReassembly {
    
    // Configuration
    ProtocolReassemblyConfig config = new ProtocolReassemblyConfig()
        .setTimeout(30_000)        // 30 second timeout
        .setMaxPackets(1000)       // Maximum packets to track
        .setMaxBytes(1_000_000);   // Maximum memory usage
        
    // Create reassembler
    ProtocolReassembly reassembly = new ProtocolReassembly(config);
    
    // Add event handlers
    reassembly.addReassemblyHandler(new ProtocolReassemblyHandler() {
        @Override
        public void handleReassembledData(ReassembledData data) {
            // Process reassembled data
        }
        
        @Override
        public void handleTimeout(ReassemblyTimeout timeout) {
            // Handle timeout event
        }
    });
    
    // Monitor statistics
    ProtocolStatistics stats = reassembly.getStatistics();
    System.out.println("Reassembled packets: " + stats.getReassembledPackets());
    System.out.println("Fragments processed: " + stats.getProcessedFragments());
}

Protocol-Specific Examples

// IP Reassembly
IpReassembly ipReassembly = new IpReassembly(new IpReassemblyConfig());
pcap.setIpReassembler(ipReassembly);

ipReassembly.addReassemblyHandler(new IpReassemblyHandler() {
    @Override
    public void reassembledIpv4(Ip4Reassembled reassembled) {
        // Handle reassembled IPv4 datagram
    }
    
    @Override
    public void reassembledIpv6(Ip6Reassembled reassembled) {
        // Handle reassembled IPv6 datagram
    }
});

// TCP Reassembly
TcpReassembly tcpReassembly = new TcpReassembly(new TcpReassemblyConfig());
pcap.setTcpReassembler(tcpReassembly);

tcpReassembly.addStreamHandler(new TcpStreamHandler() {
    @Override
    public void handleStream(TcpStream stream) {
        // Handle reassembled TCP stream
    }
});

Protocol Pack Management

Protocol packs can be dynamically managed:

ProtocolPackManager manager = ProtocolPackManager.getDefault();

// Load specific protocol pack
manager.loadPack(ProtocolPackTable.VOIP);

// Unload protocol pack
manager.unloadPack(ProtocolPackTable.VOIP);

// Check if pack is loaded
if (manager.isPackLoaded(ProtocolPackTable.VOIP)) {
    System.out.println("VoIP pack is loaded");
}

// Get information about loaded protocols
for (ProtocolDescriptor proto : manager.getProtocols(ProtocolPackTable.VOIP)) {
    System.out.println("Protocol: " + proto.getName());
}

Key points about protocol packs:

  1. Automatically discovered when on module path
  2. Can be loaded/unloaded dynamically
  3. Provide protocol-specific headers, options, and reassembly support
  4. Include protocol descriptors for extended functionality

By understanding these core concepts and patterns, you can effectively work with protocol packs in jnetpcap, regardless of the specific protocols you need to analyze.