redhound 1.0.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +97 -31
- data/docs/API.md +76 -0
- data/docs/FILTERS.md +37 -0
- data/docs/MIGRATION.md +23 -0
- data/docs/PROTOCOLS.md +45 -0
- data/docs/USAGE.md +82 -0
- data/docs/VALIDATION.md +59 -0
- data/docs/json-schema.json +64 -0
- data/exe/redhound +2 -1
- data/lib/redhound/analysis/flow_key.rb +53 -0
- data/lib/redhound/analysis/flow_table.rb +117 -0
- data/lib/redhound/analysis/ip_reassembler.rb +176 -0
- data/lib/redhound/analysis/stats.rb +138 -0
- data/lib/redhound/analysis/tcp_analysis.rb +43 -0
- data/lib/redhound/analysis/tcp_reassembler.rb +124 -0
- data/lib/redhound/analysis/tcp_stream.rb +151 -0
- data/lib/redhound/analysis.rb +129 -0
- data/lib/redhound/capture/bsd/bpf_device.rb +152 -0
- data/lib/redhound/capture/bsd/constants.rb +29 -0
- data/lib/redhound/capture/file_source.rb +83 -0
- data/lib/redhound/capture/interface.rb +66 -0
- data/lib/redhound/capture/linktype.rb +30 -0
- data/lib/redhound/capture/linux/constants.rb +37 -0
- data/lib/redhound/capture/linux/cooked.rb +18 -0
- data/lib/redhound/capture/linux/ifreq.rb +42 -0
- data/lib/redhound/capture/linux/packet_socket.rb +180 -0
- data/lib/redhound/capture/linux/sockaddr_ll.rb +33 -0
- data/lib/redhound/capture/linux/tpacket_v3.rb +132 -0
- data/lib/redhound/capture/source.rb +79 -0
- data/lib/redhound/capture/stats.rb +22 -0
- data/lib/redhound/capture.rb +69 -0
- data/lib/redhound/cli/command.rb +42 -0
- data/lib/redhound/cli/options.rb +133 -0
- data/lib/redhound/cli/privileges.rb +29 -0
- data/lib/redhound/cli/runner.rb +129 -0
- data/lib/redhound/context.rb +20 -0
- data/lib/redhound/cursor.rb +69 -0
- data/lib/redhound/diagnostic.rb +7 -0
- data/lib/redhound/dissector.rb +138 -0
- data/lib/redhound/engine.rb +66 -0
- data/lib/redhound/errors.rb +38 -0
- data/lib/redhound/field.rb +62 -0
- data/lib/redhound/file/format.rb +56 -0
- data/lib/redhound/file/pcap_reader.rb +43 -0
- data/lib/redhound/file/pcap_writer.rb +72 -0
- data/lib/redhound/file/pcapng_reader.rb +209 -0
- data/lib/redhound/file/pcapng_writer.rb +143 -0
- data/lib/redhound/file/rotating_writer.rb +98 -0
- data/lib/redhound/filter/analyzer.rb +197 -0
- data/lib/redhound/filter/bpf/assembler.rb +121 -0
- data/lib/redhound/filter/bpf/disassembler.rb +58 -0
- data/lib/redhound/filter/bpf/validator.rb +77 -0
- data/lib/redhound/filter/bpf/vm.rb +108 -0
- data/lib/redhound/filter/codegen.rb +413 -0
- data/lib/redhound/filter/lexer.rb +46 -0
- data/lib/redhound/filter/parser.rb +206 -0
- data/lib/redhound/filter/program.rb +55 -0
- data/lib/redhound/filter.rb +30 -0
- data/lib/redhound/layer.rb +75 -0
- data/lib/redhound/output/fields.rb +20 -0
- data/lib/redhound/output/follow.rb +59 -0
- data/lib/redhound/output/hexdump.rb +29 -0
- data/lib/redhound/output/json.rb +32 -0
- data/lib/redhound/output/summary.rb +59 -0
- data/lib/redhound/output/timestamp.rb +34 -0
- data/lib/redhound/output/tree.rb +24 -0
- data/lib/redhound/packet.rb +63 -0
- data/lib/redhound/protocols/arp.rb +39 -0
- data/lib/redhound/protocols/checksum.rb +38 -0
- data/lib/redhound/protocols/data.rb +21 -0
- data/lib/redhound/protocols/dhcp.rb +124 -0
- data/lib/redhound/protocols/dns.rb +268 -0
- data/lib/redhound/protocols/ethernet.rb +24 -0
- data/lib/redhound/protocols/http.rb +183 -0
- data/lib/redhound/protocols/icmp.rb +191 -0
- data/lib/redhound/protocols/ipv4.rb +56 -0
- data/lib/redhound/protocols/ipv6.rb +65 -0
- data/lib/redhound/protocols/link.rb +70 -0
- data/lib/redhound/protocols/llc.rb +37 -0
- data/lib/redhound/protocols/ntp.rb +47 -0
- data/lib/redhound/protocols/tcp.rb +80 -0
- data/lib/redhound/protocols/tls.rb +218 -0
- data/lib/redhound/protocols/tunnel.rb +48 -0
- data/lib/redhound/protocols/udp.rb +32 -0
- data/lib/redhound/protocols/vlan.rb +23 -0
- data/lib/redhound/reader.rb +8 -0
- data/lib/redhound/registry.rb +64 -0
- data/lib/redhound/stream_dissector.rb +168 -0
- data/lib/redhound/util/seq.rb +21 -0
- data/lib/redhound/version.rb +2 -1
- data/lib/redhound/writer.rb +25 -43
- data/lib/redhound.rb +81 -9
- data/sig/generated/redhound/analysis/flow_key.rbs +15 -0
- data/sig/generated/redhound/analysis/flow_table.rbs +98 -0
- data/sig/generated/redhound/analysis/ip_reassembler.rbs +40 -0
- data/sig/generated/redhound/analysis/stats.rbs +77 -0
- data/sig/generated/redhound/analysis/tcp_analysis.rbs +15 -0
- data/sig/generated/redhound/analysis/tcp_reassembler.rbs +27 -0
- data/sig/generated/redhound/analysis/tcp_stream.rbs +60 -0
- data/sig/generated/redhound/analysis.rbs +38 -0
- data/sig/generated/redhound/capture/bsd/bpf_device.rbs +39 -0
- data/sig/generated/redhound/capture/bsd/constants.rbs +40 -0
- data/sig/generated/redhound/capture/file_source.rbs +34 -0
- data/sig/generated/redhound/capture/interface.rbs +53 -0
- data/sig/generated/redhound/capture/linktype.rbs +20 -0
- data/sig/generated/redhound/capture/linux/constants.rbs +58 -0
- data/sig/generated/redhound/capture/linux/cooked.rbs +15 -0
- data/sig/generated/redhound/capture/linux/ifreq.rbs +18 -0
- data/sig/generated/redhound/capture/linux/packet_socket.rbs +57 -0
- data/sig/generated/redhound/capture/linux/sockaddr_ll.rbs +31 -0
- data/sig/generated/redhound/capture/linux/tpacket_v3.rbs +35 -0
- data/sig/generated/redhound/capture/source.rbs +44 -0
- data/sig/generated/redhound/capture/stats.rbs +25 -0
- data/sig/generated/redhound/capture.rbs +14 -0
- data/sig/generated/redhound/cli/command.rbs +12 -0
- data/sig/generated/redhound/cli/options.rbs +25 -0
- data/sig/generated/redhound/cli/privileges.rbs +12 -0
- data/sig/generated/redhound/cli/runner.rbs +27 -0
- data/sig/generated/redhound/context.rbs +27 -0
- data/sig/generated/redhound/cursor.rbs +59 -0
- data/sig/generated/redhound/diagnostic.rbs +21 -0
- data/sig/generated/redhound/dissector.rbs +113 -0
- data/sig/generated/redhound/engine.rbs +23 -0
- data/sig/generated/redhound/errors.rbs +56 -0
- data/sig/generated/redhound/field.rbs +74 -0
- data/sig/generated/redhound/file/format.rbs +33 -0
- data/sig/generated/redhound/file/pcap_reader.rbs +19 -0
- data/sig/generated/redhound/file/pcap_writer.rbs +38 -0
- data/sig/generated/redhound/file/pcapng_reader.rbs +54 -0
- data/sig/generated/redhound/file/pcapng_writer.rbs +50 -0
- data/sig/generated/redhound/file/rotating_writer.rbs +42 -0
- data/sig/generated/redhound/filter/analyzer.rbs +42 -0
- data/sig/generated/redhound/filter/bpf/assembler.rbs +39 -0
- data/sig/generated/redhound/filter/bpf/disassembler.rbs +18 -0
- data/sig/generated/redhound/filter/bpf/validator.rbs +30 -0
- data/sig/generated/redhound/filter/bpf/vm.rbs +26 -0
- data/sig/generated/redhound/filter/codegen.rbs +101 -0
- data/sig/generated/redhound/filter/lexer.rbs +15 -0
- data/sig/generated/redhound/filter/parser.rbs +65 -0
- data/sig/generated/redhound/filter/program.rbs +48 -0
- data/sig/generated/redhound/filter.rbs +10 -0
- data/sig/generated/redhound/layer.rbs +81 -0
- data/sig/generated/redhound/output/fields.rbs +15 -0
- data/sig/generated/redhound/output/follow.rbs +21 -0
- data/sig/generated/redhound/output/hexdump.rbs +15 -0
- data/sig/generated/redhound/output/json.rbs +18 -0
- data/sig/generated/redhound/output/summary.rbs +21 -0
- data/sig/generated/redhound/output/timestamp.rbs +21 -0
- data/sig/generated/redhound/output/tree.rbs +15 -0
- data/sig/generated/redhound/packet.rbs +77 -0
- data/sig/generated/redhound/protocols/arp.rbs +15 -0
- data/sig/generated/redhound/protocols/checksum.rbs +15 -0
- data/sig/generated/redhound/protocols/data.rbs +15 -0
- data/sig/generated/redhound/protocols/dhcp.rbs +28 -0
- data/sig/generated/redhound/protocols/dns.rbs +42 -0
- data/sig/generated/redhound/protocols/ethernet.rbs +15 -0
- data/sig/generated/redhound/protocols/http.rbs +36 -0
- data/sig/generated/redhound/protocols/icmp.rbs +41 -0
- data/sig/generated/redhound/protocols/ipv4.rbs +15 -0
- data/sig/generated/redhound/protocols/ipv6.rbs +24 -0
- data/sig/generated/redhound/protocols/link.rbs +33 -0
- data/sig/generated/redhound/protocols/llc.rbs +15 -0
- data/sig/generated/redhound/protocols/ntp.rbs +17 -0
- data/sig/generated/redhound/protocols/tcp.rbs +25 -0
- data/sig/generated/redhound/protocols/tls.rbs +51 -0
- data/sig/generated/redhound/protocols/tunnel.rbs +24 -0
- data/sig/generated/redhound/protocols/udp.rbs +18 -0
- data/sig/generated/redhound/protocols/vlan.rbs +12 -0
- data/sig/generated/redhound/reader.rbs +7 -0
- data/sig/generated/redhound/registry.rbs +45 -0
- data/sig/generated/redhound/stream_dissector.rbs +44 -0
- data/sig/generated/redhound/util/seq.rbs +20 -0
- data/sig/generated/redhound/version.rbs +1 -0
- data/sig/generated/redhound/writer.rbs +6 -19
- data/sig/generated/redhound.rbs +18 -0
- data/sig/shims/io.rbs +7 -0
- data/sig/shims/process.rbs +3 -0
- metadata +175 -55
- data/CODE_OF_CONDUCT.md +0 -132
- data/Dockerfile +0 -7
- data/Rakefile +0 -15
- data/Steepfile +0 -4
- data/docker-compose.yml +0 -9
- data/lib/redhound/analyzer.rb +0 -34
- data/lib/redhound/builder/packet_mreq.rb +0 -56
- data/lib/redhound/builder/socket.rb +0 -35
- data/lib/redhound/builder.rb +0 -4
- data/lib/redhound/command.rb +0 -67
- data/lib/redhound/l2/ether.rb +0 -68
- data/lib/redhound/l2/protocol.rb +0 -33
- data/lib/redhound/l2.rb +0 -4
- data/lib/redhound/l3/arp.rb +0 -114
- data/lib/redhound/l3/base.rb +0 -49
- data/lib/redhound/l3/ipv4.rb +0 -95
- data/lib/redhound/l3/ipv6.rb +0 -69
- data/lib/redhound/l3/protocol.rb +0 -173
- data/lib/redhound/l3/resolver.rb +0 -30
- data/lib/redhound/l3.rb +0 -8
- data/lib/redhound/l4/base.rb +0 -31
- data/lib/redhound/l4/icmp.rb +0 -71
- data/lib/redhound/l4/resolver.rb +0 -28
- data/lib/redhound/l4/udp.rb +0 -63
- data/lib/redhound/l4.rb +0 -6
- data/lib/redhound/receiver.rb +0 -45
- data/lib/redhound/resolver.rb +0 -22
- data/lib/redhound/source/socket.rb +0 -18
- data/lib/redhound/source.rb +0 -3
- data/rbs_collection.lock.yaml +0 -20
- data/rbs_collection.yaml +0 -17
- data/sig/generated/redhound/analyzer.rbs +0 -14
- data/sig/generated/redhound/builder/packet_mreq.rbs +0 -39
- data/sig/generated/redhound/builder/socket.rbs +0 -24
- data/sig/generated/redhound/command.rbs +0 -19
- data/sig/generated/redhound/l2/ether.rbs +0 -41
- data/sig/generated/redhound/l2/protocol.rbs +0 -15
- data/sig/generated/redhound/l3/arp.rbs +0 -57
- data/sig/generated/redhound/l3/base.rbs +0 -28
- data/sig/generated/redhound/l3/ipv4.rbs +0 -53
- data/sig/generated/redhound/l3/ipv6.rbs +0 -38
- data/sig/generated/redhound/l3/protocol.rbs +0 -16
- data/sig/generated/redhound/l3/resolver.rbs +0 -16
- data/sig/generated/redhound/l4/base.rbs +0 -19
- data/sig/generated/redhound/l4/icmp.rbs +0 -33
- data/sig/generated/redhound/l4/resolver.rbs +0 -16
- data/sig/generated/redhound/l4/udp.rbs +0 -36
- data/sig/generated/redhound/receiver.rbs +0 -19
- data/sig/generated/redhound/resolver.rbs +0 -11
- data/sig/generated/redhound/source/socket.rbs +0 -13
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/interface.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
class Interface
|
|
8
|
+
attr_reader name: untyped
|
|
9
|
+
|
|
10
|
+
attr_reader index: untyped
|
|
11
|
+
|
|
12
|
+
attr_reader linktype: untyped
|
|
13
|
+
|
|
14
|
+
attr_reader snaplen: untyped
|
|
15
|
+
|
|
16
|
+
attr_reader flags: untyped
|
|
17
|
+
|
|
18
|
+
attr_reader mtu: untyped
|
|
19
|
+
|
|
20
|
+
attr_reader mac: untyped
|
|
21
|
+
|
|
22
|
+
attr_reader description: untyped
|
|
23
|
+
|
|
24
|
+
attr_reader filter: untyped
|
|
25
|
+
|
|
26
|
+
attr_reader meta: untyped
|
|
27
|
+
|
|
28
|
+
# @rbs (name: String, ?index: Integer, ?linktype: Integer, ?snaplen: Integer, ?flags: Integer, ?mtu: Integer?, ?mac: String?, ?description: String?, ?filter: String?, ?meta: Hash[Symbol, untyped]) -> void
|
|
29
|
+
def initialize: (name: String, ?index: Integer, ?linktype: Integer, ?snaplen: Integer, ?flags: Integer, ?mtu: Integer?, ?mac: String?, ?description: String?, ?filter: String?, ?meta: Hash[Symbol, untyped]) -> void
|
|
30
|
+
|
|
31
|
+
# @rbs () -> Integer
|
|
32
|
+
def ifindex: () -> Integer
|
|
33
|
+
|
|
34
|
+
# @rbs () -> bool
|
|
35
|
+
def up?: () -> bool
|
|
36
|
+
|
|
37
|
+
# @rbs () -> bool
|
|
38
|
+
def loopback?: () -> bool
|
|
39
|
+
|
|
40
|
+
# @rbs () -> bool
|
|
41
|
+
def running?: () -> bool
|
|
42
|
+
|
|
43
|
+
# @rbs () -> String
|
|
44
|
+
def to_s: () -> String
|
|
45
|
+
|
|
46
|
+
# @rbs () -> Array[Interface]
|
|
47
|
+
def self.all: () -> Array[Interface]
|
|
48
|
+
|
|
49
|
+
# @rbs (String | Integer value) -> Interface
|
|
50
|
+
def self.find: (String | Integer value) -> Interface
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linktype.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linktype
|
|
8
|
+
VALUES: untyped
|
|
9
|
+
|
|
10
|
+
# @rbs (Integer | Symbol | String value) -> Integer
|
|
11
|
+
def self.resolve: (Integer | Symbol | String value) -> Integer
|
|
12
|
+
|
|
13
|
+
# @rbs (Integer value) -> String
|
|
14
|
+
def self.name: (Integer value) -> String
|
|
15
|
+
|
|
16
|
+
# @rbs (Integer hardware_type) -> Integer
|
|
17
|
+
def self.for_hardware: (Integer hardware_type) -> Integer
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/constants.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
module Constants
|
|
10
|
+
AF_PACKET: ::Integer
|
|
11
|
+
|
|
12
|
+
SOL_PACKET: ::Integer
|
|
13
|
+
|
|
14
|
+
ETH_P_ALL: ::Integer
|
|
15
|
+
|
|
16
|
+
PACKET_ADD_MEMBERSHIP: ::Integer
|
|
17
|
+
|
|
18
|
+
PACKET_RX_RING: ::Integer
|
|
19
|
+
|
|
20
|
+
PACKET_STATISTICS: ::Integer
|
|
21
|
+
|
|
22
|
+
PACKET_VERSION: ::Integer
|
|
23
|
+
|
|
24
|
+
PACKET_IGNORE_OUTGOING: ::Integer
|
|
25
|
+
|
|
26
|
+
PACKET_MR_PROMISC: ::Integer
|
|
27
|
+
|
|
28
|
+
PACKET_OUTGOING: ::Integer
|
|
29
|
+
|
|
30
|
+
SO_ATTACH_FILTER: ::Integer
|
|
31
|
+
|
|
32
|
+
SO_RCVBUFFORCE: ::Integer
|
|
33
|
+
|
|
34
|
+
TPACKET_V3: ::Integer
|
|
35
|
+
|
|
36
|
+
SIOCGSTAMPNS: ::Integer
|
|
37
|
+
|
|
38
|
+
SIOCGIFHWADDR: ::Integer
|
|
39
|
+
|
|
40
|
+
SIOCGIFMTU: ::Integer
|
|
41
|
+
|
|
42
|
+
SIOCGIFFLAGS: ::Integer
|
|
43
|
+
|
|
44
|
+
TP_STATUS_USER: ::Integer
|
|
45
|
+
|
|
46
|
+
TP_STATUS_CSUMNOTREADY: ::Integer
|
|
47
|
+
|
|
48
|
+
TP_STATUS_VLAN_VALID: ::Integer
|
|
49
|
+
|
|
50
|
+
TP_STATUS_VLAN_TPID_VALID: ::Integer
|
|
51
|
+
|
|
52
|
+
TP_STATUS_CSUM_VALID: ::Integer
|
|
53
|
+
|
|
54
|
+
RECEIVE_SIZE: ::Integer
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/cooked.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
module Cooked
|
|
10
|
+
# @rbs (SockaddrLL address) -> String
|
|
11
|
+
def self.header: (SockaddrLL address) -> String
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/ifreq.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
module Ifreq
|
|
10
|
+
# @rbs (String name, Integer command) -> String
|
|
11
|
+
def self.query: (String name, Integer command) -> String
|
|
12
|
+
|
|
13
|
+
# @rbs (String name, ?index: Integer) -> Interface
|
|
14
|
+
def self.interface: (String name, ?index: Integer) -> Interface
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/packet_socket.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
class PacketSocket < Source
|
|
10
|
+
attr_reader socket: untyped
|
|
11
|
+
|
|
12
|
+
attr_reader linktype: untyped
|
|
13
|
+
|
|
14
|
+
attr_reader interfaces: untyped
|
|
15
|
+
|
|
16
|
+
# @rbs (interface: String | Integer | Interface, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) -> void
|
|
17
|
+
def initialize: (interface: String | Integer | Interface, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) -> void
|
|
18
|
+
|
|
19
|
+
# @rbs (?timeout: Numeric?) -> Packet?
|
|
20
|
+
def next_packet: (?timeout: Numeric?) -> Packet?
|
|
21
|
+
|
|
22
|
+
# @rbs (untyped program) -> void
|
|
23
|
+
def attach_filter: (untyped program) -> void
|
|
24
|
+
|
|
25
|
+
# @rbs () -> Stats
|
|
26
|
+
def stats: () -> Stats
|
|
27
|
+
|
|
28
|
+
# @rbs () -> void
|
|
29
|
+
def close: () -> void
|
|
30
|
+
|
|
31
|
+
# @rbs () -> void
|
|
32
|
+
def close_resources: () -> void
|
|
33
|
+
|
|
34
|
+
# @rbs () -> void
|
|
35
|
+
def prime_timestamp: () -> void
|
|
36
|
+
|
|
37
|
+
# @rbs () -> Integer
|
|
38
|
+
def receive_snaplen: () -> Integer
|
|
39
|
+
|
|
40
|
+
# @rbs (Integer? buffer_size) -> void
|
|
41
|
+
def setup_receive_buffer: (Integer? buffer_size) -> void
|
|
42
|
+
|
|
43
|
+
# @rbs (SockaddrLL address) -> bool
|
|
44
|
+
def accept_direction?: (SockaddrLL address) -> bool
|
|
45
|
+
|
|
46
|
+
# @rbs (SockaddrLL address) -> Interface
|
|
47
|
+
def packet_interface: (SockaddrLL address) -> Interface
|
|
48
|
+
|
|
49
|
+
# @rbs () -> Integer
|
|
50
|
+
def interface_dropped: () -> Integer
|
|
51
|
+
|
|
52
|
+
# @rbs () -> Integer
|
|
53
|
+
def timestamp: () -> Integer
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/sockaddr_ll.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
class SockaddrLL
|
|
10
|
+
attr_reader protocol: untyped
|
|
11
|
+
|
|
12
|
+
attr_reader index: untyped
|
|
13
|
+
|
|
14
|
+
attr_reader hatype: untyped
|
|
15
|
+
|
|
16
|
+
attr_reader pkttype: untyped
|
|
17
|
+
|
|
18
|
+
attr_reader address: untyped
|
|
19
|
+
|
|
20
|
+
# @rbs (?protocol: Integer, ?index: Integer, ?hatype: Integer, ?pkttype: Integer, ?address: String) -> void
|
|
21
|
+
def initialize: (?protocol: Integer, ?index: Integer, ?hatype: Integer, ?pkttype: Integer, ?address: String) -> void
|
|
22
|
+
|
|
23
|
+
# @rbs () -> String
|
|
24
|
+
def to_sockaddr: () -> String
|
|
25
|
+
|
|
26
|
+
# @rbs (String bytes) -> SockaddrLL
|
|
27
|
+
def self.parse: (String bytes) -> SockaddrLL
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/linux/tpacket_v3.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
module Linux
|
|
8
|
+
# @api private
|
|
9
|
+
class TPacketV3 < PacketSocket
|
|
10
|
+
# @rbs (?timeout: Numeric?) -> Packet?
|
|
11
|
+
def next_packet: (?timeout: Numeric?) -> Packet?
|
|
12
|
+
|
|
13
|
+
# @rbs () -> void
|
|
14
|
+
def close_resources: () -> void
|
|
15
|
+
|
|
16
|
+
# @rbs () -> Integer
|
|
17
|
+
def receive_snaplen: () -> Integer
|
|
18
|
+
|
|
19
|
+
# @rbs (Integer? buffer_size) -> void
|
|
20
|
+
def setup_receive_buffer: (Integer? buffer_size) -> void
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# @rbs (Integer offset) -> Integer
|
|
25
|
+
def u32: (Integer offset) -> Integer
|
|
26
|
+
|
|
27
|
+
# @rbs (Integer offset, Integer length) -> void
|
|
28
|
+
def check_ring_bounds: (Integer offset, Integer length) -> void
|
|
29
|
+
|
|
30
|
+
# @rbs () -> void
|
|
31
|
+
def release_block: () -> void
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/source.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
class Source
|
|
8
|
+
include Enumerable[Packet]
|
|
9
|
+
|
|
10
|
+
# @rbs () -> void
|
|
11
|
+
def initialize: () -> void
|
|
12
|
+
|
|
13
|
+
# @rbs () { (Packet) -> void } -> self
|
|
14
|
+
# @rbs () -> Enumerator[Packet, self]
|
|
15
|
+
def each_packet: () { (Packet) -> void } -> self
|
|
16
|
+
| () -> Enumerator[Packet, self]
|
|
17
|
+
|
|
18
|
+
alias each each_packet
|
|
19
|
+
|
|
20
|
+
# @rbs (?timeout: Numeric?) -> Packet?
|
|
21
|
+
def next_packet: (?timeout: Numeric?) -> Packet?
|
|
22
|
+
|
|
23
|
+
# @rbs () -> Stats
|
|
24
|
+
def stats: () -> Stats
|
|
25
|
+
|
|
26
|
+
# @rbs () -> bool
|
|
27
|
+
def stopped?: () -> bool
|
|
28
|
+
|
|
29
|
+
# @rbs () -> void
|
|
30
|
+
def stop: () -> void
|
|
31
|
+
|
|
32
|
+
# @rbs () -> void
|
|
33
|
+
def close: () -> void
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# @rbs (IO io, Numeric? deadline) -> bool
|
|
38
|
+
def wait_readable: (IO io, Numeric? deadline) -> bool
|
|
39
|
+
|
|
40
|
+
# @rbs (Numeric? timeout) -> Numeric?
|
|
41
|
+
def deadline_for: (Numeric? timeout) -> Numeric?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture/stats.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @api private
|
|
7
|
+
class Stats
|
|
8
|
+
attr_accessor received: untyped
|
|
9
|
+
|
|
10
|
+
attr_accessor dropped: untyped
|
|
11
|
+
|
|
12
|
+
attr_accessor if_dropped: untyped
|
|
13
|
+
|
|
14
|
+
attr_accessor freeze_count: untyped
|
|
15
|
+
|
|
16
|
+
attr_accessor captured: untyped
|
|
17
|
+
|
|
18
|
+
# @rbs (?received: Integer, ?dropped: Integer, ?if_dropped: Integer, ?freeze_count: Integer, ?captured: Integer) -> void
|
|
19
|
+
def initialize: (?received: Integer, ?dropped: Integer, ?if_dropped: Integer, ?freeze_count: Integer, ?captured: Integer) -> void
|
|
20
|
+
|
|
21
|
+
# @rbs () -> Hash[Symbol, Integer]
|
|
22
|
+
def to_h: () -> Hash[Symbol, Integer]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Generated from lib/redhound/capture.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module Capture
|
|
6
|
+
# @rbs (interface: String | Integer | Interface, ?backend: Symbol | String, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) -> Source
|
|
7
|
+
# @rbs [T] (interface: String | Integer | Interface, ?backend: Symbol | String, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) { (Source) -> T } -> T
|
|
8
|
+
def self.open: (interface: String | Integer | Interface, ?backend: Symbol | String, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) -> Source
|
|
9
|
+
| [T] (interface: String | Integer | Interface, ?backend: Symbol | String, ?snaplen: Integer, ?promiscuous: bool, ?buffer_size: Integer?, ?direction: Symbol, ?filter: String?) { (Source) -> T } -> T
|
|
10
|
+
|
|
11
|
+
# @rbs () -> Array[Interface]
|
|
12
|
+
def self.interfaces: () -> Array[Interface]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Generated from lib/redhound/cli/command.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module CLI
|
|
6
|
+
# @api private
|
|
7
|
+
class Command
|
|
8
|
+
# @rbs (Array[String] argv, ?out: untyped, ?err: untyped) -> Integer
|
|
9
|
+
def run: (Array[String] argv, ?out: untyped, ?err: untyped) -> Integer
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Generated from lib/redhound/cli/options.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module CLI
|
|
6
|
+
# @api private
|
|
7
|
+
class Options
|
|
8
|
+
attr_reader values: untyped
|
|
9
|
+
|
|
10
|
+
attr_reader parser: untyped
|
|
11
|
+
|
|
12
|
+
# @rbs (Array[String] argv) -> void
|
|
13
|
+
def initialize: (Array[String] argv) -> void
|
|
14
|
+
|
|
15
|
+
# @rbs (Array[String] args) -> Array[String]
|
|
16
|
+
def normalize: (Array[String] args) -> Array[String]
|
|
17
|
+
|
|
18
|
+
# @rbs () -> OptionParser
|
|
19
|
+
def build_parser: () -> OptionParser
|
|
20
|
+
|
|
21
|
+
# @rbs () -> void
|
|
22
|
+
def validate: () -> void
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Generated from lib/redhound/cli/runner.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
module CLI
|
|
6
|
+
# @api private
|
|
7
|
+
class Runner
|
|
8
|
+
# @rbs (Hash[Symbol, untyped] options, ?out: untyped, ?err: untyped) -> void
|
|
9
|
+
def initialize: (Hash[Symbol, untyped] options, ?out: untyped, ?err: untyped) -> void
|
|
10
|
+
|
|
11
|
+
# @rbs () -> void
|
|
12
|
+
def run: () -> void
|
|
13
|
+
|
|
14
|
+
# @rbs () -> untyped
|
|
15
|
+
def formatter: () -> untyped
|
|
16
|
+
|
|
17
|
+
# @rbs () -> void
|
|
18
|
+
def install_signals: () -> void
|
|
19
|
+
|
|
20
|
+
# @rbs [T] () { () -> T } -> T
|
|
21
|
+
def read_capture: [T] () { () -> T } -> T
|
|
22
|
+
|
|
23
|
+
# @rbs () -> void
|
|
24
|
+
def statistics: () -> void
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Generated from lib/redhound/context.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# @api private
|
|
5
|
+
class Context
|
|
6
|
+
attr_reader packet: untyped
|
|
7
|
+
|
|
8
|
+
attr_reader registry: untyped
|
|
9
|
+
|
|
10
|
+
attr_reader layers: untyped
|
|
11
|
+
|
|
12
|
+
attr_accessor cursor: untyped
|
|
13
|
+
|
|
14
|
+
attr_accessor embedded: untyped
|
|
15
|
+
|
|
16
|
+
attr_accessor extension_count: untyped
|
|
17
|
+
|
|
18
|
+
# @rbs (Packet packet, registry: Registry, ?verify_checksums: bool) -> void
|
|
19
|
+
def initialize: (Packet packet, registry: Registry, ?verify_checksums: bool) -> void
|
|
20
|
+
|
|
21
|
+
# @rbs () -> bool
|
|
22
|
+
def verify_checksums?: () -> bool
|
|
23
|
+
|
|
24
|
+
# @rbs () -> Layer?
|
|
25
|
+
def network: () -> Layer?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Generated from lib/redhound/cursor.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# Checked binary reads within an absolute packet slice.
|
|
5
|
+
class Cursor
|
|
6
|
+
# Internal exception for a checked read beyond the captured slice.
|
|
7
|
+
class Truncated < StandardError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Underlying data and absolute start/end bounds.
|
|
11
|
+
attr_reader data: untyped
|
|
12
|
+
|
|
13
|
+
# Underlying data and absolute start/end bounds.
|
|
14
|
+
attr_reader start: untyped
|
|
15
|
+
|
|
16
|
+
# Underlying data and absolute start/end bounds.
|
|
17
|
+
attr_reader limit: untyped
|
|
18
|
+
|
|
19
|
+
# @rbs (String data, ?Integer start, ?Integer? limit) -> void
|
|
20
|
+
# Create a bounded view; reject invalid ranges.
|
|
21
|
+
def initialize: (String data, ?Integer start, ?Integer? limit) -> void
|
|
22
|
+
|
|
23
|
+
# @rbs () -> Integer
|
|
24
|
+
# Remaining slice length in bytes.
|
|
25
|
+
def remaining: () -> Integer
|
|
26
|
+
|
|
27
|
+
# @rbs (Integer off) -> Integer
|
|
28
|
+
# Read an unsigned byte.
|
|
29
|
+
def u8: (Integer off) -> Integer
|
|
30
|
+
|
|
31
|
+
# @rbs (Integer off) -> Integer
|
|
32
|
+
# Read an unsigned network-order 16-bit integer.
|
|
33
|
+
def u16: (Integer off) -> Integer
|
|
34
|
+
|
|
35
|
+
# @rbs (Integer off) -> Integer
|
|
36
|
+
# Read an unsigned network-order 32-bit integer.
|
|
37
|
+
def u32: (Integer off) -> Integer
|
|
38
|
+
|
|
39
|
+
# @rbs (Integer off) -> Integer
|
|
40
|
+
# Read an unsigned network-order 64-bit integer.
|
|
41
|
+
def u64: (Integer off) -> Integer
|
|
42
|
+
|
|
43
|
+
# @rbs (String template, Integer size, ?Integer off) -> Array[untyped]
|
|
44
|
+
# Unpack a checked fixed-width header.
|
|
45
|
+
def unpack: (String template, Integer size, ?Integer off) -> Array[untyped]
|
|
46
|
+
|
|
47
|
+
# @rbs (Integer off, Integer len) -> String
|
|
48
|
+
# Read a checked binary substring.
|
|
49
|
+
def bytes: (Integer off, Integer len) -> String
|
|
50
|
+
|
|
51
|
+
# @rbs (Integer from, Integer to) -> Cursor
|
|
52
|
+
# Create a child slice that cannot escape the parent bounds.
|
|
53
|
+
def sub: (Integer from, Integer to) -> Cursor
|
|
54
|
+
|
|
55
|
+
# @rbs (Integer off, Integer len) -> void
|
|
56
|
+
# Validate a relative offset and read length.
|
|
57
|
+
def check: (Integer off, Integer len) -> void
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Generated from lib/redhound/diagnostic.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# Structured protocol diagnostic with severity, stable code, message and optional field.
|
|
5
|
+
class Diagnostic < Data
|
|
6
|
+
attr_reader severity(): untyped
|
|
7
|
+
|
|
8
|
+
attr_reader code(): untyped
|
|
9
|
+
|
|
10
|
+
attr_reader message(): untyped
|
|
11
|
+
|
|
12
|
+
attr_reader field(): untyped
|
|
13
|
+
|
|
14
|
+
def self.new: (untyped severity, untyped code, untyped message, untyped field) -> instance
|
|
15
|
+
| (severity: untyped, code: untyped, message: untyped, field: untyped) -> instance
|
|
16
|
+
|
|
17
|
+
def self.members: () -> [ :severity, :code, :message, :field ]
|
|
18
|
+
|
|
19
|
+
def members: () -> [ :severity, :code, :message, :field ]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Generated from lib/redhound/dissector.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Redhound
|
|
4
|
+
# Base class and declarative fixed-header DSL for custom protocols.
|
|
5
|
+
class Dissector
|
|
6
|
+
# Unpack formats and byte lengths supported by the header DSL.
|
|
7
|
+
TYPES: untyped
|
|
8
|
+
|
|
9
|
+
# Build a single unpack template and its field descriptions.
|
|
10
|
+
class Header
|
|
11
|
+
# Compiled unpack template, header byte length and field definitions.
|
|
12
|
+
attr_reader template: untyped
|
|
13
|
+
|
|
14
|
+
# Compiled unpack template, header byte length and field definitions.
|
|
15
|
+
attr_reader length: untyped
|
|
16
|
+
|
|
17
|
+
# Compiled unpack template, header byte length and field definitions.
|
|
18
|
+
attr_reader definitions: untyped
|
|
19
|
+
|
|
20
|
+
# @rbs () -> void
|
|
21
|
+
# Start an empty fixed-header definition.
|
|
22
|
+
def initialize: () -> void
|
|
23
|
+
|
|
24
|
+
# @rbs (Symbol type, Symbol key, String name, **untyped opts) -> void
|
|
25
|
+
# Append a typed fixed-width field with optional format/enum metadata.
|
|
26
|
+
def field: (Symbol type, Symbol key, String name, **untyped opts) -> void
|
|
27
|
+
|
|
28
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
29
|
+
# Append an unsigned 8-bit field.
|
|
30
|
+
def uint8: (Symbol key, String name, **untyped opts) -> void
|
|
31
|
+
|
|
32
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
33
|
+
# Append a network-order unsigned 16-bit field.
|
|
34
|
+
def uint16: (Symbol key, String name, **untyped opts) -> void
|
|
35
|
+
|
|
36
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
37
|
+
# Append a network-order unsigned 32-bit field.
|
|
38
|
+
def uint32: (Symbol key, String name, **untyped opts) -> void
|
|
39
|
+
|
|
40
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
41
|
+
# Append a network-order unsigned 64-bit field.
|
|
42
|
+
def uint64: (Symbol key, String name, **untyped opts) -> void
|
|
43
|
+
|
|
44
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
45
|
+
# Append a six-byte MAC address.
|
|
46
|
+
def mac: (Symbol key, String name, **untyped opts) -> void
|
|
47
|
+
|
|
48
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
49
|
+
# Append a four-byte IPv4 address.
|
|
50
|
+
def ipv4: (Symbol key, String name, **untyped opts) -> void
|
|
51
|
+
|
|
52
|
+
# @rbs (Symbol key, String name, **untyped opts) -> void
|
|
53
|
+
# Append a sixteen-byte IPv6 address.
|
|
54
|
+
def ipv6: (Symbol key, String name, **untyped opts) -> void
|
|
55
|
+
|
|
56
|
+
# @rbs (Integer width) { (Header) [self: Header] -> void } -> void
|
|
57
|
+
# Define bit fields filling an 8/16/32/64-bit network-order word.
|
|
58
|
+
def bits: (Integer width) { (Header) [self: Header] -> void } -> void
|
|
59
|
+
|
|
60
|
+
# @rbs (Symbol key, String name, Integer width, **untyped opts) -> void
|
|
61
|
+
# Append a bit field inside bits, optionally scaled/formatted.
|
|
62
|
+
def bit: (Symbol key, String name, Integer width, **untyped opts) -> void
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @rbs () -> Symbol
|
|
66
|
+
# Registered protocol symbol.
|
|
67
|
+
def self.protocol_id: () -> Symbol
|
|
68
|
+
|
|
69
|
+
# @rbs () -> String
|
|
70
|
+
# Human-readable protocol name.
|
|
71
|
+
def self.protocol_name: () -> String
|
|
72
|
+
|
|
73
|
+
# @rbs () -> String
|
|
74
|
+
# Short output label.
|
|
75
|
+
def self.short_name: () -> String
|
|
76
|
+
|
|
77
|
+
# @rbs () -> untyped
|
|
78
|
+
# Compiled header definition, if one was declared.
|
|
79
|
+
def self.compiled_header: () -> untyped
|
|
80
|
+
|
|
81
|
+
# @rbs (Symbol id, name: String, short: String) -> void
|
|
82
|
+
# Declare protocol identity and register the dissector.
|
|
83
|
+
def self.protocol: (Symbol id, name: String, short: String) -> void
|
|
84
|
+
|
|
85
|
+
# @rbs (String key, *Integer values) -> void
|
|
86
|
+
# Register this protocol under one or more dispatch values.
|
|
87
|
+
def self.dissects_on: (String key, *Integer values) -> void
|
|
88
|
+
|
|
89
|
+
# @rbs () { (Header) [self: Header] -> void } -> void
|
|
90
|
+
# Compile a fixed header from the DSL block.
|
|
91
|
+
def self.header: () { (Header) [self: Header] -> void } -> void
|
|
92
|
+
|
|
93
|
+
# @rbs () -> String
|
|
94
|
+
# Compiled unpack template, or an empty template.
|
|
95
|
+
def self.header_template: () -> String
|
|
96
|
+
|
|
97
|
+
# @rbs (Context ctx, Cursor cursor) -> Layer
|
|
98
|
+
# Decode fixed fields then invoke the variable-header hook.
|
|
99
|
+
def parse: (Context ctx, Cursor cursor) -> Layer
|
|
100
|
+
|
|
101
|
+
# @rbs (Context ctx, Layer layer) -> void
|
|
102
|
+
# Override to parse variable fields using the bounded Context cursor.
|
|
103
|
+
def dissect: (Context ctx, Layer layer) -> void
|
|
104
|
+
|
|
105
|
+
# @rbs (Context ctx, Layer layer) -> untyped
|
|
106
|
+
# Override to return the next protocol class or nil.
|
|
107
|
+
def next_dissector: (Context ctx, Layer layer) -> untyped
|
|
108
|
+
|
|
109
|
+
# @rbs (Layer layer) -> String
|
|
110
|
+
# Override to format the layer summary.
|
|
111
|
+
def summary: (Layer layer) -> String
|
|
112
|
+
end
|
|
113
|
+
end
|