redhound 1.0.1 → 2.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +97 -31
  4. data/docs/API.md +76 -0
  5. data/docs/FILTERS.md +37 -0
  6. data/docs/MIGRATION.md +23 -0
  7. data/docs/PROTOCOLS.md +45 -0
  8. data/docs/USAGE.md +82 -0
  9. data/docs/VALIDATION.md +59 -0
  10. data/docs/json-schema.json +64 -0
  11. data/exe/redhound +2 -1
  12. data/lib/redhound/analysis/flow_key.rb +53 -0
  13. data/lib/redhound/analysis/flow_table.rb +117 -0
  14. data/lib/redhound/analysis/ip_reassembler.rb +176 -0
  15. data/lib/redhound/analysis/stats.rb +138 -0
  16. data/lib/redhound/analysis/tcp_analysis.rb +43 -0
  17. data/lib/redhound/analysis/tcp_reassembler.rb +124 -0
  18. data/lib/redhound/analysis/tcp_stream.rb +151 -0
  19. data/lib/redhound/analysis.rb +129 -0
  20. data/lib/redhound/capture/bsd/bpf_device.rb +152 -0
  21. data/lib/redhound/capture/bsd/constants.rb +29 -0
  22. data/lib/redhound/capture/file_source.rb +83 -0
  23. data/lib/redhound/capture/interface.rb +66 -0
  24. data/lib/redhound/capture/linktype.rb +30 -0
  25. data/lib/redhound/capture/linux/constants.rb +37 -0
  26. data/lib/redhound/capture/linux/cooked.rb +18 -0
  27. data/lib/redhound/capture/linux/ifreq.rb +42 -0
  28. data/lib/redhound/capture/linux/packet_socket.rb +180 -0
  29. data/lib/redhound/capture/linux/sockaddr_ll.rb +33 -0
  30. data/lib/redhound/capture/linux/tpacket_v3.rb +132 -0
  31. data/lib/redhound/capture/source.rb +79 -0
  32. data/lib/redhound/capture/stats.rb +22 -0
  33. data/lib/redhound/capture.rb +69 -0
  34. data/lib/redhound/cli/command.rb +42 -0
  35. data/lib/redhound/cli/options.rb +133 -0
  36. data/lib/redhound/cli/privileges.rb +29 -0
  37. data/lib/redhound/cli/runner.rb +129 -0
  38. data/lib/redhound/context.rb +20 -0
  39. data/lib/redhound/cursor.rb +69 -0
  40. data/lib/redhound/diagnostic.rb +7 -0
  41. data/lib/redhound/dissector.rb +138 -0
  42. data/lib/redhound/engine.rb +66 -0
  43. data/lib/redhound/errors.rb +38 -0
  44. data/lib/redhound/field.rb +62 -0
  45. data/lib/redhound/file/format.rb +56 -0
  46. data/lib/redhound/file/pcap_reader.rb +43 -0
  47. data/lib/redhound/file/pcap_writer.rb +72 -0
  48. data/lib/redhound/file/pcapng_reader.rb +209 -0
  49. data/lib/redhound/file/pcapng_writer.rb +143 -0
  50. data/lib/redhound/file/rotating_writer.rb +98 -0
  51. data/lib/redhound/filter/analyzer.rb +197 -0
  52. data/lib/redhound/filter/bpf/assembler.rb +121 -0
  53. data/lib/redhound/filter/bpf/disassembler.rb +58 -0
  54. data/lib/redhound/filter/bpf/validator.rb +77 -0
  55. data/lib/redhound/filter/bpf/vm.rb +108 -0
  56. data/lib/redhound/filter/codegen.rb +413 -0
  57. data/lib/redhound/filter/lexer.rb +46 -0
  58. data/lib/redhound/filter/parser.rb +206 -0
  59. data/lib/redhound/filter/program.rb +55 -0
  60. data/lib/redhound/filter.rb +30 -0
  61. data/lib/redhound/layer.rb +75 -0
  62. data/lib/redhound/output/fields.rb +20 -0
  63. data/lib/redhound/output/follow.rb +59 -0
  64. data/lib/redhound/output/hexdump.rb +29 -0
  65. data/lib/redhound/output/json.rb +32 -0
  66. data/lib/redhound/output/summary.rb +59 -0
  67. data/lib/redhound/output/timestamp.rb +34 -0
  68. data/lib/redhound/output/tree.rb +24 -0
  69. data/lib/redhound/packet.rb +63 -0
  70. data/lib/redhound/protocols/arp.rb +39 -0
  71. data/lib/redhound/protocols/checksum.rb +38 -0
  72. data/lib/redhound/protocols/data.rb +21 -0
  73. data/lib/redhound/protocols/dhcp.rb +124 -0
  74. data/lib/redhound/protocols/dns.rb +268 -0
  75. data/lib/redhound/protocols/ethernet.rb +24 -0
  76. data/lib/redhound/protocols/http.rb +183 -0
  77. data/lib/redhound/protocols/icmp.rb +191 -0
  78. data/lib/redhound/protocols/ipv4.rb +56 -0
  79. data/lib/redhound/protocols/ipv6.rb +65 -0
  80. data/lib/redhound/protocols/link.rb +70 -0
  81. data/lib/redhound/protocols/llc.rb +37 -0
  82. data/lib/redhound/protocols/ntp.rb +47 -0
  83. data/lib/redhound/protocols/tcp.rb +80 -0
  84. data/lib/redhound/protocols/tls.rb +218 -0
  85. data/lib/redhound/protocols/tunnel.rb +48 -0
  86. data/lib/redhound/protocols/udp.rb +32 -0
  87. data/lib/redhound/protocols/vlan.rb +23 -0
  88. data/lib/redhound/reader.rb +8 -0
  89. data/lib/redhound/registry.rb +64 -0
  90. data/lib/redhound/stream_dissector.rb +168 -0
  91. data/lib/redhound/util/seq.rb +21 -0
  92. data/lib/redhound/version.rb +2 -1
  93. data/lib/redhound/writer.rb +25 -43
  94. data/lib/redhound.rb +81 -9
  95. data/sig/generated/redhound/analysis/flow_key.rbs +15 -0
  96. data/sig/generated/redhound/analysis/flow_table.rbs +98 -0
  97. data/sig/generated/redhound/analysis/ip_reassembler.rbs +40 -0
  98. data/sig/generated/redhound/analysis/stats.rbs +77 -0
  99. data/sig/generated/redhound/analysis/tcp_analysis.rbs +15 -0
  100. data/sig/generated/redhound/analysis/tcp_reassembler.rbs +27 -0
  101. data/sig/generated/redhound/analysis/tcp_stream.rbs +60 -0
  102. data/sig/generated/redhound/analysis.rbs +38 -0
  103. data/sig/generated/redhound/capture/bsd/bpf_device.rbs +39 -0
  104. data/sig/generated/redhound/capture/bsd/constants.rbs +40 -0
  105. data/sig/generated/redhound/capture/file_source.rbs +34 -0
  106. data/sig/generated/redhound/capture/interface.rbs +53 -0
  107. data/sig/generated/redhound/capture/linktype.rbs +20 -0
  108. data/sig/generated/redhound/capture/linux/constants.rbs +58 -0
  109. data/sig/generated/redhound/capture/linux/cooked.rbs +15 -0
  110. data/sig/generated/redhound/capture/linux/ifreq.rbs +18 -0
  111. data/sig/generated/redhound/capture/linux/packet_socket.rbs +57 -0
  112. data/sig/generated/redhound/capture/linux/sockaddr_ll.rbs +31 -0
  113. data/sig/generated/redhound/capture/linux/tpacket_v3.rbs +35 -0
  114. data/sig/generated/redhound/capture/source.rbs +44 -0
  115. data/sig/generated/redhound/capture/stats.rbs +25 -0
  116. data/sig/generated/redhound/capture.rbs +14 -0
  117. data/sig/generated/redhound/cli/command.rbs +12 -0
  118. data/sig/generated/redhound/cli/options.rbs +25 -0
  119. data/sig/generated/redhound/cli/privileges.rbs +12 -0
  120. data/sig/generated/redhound/cli/runner.rbs +27 -0
  121. data/sig/generated/redhound/context.rbs +27 -0
  122. data/sig/generated/redhound/cursor.rbs +59 -0
  123. data/sig/generated/redhound/diagnostic.rbs +21 -0
  124. data/sig/generated/redhound/dissector.rbs +113 -0
  125. data/sig/generated/redhound/engine.rbs +23 -0
  126. data/sig/generated/redhound/errors.rbs +56 -0
  127. data/sig/generated/redhound/field.rbs +74 -0
  128. data/sig/generated/redhound/file/format.rbs +33 -0
  129. data/sig/generated/redhound/file/pcap_reader.rbs +19 -0
  130. data/sig/generated/redhound/file/pcap_writer.rbs +38 -0
  131. data/sig/generated/redhound/file/pcapng_reader.rbs +54 -0
  132. data/sig/generated/redhound/file/pcapng_writer.rbs +50 -0
  133. data/sig/generated/redhound/file/rotating_writer.rbs +42 -0
  134. data/sig/generated/redhound/filter/analyzer.rbs +42 -0
  135. data/sig/generated/redhound/filter/bpf/assembler.rbs +39 -0
  136. data/sig/generated/redhound/filter/bpf/disassembler.rbs +18 -0
  137. data/sig/generated/redhound/filter/bpf/validator.rbs +30 -0
  138. data/sig/generated/redhound/filter/bpf/vm.rbs +26 -0
  139. data/sig/generated/redhound/filter/codegen.rbs +101 -0
  140. data/sig/generated/redhound/filter/lexer.rbs +15 -0
  141. data/sig/generated/redhound/filter/parser.rbs +65 -0
  142. data/sig/generated/redhound/filter/program.rbs +48 -0
  143. data/sig/generated/redhound/filter.rbs +10 -0
  144. data/sig/generated/redhound/layer.rbs +81 -0
  145. data/sig/generated/redhound/output/fields.rbs +15 -0
  146. data/sig/generated/redhound/output/follow.rbs +21 -0
  147. data/sig/generated/redhound/output/hexdump.rbs +15 -0
  148. data/sig/generated/redhound/output/json.rbs +18 -0
  149. data/sig/generated/redhound/output/summary.rbs +21 -0
  150. data/sig/generated/redhound/output/timestamp.rbs +21 -0
  151. data/sig/generated/redhound/output/tree.rbs +15 -0
  152. data/sig/generated/redhound/packet.rbs +77 -0
  153. data/sig/generated/redhound/protocols/arp.rbs +15 -0
  154. data/sig/generated/redhound/protocols/checksum.rbs +15 -0
  155. data/sig/generated/redhound/protocols/data.rbs +15 -0
  156. data/sig/generated/redhound/protocols/dhcp.rbs +28 -0
  157. data/sig/generated/redhound/protocols/dns.rbs +42 -0
  158. data/sig/generated/redhound/protocols/ethernet.rbs +15 -0
  159. data/sig/generated/redhound/protocols/http.rbs +36 -0
  160. data/sig/generated/redhound/protocols/icmp.rbs +41 -0
  161. data/sig/generated/redhound/protocols/ipv4.rbs +15 -0
  162. data/sig/generated/redhound/protocols/ipv6.rbs +24 -0
  163. data/sig/generated/redhound/protocols/link.rbs +33 -0
  164. data/sig/generated/redhound/protocols/llc.rbs +15 -0
  165. data/sig/generated/redhound/protocols/ntp.rbs +17 -0
  166. data/sig/generated/redhound/protocols/tcp.rbs +25 -0
  167. data/sig/generated/redhound/protocols/tls.rbs +51 -0
  168. data/sig/generated/redhound/protocols/tunnel.rbs +24 -0
  169. data/sig/generated/redhound/protocols/udp.rbs +18 -0
  170. data/sig/generated/redhound/protocols/vlan.rbs +12 -0
  171. data/sig/generated/redhound/reader.rbs +7 -0
  172. data/sig/generated/redhound/registry.rbs +45 -0
  173. data/sig/generated/redhound/stream_dissector.rbs +44 -0
  174. data/sig/generated/redhound/util/seq.rbs +20 -0
  175. data/sig/generated/redhound/version.rbs +1 -0
  176. data/sig/generated/redhound/writer.rbs +6 -19
  177. data/sig/generated/redhound.rbs +18 -0
  178. data/sig/shims/io.rbs +7 -0
  179. data/sig/shims/process.rbs +3 -0
  180. metadata +175 -55
  181. data/CODE_OF_CONDUCT.md +0 -132
  182. data/Dockerfile +0 -7
  183. data/Rakefile +0 -15
  184. data/Steepfile +0 -4
  185. data/docker-compose.yml +0 -9
  186. data/lib/redhound/analyzer.rb +0 -34
  187. data/lib/redhound/builder/packet_mreq.rb +0 -56
  188. data/lib/redhound/builder/socket.rb +0 -35
  189. data/lib/redhound/builder.rb +0 -4
  190. data/lib/redhound/command.rb +0 -67
  191. data/lib/redhound/l2/ether.rb +0 -68
  192. data/lib/redhound/l2/protocol.rb +0 -33
  193. data/lib/redhound/l2.rb +0 -4
  194. data/lib/redhound/l3/arp.rb +0 -114
  195. data/lib/redhound/l3/base.rb +0 -49
  196. data/lib/redhound/l3/ipv4.rb +0 -95
  197. data/lib/redhound/l3/ipv6.rb +0 -69
  198. data/lib/redhound/l3/protocol.rb +0 -173
  199. data/lib/redhound/l3/resolver.rb +0 -30
  200. data/lib/redhound/l3.rb +0 -9
  201. data/lib/redhound/l4/base.rb +0 -31
  202. data/lib/redhound/l4/icmp.rb +0 -71
  203. data/lib/redhound/l4/resolver.rb +0 -28
  204. data/lib/redhound/l4/udp.rb +0 -63
  205. data/lib/redhound/l4.rb +0 -6
  206. data/lib/redhound/receiver.rb +0 -45
  207. data/lib/redhound/resolver.rb +0 -22
  208. data/lib/redhound/source/socket.rb +0 -18
  209. data/lib/redhound/source.rb +0 -3
  210. data/rbs_collection.lock.yaml +0 -20
  211. data/rbs_collection.yaml +0 -17
  212. data/sig/generated/redhound/analyzer.rbs +0 -14
  213. data/sig/generated/redhound/builder/packet_mreq.rbs +0 -39
  214. data/sig/generated/redhound/builder/socket.rbs +0 -24
  215. data/sig/generated/redhound/command.rbs +0 -19
  216. data/sig/generated/redhound/l2/ether.rbs +0 -41
  217. data/sig/generated/redhound/l2/protocol.rbs +0 -15
  218. data/sig/generated/redhound/l3/arp.rbs +0 -57
  219. data/sig/generated/redhound/l3/base.rbs +0 -28
  220. data/sig/generated/redhound/l3/ipv4.rbs +0 -53
  221. data/sig/generated/redhound/l3/ipv6.rbs +0 -38
  222. data/sig/generated/redhound/l3/protocol.rbs +0 -16
  223. data/sig/generated/redhound/l3/resolver.rbs +0 -16
  224. data/sig/generated/redhound/l4/base.rbs +0 -19
  225. data/sig/generated/redhound/l4/icmp.rbs +0 -33
  226. data/sig/generated/redhound/l4/resolver.rbs +0 -16
  227. data/sig/generated/redhound/l4/udp.rbs +0 -36
  228. data/sig/generated/redhound/receiver.rbs +0 -19
  229. data/sig/generated/redhound/resolver.rbs +0 -11
  230. data/sig/generated/redhound/source/socket.rbs +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fc9146df6d249b2bdd3ca7c529c6d72eaad8c78970e6cc21d4be41f9e233a25
