packetgen 2.1.4 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36c2e8a9384d7c08723de6f529893d0dd42e5d8d
4
- data.tar.gz: 0e91b3917d405a1a09b75a7863685645b52827d9
3
+ metadata.gz: 543fd7ef2efee43e0bf0d61c8a6520d178c869a2
4
+ data.tar.gz: bcdd42ce36fc83c202abe8c2fd6f820a13a1b588
5
5
  SHA512:
6
- metadata.gz: 55414180e5ca3bcc69cee0a00a84cbe79635a2809d3f999d35a9d6fab725b5dfc153ea5cc087c10d08985caf10c60aa7ee23df2fb4537d7ca3d6924789f2e614
7
- data.tar.gz: 51ea04c7c3a1544911ca26f4c6b8c066bc58aa0255a2dd6241f21b668fee9e16c7def036d62722c7e826f77947128225c1a56d5ee4ef27aa71d0eaff55352b5e
6
+ metadata.gz: 04c3d376f587f745972f534655f83e5fa12c30e039a58854411f89c57d769c235f9fa8faf1f6bfb37bf2deba639f45ea96a1eea8706dda77ea3c01a753aac502
7
+ data.tar.gz: ed8d4002df84be1f0e1ddbcf19dd29bbf8290ed05606648421af3e7914b6288f9aacd8ec252bec6edd1357e5c42923f84400088c0fd2bc744c06e88c179d16b0
@@ -12,6 +12,7 @@ module PacketGen
12
12
  # Config class to provide +config+ object to pgconsole
13
13
  # @author Sylvain Daubert
14
14
  # @author Kent 'picat' Gruber
15
+ # @since 1.4.1
15
16
  # @since 2.1.3 Config is singleton
16
17
  class Config
17
18
  include Singleton
@@ -99,3 +99,6 @@ require_relative 'header/ike'
99
99
  require_relative 'header/dns'
100
100
  require_relative 'header/asn1_base'
101
101
  require_relative 'header/snmp'
