packetgen 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/packetgen/header/arp.rb +54 -125
  4. data/lib/packetgen/header/base.rb +175 -0
  5. data/lib/packetgen/header/dns/name.rb +110 -0
  6. data/lib/packetgen/header/dns/opt.rb +137 -0
  7. data/lib/packetgen/header/dns/option.rb +17 -0
  8. data/lib/packetgen/header/dns/qdsection.rb +39 -0
  9. data/lib/packetgen/header/dns/question.rb +129 -0
  10. data/lib/packetgen/header/dns/rr.rb +89 -0
  11. data/lib/packetgen/header/dns/rrsection.rb +72 -0
  12. data/lib/packetgen/header/dns.rb +276 -0
  13. data/lib/packetgen/header/esp.rb +38 -70
  14. data/lib/packetgen/header/eth.rb +35 -106
  15. data/lib/packetgen/header/icmp.rb +19 -70
  16. data/lib/packetgen/header/icmpv6.rb +3 -3
  17. data/lib/packetgen/header/ip.rb +54 -210
  18. data/lib/packetgen/header/ipv6.rb +73 -164
  19. data/lib/packetgen/header/tcp/option.rb +34 -50
  20. data/lib/packetgen/header/tcp/options.rb +19 -20
  21. data/lib/packetgen/header/tcp.rb +66 -129
  22. data/lib/packetgen/header/udp.rb +31 -88
  23. data/lib/packetgen/header.rb +5 -10
  24. data/lib/packetgen/inspect.rb +5 -4
  25. data/lib/packetgen/packet.rb +74 -57
  26. data/lib/packetgen/pcapng/block.rb +49 -7
  27. data/lib/packetgen/pcapng/epb.rb +36 -34
  28. data/lib/packetgen/pcapng/file.rb +24 -8
  29. data/lib/packetgen/pcapng/idb.rb +28 -33
  30. data/lib/packetgen/pcapng/shb.rb +35 -39
  31. data/lib/packetgen/pcapng/spb.rb +18 -27
  32. data/lib/packetgen/pcapng/unknown_block.rb +11 -21
  33. data/lib/packetgen/pcapng.rb +9 -7
  34. data/lib/packetgen/types/array.rb +56 -0
  35. data/lib/packetgen/types/fields.rb +325 -0
  36. data/lib/packetgen/types/int.rb +164 -0
  37. data/lib/packetgen/types/int_string.rb +69 -0
  38. data/lib/packetgen/types/string.rb +36 -0
  39. data/lib/packetgen/types/tlv.rb +41 -0
  40. data/lib/packetgen/types.rb +13 -0
  41. data/lib/packetgen/version.rb +1 -1
  42. data/lib/packetgen.rb +1 -1
  43. metadata +19 -6
  44. data/lib/packetgen/header/header_class_methods.rb +0 -106
  45. data/lib/packetgen/header/header_methods.rb +0 -73
  46. data/lib/packetgen/structfu.rb +0 -363
@@ -5,12 +5,12 @@ module PacketGen
5
5
  class CipherError < Error;end
6
6
 
7
7
  # A ESP header consists of:
8
- # * a Security Parameters Index (#{spi}, {Int32} type),
8
+ # * a Security Parameters Index (#{spi}, {Types::Int32} type),
9
9
  # * a Sequence Number ({#sn}, +Int32+ type),
10
10
  # * a {#body} (variable length),
11
11
  # * an optional TFC padding ({#tfc}, variable length),
12
12
  # * an optional {#padding} (to align ESP on 32-bit boundary, variable length),
13
- # * a {#pad_length} ({Int8}),
13
+ # * a {#pad_length} ({Types::Int8}),
14
14
  # * a Next header field ({#next}, +Int8+),
15
15
  # * and an optional Integrity Check Value ({#icv}, variable length).
16
16
  #
@@ -62,11 +62,7 @@ module PacketGen
62
62
  #
63
63
  # pkt.esp.decrypt! cipher, intmode: hmac # => true if ICV check OK
64
64
  # @author Sylvain Daubert