4
- data.tar.gz: 9f66932249c4235042d3934579fdf7f9be92ad531f30e1e5c05ed1a55ae436e4
3
+ metadata.gz: dd9c749a43481a575813ed4bacad00dbc54dfecc7701e63a0baeb6789a1d8680
4
+ data.tar.gz: 791efd1f3e810c7e67bcf5abfbbc3e02aa0db460bd8dca51b83beecd94797bae
5
5
  SHA512:
6
- metadata.gz: 4ee95bd38fa1717c5286ae994db3b4d2c024c07119489d65f7b48a2cd9f5337b1a0cf0ebf36659f37d113052aaee178cd8ee29d50c2d995bee06d97443335fc6
7
- data.tar.gz: 895d8f8b92858aaf63ac5bfc9b7ee2dc4a4fb594313e20052a96bdf893380aaae4853988c8e2966657ea3f2788eabf604a3ef44ebb16cf9954f0df5c4aeef444
6
+ metadata.gz: 99e69fb1319c95448572dcfc2151da08987523b95301c1b50f1f1345b269752cd98e4ddcd3c24f711866bc6b7754793061b51f1d208f92428dfd337a007ac444
7
+ data.tar.gz: 1081108559a19f9f17b0c482dc91285f4950b1f7dda81c4f1221e2eac76206831839d265d50139182060c203e12dfd7752e434ecfae2fa5479310260b039fa7f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.0.0.rc1 - 2026-10-01
6
+
7
+ ### Breaking changes
8
+
9
+ - Replace the Analyzer/Builder/L2/L3/L4 API with Packet, Layer, Field and the Dissector DSL; use `Redhound.open`, `Redhound.capture` and `Redhound.dissect` for library integrations.
10
+ - Use a one-line summary by default. Select `-V` or `-T tree` for detailed output; `-v` controls verbosity and `--version` prints the version.
11
+ - Make `-w` save packets without dissection or display unless an output format is also selected.
12
+
13
+ ### Features
14
+
15
+ - Read and write pcap and pcapng, including stdin/stdout, interface metadata and size/time rotation.
16
+ - Capture on macOS BPF devices and Linux socket/TPACKET_V3 backends, including Linux `any`, directions, snaplen and drop statistics.
17
+ - Compile tcpdump-style capture filters to validated cBPF for kernel capture and file filtering; support filter files and instruction dumps.
18
+ - Decode VLAN/QinQ, LLC/SNAP, cooked/null/raw links, IPv6 extensions, ICMPv6/NDP, IGMPv3, DNS/mDNS/LLMNR, DHCP, NTP, HTTP/1.x, TLS hellos, GRE and VXLAN.
19
+ - Track flows, reassemble IP fragments and TCP application messages, report TCP analysis flags/RTT, and follow TCP streams as ASCII, hex or exact bytes.
20
+ - Add tree, hex, JSON/NDJSON and selected-field output, conversation/endpoint/interval/protocol statistics, decode-as overrides and custom Ruby dissectors.
21
+ - Support privilege dropping after capture setup and write capture files with private permissions.
22
+
23
+ ### Bug fixes
24
+
25
+ - Fix crashes on padded ARP, short frames and malformed packet headers.
26
+ - Correct IPv4 and IPv6 fields, IP options and transport payload boundaries; label ICMP types/codes and avoid false checksum failures on incomplete IPv6 fragments.
27
+ - Display TCP ports, sequence numbers, flags and payload lengths.
28
+ - Escape terminal control characters in captured payloads.
29
+ - Save packets before analysis and close captures reliably on termination or errors.
30
+ - Capture larger frames with kernel timestamps and remove loopback duplicates.
31
+ - List interfaces without duplicates and accept interface indexes.
32
+ - Protect read inputs and their aliases from rotated-output overwrites, validate filters on empty captures, and stop stdin reads cleanly on termination.
33
+ - Decode foreign-endian loopback capture headers correctly and preserve original wire lengths for truncated VLAN packets.
34
+ - Handle HEAD responses and pipelined HTTP correctly, reassemble HTTP on nonstandard ports, and report missing or incomplete TCP data at FIN and EOF.
35
+
5
36
  ## 1.0.1 - 2025-01-17
