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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dfd9d08f263a51dd186442e4b8f8395be3a964a2
4
- data.tar.gz: f68b293509bf734b7aa1760ba976b437ce3fba4c
3
+ metadata.gz: f98c7d5b928554e3d6da92e42f96bf3ee0a397a8
4
+ data.tar.gz: 994ede3f4bc303f98df8bd29e6bcb0b34932bf75
5
5
  SHA512:
6
- metadata.gz: 024c502d411c3ae81f7272bb5476964421738e3357d6a5e8b6308600408a499805f0015497d31ca792278857dc23609f2352c26a23011ef17c6edc40fe44e726
7
- data.tar.gz: 968a82ca1231067f5bc68fefae05c80842ff4b058fb17ff9c269320662e7eb6acb5db4c54435be479294857cadc41fee0d7fcb7d795437b982a30ae2fba17bed
6
+ metadata.gz: d3a0d0198fda11d157d42ca626b6e59d0af792748b194d60dff4d0bd6a928e6b664eeb4d95d5ad70c94e3f38e690e8b616377eb95fffd9fe338158766235148c
7
+ data.tar.gz: '09ba37f246d17b612f0ae247dab1408a799a9782d652e29ac3e798d8b46543225b506c983546b2e5acc7effdc52aca65f17f1fec1e3d32434f68edd535439b18'
data/README.md CHANGED
@@ -166,5 +166,5 @@ Copyright © 2016 Sylvain Daubert
166
166
  ### Other sources
167
167
  All original code maintains its copyright from its original authors and licensing.
168
168
 