65
- class ESP < Struct.new(:spi, :sn, :body, :tfc, :padding,
66
- :pad_length, :next, :icv)
67
- include StructFu
68
- include HeaderMethods
69
- extend HeaderClassMethods
65
+ class ESP < Base
70
66
 
71
67
  # IP protocol number for ESP
72
68
  IP_PROTOCOL = 50
@@ -74,6 +70,38 @@ module PacketGen
74
70
  # Well-known UDP port for ESP
75
71
  UDP_PORT = 4500
76
72
 
73
+ # @!attribute spi
74
+ # 32-bit Security Parameter Index
75
+ # @return [Integer]
76
+ define_field :spi, Types::Int32
77
+ # @!attribute sn
78
+ # 32-bit Sequence Number
79
+ # @return [Integer]
80
+ define_field :sn, Types::Int32
81
+ # @!attribute body
82
+ # @return [Types::String,Header::Base]
83
+ define_field :body, Types::String
84
+ # @!attribute tfc
85
+ # Traffic Flow Confidentiality padding
86
+ # @return [Types::String,Header::Base]
87
+ define_field :tfc, Types::String
88
+ # @!attribute padding
89
+ # ESP padding
90
+ # @return [Types::String,Header::Base]
91
+ define_field :padding, Types::String
92
+ # @!attribute pad_length
93
+ # 8-bit padding length
94
+ # @return [Integer]
95
+ define_field :pad_length, Types::Int8
96
+ # @!attribute next
97
+ # 8-bit next protocol value
98
+ # @return [Integer]
99
+ define_field :next, Types::Int8
100
+ # @!attribute icv
101
+ # Integrity Check Value
102
+ # @return [Types::String,Header::Base]
103
+ define_field :icv, Types::String
104
+
77
105
  # ICV (Integrity Check Value) length
78
106
  # @return [Integer]
79
107
  attr_accessor :icv_length
@@ -92,14 +120,7 @@ module PacketGen
92
120
  # @option options [::String] :icv Integrity Check Value
93
121
  def initialize(options={})
94
122
  @icv_length = options[:icv_length] || 0
95
- super Int32.new(options[:spi]),
96
- Int32.new(options[:sn]),
97
- StructFu::String.new.read(options[:body]),
98
- StructFu::String.new.read(options[:tfc]),
99
- StructFu::String.new.read(options[:padding]),
100
- Int8.new(options[:pad_length]),
101
- Int8.new(options[:next]),
102
- StructFu::String.new.read(options[:icv])
123
+ super
103
124
  end
104
125
 
105
126
  # Read a ESP packet from string.
@@ -111,7 +132,6 @@ module PacketGen
111
132
  # @return [self]
112
133
  def read(str)
113
134
  return self if str.nil?
114
- raise ParseError, 'string too short for ESP' if str.size < self.sz
115
135
  force_binary str
116
136
  self[:spi].read str[0, 4]
117
137
  self[:sn].read str[4, 4]
@@ -124,58 +144,6 @@ module PacketGen
124
144
  self
125
145
  end
126
146
 
127
- # Getter for SPI attribute
128
- # @return [Integer]
129
- def spi
130
- self[:spi].to_i
131
- end
132
-
133
- # Setter for SPI attribute
134
- # @param [Integer] val
135
- # @return [Integer]
136
- def spi=(val)
137
- typecast val
138
- end
139
-
140
- # Getter for SN attribute
141
- # @return [Integer]
142
- def sn
143
- self[:sn].to_i
144
- end
145
-
146
- # Setter for SN attribute
147
- # @param [Integer] val
148
- # @return [Integer]
149
- def sn=(val)
150
- typecast val
151
- end
152
-
153
- # Getter for +pad_length+ attribute
154
- # @return [Integer]
155
- def pad_length
156
- self[:pad_length].to_i
157
- end
158
-
159
- # Setter for +pad_length+ attribute
160
- # @param [Integer] val
161
- # @return [Integer]
162
- def pad_length=(val)
163
- typecast val
164
- end
165
-
166
- # Getter for +next+ attribute
167
- # @return [Integer]
168
- def next
169
- self[:next].to_i
170
- end
171
-
172
- # Setter for +next+ attribute
173
- # @param [Integer] val
174
- # @return [Integer]
175
- def next=(val)
176
- typecast val
177
- end
178
-
179
147
  # Encrypt in-place ESP payload and trailer.
