ruckus 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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