packetgen 2.1.4 → 2.2.0

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