180
148
  #
181
149
  # This method removes all data from +tfc+ and +padding+ fields, as their
@@ -252,7 +220,7 @@ module PacketGen
252
220
  # as padding is used to pad for CBC mode, this is unused
253
221
  cipher.final
254
222
 
255
- self[:body] = StructFu::String.new(iv) << enc_msg[0..-3]
223
+ self[:body] = Types::String.new(iv) << enc_msg[0..-3]
256
224
  self[:pad_length].read enc_msg[-2]
257
225
  self[:next].read enc_msg[-1]
258
226
 
@@ -364,7 +332,7 @@ module PacketGen
364
332
  def get_auth_data(opt)
365
333
  ad = self[:spi].to_s
366
334
  if opt[:esn]
367
- @esn = StructFu::Int32.new(opt[:esn])
335
+ @esn = Types::Int32.new(opt[:esn])
368
336
  ad << @esn.to_s if @conf.authenticated?
369
337
  end
370
338
  ad << self[:sn].to_s
@@ -9,8 +9,8 @@ module PacketGen
9
9
  # An Ethernet header consists of:
10
10
  # * a destination MAC address ({MacAddr}),
11
11
  # * a source MAC address (MacAddr),
12
- # * a {#ethertype} ({Int16}),
13
- # * and a body (a {String} or another Header class).
12
+ # * a {#ethertype} ({Types::Int16}),
13
+ # * and a body (a {Types::String} or another Header class).
14
14
  #
15
15
  # == Create a Ethernet header
16
16
  # # standalone
@@ -28,33 +28,30 @@ module PacketGen
28
28
  # eth.body = "This is a body"
29
29
  #
30
30
  # @author Sylvain Daubert
31
- class Eth < Struct.new(:dst, :src, :ethertype, :body)
32
- include StructFu
33
- include HeaderMethods
34
- extend HeaderClassMethods
31
+ class Eth < Base
35
32
 
36
33
  # Ethernet MAC address, as a group of 6 bytes
37
34
  # @author Sylvain Daubert
38
- class MacAddr < Struct.new(:a0, :a1, :a2, :a3, :a4, :a5)
39
- include StructFu
35
+ class MacAddr < Base
36
+ # @!attribute a0
37
+ # @return [Integer] first byte from MacAddr
38
+ define_field :a0, Types::Int8
39
+ # @!attribute a1
40
+ # @return [Integer] second byte from MacAddr
41
+ define_field :a1, Types::Int8
42
+ # @!attribute a2
43
+ # @return [Integer] third byte from MacAddr
44
+ define_field :a2, Types::Int8
45
+ # @!attribute a3
46
+ # @return [Integer] fourth byte from MacAddr
47
+ define_field :a3, Types::Int8
48
+ # @!attribute a4
49
+ # @return [Integer] fifth byte from MacAddr
50
+ define_field :a4, Types::Int8
51
+ # @!attribute a5
52
+ # @return [Integer] sixth byte from MacAddr
53
+ define_field :a5, Types::Int8
40
54
 
41
- # @param [Hash] options
42
- # @option options [Integer] :a0
43
- # @option options [Integer] :a1
44
- # @option options [Integer] :a2
45
- # @option options [Integer] :a3
46
- # @option options [Integer] :a4
47
- # @option options [Integer] :a5
48
- def initialize(options={})
49
- super Int8.new(options[:a0]),
50
- Int8.new(options[:a1]),
51
- Int8.new(options[:a2]),
52
- Int8.new(options[:a3]),
53
- Int8.new(options[:a4]),
54
- Int8.new(options[:a5])
55
-
56
- end
57
-
58
55
  # Read a human-readable string to populate +MacAddr+
59
56
  # @param [String] str
60
57
  # @return [self]
@@ -73,27 +70,10 @@ module PacketGen
73
70
  self
74
71
  end
75
72
 
