redhound 0.1.0 → 1.0.0
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 +15 -2
- data/Dockerfile +1 -1
- data/README.md +10 -1
- data/Rakefile +12 -1
- data/Steepfile +4 -0
- data/lib/redhound/analyzer.rb +19 -15
- data/lib/redhound/builder/packet_mreq.rb +56 -0
- data/lib/redhound/builder/socket.rb +35 -0
- data/lib/redhound/builder.rb +4 -0
- data/lib/redhound/command.rb +8 -2
- data/lib/redhound/l2/ether.rb +68 -0
- data/lib/redhound/l2/protocol.rb +33 -0
- data/lib/redhound/l2.rb +4 -0
- data/lib/redhound/l3/arp.rb +114 -0
- data/lib/redhound/l3/base.rb +49 -0
- data/lib/redhound/{header → l3}/ipv4.rb +27 -44
- data/lib/redhound/l3/ipv6.rb +69 -0
- data/lib/redhound/l3/protocol.rb +173 -0
- data/lib/redhound/l3/resolver.rb +30 -0
- data/lib/redhound/l3.rb +8 -0
- data/lib/redhound/l4/base.rb +31 -0
- data/lib/redhound/{header → l4}/icmp.rb +20 -26
- data/lib/redhound/l4/resolver.rb +28 -0
- data/lib/redhound/{header → l4}/udp.rb +19 -19
- data/lib/redhound/l4.rb +6 -0
- data/lib/redhound/receiver.rb +26 -6
- data/lib/redhound/resolver.rb +22 -0
- data/lib/redhound/source/socket.rb +18 -0
- data/lib/redhound/source.rb +3 -0
- data/lib/redhound/version.rb +2 -1
- data/lib/redhound/writer.rb +53 -0
- data/lib/redhound.rb +7 -3
- data/rbs_collection.lock.yaml +20 -0
- data/rbs_collection.yaml +17 -0
- data/sig/generated/redhound/analyzer.rbs +14 -0
- data/sig/generated/redhound/builder/packet_mreq.rbs +39 -0
- data/sig/generated/redhound/builder/socket.rbs +24 -0
- data/sig/generated/redhound/command.rbs +19 -0
- data/sig/generated/redhound/l2/ether.rbs +41 -0
- data/sig/generated/redhound/l2/protocol.rbs +15 -0
- data/sig/generated/redhound/l3/arp.rbs +57 -0
- data/sig/generated/redhound/l3/base.rbs +28 -0
- data/sig/generated/redhound/l3/ipv4.rbs +53 -0
- data/sig/generated/redhound/l3/ipv6.rbs +38 -0
- data/sig/generated/redhound/l3/protocol.rbs +16 -0
- data/sig/generated/redhound/l3/resolver.rbs +16 -0
- data/sig/generated/redhound/l4/base.rbs +19 -0
- data/sig/generated/redhound/l4/icmp.rbs +33 -0
- data/sig/generated/redhound/l4/resolver.rbs +16 -0
- data/sig/generated/redhound/l4/udp.rbs +36 -0
- data/sig/generated/redhound/receiver.rbs +19 -0
- data/sig/generated/redhound/resolver.rbs +11 -0
- data/sig/generated/redhound/source/socket.rbs +13 -0
- data/sig/generated/redhound/version.rbs +5 -0
- data/sig/generated/redhound/writer.rbs +25 -0
- metadata +49 -11
- data/lib/redhound/header/ether.rb +0 -68
- data/lib/redhound/header.rb +0 -6
- data/lib/redhound/packet_mreq.rb +0 -46
- data/lib/redhound/socket_builder.rb +0 -30
- data/sig/redhound.rbs +0 -4
@@ -1,24 +1,26 @@
|
|
1
|
+
# rbs_inline: enabled
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Redhound
|
4
|
-
class
|
5
|
-
class Ipv4
|
5
|
+
class L3
|
6
|
+
class Ipv4 < Base
|
6
7
|
class << self
|
8
|
+
# @rbs (bytes: Array[Integer]) -> Redhound::L3::Ipv4
|
7
9
|
def generate(bytes:)
|
8
10
|
new(bytes:).generate
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
|
13
|
-
ICMP = 1
|
14
|
-
UDP = 17
|
14
|
+
attr_reader :protocol #: Protocol
|
15
15
|
|
16
|
+
# @rbs (bytes: Array[Integer]) -> void
|
16
17
|
def initialize(bytes:)
|
17
|
-
raise ArgumentError,
|
18
|
+
raise ArgumentError, "bytes must be #{size} bytes" unless bytes.size >= size
|
18
19
|
|
19
20
|
@bytes = bytes
|
20
21
|
end
|
21
22
|
|
23
|
+
# @rbs () -> Redhound::L3::Ipv4
|
22
24
|
def generate
|
23
25
|
@version = @bytes[0]
|
24
26
|
@ihl = @bytes[0]
|
@@ -27,85 +29,66 @@ module Redhound
|
|
27
29
|
@id = @bytes[4..5]
|
28
30
|
@frag_off = @bytes[6..7]
|
29
31
|
@ttl = @bytes[8]
|
30
|
-
@protocol = @bytes[9]
|
32
|
+
@protocol = Protocol.new(protocol: @bytes[9])
|
31
33
|
@check = @bytes[10..11]
|
32
34
|
@saddr = @bytes[12..15]
|
33
35
|
@daddr = @bytes[16..19]
|
34
36
|
self
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def udp?
|
42
|
-
@protocol == UDP
|
43
|
-
end
|
39
|
+
# @rbs () -> Integer
|
40
|
+
def size = 20
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
# @rbs () -> String
|
43
|
+
def to_s
|
44
|
+
" └─ IPv4 Ver: #{version} IHL: #{ihl} TOS: #{@tos} Total Length: #{tot_len} ID: #{id} Offset: #{frag_off} TTL: #{@ttl} Protocol: #{@protocol} Checksum: #{check} Src: #{saddr} Dst: #{daddr}"
|
48
45
|
end
|
49
46
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
IHL: #{@ihl}
|
54
|
-
TOS: #{@tos}
|
55
|
-
Total Length: #{tot_len}
|
56
|
-
ID: #{id}
|
57
|
-
Fragment Offset: #{frag_off}
|
58
|
-
TTL: #{@ttl}
|
59
|
-
Protocol: #{protocol}
|
60
|
-
Checksum: #{check}
|
61
|
-
Source IP: #{saddr}
|
62
|
-
Destination IP: #{daddr}
|
63
|
-
IPV4
|
47
|
+
# @rbs () -> bool
|
48
|
+
def supported_protocol?
|
49
|
+
@protocol.udp? || @protocol.icmp? # steep:ignore
|
64
50
|
end
|
65
51
|
|
66
52
|
private
|
67
53
|
|
54
|
+
# @rbs () -> Integer
|
68
55
|
def version
|
69
56
|
@version & 0xF0
|
70
57
|
end
|
71
58
|
|
59
|
+
# @rbs () -> Integer
|
72
60
|
def ihl
|
73
61
|
@ihl & 0x0F
|
74
62
|
end
|
75
63
|
|
64
|
+
# @rbs () -> Integer
|
76
65
|
def tot_len
|
77
66
|
@tot_len.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
78
67
|
end
|
79
68
|
|
69
|
+
# @rbs () -> Integer
|
80
70
|
def id
|
81
71
|
@id.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
82
72
|
end
|
83
73
|
|
74
|
+
# @rbs () -> Integer
|
84
75
|
def frag_off
|
85
76
|
@frag_off.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16) & 0x1FFF
|
86
77
|
end
|
87
78
|
|
88
|
-
|
89
|
-
case @protocol
|
90
|
-
when ICMP
|
91
|
-
'ICMP'
|
92
|
-
when UDP
|
93
|
-
'UDP'
|
94
|
-
else
|
95
|
-
'Unknown'
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
79
|
+
# @rbs () -> Integer
|
99
80
|
def check
|
100
81
|
@check.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
101
82
|
end
|
102
83
|
|
84
|
+
# @rbs () -> String
|
103
85
|
def saddr
|
104
|
-
@saddr.
|
86
|
+
@saddr.join('.')
|
105
87
|
end
|
106
88
|
|
89
|
+
# @rbs () -> String
|
107
90
|
def daddr
|
108
|
-
@daddr.
|
91
|
+
@daddr.join('.')
|
109
92
|
end
|
110
93
|
end
|
111
94
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Redhound
|
5
|
+
class L3
|
6
|
+
class Ipv6 < Base
|
7
|
+
class << self
|
8
|
+
# @rbs (bytes: Array[Integer]) -> Redhound::L3::Ipv6
|
9
|
+
def generate(bytes:)
|
10
|
+
new(bytes:).generate
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :protocol #: Protocol
|
15
|
+
|
16
|
+
# @rbs (bytes: Array[Integer]) -> void
|
17
|
+
def initialize(bytes:)
|
18
|
+
raise ArgumentError, "bytes must be bigger than #{size} bytes" unless bytes.size >= size
|
19
|
+
|
20
|
+
@bytes = bytes
|
21
|
+
end
|
22
|
+
|
23
|
+
# @rbs () -> Integer
|
24
|
+
def size = 40
|
25
|
+
|
26
|
+
# @rbs () -> Redhound::L3::Ipv6
|
27
|
+
def generate
|
28
|
+
version_traffic_flow = @bytes[0..3].join.to_i(16)
|
29
|
+
@version = (version_traffic_flow >> 28) & 0xF
|
30
|
+
@traffic_class = (version_traffic_flow >> 20) & 0xFF
|
31
|
+
@flow_label = version_traffic_flow & 0xFFFFF
|
32
|
+
@payload_length = @bytes[4..5]
|
33
|
+
@next_header = @bytes[6]
|
34
|
+
@hop_limit = @bytes[7]
|
35
|
+
@saddr = @bytes[8..23]
|
36
|
+
@daddr = @bytes[24..39]
|
37
|
+
@protocol = Protocol.new(protocol: @next_header)
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# @rbs () -> String
|
42
|
+
def to_s
|
43
|
+
" └─ IPv6 Ver: #{@version} Traffic Class: #{@traffic_class} Flow Label: #{@flow_label} Payload Length: #{payload_length} Next Header: #{@protocol} Hop Limit: #{@hop_limit} Src: #{saddr} Dst: #{daddr}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# @rbs () -> bool
|
47
|
+
def supported_protocol?
|
48
|
+
@protocol.udp? # steep:ignore
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @rbs () -> Integer
|
54
|
+
def payload_length
|
55
|
+
@payload_length.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @rbs () -> Integer
|
59
|
+
def saddr
|
60
|
+
@saddr.map { |b| b.to_s(16).rjust(2, '0') }.join(':')
|
61
|
+
end
|
62
|
+
|
63
|
+
# @rbs () -> Integer
|
64
|
+
def daddr
|
65
|
+
@daddr.map { |b| b.to_s(16).rjust(2, '0') }.join(':')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Redhound
|
5
|
+
class L3
|
6
|
+
class Protocol
|
7
|
+
# refs: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml#protocol-numbers-1
|
8
|
+
PROTO_TABLE = {
|
9
|
+
0 => 'HOPOPT',
|
10
|
+
1 => 'ICMP',
|
11
|
+
2 => 'IGMP',
|
12
|
+
3 => 'GGP',
|
13
|
+
4 => 'IP-in-IP',
|
14
|
+
5 => 'ST',
|
15
|
+
6 => 'TCP',
|
16
|
+
7 => 'CBT',
|
17
|
+
8 => 'EGP',
|
18
|
+
9 => 'IGP',
|
19
|
+
10 => 'BBN-RCC-MON',
|
20
|
+
11 => 'NVP-II',
|
21
|
+
12 => 'PUP',
|
22
|
+
13 => 'ARGUS',
|
23
|
+
14 => 'EMCON',
|
24
|
+
15 => 'XNET',
|
25
|
+
16 => 'CHAOS',
|
26
|
+
17 => 'UDP',
|
27
|
+
18 => 'MUX',
|
28
|
+
19 => 'DCN-MEAS',
|
29
|
+
20 => 'HMP',
|
30
|
+
21 => 'PRM',
|
31
|
+
22 => 'XNS-IDP',
|
32
|
+
23 => 'TRUNK-1',
|
33
|
+
24 => 'TRUNK-2',
|
34
|
+
25 => 'LEAF-1',
|
35
|
+
26 => 'LEAF-2',
|
36
|
+
27 => 'RDP',
|
37
|
+
28 => 'IRTP',
|
38
|
+
29 => 'ISO-TP4',
|
39
|
+
30 => 'NETBLT',
|
40
|
+
31 => 'MFE-NSP',
|
41
|
+
32 => 'MERIT-INP',
|
42
|
+
33 => 'DCCP',
|
43
|
+
34 => '3PC',
|
44
|
+
35 => 'IDPR',
|
45
|
+
36 => 'XTP',
|
46
|
+
37 => 'DDP',
|
47
|
+
38 => 'IDPR-CMTP',
|
48
|
+
39 => 'TP++',
|
49
|
+
40 => 'IL',
|
50
|
+
41 => 'IPv6',
|
51
|
+
42 => 'SDRP',
|
52
|
+
43 => 'IPv6-Route',
|
53
|
+
44 => 'IPv6-Frag',
|
54
|
+
45 => 'IDRP',
|
55
|
+
46 => 'RSVP',
|
56
|
+
47 => 'GRE',
|
57
|
+
48 => 'DSR',
|
58
|
+
49 => 'BNA',
|
59
|
+
50 => 'ESP',
|
60
|
+
51 => 'AH',
|
61
|
+
52 => 'I-NLSP',
|
62
|
+
53 => 'SWIPE',
|
63
|
+
54 => 'NARP',
|
64
|
+
55 => 'MOBILE',
|
65
|
+
56 => 'TLSP',
|
66
|
+
57 => 'SKIP',
|
67
|
+
58 => 'IPv6-ICMP',
|
68
|
+
59 => 'IPv6-NoNxt',
|
69
|
+
60 => 'IPv6-Opts',
|
70
|
+
61 => 'Any host internal protocol',
|
71
|
+
62 => 'CFTP',
|
72
|
+
63 => 'Any local network',
|
73
|
+
64 => 'SAT-EXPAK',
|
74
|
+
65 => 'KRYPTOLAN',
|
75
|
+
66 => 'RVD',
|
76
|
+
67 => 'IPPC',
|
77
|
+
68 => 'Any distributed file system',
|
78
|
+
69 => 'SAT-MON',
|
79
|
+
70 => 'VISA',
|
80
|
+
71 => 'IPCV',
|
81
|
+
72 => 'CPNX',
|
82
|
+
73 => 'CPHB',
|
83
|
+
74 => 'WSN',
|
84
|
+
75 => 'PVP',
|
85
|
+
76 => 'BR-SAT-MON',
|
86
|
+
77 => 'SUN-ND',
|
87
|
+
78 => 'WB-MON',
|
88
|
+
79 => 'WB-EXPAK',
|
89
|
+
80 => 'ISO-IP',
|
90
|
+
81 => 'VMTP',
|
91
|
+
82 => 'SECURE-VMTP',
|
92
|
+
83 => 'VINES',
|
93
|
+
84 => 'TTP',
|
94
|
+
85 => 'NSFNET-IGP',
|
95
|
+
86 => 'DGP',
|
96
|
+
87 => 'TCF',
|
97
|
+
88 => 'EIGRP',
|
98
|
+
89 => 'OSPFIGP',
|
99
|
+
90 => 'Sprite-RPC',
|
100
|
+
91 => 'LARP',
|
101
|
+
92 => 'MTP',
|
102
|
+
93 => 'AX.25',
|
103
|
+
94 => 'IPIP',
|
104
|
+
95 => 'MICP',
|
105
|
+
96 => 'SCC-SP',
|
106
|
+
97 => 'ETHERIP',
|
107
|
+
98 => 'ENCAP',
|
108
|
+
99 => 'Any private encryption scheme',
|
109
|
+
100 => 'GMTP',
|
110
|
+
101 => 'IFMP',
|
111
|
+
102 => 'PNNI',
|
112
|
+
103 => 'PIM',
|
113
|
+
104 => 'ARIS',
|
114
|
+
105 => 'SCPS',
|
115
|
+
106 => 'QNX',
|
116
|
+
107 => 'A/N',
|
117
|
+
108 => 'IPComp',
|
118
|
+
109 => 'SNP',
|
119
|
+
110 => 'Compaq-Peer',
|
120
|
+
111 => 'IPX-in-IP',
|
121
|
+
112 => 'VRRP',
|
122
|
+
113 => 'PGM',
|
123
|
+
114 => 'Any 0-hop protocol',
|
124
|
+
115 => 'L2TP',
|
125
|
+
116 => 'DDX',
|
126
|
+
117 => 'IATP',
|
127
|
+
118 => 'STP',
|
128
|
+
119 => 'SRP',
|
129
|
+
120 => 'UTI',
|
130
|
+
121 => 'SMP',
|
131
|
+
122 => 'SM',
|
132
|
+
123 => 'PTP',
|
133
|
+
124 => 'IS-IS over IPv4',
|
134
|
+
125 => 'FIRE',
|
135
|
+
126 => 'CRTP',
|
136
|
+
127 => 'CRUDP',
|
137
|
+
128 => 'SSCOPMCE',
|
138
|
+
129 => 'IPLT',
|
139
|
+
130 => 'SPS',
|
140
|
+
131 => 'PIPE',
|
141
|
+
132 => 'SCTP',
|
142
|
+
133 => 'FC',
|
143
|
+
134 => 'RSVP-E2E-IGNORE',
|
144
|
+
135 => 'Mobility Header',
|
145
|
+
136 => 'UDPLite',
|
146
|
+
137 => 'MPLS-in-IP',
|
147
|
+
138 => 'manet',
|
148
|
+
139 => 'HIP',
|
149
|
+
140 => 'Shim6',
|
150
|
+
141 => 'WESP',
|
151
|
+
142 => 'ROHC',
|
152
|
+
255 => 'Reserved'
|
153
|
+
}.freeze
|
154
|
+
|
155
|
+
# @rbs (protocol: Integer) -> void
|
156
|
+
def initialize(protocol:)
|
157
|
+
@protocol = protocol
|
158
|
+
end
|
159
|
+
|
160
|
+
# @rbs () -> String
|
161
|
+
def to_s
|
162
|
+
PROTO_TABLE[@protocol] || 'Unknown'
|
163
|
+
end
|
164
|
+
|
165
|
+
PROTO_TABLE.each do |code, name|
|
166
|
+
method_name = name.downcase.gsub(/[ \-]/, '_') + '?'
|
167
|
+
define_method(method_name) do
|
168
|
+
@protocol == code
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Redhound
|
5
|
+
class L3
|
6
|
+
class Resolver
|
7
|
+
# @rbs (bytes: Array[Integer], l2: Redhound::L2::Ether) -> Redhound::L3::Base?
|
8
|
+
def self.resolve(bytes:, l2:)
|
9
|
+
new(bytes:, l2:).resolve
|
10
|
+
end
|
11
|
+
|
12
|
+
# @rbs (bytes: Array[Integer], l2: Redhound::L2::Ether) -> void
|
13
|
+
def initialize(bytes:, l2:)
|
14
|
+
@bytes = bytes
|
15
|
+
@l2 = l2
|
16
|
+
end
|
17
|
+
|
18
|
+
# @rbs () -> Redhound::L3::Base?
|
19
|
+
def resolve
|
20
|
+
if @l2.type.ipv4?
|
21
|
+
Ipv4.generate(bytes: @bytes)
|
22
|
+
elsif @l2.type.ipv6?
|
23
|
+
Ipv6.generate(bytes: @bytes)
|
24
|
+
elsif @l2.type.arp?
|
25
|
+
Arp.generate(bytes: @bytes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/redhound/l3.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Redhound
|
5
|
+
class L4
|
6
|
+
class Base
|
7
|
+
class << self
|
8
|
+
# @rbs (bytes: Array[Integer]) -> Redhound::L4::Base
|
9
|
+
def generate(bytes:)
|
10
|
+
new(bytes:).generate
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @rbs (bytes: Array[Integer]) -> void
|
15
|
+
def initialize(bytes:)
|
16
|
+
warn 'initialize method must be implemented'
|
17
|
+
end
|
18
|
+
|
19
|
+
# @rbs () -> Redhound::L4::Base
|
20
|
+
def generate
|
21
|
+
warn 'generate method must be implemented'
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
# @rbs () -> void
|
26
|
+
def dump
|
27
|
+
puts self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,20 +1,17 @@
|
|
1
|
+
# rbs_inline: enabled
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Redhound
|
4
|
-
class
|
5
|
-
class Icmp
|
6
|
-
|
7
|
-
def generate(bytes:)
|
8
|
-
new(bytes:).generate
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
5
|
+
class L4
|
6
|
+
class Icmp < Base
|
7
|
+
# @rbs (bytes: Array[Integer]) -> void
|
12
8
|
def initialize(bytes:)
|
13
|
-
raise ArgumentError,
|
9
|
+
raise ArgumentError, "bytes must be bigger than #{size} bytes" unless bytes.size >= size
|
14
10
|
|
15
11
|
@bytes = bytes
|
16
12
|
end
|
17
13
|
|
14
|
+
# @rbs () -> Redhound::L4::Icmp
|
18
15
|
def generate
|
19
16
|
@type = @bytes[0]
|
20
17
|
@code = @bytes[1]
|
@@ -30,47 +27,44 @@ module Redhound
|
|
30
27
|
self
|
31
28
|
end
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
puts self
|
36
|
-
end
|
30
|
+
# @rbs () -> Integer
|
31
|
+
def size = 8
|
37
32
|
|
33
|
+
# @rbs () -> String
|
38
34
|
def to_s
|
39
35
|
if @type.zero? || @type == 8
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
Checksum: #{check}
|
44
|
-
ID: #{id}
|
45
|
-
Sequence: #{seq}
|
46
|
-
Data: #{data}
|
36
|
+
<<-ICMP.chomp
|
37
|
+
└─ ICMP Type: #{@type} Code: #{@code} Checksum: #{check} ID: #{id} Sequence: #{seq}
|
38
|
+
└─ Payload: #{data}
|
47
39
|
ICMP
|
48
40
|
else
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
Checksum: #{check}
|
53
|
-
Data: #{data}
|
41
|
+
<<-ICMP.chomp
|
42
|
+
└─ ICMP Type: #{@type} Code: #{@code} Checksum: #{check}
|
43
|
+
└─ Payload: #{data}
|
54
44
|
ICMP
|
55
45
|
end
|
56
46
|
end
|
57
47
|
|
58
48
|
private
|
59
49
|
|
50
|
+
# @rbs () -> Integer
|
60
51
|
def check
|
61
52
|
@check.map { |b| b.to_s(16).rjust(2, '0') }.join
|
62
53
|
end
|
63
54
|
|
55
|
+
# @rbs () -> Integer
|
64
56
|
def id
|
65
57
|
@id.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
66
58
|
end
|
67
59
|
|
60
|
+
# @rbs () -> Integer
|
68
61
|
def seq
|
69
62
|
@seq.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
70
63
|
end
|
71
64
|
|
65
|
+
# @rbs () -> String
|
72
66
|
def data
|
73
|
-
@data.map(&:chr).join
|
67
|
+
@data.map(&:chr).join.force_encoding("UTF-8")
|
74
68
|
end
|
75
69
|
end
|
76
70
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Redhound
|
5
|
+
class L4
|
6
|
+
class Resolver
|
7
|
+
# @rbs (bytes: Array[Integer], l3: Redhound::L3::Base) -> Redhound::L4::Base?
|
8
|
+
def self.resolve(bytes:, l3:)
|
9
|
+
new(bytes:, l3:).resolve
|
10
|
+
end
|
11
|
+
|
12
|
+
# @rbs (bytes: Array[Integer], l3: Redhound::L3::Base) -> void
|
13
|
+
def initialize(bytes:, l3:)
|
14
|
+
@bytes = bytes
|
15
|
+
@l3 = l3
|
16
|
+
end
|
17
|
+
|
18
|
+
# @rbs () -> Redhound::L4::Base?
|
19
|
+
def resolve
|
20
|
+
if @l3.protocol.udp?
|
21
|
+
Udp.generate(bytes: @bytes)
|
22
|
+
elsif @l3.protocol.icmp?
|
23
|
+
Icmp.generate(bytes: @bytes)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,20 +1,17 @@
|
|
1
|
+
# rbs_inline: enabled
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Redhound
|
4
|
-
class
|
5
|
-
class Udp
|
6
|
-
|
7
|
-
def generate(bytes:)
|
8
|
-
new(bytes:).generate
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
5
|
+
class L4
|
6
|
+
class Udp < Base
|
7
|
+
# @rbs (bytes: Array[Integer]) -> void
|
12
8
|
def initialize(bytes:)
|
13
|
-
raise ArgumentError,
|
9
|
+
raise ArgumentError, "bytes must be bigger than #{size} bytes" unless bytes.size >= size
|
14
10
|
|
15
11
|
@bytes = bytes
|
16
12
|
end
|
17
13
|
|
14
|
+
# @rbs () -> Redhound::L4::Udp
|
18
15
|
def generate
|
19
16
|
@sport = @bytes[0..1]
|
20
17
|
@dport = @bytes[2..3]
|
@@ -24,37 +21,40 @@ module Redhound
|
|
24
21
|
self
|
25
22
|
end
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
puts self
|
30
|
-
end
|
24
|
+
# @rbs () -> Integer
|
25
|
+
def size = 8
|
31
26
|
|
27
|
+
# @rbs () -> String
|
32
28
|
def to_s
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
Length: #{len}
|
37
|
-
Checksum: #{check}
|
38
|
-
Data: #{data}
|
29
|
+
<<-UDP
|
30
|
+
└─ UDP Src: #{sport} Dst: #{dport} Len: #{len} Checksum: #{check}
|
31
|
+
└─ Payload: #{data}
|
39
32
|
UDP
|
40
33
|
end
|
41
34
|
|
35
|
+
private
|
36
|
+
|
37
|
+
# @rbs () -> Integer
|
42
38
|
def sport
|
43
39
|
@sport.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
44
40
|
end
|
45
41
|
|
42
|
+
# @rbs () -> Integer
|
46
43
|
def dport
|
47
44
|
@dport.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
48
45
|
end
|
49
46
|
|
47
|
+
# @rbs () -> Integer
|
50
48
|
def len
|
51
49
|
@len.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
52
50
|
end
|
53
51
|
|
52
|
+
# @rbs () -> Integer
|
54
53
|
def check
|
55
54
|
@check.map { |b| b.to_s(16).rjust(2, '0') }.join.to_i(16)
|
56
55
|
end
|
57
56
|
|
57
|
+
# @rbs () -> String
|
58
58
|
def data
|
59
59
|
@data.map(&:chr).join
|
60
60
|
end
|