ruckus 0.5.4

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 (59) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/README +0 -0
  4. data/README.markdown +51 -0
  5. data/Rakefile +54 -0
  6. data/VERSION +1 -0
  7. data/lib/ruckus.rb +70 -0
  8. data/lib/ruckus/blob.rb +113 -0
  9. data/lib/ruckus/choice.rb +55 -0
  10. data/lib/ruckus/dfuzz.rb +231 -0
  11. data/lib/ruckus/dictionary.rb +119 -0
  12. data/lib/ruckus/enum.rb +39 -0
  13. data/lib/ruckus/extensions/array.rb +33 -0
  14. data/lib/ruckus/extensions/class.rb +168 -0
  15. data/lib/ruckus/extensions/duplicable.rb +37 -0
  16. data/lib/ruckus/extensions/file.rb +24 -0
  17. data/lib/ruckus/extensions/fixnum.rb +26 -0
  18. data/lib/ruckus/extensions/hash.rb +10 -0
  19. data/lib/ruckus/extensions/integer.rb +26 -0
  20. data/lib/ruckus/extensions/ipaddr.rb +155 -0
  21. data/lib/ruckus/extensions/irb.rb +30 -0
  22. data/lib/ruckus/extensions/math.rb +6 -0
  23. data/lib/ruckus/extensions/module.rb +37 -0
  24. data/lib/ruckus/extensions/numeric.rb +117 -0
  25. data/lib/ruckus/extensions/object.rb +22 -0
  26. data/lib/ruckus/extensions/range.rb +16 -0
  27. data/lib/ruckus/extensions/socket.rb +20 -0
  28. data/lib/ruckus/extensions/string.rb +327 -0
  29. data/lib/ruckus/filter.rb +16 -0
  30. data/lib/ruckus/human_display.rb +79 -0
  31. data/lib/ruckus/ip.rb +38 -0
  32. data/lib/ruckus/mac_addr.rb +31 -0
  33. data/lib/ruckus/mutator.rb +318 -0
  34. data/lib/ruckus/null.rb +24 -0
  35. data/lib/ruckus/number.rb +360 -0
  36. data/lib/ruckus/parsel.rb +363 -0
  37. data/lib/ruckus/selector.rb +92 -0
  38. data/lib/ruckus/str.rb +164 -0
  39. data/lib/ruckus/structure.rb +263 -0
  40. data/lib/ruckus/structure/atcreate.rb +23 -0
  41. data/lib/ruckus/structure/beforebacks.rb +28 -0
  42. data/lib/ruckus/structure/defaults.rb +57 -0
  43. data/lib/ruckus/structure/factory.rb +42 -0
  44. data/lib/ruckus/structure/fixupfields.rb +16 -0
  45. data/lib/ruckus/structure/initializers.rb +14 -0
  46. data/lib/ruckus/structure/relate.rb +34 -0
  47. data/lib/ruckus/structure/replacement.rb +30 -0
  48. data/lib/ruckus/structure/searchmods.rb +33 -0
  49. data/lib/ruckus/structure/structureproxies.rb +28 -0
  50. data/lib/ruckus/structure/validate.rb +12 -0
  51. data/lib/ruckus/structure_shortcuts.rb +109 -0
  52. data/lib/ruckus/time_t.rb +26 -0
  53. data/lib/ruckus/vector.rb +97 -0
  54. data/ruckus.gemspec +104 -0
  55. data/test/test_decides.rb +61 -0
  56. data/test/test_mutator.rb +29 -0
  57. data/test/test_override.rb +23 -0
  58. data/test/test_replace.rb +39 -0
  59. metadata +138 -0