76
- # Read a +MacAddr+ from a binary string
77
- # @param [String] str binary string
78
- # @return [self]
79
- def read(str)
80
- return self if str.nil?
81
- raise ParseError, 'string too short for Eth' if str.size < self.sz
82
- force_binary str
83
- [:a0, :a1, :a2, :a3, :a4, :a5].each_with_index do |byte, i|
84
- self[byte].read str[i, 1]
85
- end
86
- end
87
-
88
- [:a0, :a1, :a2, :a3, :a4, :a5].each do |sym|
89
- class_eval "def #{sym}; self[:#{sym}].to_i; end\n" \
90
- "def #{sym}=(v); self[:#{sym}].read v; end"
91
- end
92
-
93
73
  # +MacAddr+ in human readable form (colon format)
94
74
  # @return [String]
95
75
  def to_human
96
- members.map { |m| "#{'%02x' % self[m]}" }.join(':')
76
+ fields.map { |m| "#{'%02x' % self[m]}" }.join(':')
97
77
  end
98
78
  end
99
79
 
@@ -104,69 +84,18 @@ module PacketGen
104
84
  # @private timeout for PCAPRUB
105
85
  PCAP_TIMEOUT = 1
106
86
 
107
- # @param [Hash] options
108
- # @option options [String] :dst MAC destination address
109
- # @option options [String] :src MAC source address
110
- # @option options [Integer] :ethertype
111
- def initialize(options={})
112
- super MacAddr.new.from_human(options[:dst] || '00:00:00:00:00:00'),
113
- MacAddr.new.from_human(options[:src] || '00:00:00:00:00:00'),
114
- Int16.new(options[:ethertype] || 0),
115
- StructFu::String.new.read(options[:body])
116
- end
117
-
118
- # Read a Eth header from a string
119
- # @param [String] str binary string
120
- # @return [self]
121
- def read(str)
122
- return self if str.nil?
123
- raise ParseError, 'string too short for Eth' if str.size < self.sz
124
- force_binary str
125
- self[:dst].read str[0, 6]
126
- self[:src].read str[6, 6]
127
- self[:ethertype].read str[12, 2]
128
- self[:body].read str[14..-1]
129
- self
130
- end
131
-
132
- # Get MAC destination address
133
- # @return [String]
134
- def dst
135
- self[:dst].to_human
136
- end
137
-
138
- # Set MAC destination address
139
- # @param [String] addr
140
- # @return [String]
141
- def dst=(addr)
142
- self[:dst].from_human addr
143
- end
144
-
145
- # Get MAC source address
146
- # @return [String]
147
- def src
148
- self[:src].to_human
149
- end
150
-
151
- # Set MAC source address
152
- # @param [String] addr
153
- # @return [String]
154
- def src=(addr)
155
- self[:src].from_human addr
156
- end
157
-
158
- # Get ethertype field
159
- # @return [Integer]
160
- def ethertype
161
- self[:ethertype].to_i
162
- end
163
-
164
- # Set ethertype field
165
- # @param [Integer] type
166
- # @return [Integer]
167
- def ethertype=(type)
168
- self[:ethertype].value = type
169
- end
87
+ # @!attribute dst
88
+ # @return [MacAddr] Destination MAC address
89
+ define_field :dst, MacAddr, default: '00:00:00:00:00:00'
90
+ # @!attribute src
91
+ # @return [MacAddr] Source MAC address
92
+ define_field :src, MacAddr, default: '00:00:00:00:00:00'
93
+ # @!attribute ethertype
94
+ # @return [Integer] 16-bit integer to determine payload type
95
+ define_field :ethertype, Types::Int16, default: 0
96
+ # @!attribute body
97
+ # @return [Types::String,Header::Base]
98
+ define_field :body, Types::String
170
99
 
171
100
  # send Eth packet on wire.
172
101
  # @param [String] iface interface name
@@ -7,9 +7,9 @@ module PacketGen
7
7
  module Header
8
8
 
9
9
  # A ICMP header consists of:
10
- # * a {#type} field ({Int8} type),
11
- # * a {#code} field ({Int8} type),
12
- # * a {#checksum} field ({Int16} type),
10
+ # * a {#type} field ({Types::Int8} type),
11
+ # * a {#code} field ({Types::Int8} type),
12
+ # * a {#checksum} field ({Types::Int16} type),
13
13
  # * and a {#body}.