102
+ require_relative 'header/bootp'
103
+ require_relative 'header/dhcp'
104
+ require_relative 'header/http'
@@ -0,0 +1,151 @@
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
+ # Bootstrap Protocol, {https://tools.ietf.org/html/rfc951
10
+ # RFC 951}
11
+ #
12
+ # A BOOTP header consists of:
13
+ # * an operation code field ({#op} of type {Types::Int8Enum}),
14
+ # * a hardware address type ({#htype} of type {Types::Int8}),
15
+ # * a hardware address length ({#hlen} of type {Types::Int8}),
16
+ # * a {#hops} field ({Types::Int8}),
17
+ # * a transaction ID ({#xid} of type {Types::Int32}),
18
+ # * a {#secs} field (){Types::Int16}),
19
+ # * a {#flags} field (){Types::Int16}):
20
+ # * a 1-bit broadcast flag ({#b}),
21
+ # * a 15-bit Must Be Zero field ({#mbz}),
22
+ # * a {#ciaddr} field ({IP::Addr}),
23
+ # * a {#yiaddr} field ({IP::Addr}),
24
+ # * a {#siaddr} field ({IP::Addr}),
25
+ # * a {#giaddr} field ({IP::Addr}),
26
+ # * a {#chaddr} field (16-byte {Types::String}),
27
+ # * a {#sname} field (64-byte {Types::CString}),
28
+ # * a {#file} field (128-byte {Types::CString}),
29
+ # * and a body ({Types::String}).
30
+ #
31
+ # == Create a BOOTP header
32
+ # # standalone
33
+ # bootp = PacketGen::Header::BOOTP.new
34
+ # # in a packet
35
+ # pkt = PacketGen.gen('IP').add('BOOTP')
36
+ # # access to BOOTP header
37
+ # pkt.bootp # => PacketGen::Header::BOOTP
38
+ # @author Sylvain Daubert
39
+ # @since 2.2.0
40
+ class BOOTP < Base
41
+
42
+ UDP_SERVER_PORT = 67
43
+ UDP_CLIENT_PORT = 68
44
+
45
+ # DHCP opcodes
46
+ OPCODES = {
47
+ 'BOOTREQUEST' => 1,
48
+ 'BOOTREPLY' => 2
49
+ }
50
+
51
+ # @!attribute op
52
+ # 8-bit opcode
53
+ # @return [Integer]
54
+ define_field :op, Types::Int8Enum, enum: OPCODES
55
+
56
+ # @!attribute htype
57
+ # 8-bit hardware address type
58
+ # @return [Integer]
59
+ define_field :htype, Types::Int8, default: 1
60
+
61
+ # @!attribute hlen
62
+ # 8-bit hardware address length
63
+ # @return [Integer]
64
+ define_field :hlen, Types::Int8, default: 6
65
+
66
+ # @!attribute hops
67
+ # @return [Integer]
68
+ define_field :hops, Types::Int8
69
+
70
+ # @!attribute xid
71
+ # 32-bit Transaction ID
72
+ # @return [Integer]
73
+ define_field :xid, Types::Int32
74
+
75
+ # @!attribute secs
76
+ # 16-bit integer: number of seconds elapsed since client began address
77
+ # acquisition or renewal process
78
+ # @return [Integer]
79
+ define_field :secs, Types::Int16
80
+
81
+ # @!attribute flags
82
+ # 16-bit flag field
83
+ # @return [Integer]
84
+ define_field :flags, Types::Int16
85
+
86
+ # @!attribute ciaddr
87
+ # client IP address
88
+ # @return [String]
89
+ define_field :ciaddr, IP::Addr
90
+
91
+ # @!attribute yiaddr
92
+ # 'your' (client) IP address
93
+ # @return [String]
94
+ define_field :yiaddr, IP::Addr
95
+
96
+ # @!attribute siaddr
97
+ # IP address of next server to use in bootstrap
98
+ # @return [String]
99
+ define_field :siaddr, IP::Addr
100
+
101
+ # @!attribute giaddr
102
+ # Relay agent IP address, used in booting via a relay agent
103
+ # @return [String]
104
+ define_field :giaddr, IP::Addr
105
+
106
+ # @!attribute chaddr
107
+ # client hardware address
108
+ # @return [String]
109
+ define_field :chaddr, Types::String, static_length: 16
110
+
111
+ # @!attribute sname
112
+ # optional server hostname, null-terminated string
113
+ # @return [String]
114
+ define_field :sname, Types::CString, static_length: 64
115
+
116
+ # @!attribute file
117
+ # Boot file name, null terminated string
118
+ # @return [String]
119
+ define_field :file, Types::CString, static_length: 128
120
+
121
+ # @!attribute body
122
+ # @return [String]
123
+ define_field :body, Types::String
124
+
125
+ # @!attribute b
126
+ # Broadcast flag, from {#flags}
127
+ # @return [Boolean]
128
+ # @!attribute mbz
129
+ # 15-bit Must Be Zero bits, from {#flags}
130
+ # @return [Boolean]
131
+ define_bit_fields_on :flags, :b, :mbz, 15
132
+
133
+ def inspect
134
+ str = Inspect.dashed_line(self.class, 2)
135
+ fields.each do |attr|
136
+ next if attr == :body
137
+ next unless is_present?(attr)
138
+ if attr == :chaddr and self.hlen == 6
139
+ str << Inspect.inspect_attribute(attr, Eth::MacAddr.new.read(self[:chaddr][0, 6]), 2)
140
+ else
141
+ str << Inspect.inspect_attribute(attr, self[attr], 2)
142
+ end
143
+ end
144
+ str
145
+ end
146
+ end
147
+
148
+ UDP.bind_header BOOTP, sport: 67, dport: 68
149
+ UDP.bind_header BOOTP, sport: 68, dport: 67
150
+ end
151
+ end
@@ -0,0 +1,65 @@
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
+ # Dynamic Host Configuration Protocol, {https://tools.ietf.org/html/rfc2131
10
+ # RFC 2131}
11
+ #
12
+ # A DHCP header is quite simple. It is composed of:
13
+ # * a {#magic} field ({Types::Int32}) to retrieve it in a BOOTP header,
14
+ # * a, {#options} field ({Options} type, which is a collection of DHCP
15
+ # options).
16
+ #
17
+ # In PacketGen, a DHCP header is always a secondary header after {BOOTP} one.
18
+ #
19
+ # == Create a DHCP header
20
+ # # standalone
21
+ # dhcp = PacketGen::Header::DHCP.new
22
+ # # in a packet
23
+ # pkt = PacketGen.gen('IP').add('BOOTP').add('DHCP')
24
+ # # access to DHCP header
25
+ # pkt.dhcp # => PacketGen::Header::DHCP
26
+ #
27
+ # == Add options
28
+ # Options may be added these ways:
29
+ # dhcp = PacketGen::Header::DHCP.new
30
+ # # Add a lease_time option
31
+ # dhcp.options << { type: 'lease_time', value: 3600 }
32
+ # # Add a domain option. Here, use integer type
33
+ # dhcp.options << { type: 15, value: 'example.net'}
34
+ # # Add an end option
35
+ # dhcp.options << { type: 'end' }
36
+ # # And finish with padding
37
+ # dhcp.options << { type: 'pad' }
38
+ # @author Sylvain Daubert
39
+ # @since 2.2.0
40
+ class DHCP < Base; end
41
+
42
+ require_relative 'dhcp/option'
43
+ require_relative 'dhcp/options'
44
+
45
+ class DHCP < Base
46
+ # DHCP magic value in BOOTP options
47
+ DHCP_MAGIC = 0x63825363
48
+
49
+ # @!attribute magic
50
+ # @return [Integer]
51
+ define_field :magic, Types::Int32, default: 0x63825563
52
+ # @!attribute options
53
+ # @return [DHCP::Options]
54
+ define_field :options, DHCP::Options
55
+
56
+ # differentiate from BOOTP by checking presence of DHCP magic
57
+ # @return [Boolean]
58
+ def parse?
59
+ self.magic == DHCP_MAGIC
60
+ end
61
+ end
62
+
63
+ BOOTP.bind_header DHCP
64
+ end
65
+ end
@@ -0,0 +1,154 @@
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
+ class DHCP
9
+
10
+ # define DHCP Options.
11
+ # keys are option type, value are arrays containing option names
12
+ # as strings, and a hash passed to {Option#initialize}.
13
+ DHCPOptions = {
14
+ 1 => ['subnet_mask', length: 4, v: IP::Addr],
15
+ 2 => ['time_zone'],
16
+ 3 => ['router', length: 4, v: IP::Addr],
17
+ 4 => ['time_server', length: 4, v: IP::Addr],
18
+ 5 => ['IEN_name_server', length: 4, v: IP::Addr],
19
+ 6 => ['name_server', length: 4, v: IP::Addr],
20
+ 7 => ['log_server', length: 4, v: IP::Addr],
21
+ 8 => ['cookie_server', length: 4, v: IP::Addr],
22
+ 9 => ['lpr_server', length: 4, v: IP::Addr],
23
+ 12 => ['hostname'],
24
+ 14 => ['dump_path'],
25
+ 15 => ['domain'],
26
+ 17 => ['root_disk_path'],
27
+ 23 => ['default_ttl'],
28
+ 24 => ['pmtu_timeout'],
29
+ 28 => ['broadcast_address', length: 4, v: IP::Addr],
30
+ 40 => ['NIS_domain'],
31
+ 41 => ['NIS_server', length: 4, v: IP::Addr],
32
+ 42 => ['NTP_server', length: 4, v: IP::Addr],
33
+ 43 => ['vendor_specific'],
34
+ 44 => ['NetBIOS_server', length: 4, v: IP::Addr],
35
+ 45 => ['NetBIOS_dist_server', length: 4, v: IP::Addr],
36
+ 50 => ['requested_addr', length: 4, v: IP::Addr],
37
+ 51 => ['lease_time', length: 4, v: Types::Int32, value: 43200],
38
+ 53 => ['message-type', length: 1, v: Types::Int8],
39
+ 54 => ['server_id', length: 4, v: IP::Addr],
40
+ 55 => ['param_req_list'],
41
+ 56 => ['error_message'],
42
+ 57 => ['max_dhcp_size', length: 2, v: Types::Int16, value: 1500],
43
+ 58 => ['renewal_time', length: 4, v: Types::Int32, value: 21600],
44
+ 59 => ['rebinding_time', length: 4, v: Types::Int32, value: 37800],
45
+ 60 => ['vendor_class_id'],
46
+ 61 => ['client_id'],
47
+ 64 => ['NISplus_domain'],
48
+ 65 => ['NISplus_server', length: 4, v: IP::Addr],
49
+ 69 => ['SMTP_server', length: 4, v: IP::Addr],
50
+ 70 => ['POP3_server', length: 4, v: IP::Addr],
51
+ 71 => ['NNTP_server', length: 4, v: IP::Addr],
52
+ 72 => ['WWW_server', length: 4, v: IP::Addr],
53
+ 73 => ['finger_server', length: 4, v: IP::Addr],
54
+ 74 => ['IRC_server', length: 4, v: IP::Addr]
55
+ }
56
+
57
+ # Class to indicate DHCP options end
58
+ class End < Types::Int8
59
+ def initialize(value=255)
60
+ super
61
+ end
62
+ def to_human; self.class.to_s.sub(/.*::/, '').downcase; end
63
+ alias human_type to_human
64
+ end
65
+
66
+ # Class to indicate padding after DHCP options
67
+ class Pad < End
68
+ def initialize(value=0)
69
+ super
70
+ end
71
+ end
72
+
73
+ # DHCP option
74
+ #
75
+ # A DHCP option is a {Types::TLV TLV}, so it has:
76
+ # * a {#type} ({Types::Int8}),
77
+ # * a {#length} ({Types::Int8}),
78
+ # * and a {#value}. Defalt type is {Types::String} but some options
79
+ # may use more suitable type (by example, a {IP::Addr} for +router+
80
+ # option).
81
+ # @author Sylvain Daubert
82
+ class Option < Types::TLV
83
+
84
+ # Option types
85
+ TYPES = Hash[DHCPOptions.to_a.map { |type, ary| [type, ary[0]] }]
86
+
87
+ # @param [Hash] options
88
+ # @option options [Integer] :type
89
+ # @option options [Integer] :length
90
+ # @option options [String] :value
91
+ def initialize(options={})
92
+ super
93
+ if DHCPOptions.has_key?(self.type)
94
+ h = DHCPOptions[self.type].last
95
+ if h.is_a? Hash
96
+ h.each do |k, v|
97
+ self.length = v if k == :length
98
+ if k == :v
99
+ self[:value] = v.new
100
+ self.value = options[:value] if options[:value]
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # @private
108
+ alias private_read read
109
+
110
+ # Populate object from a binary string
111
+ # @param [String] str
112
+ # @return [Option,End,Pad] may return another object than itself
113
+ def read(str)
114
+ read_type = str[0].unpack('C').first
115
+ if read_type == 0
116
+ Pad.new.read(str)
117
+ elsif read_type == 255
118
+ End.new.read(str)
119
+ elsif DHCPOptions.has_key?(read_type)
120
+ Option.new(DHCPOptions[read_type][1] || {}).private_read(str)
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ def has_human_types?
127
+ true
128
+ end
129
+
130
+ def human_type
131
+ if DHCPOptions.has_key?(type)
132
+ DHCPOptions[type].first.dup
133
+ else
134
+ type.to_s
135
+ end
136
+ end
137
+
138
+ def to_human
139
+ s = human_type
140
+ if length > 0
141
+ if value.respond_to? :to_human
142
+ s << ":#{value.to_human}"
143
+ elsif self[:value].is_a? Types::Int
144
+ s << ":#{self.value.to_i}"
145
+ else
146
+ s << ":#{value.inspect}"
147
+ end
148
+ end
149
+ s
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,42 @@
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
+ class DHCP
9
+
10
+ # Container class for DHCP Options
11
+ #
12
+ # == Add DHCP options to an +Options+ instance
13
+ # options = PacketGen::Header::DHCP::Options.new
14
+ # # Add a lease_time option
15
+ # options << { type: 'lease_time', value: 3600 }
16
+ # # Add a domain option. Here, use integer type
17
+ # options << { type: 15, value: 'example.net'}
18
+ # # Add an end option
19
+ # options << { type: 'end' }
20
+ # # And finish with padding
21
+ # options << { type: 'pad' }
22
+ # @author Sylvain Daubert
23
+ class Options < Types::Array
24
+ set_of Option
25
+
26
+ private
27
+
28
+ def record_from_hash(hsh)
29
+ case hsh[:type]
30
+ when 'pad', 0
31
+ Pad.new
32
+ when 'end', 255
33
+ End.new
34
+ else
35
+ obj_klass = self.class.class_eval { @klass }
36
+ obj_klass.new(hsh)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -144,16 +144,16 @@ module PacketGen
144
144
  define_field :arcount, Types::Int16
145
145
  # @!attribute qd
146
146
  # @return [QDSection]
147
- define_field :qd, QDSection, builder: ->(dns) { QDSection.new(dns, dns[:qdcount]) }
147
+ define_field :qd, QDSection, builder: ->(h,t) { t.new(h, h[:qdcount]) }
148
148
  # @!attribute an
149
149
  # @return [RRSection]
150
- define_field :an, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:ancount]) }
150
+ define_field :an, RRSection, builder: ->(h,t) { t.new(h, h[:ancount]) }
151
151
  # @!attribute ns
152
152
  # @return [RRSection]
153
- define_field :ns, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:nscount]) }
153
+ define_field :ns, RRSection, builder: ->(h,t) { t.new(h, h[:nscount]) }
154
154
  # @!attribute ar
155
155
  # @return [RRSection]
156
- define_field :ar, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:arcount]) }
156
+ define_field :ar, RRSection, builder: ->(h,t) { t.new(h, h[:arcount]) }
157
157
 
158
158
  # @!attribute qr
159
159
  # @return [Boolean] query (+false+) or response (+true+)