6
37
 
7
38
  - Fix an NameError in Redhound::L3::Arp
data/README.md CHANGED
@@ -1,51 +1,117 @@
1
1
  # Redhound [![Gem Version](https://badge.fury.io/rb/redhound.svg)](https://badge.fury.io/rb/redhound) [![Test](https://github.com/ydah/redhound/actions/workflows/main.yml/badge.svg)](https://github.com/ydah/redhound/actions/workflows/main.yml)
2
2
 
3
- Pure Ruby packet analyzer.
4
- At this time, it is only guaranteed to work on Linux.
3
+ Capture and analyze network packets in Pure Ruby. Redhound runs on Linux and
4
+ macOS, reads and writes pcap/pcapng, compiles capture filters to cBPF, and
5
+ provides summary, tree, hex and JSON output. No libpcap, Fiddle or runtime gem
6
+ dependency is required. Ruby 3.3 or later is required.
5
7
 
6
- ## Installation
8
+ Version 2 is currently a release candidate. See [validation status](docs/VALIDATION.md)
9
+ for remaining GA evaluation gates.
7
10
 
8
- Install the gem and add to the application's Gemfile by executing:
11
+ ## Installation
9
12
 
10
- ```bash
11
- bundle add redhound
13
+ ```sh
14
+ gem install redhound --pre
12
15
  ```
13
16
 
14
- If bundler is not being used to manage dependencies, install the gem by executing:
17
+ Or add `gem 'redhound', '~> 2.0.0.rc1'` to your Gemfile.
15
18
 
16
- ```bash
17
- gem install redhound
19
+ ## Usage
20
+
21
+ ```sh
22
+ redhound -D
23
+ sudo redhound -i any 'tcp port 443'
24
+ sudo redhound -i en0 -c 100 -w trace.pcapng
25
+ redhound -r trace.pcapng -T tree
26
+ redhound -r trace.pcap --stats conv,tcp
27
+ redhound -r trace.pcap --follow tcp,ascii,0
18
28
  ```