169
- This is mainly for StrucFu (copied from [PacketFu](https://github.com/packetfu/packetfu))
170
- and PcapNG module (also copied from PacketFu, but I am the author).
169
+ This is mainly for PcapNG (copied from [PacketFu](https://github.com/packetfu/packetfu),
170
+ but i am the original author).
@@ -7,9 +7,9 @@ module PacketGen
7
7
  module Header
8
8
 
9
9
  # An ARP header consists of:
10
- # * a hardware type ({#hrd} or {#htype}) field ({Int16}),
10
+ # * a hardware type ({#hrd} or {#htype}) field ({Types::Int16}),
11
11
  # * a protocol type ({#pro} or {#ptype}) field (+Int16+),
12
- # * a hardware address length ({#hln} or {#hlen}) field ({Int8}),
12
+ # * a hardware address length ({#hln} or {#hlen}) field ({Types::Int8}),
13
13
  # * a protocol address length ({#pln} or {#plen}) field (+Int8+),
14
14
  # * a {#opcode} (or {#op}) field (+Int16+),
15
15
  # * a source hardware address ({#sha} or {#src_mac}) field ({Eth::MacAddr}),
@@ -27,11 +27,47 @@ module PacketGen
27
27
  # pkt.arp # => PacketGen::Header::ARP
28
28
  #
29
29
  # @author Sylvain Daubert
30
- class ARP < Struct.new(:hrd, :pro, :hln, :pln, :op,
31
- :sha, :spa, :tha, :tpa, :body)
32
- include StructFu
33
- include HeaderMethods
34
- extend HeaderClassMethods
30
+ class ARP < Base
31
+
32
+ # @!attribute hrd
33
+ # 16-bit hardware protocol type
34
+ # # @return [Integer]
35
+ define_field :hrd, Types::Int16, default: 1
36
+ # @!attribute pro
37
+ # 16-bit internet protocol type
38
+ # # @return [Integer]
39
+ define_field :pro, Types::Int16, default: 0x800
40
+ # @!attribute hln
41
+ # 8-bit hardware address length
42
+ # # @return [Integer]
43
+ define_field :hln, Types::Int8, default: 6
44
+ # @!attribute pln
45
+ # 8-bit internet address length
46
+ # # @return [Integer]
47
+ define_field :pln, Types::Int8, default: 4
48
+ # @!attribute op
49
+ # 16-bit operation code
50
+ # # @return [Integer]
51
+ define_field :op, Types::Int16, default: 1
52
+ # @!attribute sha
53
+ # source hardware address
54
+ # @return [Eth::MacAddr]
55
+ define_field :sha, Eth::MacAddr
56
+ # @!attribute spa
57
+ # source protocol address
58
+ # @return [IP::Addr]
59
+ define_field :spa, IP::Addr
60
+ # @!attribute tha
61
+ # target hardware address
62
+ # @return [Eth::MacAddr]
63
+ define_field :tha, Eth::MacAddr
64
+ # @!attribute tpa
65
+ # target protocol address
66
+ # @return [IP::Addr]
67
+ define_field :tpa, IP::Addr
68
+ # @!attribute body
69
+ # @return [Types::String,Header::Base]
70
+ define_field :body, Types::String
35
71
 
36
72
  # @param [Hash] options
37
73
  # @option options [Integer] :hrd network protocol type (default: 1)
@@ -44,143 +80,36 @@ module PacketGen
44
80
  # @option options [String] :spa sender internet address
45
81
  # @option options [String] :tha target hardware address
46
82
  # @option options [String] :tpa targetr internet address
47
- def initialize(options={})
48
- super Int16.new(options[:hrd] || options[:htype] || 1),
49
- Int16.new(options[:pro] || options[:ptype] || 0x800),
50
- Int8.new(options[:hln] || options[:hlen] || 6),
51
- Int8.new(options[:pln] || options[:plen] || 4),
52
- Int16.new(options[:op] || options[:opcode] || 1),
53
- Eth::MacAddr.new.from_human(options[:sha] || options[:src_mac]),
54
- IP::Addr.new.from_human(options[:spa] || options[:src_ip]),
55
- Eth::MacAddr.new.from_human(options[:tha] || options[:dst_mac]),
56
- IP::Addr.new.from_human(options[:tpa] || options[:dst_ip]),
57
- StructFu::String.new.read(options[:body])
83
+ def initialize(options={})
84
+ options[:hrd] ||= options[:htype]
85
+ options[:pro] ||= options[:ptype]
86
+ options[:hln] ||= options[:hlen]
87
+ options[:pln] ||= options[:plen]
88
+ options[:op] ||= options[:opcode]
89
+ options[:sha] ||= options[:src_mac]
90
+ options[:spa] ||= options[:src_ip]
91
+ options[:tha] ||= options[:dst_mac]
92
+ options[:tpa] ||= options[:dst_ip]
93
+ super
58
94
  end
59
95
 
60
- # Read a ARP header from a string
61
- # @param [String] str binary string
62
- # @return [self]
63
- def read(str)
64
- force_binary str
65
- raise ParseError, 'string too short for ARP' if str.size < self.sz
66
- self[:hrd].read str[0, 2]
67
- self[:pro].read str[2, 2]
68
- self[:hln].read str[4, 1]
69
- self[:pln].read str[5, 1]
70
- self[:op].read str[6, 2]
71
- self[:sha].read str[8, 6]
72
- self[:spa].read str[14, 4]
73
- self[:tha].read str[18, 6]
74
- self[:tpa].read str[24, 4]
75
- self[:body].read str[28..-1]
76
- end
77
-
78
- # @!attribute [rw] hrd
79
- # @return [Integer]
80
- def hrd
81
- self[:hrd].to_i
82
- end
83
96
  alias :htype :hrd
84
-
85
- def hrd=(i)
86
- self[:hrd].read i
87
- end
88
97
  alias :htype= :hrd=
89
-
90
- # @!attribute [rw] pro
91
- # @return [Integer]
92
- def pro
93
- self[:pro].to_i
94
- end
95
98
  alias :ptype :pro
96
-
97
- def pro=(i)
98
- self[:pro].read i
99
- end
100
99
  alias :ptype= :pro=
101
-
102
- # @!attribute [rw] hln
103
- # @return [Integer]
104
- def hln
105
- self[:hln].to_i
106
- end
107
100
  alias :hlen :hln
108
-
109
- def hln=(i)
110
- self[:hln].read i
111
- end
112
101
  alias :hlen= :hln=
113
-
114
- # @!attribute [rw] pln
115
- # @return [Integer]
116
- def pln
117
- self[:pln].to_i
118
- end
119
102
  alias :plen :pln
120
-
121
- def pln=(i)
122
- self[:pln].read i
123
- end
124
103
  alias :plen= :pln=
125
-
126
- # @!attribute [rw] op
127
- # @return [Integer]
128
- def op
129
- self[:op].to_i
130
- end
131
104
  alias :opcode :op
132
-
133
- def op=(i)
134
- self[:op].read i
135
- end
136
105
  alias :opcode= :op=
137
-
138
- # @!attribute [rw] sha
139
- # @return [String]
140
- def sha
141
- self[:sha].to_human
142
- end
143
106
  alias :src_mac :sha
144
-
145
- def sha=(addr)
146
- self[:sha].from_human addr
147
- end
148
107
  alias :src_mac= :sha=
149
-
150
- # @!attribute [rw] spa
151
- # @return [String]
152
- def spa
153
- self[:spa].to_human
154
- end
155
108
  alias :src_ip :spa
156
-
157
- def spa=(addr)
158
- self[:spa].from_human addr
159
- end
160
109
  alias :src_ip= :spa=
161
-
162
- # @!attribute [rw] tha
163
- # @return [String]
164
- def tha
165
- self[:tha].to_human
166
- end
167
110
  alias :dst_mac :tha
168
-
169
- def tha=(addr)
170
- self[:tha].from_human addr
171
- end
172
111
  alias :dst_mac= :tha=
173
-
174
- # @!attribute [rw] tpa
175
- # @return [String]
176
- def tpa
177
- self[:tpa].to_human
178
- end
179
112
  alias :dst_ip :tpa
180
-
181
- def tpa=(addr)
182
- self[:tpa].from_human addr
183
- end
184
113
  alias :dst_ip= :tpa=
185
114
  end
186
115
 
@@ -0,0 +1,175 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ module PacketGen
7
+ module Header
8
+
9
+ # @abstract
10
+ # Base class for all header types
11
+ # @author Sylvain Daubert
12
+ class Base < Types::Fields
13
+
14
+ # @api private
15
+ # Simple class to handle a header association
16
+ class Binding < Struct.new(:key, :value)
17
+ # Check +fields+ responds to binding
18
+ # @param [Types::Fields] fields
19
+ # @return [Boolean]
20
+ def check?(fields)
21
+ case self[:value]
22
+ when Proc
23
+ self[:value].call fields.send(self[:key])
24
+ else
25
+ fields.send(self[:key]) == self[:value]
26
+ end
27
+ end
28
+
29
+ # Set +fields+ field to binding value
30
+ # @param [Types::Fields] fields
31
+ # @return [void]
32
+ def set(fields)
33
+ case self[:value]
34
+ when Proc
35
+ fields.send "#{self[:key]}=", self[:value].call(nil)
36
+ else
37
+ fields.send "#{self[:key]}=", self[:value]
38
+ end
39
+ end
40
+ end
41
+
42
+ # @api private
43
+ # Class to handle header associations
44
+ class Bindings
45
+ include Enumerable
46
+
47
+ # op type
48
+ # @return [:or,:and]
49
+ attr_accessor :op
50
+ # @return [Array<Binding>]
51
+ attr_accessor :bindings
52
+
53
+ # @param [:or, :and] op
54
+ def initialize(op)
55
+ @op = op
56
+ @bindings = []
57
+ end
58
+
59
+ # @param [Object] arg
60
+ # @return [Bindings] self
61
+ def <<(arg)
62
+ @bindings << arg
63
+ end
64
+
65
+ # each iterator
66
+ # @return [void]
67
+ def each
68
+ @bindings.each { |b| yield b }
69
+ end
70
+
71
+ # @return [Boolean]
72
+ def empty?
73
+ @bindings.empty?
74
+ end
75
+
76
+ # @return [Hash]
77
+ def to_h
78
+ hsh = {}
79
+ each { |b| hsh[b.key] = b.value }
80
+ hsh
81
+ end
82
+
83
+ # Check +fields+ responds to set of bindings
84
+ # @param [Types::Fields] fields
85
+ # @return [Boolean]
86
+ def check?(fields)
87
+ case @op
88
+ when :or
89
+ @bindings.any? { |binding| binding.check?(fields) }
90
+ when :and
91
+ @bindings.all? { |binding| binding.check?(fields) }
92
+ end
93
+ end
94
+
95
+ # Set +fields+ to bindings value
96
+ # @param [Types::Fields] fields
97
+ # @return [void]
98
+ def set(fields)
99
+ @bindings.each { |b| b.set fields }
100
+ end
101
+ end
102
+
103
+ # @api private
104
+ # Reference on packet which owns this header
105
+ attr_accessor :packet
106
+
107
+ # On inheritage, create +@known_headers+ class variable
108
+ # @param [Class] klass
109
+ # @return [void]
110
+ def self.inherited(klass)
111
+ super
112
+ klass.class_eval { @known_headers = {} }
113
+ end
114
+
115
+ # Bind a upper header to current class
116
+ # Header1.bind_header Header2, field1: 43
117
+ # Header1.bind_header Header2, field1: 43, field2: 43
118
+ # Header1.bind_header Header2, op: :and, field1: 43, field2: 43
119
+ # Header1.bind_header Header2, field1: ->(v) { v.nil? ? 128 : v > 127 }
120
+ # @param [Class] header_klass header class to bind to current class
121
+ # @param [Hash] args current class fields and their value when +header_klass+
122
+ # is embedded in current class. Given value may be a lambda, whose alone argument
123
+ # is the value extracted from header field (or +nil+ when lambda is used to set
124
+ # field while adding a header).
125
+ #
126
+ # If multiple fields are given, a special key +:op+ may be given to set parse
127
+ # operation on this binding. By default, +:op+ is +:or+ (at least one binding
128
+ # must match to parse it). It also may be set to +:and+ (all bindings must match
129
+ # to parse it).
130
+ # @return [void]
131
+ def self.bind_header(header_klass, args={})
132
+ op = args.delete(:op) || :or
133
+ bindings = Bindings.new(op)
134
+ @known_headers[header_klass] = bindings
135
+ args.each do |key, value|
136
+ bindings << Binding.new(key, value)
137
+ end
138
+ end
139
+
140
+ # @api private
141
+ # Get knwon headers
142
+ # @return [Hash] keys: header classes, values: hashes
143
+ def self.known_headers
144
+ @known_headers
145
+ end
146
+
147
+ # @api private
148
+ # Get +header+ id in packet headers array
149
+ # @param [Header] header
150
+ # @return [Integer]
151
+ # @raise FormatError +header+ not in a packet
152
+ def header_id(header)
153
+ raise FormatError, "header of type #{header.class} not in a packet" if packet.nil?
154
+ id = packet.headers.index(header)
155
+ if id.nil?
156
+ raise FormatError, "header of type #{header.class} not in packet #{packet}"
157
+ end
158
+ id
159
+ end
160
+
161
+ # @api private
162
+ # Get IP or IPv6 previous header from +header+
163
+ # @param [Header] header
164
+ # @return [Header]
165
+ # @raise FormatError no IP or IPv6 header previous +header+ in packet
166
+ # @raise FormatError +header+ not in a packet
167
+ def ip_header(header)
168
+ hid = header_id(header)
169
+ iph = packet.headers[0...hid].reverse.find { |h| h.is_a? IP or h.is_a? IPv6 }
170
+ raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
171
+ iph
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,110 @@
1
+ module PacketGen
2
+ module Header
3
+ class DNS
4
+
5
+ # DNS Name, defined as a suite of labels. A label is of type {Types::IntString}.
6
+ # @author Sylvain Daubert
7
+ class Name < Types::Array
8
+
9
+ # Mask to decode a pointer on another label
10
+ POINTER_MASK = 0xc000
11
+
12
+ # @return [DNS]
13
+ attr_accessor :dns
14
+
15
+ def initialize
16
+ super
17
+ @pointer = nil
18
+ @pointer_name = nil
19
+ end
20
+
21
+ # @!method push(label)
22
+ # @param [Types::IntString] label
23
+ # @return [Name] self
24
+ # @!method <<(label)
25
+ # @param [Types::IntString] label
26
+ # @return [Name] self
27
+
28
+ # Read a set of labels form a dotted string
29
+ # @param [String] str
30
+ # @return [Name] self
31
+ def from_human(str)
32
+ clear
33
+ return self if str.nil?
34
+
35
+ str.split('.').each do |label|
36
+ self << Types::IntString.new(label)
37
+ end
38
+ self << Types::IntString.new('')
39
+ end
40
+
41
+ # Read a sequence of label from a string
42
+ # @param [String] str binary string
43
+ # @return [Name] self
44
+ def read(str)
45
+ @pointer = nil
46
+ @pointer_name = nil
47
+ clear
48
+ return self if str.nil?
49
+
50
+ force_binary str
51
+ start = 0
52
+ while true
53
+ index = str[start, 2].unpack('n').first
54
+ if pointer? index
55
+ # Pointer on another label
56
+ @pointer = str[start, 2]
57
+ break
58
+ else
59
+ label = Types::IntString.new
60
+ label.read(str[start..-1])
61
+ start += label.sz
62
+ self << label
63
+ break if label.length == 0 or str[start..-1].length == 0
64
+ end
65
+ end
66
+ self
67
+ end
68
+
69
+ # Get options binary string
70
+ # @return [String]
71
+ def to_s
72
+ super << @pointer.to_s
73
+ end
74
+
75
+ # Get a human readable string
76
+ # @return [String]
77
+ def to_human
78
+ ary = map(&:string)
79
+ np = name_from_pointer
80
+ ary << np if np
81
+ str = ary.join('.')
82
+ str.empty? ? '.' : str
83
+ end
84
+
85
+ private
86
+
87
+ def pointer?(index)
88
+ return false if index.nil?
89
+ index & POINTER_MASK == POINTER_MASK
90
+ end
91
+
92
+ def name_from_pointer
93
+ return nil unless @pointer
94
+ return @pointer_name if @pointer_name
95
+
96
+ index = @pointer.unpack('n').first
97
+ mask = ~POINTER_MASK & 0xffff
98
+ ptr = index & mask
99
+ name = Name.new
100
+ name.dns = @dns
101
+ @pointer_name = name.read(self.dns.to_s[ptr..-1]).to_human
102
+ end
103
+
104
+ def record_from_hash(hsh)
105
+ raise NotImplementedError, "not supported by #{self.class}"
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,137 @@
1
+ require_relative 'option'
2
+
3
+ module PacketGen
4
+ module Header
5
+ class DNS
6
+
7
+ # OPT pseudo-RR. Used by Extended DNS (EDNS(0), cf. RFC 6891).
8
+ #
9
+ # a OPT record may contain zero or more {Option options} in its {#rdata}.
10
+ # @author Sylvain Daubert
11
+ class OPT < RR
12
+ # @return [Array<Option>]
13
+ attr_reader :options
14
+
15
+ # @param [DNS] dns
16
+ # @param [Hash] options
17
+ # @option options [String] :name domain as a dotted string. Default to +"."+
18
+ # @option options [Integer,String] :type see {TYPES}. Default to +'OPT'+
19
+ # @option options [Integer] :udp_size UDP maximum size. Also +:rrclass+.
20
+ # Default to 512.
21
+ # @option options [Integer] :ext_rcode
22
+ # @option options [Integer] :version
23
+ # @option options [Boolean] :do DO bit
24
+ # @option options [Integer] :ttl set +ext_rcode+, +version+, +do+ and
25
+ # +z+ at once
26
+ # @option options [Integer] :rdlength if not provided, automatically set
27
+ # from +:rdata+ length
28
+ # @option options [String] :rdata
29
+ def initialize(dns, options={})
30
+ opts = { name: '.', rrclass: 512, type: 41 }.merge!(options)
31
+ super dns, opts
32
+ @options = []
33
+
34
+ self.udp_size = options[:udp_size] if options[:udp_size]
35
+ self.ext_rcode = options[:ext_rcode] if options[:ext_rcode]
36
+ self.version = options[:version] if options[:version]
37
+ self.do = options[:do] unless options[:do].nil?
38
+ end
39
+
40
+ # @overload ext_rcode=(v)
41
+ # Setter for upper 8 bits of extended 12-bit RCODE
42
+ # @param [Integer] v
43
+ # @return [Integer]
44
+ # @overload ext_rcode
45
+ # Getter for upper 8 bits of extended 12-bit RCODE
46
+ # @return [Integer]
47
+ # @return [Integer]
48
+ def ext_rcode=(v=nil)
49
+ if v
50
+ self[:ttl].value = self[:ttl].to_i & (0xffffffff & ~(0xff << 24))
51
+ self[:ttl].value |= (v & 0xff) << 24
52
+ end
53
+ (self[:ttl].to_i >> 24) & 0xff
54
+ end
55
+ alias ext_rcode ext_rcode=
56
+
57
+ # @overload version=(v)
58
+ # Setter EDNS version
59
+ # @param [Integer] v
60
+ # @return [Integer]
61
+ # @overload version
62
+ # Getter for EDNS version
63
+ # @return [Integer]
64
+ # @return [Integer]
65
+ def version=(v=nil)
66
+ if v
67
+ self[:ttl].value = self[:ttl].to_i & (0xffffffff & ~(0xff << 16))
68
+ self[:ttl].value |= (v & 0xff) << 16
69
+ end
70
+ (self[:ttl].to_i >> 16) & 0xff
71
+ end
72
+ alias version version=
73
+
74
+ # @overload do=(v)
75
+ # Setter EDNS do
76
+ # @param [Boolean] v
77
+ # @return [Boolean]
78
+ # @overload do?
79
+ # Getter for EDNS do
80
+ # @return [Boolean]
81
+ # @return [Boolean]
82
+ def do=(v=nil)
83
+ b = v ? 1 : 0
84
+ unless v.nil?
85
+ self[:ttl].value = self[:ttl].to_i & (0xffffffff & ~(1 << 15))
86
+ self[:ttl].value |= (b & 1) << 15
87
+ end
88
+ ((self[:ttl].to_i >> 15) & 1) == 1 ? true : false
89
+ end
90
+ alias :do? :do=
91
+
92
+ # @overload z=(v)
93
+ # @param [Integer] v
94
+ # @return [Integer]
95
+ # @overload z
96
+ # @return [Integer]
97
+ # @return [Integer]
98
+ def z=(v=nil)
99
+ if v
100
+ self[:ttl].value = self[:ttl].to_i & (0xffffffff & ~0x7fff)
101
+ self[:ttl].value |= v & 0x7fff
102
+ end
103
+ self[:ttl].to_i & 0x7fff
104
+ end
105
+ alias z z=
106
+
107
+ # @!attribute udp_size
108
+ # @return [Integer] UDP payload size
109
+ alias udp_size rrclass
110
+ alias udp_size= rrclass=
111
+
112
+ # @return [String]
113
+ def human_flags
114
+ do? ? 'do' : 'none'
115
+ end
116
+
117
+ # @return [String]
118
+ def human_options
119
+ str = @options.map(&:to_human).join(';')
120
+ str.empty? ? 'none' : str
121
+ end
122
+
123
+ # @return [String]
124
+ def to_human
125
+ "#{name} #{human_type} UDPsize:#{udp_size} " \
126
+ "extRCODE:#{ext_rcode} EDNSversion:#{version} flags:#{human_flags} " \
127
+ "options:#{human_options}"
128
+ end
129
+
130
+ # @return [String]
131
+ def to_s
132
+ super + @options.map(&:to_s).join
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,17 @@
1
+ module PacketGen
2
+ module Header
3
+ class DNS
4
+
5
+ # DNS option
6
+ # @author Sylvain Daubert
7
+ class Option < Types::TLV
8
+
9
+ # Force {#type} and {#length} fields to be {Types::Int16}
10
+ # @see TLV#initialize
11
+ def initialize(options={})
12
+ super options.merge!(t: Types::Int16, l: Types::Int16)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end