@@ -0,0 +1,31 @@
1
+ # instead of dealing with .value directly, this class exposes 'set' and
2
+ # 'display' methods for handling @value as a mac address string.
3
+ class MacAddr < Ruckus::Str
4
+ def initialize(opts={})
5
+ opts[:size] = 6
6
+ super(opts)
7
+ @width = 48
8
+ end
9
+
10
+ # mac address may be specified as either
11
+ # aa-bb-cc-dd-ee-ff
12
+ # or
13
+ # aa:bb:cc:dd:ee:ff
14
+ def set(val)
15
+ unless m=/^([0-9a-f]{2})([:-]?)([0-9a-f]{2})\2([0-9a-f]{2})\2([0-9a-f]{2})\2([0-9a-f]{2})\2([0-9a-f]{2})$/i.match(val)
16
+ raise "argument must be a mac_addr string as in aa:bb:cc:dd:ee:ff"
17
+ end
18
+ self.value = [$1,$3,$4,$5,$6,$7].join('').dehexify
19
+ end
20
+
21
+
22
+ def display
23
+ self.value.split('').map {|x| x.hexify}.join(':')
24
+ end
25
+
26
+ def to_human(indent=nil)
27
+ indent ||= ""
28
+ "#{indent}#{name} = #{self.display}"
29
+ end
30
+ end
31
+
@@ -0,0 +1,318 @@
1
+ # === Mutator is a half-assed fuzzing framework intended to snap in to Ruckus.
2
+ # Mutator provides a decorator-style interface to fuzzed integers and strings,
3
+ # so that you can chain them to get strings that grow and include metacharacters
4
+ # with X probability, etc.
5
+ #
6
+ # There are two core objects in here:
7
+ # * <tt>Mutator</tt> is a base type, like a String or an Integer, wrapped
8
+ # in an object that provides a <tt>permute</tt> method to change the
9
+ # value, and a stack of <tt>Modifier</tt> objects.
10
+ # * <tt>Modifier</tt> is an object that takes a value and changes it
11
+ # to do evil. Modifiers chain.
12
+ #
13
+ # This stuff is really kind of an afterthought; the real work in building
14
+ # fuzzer is getting the encoding right, so you can reach more of the target
15
+ # code. Ruckus hides the details of how strings and integers are actually
16
+ # encoded, so most of the "fuzzing" part just comes down to making evil
17
+ # looking strings. The Parsel framework takes care of encoding those evil
18
+ # strings properly so that a CIFS stack will read them.
19
+ #
20
+ module Ruckus
21
+ module Mutator
22
+
23
+ # Create me with a String, and I wrap the string, forwarding method
24
+ # invocations to it. Call "permute" and I'll run through my Modifier
25
+ # chain to derive a new value (for instance, tripling the number of
26
+ # characters).
27
+ #
28
+ class Mutator
29
+
30
+ # <tt>base</tt> is usually a String (like "helu") or Fixnum.
31
+ # Stack is a set of modifier objects (or class names, if you
32
+ # just want to use the defaults). A Mutator with an empty
33
+ # Modifier stack doesn't do anything and behaves just like an
34
+ # ordinary String or Fixnum.
35
+ #
36
+ def initialize(base=nil, stack=[])
37
+ @base = base
38
+ @cur = @base
39
+ @stack = stack.map do |o|
40
+ o = o.new if o.kind_of? Class
41
+ o
42
+ end
43
+ end
44
+
45
+ def method_missing(meth, *args)
46
+ @cur.send(meth, *args)
47
+ end
48
+
49
+ # A fuzzer clock tick; mess up the enclosed value.
50
+ #
51
+ def permute
52
+ @cur = @stack.inject(@cur) {|cur, mod| mod << cur}
53
+ end
54
+ end
55
+
56
+ # The guts; each Modifier class implements some way of screwing
57
+ # with a value to catch bugs. Modifiers are all created with
58
+ # keyword args; the base class catches:
59
+ # now:: true/false (def: false) fire immediately, just once,
60
+ # irrespective of probability, even if probability is
61
+ # provided.
62
+ # prob:: (def: 100) pctg chance this modifier will fire on this
63
+ # tick
64
+ # max_steps:: number of times to fire this modifier before it stops
65
+ # and just starts acting like a no-op. -1 equals no max
66
+ #
67
+ class Modifier
68
+ def initialize(opts={})
69
+ @now = opts[:now] || false
70
+ @prob = opts[:prob] || 100
71
+ @max_steps = opts[:max_steps] || 700
72
+ @cur = 0
73
+ @opts = opts
74
+ end
75
+
76
+ # Should this fire, based on prob?
77
+ #
78
+ def go?
79
+ if @now
80
+ @now = false
81
+ return true
82
+ end
83
+ rand(100) < @prob
84
+ end
85
+
86
+ # Base class stub does nothing. Subclasses override this method
87
+ # to implement logic. Callers don't use this method, though: they
88
+ # use operator<<.
89
+ #
90
+ def mod(x); x; end
91
+
92
+ # This is what callers call. Subclasses do not override this
93
+ # method. This implements probability and max-steps. How it
94
+ # looks:
95
+ #
96
+ # str = modifier << str
97
+ #
98
+ def <<(x)
99
+ return x if (@cur += 1) > @max_steps && @max_steps != -1
100
+ return x if not go?
101
+ mod(x)
102
+ end
103
+ end
104
+
105
+ # Geometrically increases size.
106
+ #
107
+ # A
108
+ # AA
109
+ # AAAA
110
+ # AAAAAAAA ... etc
111
+ #
112
+ class Multiplier < Modifier
113
+
114
+ # Takes:
115
+ # multiplier:: (def: 2) how much to multiply by.
116
+ #
117
+ def initialize(opts={})
118
+ @step = opts[:multiplier] || 2
119
+ super
120
+ end
121
+
122
+ def mod(x)
123
+ x * @step
124
+ end
125
+ end
126
+
127
+ # Adds fixed amounts of data.
128
+ #
129
+ # A
130
+ # AA
131
+ # AAA
132
+ # AAAA ... etc
133
+ #
134
+ class Adder < Modifier
135
+
136
+ # Takes:
137
+ # base:: (def: "A") what to add
138
+ # step:: (def: 100) how much of this to add at each step
139
+ #
140
+ def initialize(opts={})
141
+ @base = opts[:base] || "A"
142
+ @step = opts[:step] || 100
143
+ super
144
+ end
145
+
146
+ def mod(x)
147
+ if x.kind_of? String
148
+ x + (@base * @step)
149
+ else
150
+ x + @step
151
+ end
152
+ end
153
+ end
154
+
155
+ # Path traversal metacharacters and keywords, cycled. Add new
156
+ # ones to the STRINGS array.
157
+ #
158
+ class PathTraversal < Modifier
159
+ STRINGS = [ "etc/passwd",
160
+ "etc/passwd\x00",
161
+ "etc/passwd%00",
162
+ "boot.ini",
163
+ "boot.ini\x00",
164
+ "boot.ini%00" ]
165
+ def mod(x)
166
+ x = x + ("../" * (@cur + 1)) + STRINGS[@cur % STRINGS.size]
167
+ if (@cur % 2) == 0
168
+ x.gsub!("/", "\\")
169
+ end
170
+ return x
171
+ end
172
+ end
173
+
174
+ # The format strings, cycled. Add new ones to the STRINGS array.
175
+ #
176
+ class FormatStrings < Modifier
177
+ STRINGS = [ "%n", "%25n", "%s", "%x" ]
178
+
179
+ def mod(x)
180
+ x + STRINGS[@cur % STRINGS.size]
181
+ end
182
+ end
183
+
184
+ # The most likely evil metachars, but if you're thorough, you
185
+ # just try all non-isalnums.
186
+ #
187
+ class Metacharacters < Modifier
188
+ STRINGS = [ ".", "/", "\\", "$", "-", "%", "$", ";",
189
+ "'", '"', "*", "\x00" ]
190
+
191
+ def mod
192
+ x = x + STRINGS[@cur % STRINGS.size]
193
+ if opts[:hexify]
194
+ 0.upto(x.size - 1) do |i|
195
+ x[i] = "%#{ x[i].to_s(16) }"
196
+ end
197
+ end
198
+ return x
199
+ end
200
+ end
201
+
202
+ # Things that will break SQL queries.
203
+ #
204
+ class SQLStrings < Modifier
205
+ STRINGS = [ "'sql0", "+sql1", "sql2;", "sql3 ;--", "(sql4)" ]
206
+
207
+ def mod
208
+ x + STRINGS[@cur % STRINGS.size]
209
+ end
210
+ end
211
+
212
+ # Trivial XSS tickler.
213
+ #
214
+ class XSS < Modifier
215
+ def mod
216
+ x + "<script>alert(document.location);</script>"
217
+ end
218
+ end
219
+
220
+ # Generate random numbers
221
+ #
222
+ class Random < Modifier
223
+ def initialize(opts={})
224
+ srand((@seed = opts[:seed])) if opts[:seed]
225
+ super
226
+ @max = opts[:max] || 0xFFFFFFFF
227
+ if opts[:width]
228
+ @max = Numeric.mask_for(opts[:width])
229
+ end
230
+ end
231
+
232
+ def mod(i)
233
+ rand(@max)
234
+ end
235
+ end
236
+
237
+ # Randomly sets the top bit of each byte, turning ASCII into
238
+ # hi-ASCII.
239
+ #
240
+ class Hibit < Modifier
241
+ def initialize(opts={})
242
+ opts[:prob] ||= 50
243
+ @width = opts[:width] || 32
244
+ super
245
+ end
246
+
247
+ def mod(x)
248
+ if x.kind_of? String
249
+ 0.upto(x.size - 1) do |i|
250
+ x[i] |= 0x80 if go?
251
+ end
252
+ else
253
+ x |= (0x80 << (@width - 8))
254
+ end
255
+ return x
256
+ end
257
+ end
258
+
259
+ # Cache the starting value (this is meant to the be first modifier
260
+ # in the chain, if you're using it) and randomly reset the string
261
+ # back to that starting value.
262
+ #
263
+ class Reset < Modifier
264
+ def initialize(opts={})
265
+ opts[:prob] ||= 25
266
+ super(opts.merge(:now => true))
267
+ end
268
+
269
+ def mod(x)
270
+ (@orig ||= x.clone).clone
271
+ end
272
+ end
273
+
274
+ # Randomize a string.
275
+ #
276
+ class Randomizer < Modifier
277
+ def mod(x)
278
+ 0.upto(x.size-1) do |i|
279
+ x[i] = rand(0xff)
280
+ end
281
+ return x
282
+ end
283
+ end
284
+
285
+ # Wrap Number with Mutator, make to_i work.
286
+ #
287
+ class Number < Mutator
288
+ def initialize(base=0, stack=[]); super; end
289
+ def to_i; @cur.to_i; end
290
+ end
291
+
292
+ # Wrap String with Mutator, make to_s work.
293
+ #
294
+ class Str < Mutator
295
+ def initialize(base="", stack=[]); super; end
296
+ def to_s(off=nil); @cur.to_s; end
297
+ end
298
+
299
+ class << self
300
+ def random_int(opts={})
301
+ Number.new(1, [Random.new(opts)])
302
+ end
303
+
304
+ def r8; random_int(:width => 8); end
305
+ def r16; random_int(:width => 16); end
306
+ def r32; random_int(:width => 32); end
307
+ def r64; random_int(:width => 64); end
308
+
309
+ def grostring(base="A", opts={})
310
+ Str.new(base, [Reset, Adder.new(opts)])
311
+ end
312
+
313
+ def randstr(base="A")
314
+ Str.new(base, [Reset, Randomizer])
315
+ end
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,24 @@
1
+ module Ruckus
2
+ class Null < Parsel
3
+ def initialize(opts={})
4
+ super(opts)
5
+ end
6
+
7
+ def to_s(off=nil)
8
+ @rendered_offset = off || 0
9
+ if off
10
+ return "", off
11
+ else
12
+ return ""
13
+ end
14
+ end
15
+
16
+ def capture(str)
17
+ return str
18
+ end
19
+
20
+ def size
21
+ 0
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,360 @@
1
+ # === Most things you want to render are Numbers
2
+
3
+ module Ruckus
4
+ # A Ruckus::Number is a type of Parsel that wraps an Integer.
5
+ class Number < Parsel
6
+ attr_accessor :width, :endian, :radix, :pad, :ascii
7
+ attr_accessor :value
8
+
9
+
10
+ # Options:
11
+ # width:: (Default: 32) Width in bits --- can be odd!
12
+ # endian:: (Default: :little) Endianness --- not honored for
13
+ # odd widths
14
+ # value:: Usually a fixnum, but can be a method to call on
15
+ # sibling Parsel, e.g. :size for "Length" fields.
16
+ #
17
+ # Note: odd-width fields must be parented (see Blob or Structure)
18
+ # to render or capture their values
19
+ #
20
+ def initialize(opts={})
21
+ opts[:width] ||= 32
22
+ opts[:endian] ||= :little
23
+ # opts[:value] ||= 0xABADCAFE
24
+ opts[:value] ||= 0
25
+ opts[:radix] ||= 0
26
+
27
+ if opts[:endian] == :native
28
+ opts[:endian] = Parsel.endian?
29
+ end
30
+ super(opts)
31
+ end
32
+
33
+ private
34
+
35
+ def widthcode
36
+ case @width
37
+ when 8; code = "C"
38
+ when 16; code = "S"
39
+ when 32; code = "I"
40
+ when 64; code = "Q"
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ public
47
+
48
+ # this is some seriously weak shit down here
49
+
50
+ # Is this an odd-width (single bit, nibble, etc) number?
51
+ #
52
+ def odd_width? ; not widthcode ; end
53
+
54
+ private
55
+
56
+ def span_start
57
+ i_am = where_am_i?
58
+ first = i_am
59
+ (i_am - 1).downto(0) do |i|
60
+ begin
61
+ break if not parent[i].odd_width?
62
+ rescue
63
+ break
64
+ end
65
+ first = i
66
+ end
67
+ return first
68
+ end
69
+
70
+ public
71
+
72
+ # For odd-width fields --- find how big the span of neighboring odd-width
73
+ # fields is, in bits.
74
+ #
75
+ def span_bits
76
+ last = where_am_i?
77
+ span_start.upto(parent.count - 1) do |i|
78
+ break if not parent[i].respond_to? :odd_width?
79
+ break if not parent[i].odd_width?
80
+ last = i
81
+ end
82
+
83
+ tot = 0
84
+ span_start.upto(last) { |i| tot += parent[i].width }
85
+ tot
86
+ end
87
+
88
+ # Where are we in the span of neighboring odd-width fields?
89
+ #
90
+ def span_offset
91
+ tot = 0
92
+ span_start.upto(where_am_i? - 1) {|i| tot += parent[i].width}
93
+ tot
94
+ end
95
+
96
+ # Given: a string, return: the remainder of the string after
97
+ # parsing the number, side-effect: populate @value
98
+ #
99
+ def capture(str)
100
+ return ascii_capture(str) if @ascii
101
+ return odd_width_capture(str) if not (code = widthcode)
102
+
103
+ incomplete! if str.size < size
104
+ cap = str.shift(size)
105
+ cap = cap.reverse if not Parsel.native?(@endian)
106
+ @value = cap.unpack(code).first
107
+ return str
108
+ end
109
+
110
+ BASERX = {
111
+ 2 => /([01]+)/,
112
+ 8 => /([0-7]+)/,
113
+ 10 => /([0-9]+)/,
114
+ 16 => /([0-9a-fA-F]+)/
115
+ }
116
+
117
+ def ascii_capture(str)
118
+ incomplete! if str.empty?
119
+
120
+ # weak
121
+ if (rad = resolve(@radix)) == 0
122
+ if str.starts_with? "0x"
123
+ rad = 16
124
+ str.shift 2
125
+ else
126
+ rad = 10
127
+ end
128
+ end
129
+
130
+ if(str =~ BASERX[rad])
131
+ @value = $1.to_i(rad)
132
+ str.shift($1.size)
133
+ else
134
+ @value = 0
135
+ end
136
+
137
+ return str
138
+ end
139
+
140
+ # Quick hack: true is 1, false is 0, nil is 0.
141
+ #
142
+ def resolve(x)
143
+ r = super
144
+ r = 1 if r == true
145
+ r = 0 if r == false
146
+ r = 0 if r == nil
147
+ return r
148
+ end
149
+
150
+ # Render this number (or, if odd-width, this span of odd-width
151
+ # values, if we're the first element of the span) as a bit string.
152
+ #
153
+ def to_s(off=nil)
154
+ @rendered_offset = off || 0
155
+
156
+ begin
157
+ if @ascii
158
+ r = ascii_to_s
159
+ elsif not (code = widthcode)
160
+ r = odd_width_to_s
161
+ else
162
+ val = resolve(@value).to_i
163
+ r = [val].pack(code)
164
+ r = r.reverse if @endian != Parsel.endian?
165
+ end
166
+
167
+ if off
168
+ return r, off+r.size
169
+ else
170
+ return r
171
+ end
172
+ rescue
173
+ raise
174
+ end
175
+ end
176
+
177
+ def ascii_to_s
178
+ if((rad = resolve(@radix)) == 0)
179
+ rad = 10
180
+ end
181
+
182
+ pad = resolve(@pad) || 0
183
+ @value.to_s(rad).rjust(pad, "0")
184
+ end
185
+
186
+ # Render a span of odd-width numbers as a byte string
187
+ #
188
+ def odd_width_to_s
189
+ return "" if not odd_width_first?
190
+
191
+ acc = 0
192
+ tot = 0
193
+ bits = span_bits
194
+
195
+ # Cheat horribly: Ruby has bignums, so just treat the whole
196
+ # span as one giant bignum and math it into place.
197
+
198
+ where_am_i?.upto(parent.count - 1) do |i|
199
+ break if not parent[i].respond_to? :odd_width?
200
+ break if not parent[i].odd_width?
201
+ acc <<= parent[i].width
202
+ tot += parent[i].width
203
+ acc |= parent[i].resolve(parent[i].value) & Numeric.mask_for(parent[i].width)
204
+ end
205
+ acc <<= 8 - (tot % 8) if (tot % 8) != 0
206
+
207
+ # Dump the bignum to a binary string
208
+
209
+ ret = ""
210
+ while bits > 0
211
+ ret << (acc & 0xff).chr
212
+ acc >>= 8
213
+ bits -= 8
214
+ end
215
+
216
+ ret.reverse! if @endian == :big
217
+ return ret
218
+ end
219
+
220
+ # Are we the first odd-width number in the span?
221
+ #
222
+ def odd_width_first?
223
+ return true if odd_width? and where_am_i? == 0
224
+ begin
225
+ not parent[where_am_i? - 1].odd_width?
226
+ rescue
227
+ true
228
+ end
229
+ end
230
+
231
+ # Capture a whole span of odd-width numbers, see capture
232
+ #
233
+ def odd_width_capture(str)
234
+ return str if not odd_width_first?
235
+
236
+ incomplete! if str.size < (bytes_for_bits = Parsel.bytes_for_bits(span_bits))
237
+
238
+ cap = str.shift(bytes_for_bits)
239
+
240
+ acc = 0
241
+ cap.each_byte do |b|
242
+ acc <<= 8
243
+ acc |= b
244
+ end
245
+ tbits = cap.size * 8
246
+ tot = 0
247
+ where_am_i?.upto(parent.count - 1) do |i|
248
+ break if not parent[i].respond_to? :odd_width?
249
+ break if not parent[i].odd_width?
250
+ tot += parent[i].width
251
+ parent[i].value = (acc >> (tbits - tot)) & Numeric.mask_for(parent[i].width)
252
+ end
253
+
254
+ return str
255
+ end
256
+
257
+ # How big is the encoded number?
258
+ #
259
+ def size
260
+ if not odd_width?
261
+ s = Parsel.bytes_for_bits(@width);
262
+ elsif odd_width_first?
263
+ s = span_bits * 8
264
+ else
265
+ s = 0
266
+ end
267
+ s
268
+ end
269
+ end
270
+
271
+ Num = Number.clone
272
+
273
+ ## ---------------------------------------------------------
274
+ ## XXX DRY, refactoring in process
275
+ ##
276
+ ## Moved this from classmethods to classes so we can encode
277
+ ## more into the type, useful for selectors
278
+
279
+ class Le16 < Number
280
+ def initialize(opts={}); super(opts.merge(:width => 16, :endian => :little))
281
+ end
282
+ end
283
+
284
+ # For no good reason, "halfwords" are little endian, but "shorts" are
285
+ # network byte order. You're welcome.
286
+
287
+ H16, Uint16le, Half, Halfword = [ Le16.clone, Le16.clone, Le16.clone, Le16.clone ]
288
+
289
+ class Le32 < Number
290
+ def initialize(opts={}); super(opts.merge(:width => 32, :endian => :little))
291
+ end
292
+ end
293
+
294
+ H32 = Le32.clone
295
+ Uint32le = Le32.clone
296
+
297
+ class Le64 < Number
298
+ def initialize(opts={}); super(opts.merge(:width => 64, :endian => :little))
299
+ end
300
+ end
301
+
302
+ H64 = Le64.clone
303
+ Uint64le = Le64.clone
304
+
305
+ class Be16 < Number
306
+ def initialize(opts={}); super(opts.merge(:width => 16, :endian => :big))
307
+ end
308
+ end
309
+
310
+ N16, Uint16be, Short = [Be16.clone, Be16.clone, Be16.clone]
311
+
312
+ class Be32 < Number
313
+ def initialize(opts={}); super(opts.merge(:width => 32, :endian => :big))
314
+ end
315
+ end
316
+
317
+ N32 = Be32.clone
318
+ Uint32be = Be32.clone
319
+
320
+ class Be64 < Number
321
+ def initialize(opts={}); super(opts.merge(:width => 64, :endian => :big))
322
+ end
323
+ end
324
+
325
+ N64 = Be64.clone
326
+ Uint64be = Be64.clone
327
+
328
+ class Byte < Number
329
+ def initialize(opts={}); super(opts.merge(:width => 8))
330
+ end
331
+ end
332
+
333
+ Le8, Be8, N8, H8 = [Byte.clone, Byte.clone, Byte.clone, Byte.clone]
334
+
335
+ class Bit < Number
336
+ def initialize(opts={}); super(opts.merge(:width => 1))
337
+ end
338
+ end
339
+
340
+ class Nibble < Number
341
+ def initialize(opts={}); super(opts.merge(:width => 4))
342
+ end
343
+ end
344
+ Nybble = Nibble.clone
345
+
346
+ # A length field (specify the width, if it's not 32 bits
347
+ # little-endian) --- its value will be :size of the following
348
+ # field (or provide :offset)
349
+
350
+ class Len < Number
351
+ def initialize(opts={})
352
+ super(opts.merge(:width => 32, :value => :size))
353
+ end
354
+ end
355
+
356
+ class Decimal < Ruckus::Number
357
+ OPTIONS = { :ascii => true, :radix => 10 }
358
+ end
359
+
360
+ end