v1.7.0.0 · Apache‑2.0 · Linux · C/C++

A deep packet inspection engine for C.

Link libmmt_core, register the protocol fields you need, and process packets from a pcap or a live interface. MMT‑DPI classifies 643 protocols, extracts 6,334 typed attributes, and tracks per-flow sessions — all behind one callback API.

hello_packet.c — your first program
#include "mmt_core.h"

// Called after MMT classifies and extracts each packet.
int on_packet(const ipacket_t *ipacket, void *args) {
    uint32_t *len = get_attribute_extracted_data_by_name(ipacket, "META", "PACKET_LEN");
    if (len) printf("packet size: %u\n", *len);
    return 0;
}

int main(void) {
    init_extraction();
    char errbuf[1024];
    mmt_handler_t *h = mmt_init_handler(DLT_EN10MB, 0, errbuf);

    register_extraction_attribute_by_name(h, "META", "PACKET_LEN");
    register_packet_handler(h, 1, on_packet, NULL);
    // ... feed packets (pcap or live) — see the API section ...
}
643
protocols classified
6,334
named attributes
5G
LTE & mobile core
5+
Linux distros
// the problem

Traffic moved on. Most parsers didn't.

Fixed-protocol tools can't follow traffic as it shifts to QUIC, HTTP/2, and 5G control planes. Hand-rolled parsers turn every new protocol into a brittle byte-offset rewrite — and they fall over on malformed or fragmented input.

[ 0x ]

Offset math everywhere

Every field is a hardcoded slice. One spec change, one option flag, and your parser silently returns garbage.

[ ✕ ]

Blind to modern transports

QUIC, HTTP/2, DTLS, 5G NAS/NGAP. If your stack can't classify them, half your traffic is "unknown."

[ ⚠ ]

Breaks under fragmentation

Out-of-order, overlapping, duplicated segments, IP fragmentation evasion — the cases that matter most are the ones that crash naive code.


// the engine

One engine you query by name.

Register the fields you care about by (protocol, attribute). The engine classifies every packet, extracts your fields, reassembles sessions, and calls you back — battle-tested across a decade of Montimage monitoring products.

classification

643 protocols, auto-detected

Classification across the full TCP/IP stack and application layer — not by port number, but by payload signature. From Ethernet to QUIC to S7COMM.

extraction

6,334 named attributes

Pull any protocol field — IPs, ports, headers, payload values — by name. No manual offset math, no per-protocol glue code in your application.

sessions

Flow tracking & stats

Per-flow RTT, retransmissions, byte and packet counts, sub-session statistics. TCP reassembly handles out-of-order, overlap, and retransmission.

plugins

Extensible by design

Cover a protocol MMT doesn't ship yet by adding a module: declare its fields and classification logic and register it with the core at build time.

5G / LTE

Mobile-core ready

NAS, S1AP, NGAP, GTPv2, Diameter, GTP — extract IMSI and control-plane fields for mobile-network monitoring and security.

performance

Built for line rate

Lean C with a callback-driven API, static-analysis-hardened (PVS-Studio, cppcheck). Designed to run inside high-throughput probes.


// the api

From one attribute to live session analysis — in real code.

The same four calls scale from a five-line program to a live probe. Pick a tier — every snippet compiles against libmmt_core (link with -lmmt_core -ldl -lpcap).

hello_packet.c
#include <pcap.h>
#include "mmt_core.h"

// Fires after MMT classifies & extracts each packet.
int on_packet(const ipacket_t *ipacket, void *args) {
    uint32_t *len = get_attribute_extracted_data_by_name(ipacket, "META", "PACKET_LEN");
    if (len) printf("packet size: %u\n", *len);
    return 0;
}

int main(int argc, char **argv) {
    init_extraction();
    char errbuf[1024];
    mmt_handler_t *h = mmt_init_handler(DLT_EN10MB, 0, errbuf);

    register_extraction_attribute_by_name(h, "META", "PACKET_LEN");
    register_packet_handler(h, 1, on_packet, NULL);

    // Feed packets from a .pcap file.
    pcap_t *pcap = pcap_open_offline(argv[1], errbuf);
    struct pcap_pkthdr ph; struct pkthdr hdr;
    const u_char *data;
    while ((data = pcap_next(pcap, &ph))) {
        hdr.ts = ph.ts; hdr.caplen = ph.caplen; hdr.len = ph.len;
        packet_process(h, &hdr, data);
    }

    mmt_close_handler(h);
    close_extraction();
}