14
14
  #
15
15
  # == Create a ICMP header
@@ -26,38 +26,26 @@ module PacketGen
26
26
  # icmp.checksum = 0x248a
27
27
  # icmp.body.read 'this is a body'
28
28
  # @author Sylvain Daubert
29
- class ICMP < Struct.new(:type, :code, :checksum, :body)
30
- include StructFu
31
- include HeaderMethods
32
- extend HeaderClassMethods
29
+ class ICMP < Base
33
30
 
34
31
  # ICMP internet protocol number
35
32
  IP_PROTOCOL = 1
36
33
 
37
- # @param [Hash] options
38
- # @option options [Integer] :type
39
- # @option options [Integer] :code
40
- # @option options [Integer] :checksum
41
- # @option options [String] :body
42
- def initialize(options={})
43
- super Int8.new(options[:type]),
44
- Int8.new(options[:code]),
45
- Int16.new(options[:checksum]),
46
- StructFu::String.new.read(options[:body])
47
- end
48
-
49
- # Read a ICMP header from a string
50
- # @param [String] str binary string
51
- # @return [self]
52
- def read(str)
53
- return self if str.nil?
54
- raise ParseError, 'string too short for ICMP' if str.size < self.sz
55
- force_binary str
56
- self[:type].read str[0, 1]
57
- self[:code].read str[1, 1]
58
- self[:checksum].read str[2, 2]
59
- self[:body].read str[4..-1]
60
- end
34
+ # @!attribute type
35
+ # 8-bit ICMP type
36
+ # @return [Integer]
37
+ define_field :type, Types::Int8
38
+ # @!attribute code
39
+ # 8-bit ICMP code
40
+ # @return [Integer]
41
+ define_field :code, Types::Int8
42
+ # @!attribute checksum
43
+ # 16-bit ICMP checksum
44
+ # @return [Integer]
45
+ define_field :checksum, Types::Int16
46
+ # @!attribute body
47
+ # @return [Types::String,Header::Base]
48
+ define_field :body, Types::String
61
49
 
62
50
  # Compute checksum and set +checksum+ field
63
51
  # @return [Integer]
@@ -74,45 +62,6 @@ module PacketGen
74
62
  sum = ~sum & 0xffff
75
63
  self[:checksum].value = (sum == 0) ? 0xffff : sum
76
64
  end
77
-
78
- # Getter for type attribute
79
- # @return [Integer]
80
- def type
81
- self[:type].to_i
82
- end
83
-
84
- # Setter for type attribute
85
- # @param [Integer] type
86
- # @return [Integer]
87
- def type=(type)
88
- self[:type].value = type
89
- end
90
-
91
- # Getter for code attribute
92
- # @return [Integer]
93
- def code
94
- self[:code].to_i
95
- end
96
-
97
- # Setter for code attribute
98
- # @param [Integer] code
99
- # @return [Integer]
100
- def code=(code)
101
- self[:code].value = code
102
- end
103
-
104
- # Getter for checksum attribute
105
- # @return [Integer]
106
- def checksum
107
- self[:checksum].to_i
108
- end
109
-
110
- # Setter for checksum attribute
111
- # @param [Integer] sum
112
- # @return [Integer]
113
- def checksum=(sum)
114
- self[:checksum].value = sum
115
- end
116
65
  end
117
66
 
118
67
  self.add_class ICMP
@@ -7,9 +7,9 @@ module PacketGen
7
7
  module Header
8
8
 
9
9
  # A ICMPv6 header consists of:
10
- # * a +type+ field ({Int8} type),
11
- # * a +code+ field ({Int8} type),
12
- # * a +checksum+ field ({Int16} type),
10
+ # * a +type+ field ({Types::Int8} type),
11
+ # * a +code+ field ({Types::Int8} type),
12
+ # * a +checksum+ field ({Types::Int16} type),
13
13
  # * and a +body+.
14
14
  #
15
15
  # == Create a ICMPv6 header