19
29
 
20
- ## Usage
30
+ Live capture normally requires root or capture permissions. File analysis does
31
+ not. `-i any` is Linux only; use `lo0`/`en0` on macOS. `-w` alone saves packets
32
+ without dissection; add `-T summary` to also print them. Addresses are numeric
33
+ by default. Use `-N` to resolve names.
34
+
35
+ ```text
36
+ Usage: redhound [options] [filter expression]
37
+ -i, --interface IF interface name, index or any
38
+ -D, --list-interfaces list interfaces and exit
39
+ -r, --read FILE read pcap or pcapng (- for stdin)
40
+ -c, --count N stop after N packets
41
+ -s, --snaplen N capture length (default 262144)
42
+ -p, --no-promiscuous disable promiscuous capture
43
+ -B, --buffer-size KiB kernel buffer size
44
+ -Q, --direction DIR capture direction
45
+ -F, --filter-file FILE read a capture filter
46
+ --capture-backend BACKEND capture backend
47
+ -w, --write FILE write capture (- for stdout)
48
+ --format FORMAT capture file format
49
+ -C MB rotate after MB (decimal)
50
+ -G SECONDS rotate at this interval
51
+ -W N maximum rotation file count
52
+ --post-rotate-command CMD command to run after closing each file
53
+ -U, --packet-buffered flush each packet
54
+ -T, --output-format FORMAT packet output format
55
+ -V show packet details
56
+ -q quick output and no capture statistics
57
+ --time-stamp-precision PRECISION
58
+ timestamp digits
59
+ -N, --resolve-names resolve addresses
60
+ -n disable address resolution (default)
61
+ --stats SPEC io,N / conv,TYPE / endpoints,TYPE / phs
62
+ --follow SPEC tcp,ascii|hex|raw,N
63
+ --decode-as RULE e.g. udp.port==8443,dns
64
+ -I, --require FILE load a custom dissector
65
+ -d dump cBPF instructions
66
+ -Z, --relinquish-privileges USER drop capture privileges
67
+ --list-protocols list protocols and fields
68
+ --debug print error backtraces
69
+ --no-yjit disable automatic YJIT activation
70
+ -h, --help print help
71
+ --version print version
72
+ -e [-T fields: FIELD] link header or selected field (repeatable)
73
+ -v / -vv / -vvv verbosity and checksum verification
74
+ -t / -tt / -ttt / -tttt / -ttttt timestamp style
75
+ -x / -xx / -X / -XX hex dump, with link header / ASCII
76
+ ```
21
77
 
22
- ```command
23
- ___ ____ __
24
- / _ \___ ___/ / / ___ __ _____ ___/ /
25
- / , _/ -_) _ / _ \/ _ \/ // / _ \/ _ /
26
- /_/|_|\__/\_,_/_//_/\___/\_,_/_//_/\_,_/
78
+ See [usage and tcpdump option mapping](docs/USAGE.md),
79
+ [supported protocols](docs/PROTOCOLS.md), [capture filters](docs/FILTERS.md),
80
+ [Ruby API and plugins](docs/API.md), and [migration from 1.x](docs/MIGRATION.md).
27
81
 
28
- Version: 1.0.1
29
- Dump and analyze network packets.
82
+ ## Library
30
83
 
31
- Usage: redhound [options] ...
84
+ ```ruby
85
+ require 'redhound'
32
86
 
33
- Options:
34
- -i, --interface INTERFACE name or idx of interface
35
- -D, --list-interfaces print list of interfaces and exit
36
- -w FILE write packets to a pcap capture file format to file
37
- -h, --help display this help and exit
38
- -v, --version display version information and exit
39
- ```
87
+ Redhound.open('trace.pcapng', filter: 'udp port 53') do |reader|
88
+ reader.each { |packet| puts packet.summary }
89
+ end
40
90
 
41
- ## Contributing
91
+ packet = Redhound.dissect(frame_bytes, linktype: :ethernet)
92
+ p packet['ip.src']
93
+ p packet.to_h
94
+ ```
42
95
 
43
- Bug reports and pull requests are welcome on GitHub at https://github.com/ydah/redhound. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/ydah/redhound/blob/main/CODE_OF_CONDUCT.md).
96
+ ## Development
44
97
 
45
- ## License
98
+ ```sh
99
+ bundle install
100
+ bundle exec rbs collection install --frozen
101
+ bundle exec rake
102
+ bundle exec yard stats --list-undoc
103
+ FUZZ_ITERATIONS=1000000 bundle exec rspec spec/fuzz
104
+ sudo -E env "PATH=$PATH" REDHOUND_LIVE=1 bundle exec rspec --tag live
105
+ ```
46
106
 
47
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
107
+ Differential tests use tcpdump/tshark as development tools. Fixtures are
108
+ regenerated with `ruby -Ilib spec/fixtures/generators/applications.rb` and
109
+ `ruby -Ilib spec/fixtures/generators/network.rb`. Update output snapshots with
110
+ `UPDATE_GOLDEN=1 bundle exec rspec spec/golden`, then review the changes.
111
+ See [benchmark results](bench/RESULTS.md) for reproducible performance checks.
48
112
 