Adapted from the bundled src/examples/packet_handler.c. The handler returns int (the callback contract); "META"/"PACKET_LEN" is a built-in meta attribute available on every packet.

extract_fields.c
#include "mmt_core.h"

int on_packet(const ipacket_t *ipacket, void *args) {
    uint32_t *src  = get_attribute_extracted_data_by_name(ipacket, "ip",   "src");
    uint32_t *dst  = get_attribute_extracted_data_by_name(ipacket, "ip",   "dst");
    uint16_t *port = get_attribute_extracted_data_by_name(ipacket, "tcp",  "dest_port");
    mmt_header_line_t *host = get_attribute_extracted_data_by_name(ipacket, "http", "host");

    if (src && dst && port) {
        uint8_t *s = (uint8_t*)src, *d = (uint8_t*)dst;   // IP = 4 octets, net order
        // host is an mmt_header_line_t (ptr + len) — not a null-terminated string.
        printf("%u.%u.%u.%u → %u.%u.%u.%u:%u  %.*s\n",
               s[0],s[1],s[2],s[3], d[0],d[1],d[2],d[3], *port,
               host ? (int)host->len : 1, host ? host->ptr : "-");
    }
    return 0;
}

int main(void) {
    init_extraction();
    char errbuf[1024];
    mmt_handler_t *h = mmt_init_handler(DLT_EN10MB, 0, errbuf);

    // Register the fields you care about — by (protocol, attribute) name.
    register_extraction_attribute_by_name(h, "ip",   "src");
    register_extraction_attribute_by_name(h, "ip",   "dst");
    register_extraction_attribute_by_name(h, "tcp",  "dest_port");
    register_extraction_attribute_by_name(h, "http", "host");
    register_packet_handler(h, 1, on_packet, NULL);

    // ... same pcap / packet_process() loop as Tier 1 ...
}

Each attribute has a typed value — numeric fields come back as uint*_t*, while header strings like http/host are mmt_header_line_t* (a ptr+len pair, not null-terminated). Names map to MMT's 6,334 attributes; the engine classifies by payload signature, so these resolve regardless of port. See MMT-Attributes.

live_sessions.c
#include <pcap.h>
#include <inttypes.h>   // PRIu64
#include "mmt_core.h"

// Called periodically per active session — read flow-level stats.
void on_session(const mmt_session_t *s, void *args) {
    printf("session %"PRIu64": %"PRIu64" pkts, %"PRIu64" bytes\n",
           get_session_id(s),
           get_session_packet_count(s),
           get_session_byte_count(s));
}

// pcap delivers each frame straight into MMT.
void on_capture(u_char *user, const struct pcap_pkthdr *ph, const u_char *data) {
    mmt_handler_t *h = (mmt_handler_t*)user;
    struct pkthdr hdr = { .ts = ph->ts, .caplen = ph->caplen, .len = ph->len };
    packet_process(h, &hdr, data);
}

int main(int argc, char **argv) {
    init_extraction();
    char errbuf[1024];
    mmt_handler_t *h = mmt_init_handler(DLT_EN10MB, 0, errbuf);

    // Report each session on a timer (0 = include incomplete packets).
    register_session_timer_handler(h, on_session, NULL, 0);

    // Capture live from an interface and pump frames into MMT.
    pcap_t *pcap = pcap_open_live(argv[1], 65535, 1, 1000, errbuf);
    pcap_loop(pcap, -1, on_capture, (u_char*)h);
}

Session accessors expose packet/byte counts, uplink/downlink splits, and more. Built-in tcp/rtt and tcp/retransmission attributes add per-flow timing. Run live captures with sudo.

Adding a protocol MMT doesn't cover yet is a library-level extension: a module implements init_proto_<name>_struct(), declares its fields, and registers with the core at build time — see Adding New Protocols. Full runnable examples live in src/examples/.


// coverage

From Ethernet to 5G, classified out of the box.

A selection of the 643 protocols MMT‑DPI recognizes — across the TCP/IP stack, application layer, mobile core, and industrial/OT.

