# Technology Stack **Project:** NetSynth v1.2 — Extended Protocol Coverage with Grouped Sound Families **Researched:** 2026-03-26 **Scope:** Additions/changes only. Existing stack (gopacket, go-pcap, go-lame, cobra, BurntSushi/toml) is validated and unchanged. --- ## Existing Stack (Do Not Re-research) | Technology | Version | Status | |------------|---------|--------| | `github.com/gopacket/gopacket` | v1.5.0 | Validated in v1.0/v1.1, unchanged | | `github.com/packetcap/go-pcap` | v0.0.0-20251215 | Validated in v1.0/v1.1, unchanged | | `github.com/sjzar/go-lame` | v0.0.9 | Validated in v1.0/v1.1, unchanged | | `github.com/spf13/cobra` | v1.10.2 | Validated in v1.0/v1.1, unchanged | | `github.com/BurntSushi/toml` | v1.6.0 | Validated in v1.1, unchanged | | Hand-rolled additive synth + EMA | — | Validated, extend in place | | Ordered `[]Rule` classifier | — | Validated, extend in place | --- ## New Dependencies for v1.2 **None required.** All features for extended protocol coverage and grouped sound families can be implemented by extending existing packages in place. No new external dependencies are needed. --- ## gopacket Protocol Decoder Coverage This is the critical research question for v1.2. The `layers` package in `gopacket/gopacket v1.5.0` is the authoritative source. ### Protocols with Native gopacket Layer Decoders These protocols have a dedicated `LayerType` constant and `DecodeFromBytes` implementation in `github.com/gopacket/gopacket/layers`. They auto-register via UDP/TCP port dispatch — `pkt.Layer(layers.LayerTypeSIP)` just works after gopacket decodes the packet. | Protocol | LayerType Constant | Port Auto-Registered | Notes | |----------|-------------------|---------------------|-------| | ICMP v4 | `LayerTypeICMPv4` | IP protocol 1 | Already used in v1.0 | | ICMP v6 | `LayerTypeICMPv6` | IP protocol 58 | Already used in v1.0 | | DNS | `LayerTypeDNS` | UDP/TCP 53 | Already used in v1.0 | | DHCP v4 | `LayerTypeDHCPv4` | UDP 67, 68 | Already used in v1.0 | | DHCP v6 | `LayerTypeDHCPv6` | UDP 546, 547 | NEW: can add DHCPv6 classification rule | | NTP | `LayerTypeNTP` | UDP 123 | Already used in v1.0 | | TLS | `LayerTypeTLS` | TCP 443, 636, 989-995, 5061, etc. | Can use to improve HTTPS/SMTPS/LDAPS detection | | SIP | `LayerTypeSIP` | UDP/TCP/SCTP 5060, 5082, 5083 | NEW: native layer decoder available | | RADIUS | `LayerTypeRADIUS` | UDP 1812 | Possible addition for network infra traffic | | SCTP | `LayerTypeSCTP` | IP protocol 132 | Available if needed | | GRE | `LayerTypeGRE` | IP protocol 47 | Tunnel protocol, probably skip | | Modbus TCP | `LayerTypeModbusTCP` | TCP/UDP 502 | Industrial — niche | Source: `github.com/gopacket/gopacket/blob/master/layers/layertypes.go` and `layers/ports.go` — confirmed via direct inspection. ### Protocols WITHOUT gopacket Layer Decoders (Port-Based Classification Only) These protocols do NOT have a `LayerType` in gopacket. Classification must use the existing `Rule{Protocol, DstPort, Class}` mechanism — matching by transport protocol + destination port number. This is already how most of the v1.0 rules work (SSH, HTTP, HTTPS, SMTP are all port-based). | Protocol | Standard Port(s) | Transport | Classification Approach | |----------|-----------------|-----------|------------------------| | FTP | 21 (control), 20 (data) | TCP | Port-based rule: `{tcp, 21, ClassFTP}` | | IMAP | 143, 993 (TLS) | TCP | Port-based rules: `{tcp, 143}`, `{tcp, 993}` | | POP3 | 110, 995 (TLS) | TCP | Port-based rules: `{tcp, 110}`, `{tcp, 995}` | | SNMP | 161 (queries), 162 (traps) | UDP | Port-based rules: `{udp, 161}`, `{udp, 162}` | | LDAP | 389, 636 (TLS) | TCP | Port-based rules: `{tcp, 389}`, `{tcp, 636}` (note: 636 already hits LayerTypeTLS) | | RDP | 3389 | TCP | Port-based rule: `{tcp, 3389}` | | SMB | 445 (direct), 139 (NetBIOS) | TCP | Port-based rules: `{tcp, 445}`, `{tcp, 139}` | | mDNS | 5353 | UDP | Port-based rule: `{udp, 5353}` — gopacket uses LayerTypeDNS registered on 53, not 5353 | | QUIC / HTTP3 | 443 | UDP | Port-based rule: `{udp, 443}` distinguishes from HTTPS/TLS on TCP 443 | | Telnet | 23 | TCP | Port-based rule: `{tcp, 23}` | | HTTP alt | 8080, 8443 | TCP | Can add as additional Web family rules | **mDNS detail:** gopacket's DNS layer registers only on UDP port 53. mDNS on UDP 5353 will decode as raw UDP payload — the existing `hashBucket` fallback handles it. A `{udp, 5353, ClassMDNS}` rule is correct and sufficient for classification without needing any layer decoder. **QUIC detail:** QUIC uses UDP port 443 (same port HTTPS uses on TCP). The existing `{tcp, 443, ClassHTTPS}` rule only fires on TCP. A `{udp, 443, ClassQUIC}` rule is unambiguous — UDP 443 is QUIC/HTTP3 traffic on modern networks. No deep packet inspection needed for classification purposes. **SIP detail:** gopacket v1.5.0 has a native SIP decoder (`LayerTypeSIP`) registered on UDP/TCP 5060. This means `pkt.Layer(layers.LayerTypeSIP)` works after gopacket decodes the packet. However, since the existing classifier already dispatches by transport + port via the `Rule` struct, a simple `{udp, 5060, ClassSIP}` / `{tcp, 5060, ClassSIP}` rule pair is simpler and more consistent than adding a special Layer-based code path. Use port-based rules. The native SIP layer decoder is available if future features need SIP message parsing (call rates, request types), but v1.2 only needs classification. --- ## In-Place Extensions Required ### 1. classify package — New TrafficClass constants and DefaultRules Add new `TrafficClass` constants to `classify/types.go` for each new protocol. Extend `classify/rules.go` `DefaultRules` with new ordered entries. **Proposed new classes by family:** ``` Mail family: ClassIMAP, ClassPOP3, ClassSMTPS (SMTP over TLS = 465/587) Web family: ClassHTTP (existing), ClassHTTPS (existing), ClassHTTP8080, ClassQUIC Remote family: ClassSSH (existing), ClassRDP, ClassTelnet Discovery: ClassMDNS, ClassDHCP (existing), ClassDHCPv6 File Transfer: ClassFTP Directory: ClassLDAP Monitoring: ClassSNMP Messaging: ClassSIP Infra: ClassSMB ``` The exact set is a product decision (FEATURES.md), but every entry requires only a new `TrafficClass` string constant and a `Rule{Protocol, DstPort, Class}` entry in `DefaultRules`. No code path changes needed. **Insertion point in DefaultRules:** New rules must come before the existing catch-alls (`{tcp, 0, ClassOtherTCP}` and `{udp, 0, ClassOtherUDP}`). Ordering within the new rules does not matter since they are distinct ports. ### 2. synth package — Frequency map and group detuning Extend `synth/config.go` `ClassFreqConfigs` with an entry for each new `TrafficClass`. No API change — it's a map addition. **Group-based frequency allocation approach (no new code needed):** Group related protocols into a frequency band, using slight detuning within the band for distinction. The existing `FreqConfig.BaseHz` + `FreqConfig.Harmonics` already supports this — give family members adjacent base frequencies (e.g., 5-15 Hz apart at low frequencies, 15-30 Hz at mid frequencies) with the same harmonic shape but different waveform types. Example for Mail family: ```go ClassSMTP: {BaseHz: 440.0, Harmonics: ...sawtooth..., Pan: -0.55} // existing ClassIMAP: {BaseHz: 450.0, Harmonics: ...sawtooth..., Pan: 0.55} // same family, detuned +10 Hz ClassPOP3: {BaseHz: 435.0, Harmonics: ...sawtooth..., Pan: -0.3} // same family, detuned -5 Hz ``` The `WaveformType` field already encodes "same character within group." The existing bandlimited synthesis code handles all this correctly. **NumLayers constant:** Currently hardcoded to 14 in `synth/config.go`. Must be updated to reflect the new total class count. Alternatively, compute it dynamically from `len(ClassFreqConfigs)`. The dynamic approach is more maintainable and requires touching only `synth/config.go`. **GainPerLayer:** Computed as `1.0 / float64(NumLayers)`. With more layers active simultaneously, individual gain drops. This is the correct behavior — prevents clipping. Verify mix levels after adding classes. ### 3. config package — --print-config output `--print-config` currently emits commented TOML grouped by class. With protocol families, adding a `Group` field to `FreqConfig` or a separate group-to-classes mapping in `synth/config.go` allows `--print-config` to emit sections with comment headers like `# Mail family`. This is cosmetic; no behavioral change needed. No new dependency needed. Add a `GroupName string` field to `FreqConfig` (zero value = ungrouped) or a `var ClassGroups = map[string][]TrafficClass{...}` in `synth/config.go`. --- ## What NOT to Add | Avoid | Why | What to Do Instead | |-------|-----|-------------------| | Any deep packet inspection library (gopacket TLS layer for HTTPS detection) | v1.2 goal is protocol family classification by port, not payload analysis. TLS handshake parsing adds complexity for no classification benefit since port is unambiguous. | Port-based `Rule{tcp, 443, ClassHTTPS}` — already working | | `github.com/google/gopacket` (original) | Superseded by community fork; 270 open issues, not maintained | `gopacket/gopacket v1.5.0` (already in use) | | Any SNMP library (e.g., `gosnmp`) | v1.2 only needs to detect SNMP traffic, not decode OIDs or walk MIBs | `{udp, 161, ClassSNMP}` port rule | | Any SIP parsing library | v1.2 only needs to detect SIP presence for sonification, not parse SIP messages, headers, or call state | `{udp, 5060, ClassSIP}` + `{tcp, 5060, ClassSIP}` port rules | | Separate "group" abstraction layer in classify | A `Group` field on `FreqConfig` (in synth) is sufficient for --print-config display. The classifier itself doesn't need to know about groups — families emerge from frequency proximity in the audio output. | `GroupName string` in `synth.FreqConfig` | | Dynamic port range rules (e.g., "all TCP 1024-65535 → ClassOtherTCP") | Existing catch-alls (`DstPort: 0`) already cover this. Current Rule struct is optimized for exact-match dispatch. | Keep existing catch-all rules | --- ## Frequency Rebalancing Scope Current v1.1 spectrum allocation (for reference): ``` 65 Hz — ICMP 110 Hz — DNS 175 Hz — HTTPS 220 Hz — HTTP 330 Hz — SSH 440 Hz — SMTP 520 Hz — NTP 600 Hz — DHCP 700 Hz — OtherTCP 780 Hz — OtherUDP 862 Hz — Unknown-1 (dissonant band) 920 Hz — Unknown-2 981 Hz — Unknown-3 1047 Hz — Unknown-4 ``` Adding ~8-12 new protocol classes requires rebalancing. The 65-780 Hz "known protocol" band currently has 8 classes spread over ~715 Hz (average spacing ~90 Hz). Adding 8+ new entries will compress that to ~40-50 Hz average spacing — still audibly distinct with different waveforms. The unknown-1-4 dissonant band (862-1047 Hz) should stay — it provides the "something unknown" sound character. The rebalancing task is purely a `synth/config.go` constant edit, not a code change. --- ## Version Compatibility (Unchanged) | Package | Version | Compatible With | Notes | |---------|---------|-----------------|-------| | `gopacket/gopacket` | v1.5.0 | Go 1.24+ | New protocol rules use existing API — no compat concerns | | All other existing packages | (unchanged) | (unchanged) | No updates needed | --- ## Confidence Assessment | Area | Confidence | Source | |------|------------|--------| | gopacket LayerType SIP exists at v1.5.0 | HIGH | Direct inspection of `layers/layertypes.go` and `layers/sip.go` via GitHub | | gopacket LayerType TLS exists at v1.5.0 | HIGH | Direct inspection of `layers/layertypes.go` and `layers/ports.go` via GitHub | | gopacket port registrations (ports.go) | HIGH | Direct inspection of `layers/ports.go` via GitHub; explicit list of pre-registered UDP/TCP ports | | mDNS NOT registered in gopacket layers | HIGH | Port 5353 absent from `layers/ports.go` pre-registration list; confirmed via GitHub | | QUIC NOT registered in gopacket layers | HIGH | No `quic.go` in layers directory; no port 443 UDP registration in `layers/ports.go` | | SNMP, LDAP, RDP, SMB, FTP, IMAP, POP3 NOT in gopacket layers | HIGH | No corresponding .go files found in layers directory | | Port-based Rule classification sufficiency for all new protocols | HIGH | All protocols have well-known IANA port assignments; existing Rule struct handles them identically to SSH/HTTP/SMTP | | No new external dependencies needed | HIGH | All new functionality is data additions (constants, map entries) to existing packages | --- ## Sources - `github.com/gopacket/gopacket/blob/master/layers/layertypes.go` — LayerTypeSIP (id 133), LayerTypeTLS (id 140) confirmed - `github.com/gopacket/gopacket/blob/master/layers/sip.go` — SIP decoder implementation confirmed - `github.com/gopacket/gopacket/blob/master/layers/ports.go` — UDP/TCP port pre-registration list; mDNS (5353), SNMP (161/162), QUIC (UDP 443) absent; SIP (5060, 5082, 5083) present - `github.com/gopacket/gopacket/tree/master/layers` — directory listing; no mdns.go, quic.go, snmp.go, ldap.go, smb.go, rdp.go, ftp.go, imap.go, or pop3.go files - `pkg.go.dev/github.com/gopacket/gopacket/layers` — package index confirming layer types - IANA port assignments — standard reference for FTP/21, IMAP/143, POP3/110, SNMP/161, LDAP/389, RDP/3389, SMB/445, mDNS/5353, SIP/5060, QUIC/UDP-443 --- *Stack research for: NetSynth v1.2 — Extended Protocol Coverage with Grouped Sound Families* *Researched: 2026-03-26*