1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Compile-time guards on the `l7` / `full` Cargo umbrellas (issue #87).
//!
//! Background: before this guard, `full` silently carried *fewer* parsers
//! than `l7` (it was not a superset), so `--features full` quietly omitted
//! most of the Tier-2 protocol work. `--all-features` (docs.rs / CI) masked
//! the gap. These `compile_error!`s make any future drift a hard build
//! failure instead of a silent regression.
//!
//! Invariants enforced:
//!
//! 1. **`l7` enables every license-clean protocol parser.** (The only
//! parser-ish feature deliberately excluded is the FoxIO-licensed
//! `ja4plus` suite.)
//! 2. **`full` is a superset of `l7`** — it pulls `l7` directly, and that
//! edge is itself asserted below.
//! 3. **`full` enables every license-clean capability** (parsers via `l7`,
//! plus the non-l7 parser/fingerprint/asset/ml/ipfix/observability/emit
//! groups). `ja4plus` stays excluded so `full` is royalty-free-clean.
//! 4. **Each coarse tier enables its own members** (issue #87) —
//! `parsers-core` / `parsers-l2l3` / `parsers-tier2` / `ml` / `export` /
//! `nsm`. `l7` / `full` are recomposed from these tiers, so the leaves
//! are already covered transitively; the tier guards pin membership even
//! when a tier is built on its own.
//!
//! This module is intentionally empty at runtime — it exists only for its
//! `cfg`-gated `compile_error!` arms.
// ── 1. `l7` ⊇ every license-clean parser ──────────────────────────────
macro_rules! l7_requires {
($($feat:literal),* $(,)?) => {
$(
#[cfg(all(feature = "l7", not(feature = $feat)))]
compile_error!(concat!("`l7` umbrella must enable `", $feat, "`"));
)*
};
}
l7_requires!(
"http",
"tls",
"tls-fingerprints",
"dns",
"icmp",
"arp",
"ndp",
"dhcp",
"lldp",
"cdp",
"ssh",
"ntp",
"ssdp",
"tftp",
"mdns",
"netbios-ns",
"ftp",
"smtp",
"wireguard",
"modbus",
"stun",
"rdp",
"snmp",
"radius",
"quic",
"smb",
"ldap",
"kerberos",
"dnp3",
);
// ── 2. `full` ⊇ `l7` ──────────────────────────────────────────────────
#[cfg(all(feature = "full", not(feature = "l7")))]
compile_error!("`full` umbrella must be a superset of `l7` (enable `l7`)");
// ── 3. `full` ⊇ every license-clean capability beyond `l7` ─────────────
macro_rules! full_requires {
($($feat:literal),* $(,)?) => {
$(
#[cfg(all(feature = "full", not(feature = $feat)))]
compile_error!(concat!("`full` umbrella must enable `", $feat, "`"));
)*
};
}
full_requires!(
"tcp_fingerprint",
"asset",
"analysis",
"ml-features",
"ml-features-nprint",
"ipfix",
"ipfix-export",
"pcap",
"metrics",
"tracing",
"serde",
"emit",
"emit-ndjson",
"emit-eve",
"aggregate",
"chrono",
"file-hash",
"fingerprint",
"community-id",
);
// ── 4. Coarse tiers ⊇ their members (issue #87) ───────────────────────
// `l7` / `full` are recomposed from these tiers, so the invariants above
// already cover the leaves transitively. These extra guards pin each
// tier's own membership so a tier can't silently lose a parser even when
// built on its own (`--features parsers-tier2`).
macro_rules! tier_requires {
($tier:literal => $($feat:literal),* $(,)?) => {
$(
#[cfg(all(feature = $tier, not(feature = $feat)))]
compile_error!(concat!("`", $tier, "` tier must enable `", $feat, "`"));
)*
};
}
tier_requires!("parsers-core" => "http", "tls", "dns", "icmp");
tier_requires!("parsers-l2l3" => "arp", "ndp", "lldp", "cdp", "dhcp");
tier_requires!("parsers-tier2" =>
"ssh", "ntp", "ssdp", "tftp", "mdns", "netbios-ns", "ftp", "smtp",
"wireguard", "modbus", "stun", "rdp", "snmp", "radius", "quic",
"smb", "ldap", "kerberos", "dnp3",
);
tier_requires!("ml" => "ml-features", "ml-features-nprint");
tier_requires!("export" =>
"ipfix", "ipfix-export", "emit", "emit-ndjson", "emit-eve");
tier_requires!("nsm" => "fingerprint", "tls-fingerprints", "analysis");