TCPIPv4/IPv6HTTP HTTP/2QUICDNS TLS/DTLSFTPMQTT RTSPSMBRADIUS OSPFSCTPVLAN / 802.1ad 5G NGAPNASS1AP GTP / GTPv2DiameterSIP S7COMMCOTP / TPKTCDP / DTP DICOMVNCMSSQL + 600 more

// where it runs

The extraction layer under real systems.

[ nids ]

Intrusion detection & security monitoring

Feed classified, attribute-level events into detection engines. MMT-DPI powers Montimage's network security monitoring and IP-fragmentation evasion detection.

[ 5g ]

5G & mobile network analysis

Decode control-plane signaling (NGAP, NAS, S1AP, Diameter). Underpins 5GReplay, a 5G traffic fuzzer presented at ARES 2021.

[ iot ]

IoT & industrial monitoring

Classify OT/industrial protocols (S7COMM, COTP) and IoT traffic. Deployed in security-monitoring frameworks on Fed4Fire+ testbeds.

[ qoe ]

Traffic analytics & QoE

Session-level RTT, retransmissions, and per-flow counters give you the raw signals for quality-of-experience and performance analytics.

// proven in research & production

A decade of peer-reviewed work runs on this engine.

MMT-DPI is the data-extraction core of the wider Montimage Monitoring Tool (MMT) suite, cited and evaluated across DPI, IoT, 5G, and intrusion-detection research.

5GReplay: A 5G Network Traffic Fuzzer — Application to Attack Injection
ARES 2021 · [5g] [nids]
A Network Traffic Mutation Based Ontology to Expand the Training Set of AI-Based NIDS
IEEE Access, 2023 · [nids]
A Framework for Security Monitoring of Real IoT Testbeds
ICSOFT 2021 · [iot]
Online Network Traffic Security Inspection Using MMT Tool
System Testing & Validation, 2012 · [dpi-core]

See the full publication list →

// install & link

Get the library, then compile against it.

Install the SDK to /opt/mmt/dpi (headers in include/, libmmt_core in lib/), then build your program. Linux: Debian/Ubuntu, Fedora/RHEL, Arch, Alpine, openSUSE.

bash
# 1 — install the library (one line; or grab a .deb/.rpm from Releases)
$ curl -sSL https://raw.githubusercontent.com/montimage-projects/mmt-dpi/main/install.sh | bash
# 2 — compile your program against libmmt_core
$ gcc -o hello_packet hello_packet.c \
-I /opt/mmt/dpi/include -L /opt/mmt/dpi/lib -lmmt_core -ldl -lpcap
# 3 — run it on a capture
$ ./hello_packet traffic.pcap
packet size: 1514

// questions

Common questions

What exactly is MMT-DPI?

A high-performance C library for deep packet inspection. It classifies network traffic into 643 protocols and lets you extract 6,334 named, typed attributes from packets, server logs, and structured events — for real-time analysis. It's the extraction core inside the broader Montimage Monitoring Tool (MMT) suite.

Which platforms are supported?

Linux only. Tested across Debian/Ubuntu, Fedora/RHEL, Arch, Alpine, and openSUSE, with GCC or Clang, plus ARM cross-compilation. macOS and Windows are not currently supported.

How do I add a protocol that isn't covered?

Write a plugin. You declare the protocol's attributes and its classification logic as a modular plugin and drop it in — no changes to the core engine. See the Adding New Protocols guide.

Is it really free? What's the license?

Yes — MMT-DPI is open source under the Apache License 2.0. You can use it commercially, modify it, and ship it, subject to the license terms. No license keys, no usage caps.

Does it classify by port number?

Not by default. Classification is driven by payload signatures (with hostname- and IP-range-based methods), so it identifies protocols on non-standard ports and across modern transports. Port number is treated as the weakest signal — a last-resort hint consulted only after the signature-based methods return unknown, and only if you explicitly opt in with enable_port_classify() (disabled by default).

Can it handle fragmented or out-of-order traffic?

Yes. TCP reassembly (enable it per handler) reconstructs payloads across out-of-order, overlapping, and retransmitted segments, and the engine raises events for IP-fragmentation conditions — including evasion patterns like overlapping, duplicated, and too-many fragments.

Stop writing byte-offset parsers.
Start querying packets by name.

643 protocols, 6,334 attributes, plugin-extensible — open source under Apache-2.0. One command and you're running.