49
- ## Code of Conduct
113
+ ## Contributing and license
50
114
 
51
- Everyone interacting in the Redhound project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ydah/redhound/blob/main/CODE_OF_CONDUCT.md).
115
+ Bug reports and pull requests are welcome at [GitHub](https://github.com/ydah/redhound).
116
+ Contributors must follow the [code of conduct](CODE_OF_CONDUCT.md).
117
+ Redhound is available under the [MIT License](LICENSE.txt).
data/docs/API.md ADDED
@@ -0,0 +1,76 @@
1
+ # Ruby API
2
+
3
+ ```ruby
4
+ require 'redhound'
5
+
6
+ Redhound.open('trace.pcapng', filter: 'tcp port 443') do |reader|
7
+ reader.each do |packet|
8
+ puts packet.summary
9
+ puts packet['ip.src']
10
+ p packet[:tcp]&.values
11
+ p packet.to_h
12
+ end
13
+ end
14
+
15
+ Redhound.capture(interface: 'lo', count: 10, filter: 'udp') do |packet|
16
+ puts packet.summary
17
+ end
18
+
19
+ packet = Redhound.dissect(frame_bytes, linktype: :ethernet,
20
+ timestamp_ns: 1_700_000_000_123_456_789)
21
+ Redhound::Writer.open('copy.pcapng') { |writer| writer << packet }
22
+ ```
23
+
24
+ `Redhound.open` accepts a path, `-`, or a binary IO. Reader is Enumerable,
25
+ provides `next_packet`, `stats`, `interfaces`, `stop`, and `close`; a block always
26
+ closes it. `Redhound.capture` yields packets and closes the live source even if
27
+ the block fails. Capture options include `snaplen`, `promiscuous`, `buffer_size`
28
+ (bytes), `direction` (`:in`, `:out`, `:inout`), `backend`, and `filter`.
29
+
30
+ `Redhound.dissect` creates an immutable-byte Packet and decodes its layers lazily.
31
+ Packet metadata includes `timestamp_ns`, `original_length`, `linktype`,
32
+ `interface`, `direction`, and `number`. `caplen`, `truncated?`, and `time` expose
33
+ capture properties. A symbol index selects the first Layer; a dotted string
34
+ selects a decoded field value. `layers_of`, `innermost`, and `field_values` expose
35
+ repeated or tunneled layers. Layer has `values`, `fields`, and `diagnostics`.
36
+ `to_h` follows [json-schema.json](json-schema.json); bytes use hexadecimal strings,
37
+ addresses use text, booleans remain booleans, repeated fields become arrays.
38
+
39
+ Writer accepts `format: :pcap|:pcapng`, `linktype`, `snaplen`, `precision`,
40
+ `packet_buffered`, `max_bytes`, `interval`, `file_count`, and
41
+ `post_rotate_command`. `write`/`<<`, `flush`, `write_stats`, and `close` are
42
+ available. Use a block for deterministic closure.
43
+
44
+ ## Custom dissectors
45
+
46
+ ```ruby
47
+ class Example < Redhound::Dissector
48
+ protocol :example, name: 'Example protocol', short: 'EXAMPLE'
49
+ dissects_on 'udp.port', 9999
50
+ header do
51
+ uint16 :message_id, 'example.id'
52
+ uint8 :kind, 'example.kind'
53
+ end
54
+
55
+ def summary(layer)
56
+ "Example id #{layer[:message_id]}"
57
+ end
58
+ end
59
+ ```
60
+
61
+ Header fields support unsigned integers, MAC/IPv4/IPv6 addresses and bit fields.
62
+ Use `dissect(ctx, layer)` for bounded variable-length parsing through
63
+ `ctx.cursor`; append fields with `layer.add`. `next_dissector(ctx, layer)` returns
64
+ a registered dissector class, or nil. Child cursors cannot escape their packet
65
+ bounds. Truncated input creates a diagnostic. `REDHOUND_STRICT=1` re-raises
66
+ unexpected implementation errors for tests. Ordinary malformed input remains
67
+ safe. Registry copies allow per-session decode-as rules without changing global
68
+ registrations.
69
+
70
+ `Analysis::Session#update(packet)` adds flow/stream analysis and completed
71
+ application PDUs. It provides bounded flow/reassembly state and `snapshot`,
72
+ `finish`; library users opt into it explicitly. Reassembly does not modify the
73
+ packet's captured bytes. `Filter.compile(expression, linktype:)` returns a
74
+ validated cBPF Program with `match?`, `evaluate`, `serialize`, and `disassemble`.
75
+
76
+ Generate reference documentation with `bundle exec yard doc lib/**/*.rb`.
data/docs/FILTERS.md ADDED
@@ -0,0 +1,37 @@
1
+ # Capture filters
2
+
3
+ Redhound compiles filters to classic BPF in Ruby. Live capture attaches the verified program to the kernel; file capture executes the same instructions in the Ruby VM. No libpcap or external command is needed at runtime.
4
+
5
+ ```ruby
6
+ program = Redhound::Filter.compile('ip and udp dst port 53', linktype: :ethernet)
7
+ program.match?(packet)
8
+ program.instructions # [code, jt, jf, k] tuples
9
+ program.packed # native struct sock_filter bytes
10
+ program.disassemble(format: :text) # :ruby and :decimal are also available
11
+ ```
12
+
13
+ Supported primitives include `ip`, `ip6`, `arp`, `rarp`, `tcp`, `udp`, `sctp`, `icmp`, `icmp6`, and `igmp`; `host`, `net`, `port`, `portrange`, `proto`; `src`, `dst`, `src or dst`, `src and dst`; Ethernet addresses and EtherTypes; `vlan [id]`; `greater`, `less`, `broadcast`, and `multicast`. Numeric IPv4 and IPv6 addresses, CIDR networks, IPv4 netmasks, host names, protocol names, and service names are resolved when compiling. For reserved protocol names after `proto`, tcpdump spells them with an escape, e.g. `ip proto \tcp`; Redhound also accepts the unescaped spelling.
14
+
15
+ Identical qualifiers carry forward: `tcp dst port 80 or 443` means `tcp dst port 80 or tcp dst port 443`. Parenthesized operand lists work as well: `tcp dst port (80 or 443)`.
16
+
17
+ As specified by [pcap-filter](https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-filter.manmisc.in), `and` and `or` have **equal precedence** and associate from left to right; `not` binds more tightly. Thus `udp or tcp and port 443` means `(udp or tcp) and port 443`. Use parentheses to express a different grouping. This corrects the separate AND/OR precedence in the original design's EBNF and is checked against tcpdump.
18
+
19
+ Arithmetic supports `len`, packet accesses of width 1, 2, or 4, `+ - * / % & | ^ << >>`, unary minus, and comparisons `= == != < <= > >=` with unsigned 32-bit values:
20
+
21
+ ```text
22
+ ip[2:2] > 576
23
+ tcp[tcpflags] & (tcp-syn | tcp-fin) != 0
24
+ (ip[0] & 15) * 4 = 20
25
+ icmp6[0] = 128
26
+ len >= 100
27
+ ```
28
+
29
+ Transport accesses and ports check IPv4 fragment offsets and honor IPv4 options. IPv6 ports require a directly following TCP/UDP/SCTP header; extension-header traversal (`protochain`) is outside the v2 subset. Plain protocol predicates additionally recognize an IPv6 fragment header's next-header field. `tcp[]`, `udp[]`, `icmp[]`, and `igmp[]` access IPv4 transport headers, matching libpcap; `icmp6[]` accesses a directly following ICMPv6 header.
30
+
31
+ `vlan` changes the offsets for all following primitives, including those in subsequent `or` branches, matching tcpdump. Repeated `vlan` predicates support nested tags. Linux live Ethernet filters also recognize hardware-stripped tags through VLAN ancillary loads; the VM reads these from `packet.meta[:vlan_tci]` (including tag ID zero). Linux `any` filters compile for kernel network-layer bytes and protocol metadata, while file filters use the synthetic SLL2 header.
32
+
33
+ Linktypes are Ethernet (1), RAW (101), Linux SLL (113), Linux SLL2 (276), NULL (0), LOOP (108), IPv4 (228), and IPv6 (229). Their corresponding symbol names are `:ethernet`, `:raw`, `:linux_sll`, `:linux_sll2`, `:null`, `:loop`, `:ipv4`, and `:ipv6`. Ethernet address and VLAN predicates require Ethernet. IPv4 `broadcast` without an interface netmask recognizes zero and all-one destinations; link broadcast compares the Ethernet destination.
34
+
35
+ `FilterSyntaxError` supplies the original expression and error position. Programs are limited to 4096 instructions and 16 scratch words; oversized programs raise `FilterTooLarge`. The verifier rejects invalid opcodes, jumps, memory accesses, uninitialized scratch reads, and constant zero divisors. Truncated packet loads and dynamic zero divisors reject the packet. Conditional branches beyond 255 instructions use forward jump trampolines.
36
+
37
+ The differential suite contains more than 160 expressions and compares selected packets and tcpdump-generated bytecode on Ethernet, RAW, SLL, SLL2, and NULL. tcpdump is a test dependency only. Historical protocols, `gateway`, and `protochain` are unsupported; network operands use numeric addresses rather than `/etc/networks` aliases.
data/docs/MIGRATION.md ADDED
@@ -0,0 +1,23 @@
1
+ # Migrating from 1.x
2
+
3
+ Redhound 2 replaces the former Analyzer/Builder/L2/L3/L4 classes with Packet,
4
+ Layer, Field and Dissector. Those internal classes have been removed. Migrate
5
+ library integrations to the APIs in [API.md](API.md). Ruby 3.3 remains the
6
+ minimum version.
7
+
8
+ The default CLI output is now a one-line summary. Use `-V` or `-T tree` for
9
+ packet details. `-v` now increases verbosity; use `--version` to print the
10
+ version. Numeric addresses remain the default.
11
+
12
+ `-w` alone records packets without printing or parsing them. Use `-w capture.pcap
13
+ -T summary` to save and display. Unknown protocols remain accessible as Data
14
+ layers, and malformed headers produce diagnostics instead of terminating the
15
+ capture. Payload text escapes terminal control bytes.
16
+
17
+ Interface indexes and Linux `any` are supported. Linux loopback duplicates are
18
+ removed. Capture timestamps come from the kernel; captured and original packet
19
+ lengths are recorded separately. pcapng supports multiple interfaces and metadata.
20
+
21
+ Version 2.0.0.rc1 is a prerelease. The two-week RC evaluation and long capture
22
+ soak gates remain prerequisites for GA; a 1.x maintenance deadline will be
23
+ announced when GA is published.
data/docs/PROTOCOLS.md ADDED
@@ -0,0 +1,45 @@
1
+ # Supported protocols
2
+
3
+ Built-in protocol registry (regenerate with `redhound --list-protocols`):
4
+
5
+ ```text
6
+ data: Data
7
+ eth: Ethernet eth.dst eth.src eth.type
8
+ vlan: 802.1Q VLAN vlan.priority vlan.dei vlan.id vlan.etype
9
+ llc: Logical Link Control llc.dsap llc.ssap llc.control
10
+ sll: Linux cooked capture sll.pkttype sll.hatype sll.halen sll.src sll.etype
11
+ sll2: Linux cooked capture v2 sll.etype sll.reserved sll.ifindex sll.hatype sll.pkttype sll.halen sll.src
12
+ null: BSD loopback
13
+ raw: Raw IP
14
+ arp: Address Resolution Protocol arp.hw.type arp.proto.type arp.hw.size arp.proto.size arp.opcode
15
+ ipv4: Internet Protocol v4 ip.version ip.hdr_len ip.dsfield.dscp ip.dsfield.ecn ip.len ip.id ip.flags.rb ip.flags.df ip.flags.mf ip.frag_offset ip.ttl ip.proto ip.checksum ip.src ip.dst
16
+ ipv6: Internet Protocol v6 ipv6.version ipv6.tclass ipv6.flow ipv6.plen ipv6.nxt ipv6.hlim ipv6.src ipv6.dst
17
+ ipv6_ext: IPv6 extension
18
+ udp: User Datagram Protocol udp.srcport udp.dstport udp.length udp.checksum
19
+ tcp: Transmission Control Protocol tcp.srcport tcp.dstport tcp.seq tcp.ack tcp.hdr_len tcp.reserved tcp.flags tcp.window_size_value tcp.checksum tcp.urgent_pointer
20
+ icmp: Internet Control Message Protocol icmp.type icmp.code icmp.checksum icmp.ident icmp.seq
21
+ icmpv6: ICMPv6 / Neighbor Discovery icmpv6.type icmpv6.code icmpv6.checksum
22
+ igmp: Internet Group Management Protocol igmp.type igmp.max_resp igmp.checksum
23
+ gre: Generic Routing Encapsulation gre.flags gre.proto
24
+ vxlan: Virtual eXtensible LAN vxlan.flags vxlan.vni_word
25
+ dns: Domain Name System
26
+ dhcp: Dynamic Host Configuration Protocol dhcp.type dhcp.hw.type dhcp.hw.len dhcp.hops dhcp.id dhcp.secs dhcp.flags dhcp.ip.client dhcp.ip.your dhcp.ip.server dhcp.ip.relay
27
+ ntp: Network Time Protocol ntp.flags.li ntp.flags.vn ntp.flags.mode ntp.stratum ntp.ppoll ntp.precision ntp.rootdelay ntp.rootdispersion ntp.refid ntp.reftime ntp.org ntp.rec ntp.xmt
28
+ http: Hypertext Transfer Protocol
29
+ tls: Transport Layer Security
30
+ ```
31
+
32
+ Variable-length fields, including options, resource records, application headers
33
+ and stream analysis, are added while parsing and appear in tree/JSON output.
34
+ Unknown protocols produce a Data layer; unsupported encrypted TLS content stays
35
+ opaque. HTTP is limited to HTTP/1.x. TLS parsing covers record framing and
36
+ ClientHello/ServerHello metadata including SNI, ALPN and supported versions.
37
+ DNS includes mDNS/LLMNR and TCP framing. IPv6 supports Hop-by-Hop, Routing,
38
+ Fragment, Destination and AH headers; ESP stops dissection. GRE and VXLAN
39
+ encapsulations decode inner packet layers.
40
+
41
+ Dissectors use checked cursors and parent payload boundaries. Truncation,
42
+ malformed lengths, checksum failures and reassembly gaps are available as
43
+ structured diagnostics. Checksum verification is enabled by `-v` or
44
+ `Engine.new(verify_checksums: true)`; outgoing/offloaded packets are marked
45
+ unverified.
data/docs/USAGE.md ADDED
@@ -0,0 +1,82 @@
1
+ # Using Redhound
2
+
3
+ Ruby 3.3 or later is required. File analysis needs no capture privileges.
4
+ Live capture uses Linux AF_PACKET or macOS BPF devices and normally requires
5
+ root or an appropriate device/capability grant. Runtime dependencies are Ruby's
6
+ standard libraries; neither libpcap nor a native extension is required.
7
+
8
+ ```sh
9
+ redhound -D
10
+ sudo redhound -i any 'tcp port 443'
11
+ sudo redhound -i en0 -c 100 -w trace.pcapng
12
+ redhound -r trace.pcapng -T tree
13
+ redhound -r trace.pcap -T ndjson 'udp port 53'
14
+ redhound -r trace.pcap -T fields -e ip.src -e tcp.dstport
15
+ redhound -r trace.pcap --stats conv,tcp --stats io,1
16
+ redhound -r trace.pcap --follow tcp,ascii,0
17
+ ```
18
+
19
+ Options must precede the filter expression. Quote filters containing shell
20
+ operators. Addresses are numeric by default; `-N` enables name resolution.
21
+ `--help` lists every option. `--list-protocols` lists registered protocols and
22
+ their declared fields. Dynamic fields also appear in detailed and JSON output.
23
+
24
+ ## Options for tcpdump users
25
+
26
+ | tcpdump | Redhound |
27
+ | --- | --- |
28
+ | `-i`, `-D`, `-c`, `-s`, `-p`, `-B`, `-Q` | Same purpose; `-i any` is Linux only |
29
+ | `-r`, `-w`, `-U` | Read/write pcap or pcapng; `-` selects stdin/stdout |
30
+ | `-C`, `-G`, `-W` | Size/time rotation and file count |
31
+ | `-e`, `-q`, `-v`, `-vv`, `-vvv` | Link header, short output, increasing detail/checksums |
32
+ | `-t` through `-ttttt` | No time, epoch, delta, date/time, elapsed time |
33
+ | `-x`, `-xx`, `-X`, `-XX` | Hex/ASCII, optionally including the link header |
34
+ | `-F`, `-d`, `-dd`, `-ddd` | Filter file and cBPF listing |
35
+ | `-Z USER` | Drop user/group privileges after opening capture and output |
36
+
37
+ See [supported capture filters](FILTERS.md). Capture filters select packets;
38
+ Wireshark display filters are not supported. `--decode-as udp.port==8443,dns`
39
+ overrides port dispatch. `-I plugin.rb` loads a Ruby dissector before capture.
40
+
41
+ ## Saving and rotation
42
+
43
+ `-w` alone saves raw packets without dissection. Add `-T summary` or `-V` to
44
+ also display them. Binary output to stdout cannot be combined with text output.
45
+ `--format pcapng` overrides the extension. pcapng preserves interface identities,
46
+ nanosecond timestamps, packet directions and available drop statistics.
47
+
48
+ `-C` uses decimal megabytes; `-G` uses seconds. Rotated files receive a five-digit
49
+ sequence before the extension. With `-C -W`, names form an overwrite ring.
50
+ With `-G -W` alone, capture stops after the requested number of files. `-G`
51
+ expands strftime directives in the base name. Rotation happens when the next
52
+ packet arrives. `--post-rotate-command 'gzip -f'` invokes an argument vector,
53
+ appending the closed filename; it does not invoke a shell. Input files and their
54
+ aliases are protected from output truncation, including rotated destinations.
55
+
56
+ ## Analysis and termination
57
+
58
+ Displayed TCP packets receive stream IDs and analysis flags. IP fragments and
59
+ TCP application messages are reassembled within bounded state. Conflicting
60
+ IPv6 overlaps discard the datagram; IPv4/TCP retain first-seen bytes and report
61
+ conflicts. Incomplete, expired or evicted state is diagnosed, not retained
62
+ indefinitely. `--follow tcp,raw,N` emits the selected stream bytes without headers;
63
+ ASCII and hex modes label the endpoints and directions.
64
+
65
+ Statistics accept `io,SECONDS`, `conv,eth|ip|ipv6|tcp|udp`,
66
+ `endpoints,eth|ip|ipv6|tcp|udp`, or `phs`; options can be repeated. Packet counts
67
+ and byte totals use captured packets and original frame lengths. SIGUSR1 (and
68
+ SIGINFO on macOS) prints a statistics snapshot; SIGINT/SIGTERM close output and
69
+ capture sources cleanly. Capture statistics go to stderr. Exit status is 0 on
70
+ success, 1 on capture/file failures and 2 on invalid arguments.
71
+
72
+ ## Platforms and limits
73
+
74
+ Linux `auto` uses TPACKET_V3 on x86_64 and falls back to the socket backend when
75
+ mapping is unavailable. Other Linux architectures default to sockets; `ring`
76
+ can be selected explicitly. macOS uses BPF, with native timestamp precision
77
+ reported by the device. Linux socket capture cannot recover NIC-stripped VLAN
78
+ tags; choose the ring backend for that metadata.
79
+
80
+ Windows, Wi-Fi monitor mode, packet transmission, TLS decryption, complete
81
+ HTTP/2/QUIC dissection, display-filter syntax and a TUI are outside v2's scope.
82
+ See [release validation status](VALIDATION.md) before promoting a prerelease.
@@ -0,0 +1,59 @@
1
+ # Release validation
2
+
3
+ ## 2.0.0.rc1
4
+
5
+ The implementation covers the v2 roadmap: the packet/dissector API, network and
6
+ application protocols, Ruby cBPF compiler/VM, Linux socket/ring and macOS BPF
7
+ backends, capture files/rotation/privilege drop, bounded stateful analysis,
8
+ statistics, follow output and documentation. This is a release candidate,
9
+ not a claim that time-dependent GA acceptance checks have completed.
10
+
11
+ Reproducible checks:
12
+
13
+ - `bundle exec rake`: RSpec, generated RBS and Steep.
14
+ - `REDHOUND_COVERAGE_GATE=1 bundle exec rake`: at least 90% total line coverage
15
+ and 95% protocol line coverage.
16
+ - `bundle exec rspec spec/differential`: tcpdump filter match/bytecode parity
17
+ (163 expressions across five link types), tshark protocol and stateful analysis
18
+ field/statistics/follow comparisons.
19
+ - `FUZZ_ITERATIONS=1000000 bundle exec rspec spec/fuzz`: strict parser fuzzing.
20
+ - `sudo -E env "PATH=$PATH" REDHOUND_LIVE=1 bundle exec rspec --tag live`:
21
+ native capture, attached filters, kernel time, snaplen, stop and loopback.
22
+ - `sudo -E env "PATH=$PATH" REDHOUND_LIVE=1 REDHOUND_NETNS=1 bundle exec rspec spec/integration/netns_capture_spec.rb --tag live`:
23
+ Linux veth socket/ring parity and offloaded VLAN restoration/filtering.
24
+ - `bundle exec yard stats --list-undoc`: documented public API.
25
+ - `actionlint`: test and release workflow validation.
26
+
27
+ Fixtures are generated without runtime dependencies. Golden output freezes
28
+ addresses and timestamps, and validates all JSON snapshots against the schema.
29
+ The CI matrix checks Ruby 3.3/3.4/4.0/head, Linux/macOS live capture and tool
30
+ comparisons. Scheduled runs execute one million fuzz cases. Benchmark jobs warn
31
+ on a summary throughput regression over 15% compared with the previous commit.
32
+
33
+ Local validation on 2026-10-01: Linux aarch64 Ruby 3.4 passed all 171 non-live
34
+ examples, including tcpdump/tshark differential checks, and five live capture
35
+ examples using socket and ring backends. Native macOS Ruby 4.0 passed unit,
36
+ golden and filter checks; BPF ioctl constants match the installed SDK. Native
37
+ BPF loopback and en0 Ethernet capture, attached filters, timestamps, truncation,
38
+ termination, privilege dropping and pcapng metadata passed the macOS CI job.
39
+ The Linux namespace test passed socket/ring parity and offloaded VLAN checks.
40
+ Ruby 3.3/3.4/4.0/head all passed the CI type, signature and coverage gates.
41
+ Whole-library line coverage measured 90.92%; isolated protocol line coverage
42
+ measured 99.90%. See [benchmarks](../bench/RESULTS.md)
43
+ for throughput figures and measurement limits.
44
+
45
+ ## Remaining GA acceptance gates
46
+
47
+ - Run a 24-hour continuous capture stability check.
48
+ - Run a 72-hour rotation soak and record RSS, descriptor counts and drop rates.
49
+ - Run an hour of high-load aarch64 socket/ring comparison before changing its
50
+ automatic backend default.
51
+ - Confirm x86_64 single-core throughput and live drop targets on the specified
52
+ workload; file benchmarks alone cannot establish loss-free live throughput.
53
+ - Keep rc1 available for two weeks, classify reports, and fix critical/high
54
+ failures before GA.
55
+
56
+ These elapsed-time/hardware gates are not marked complete by unit tests.
57
+ Promote to 2.0.0 only after their evidence is recorded. A 1.x maintenance
58
+ end date is set at GA plus six months; no maintenance branch is created by this
59
+ main-only implementation.
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/ydah/redhound/blob/main/docs/json-schema.json",
4
+ "title": "Redhound packet",
5
+ "description": "One packet object emitted by Packet#to_h, NDJSON, or an element of the JSON output array. Nanosecond timestamps and lengths are integers; byte fields use hexadecimal strings; repeated fields use arrays.",
6
+ "type": "object",
7
+ "required": ["frame", "layers", "diagnostics"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "frame": {
11
+ "type": "object",
12
+ "required": ["number", "time_epoch_ns", "time", "caplen", "len", "interface", "direction", "linktype"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "number": { "type": "integer", "minimum": 1 },
16
+ "time_epoch_ns": { "type": "integer" },
17
+ "time": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{9}Z$" },
18
+ "caplen": { "type": "integer", "minimum": 0 },
19
+ "len": { "type": "integer", "minimum": 0 },
20
+ "interface": { "type": ["string", "null"] },
21
+ "direction": { "enum": ["in", "out", null] },
22
+ "linktype": { "type": "integer", "minimum": 0 }
23
+ }
24
+ },
25
+ "layers": {
26
+ "type": "array",
27
+ "items": {
28
+ "type": "object",
29
+ "required": ["protocol", "offset", "length", "embedded", "fields"],
30
+ "additionalProperties": false,
31
+ "properties": {
32
+ "protocol": { "type": "string" },
33
+ "offset": { "type": "integer", "minimum": 0 },
34
+ "length": { "type": "integer", "minimum": 0 },
35
+ "embedded": { "type": "boolean" },
36
+ "fields": { "type": "object", "additionalProperties": { "$ref": "#/$defs/fieldValue" } }
37
+ }
38
+ }
39
+ },
40
+ "diagnostics": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "object",
44
+ "required": ["layer", "severity", "code", "message", "field"],
45
+ "additionalProperties": false,
46
+ "properties": {
47
+ "layer": { "type": "string" },
48
+ "severity": { "enum": ["note", "warn", "warning", "error"] },
49
+ "code": { "type": "string" },
50
+ "message": { "type": "string" },
51
+ "field": { "type": ["string", "null"] }
52
+ }
53
+ }
54
+ }
55
+ },
56
+ "$defs": {
57
+ "fieldValue": {
58
+ "anyOf": [
59
+ { "type": ["string", "number", "boolean", "null"] },
60
+ { "type": "array", "items": { "$ref": "#/$defs/fieldValue" } }
61
+ ]
62
+ }
63
+ }
64
+ }
data/exe/redhound CHANGED
@@ -4,4 +4,5 @@
4
4
  $LOAD_PATH << File.join(__dir__, '../lib')
5
5
  require 'redhound'
6
6
 
7
- Redhound::Command.new.run(ARGV.dup)
7
+ RubyVM::YJIT.enable if defined?(RubyVM::YJIT) && RubyVM::YJIT.respond_to?(:enable) && !ARGV.include?('--no-yjit')
8
+ exit Redhound::CLI::Command.new.run(ARGV.dup)