net-dhcp 1.0.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.
- data/.document +11 -0
- data/.gitignore +40 -0
- data/Gemfile +4 -0
- data/LICENSE +12 -0
- data/README +14 -0
- data/README.etd.original +9 -0
- data/Rakefile +42 -0
- data/bin/net-dhcp +37 -0
- data/lib/net-dhcp.rb +2 -0
- data/lib/net-dhcp/version.rb +5 -0
- data/lib/net/dhcp.rb +48 -0
- data/lib/net/dhcp/constants.rb +182 -0
- data/lib/net/dhcp/core.rb +322 -0
- data/lib/net/dhcp/options.rb +621 -0
- data/lib/net/dhcp/oui.txt +68928 -0
- data/net-dhcp.gemspec +35 -0
- data/spec/net-dhcp_spec.rb +7 -0
- data/spec/spec_helper.rb +19 -0
- data/test/dhcp_test.rb +71 -0
- metadata +142 -0
data/.document
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# .document is used by rdoc and yard to know how to generate documentation
|
2
|
+
# for example, it can be used to control how rdoc gets built when you do `gem install foo`
|
3
|
+
|
4
|
+
README.rdoc
|
5
|
+
lib/**/*.rb
|
6
|
+
bin/*
|
7
|
+
|
8
|
+
# Files below this - are treated as 'extra files', and aren't parsed for ruby code
|
9
|
+
-
|
10
|
+
features/**/*.feature
|
11
|
+
LICENSE
|
data/.gitignore
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
*.gem
|
2
|
+
.bundle
|
3
|
+
Gemfile.lock
|
4
|
+
pkg/*
|
5
|
+
# rcov generated
|
6
|
+
coverage
|
7
|
+
|
8
|
+
# rdoc generated
|
9
|
+
rdoc
|
10
|
+
|
11
|
+
# yard generated
|
12
|
+
doc
|
13
|
+
.yardoc
|
14
|
+
|
15
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
16
|
+
#
|
17
|
+
# * Create a file at ~/.gitignore
|
18
|
+
# * Include files you want ignored
|
19
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
20
|
+
#
|
21
|
+
# After doing this, these files will be ignored in all your git projects,
|
22
|
+
# saving you from having to 'pollute' every project you touch with them
|
23
|
+
#
|
24
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
25
|
+
#
|
26
|
+
# For MacOS:
|
27
|
+
#
|
28
|
+
#.DS_Store
|
29
|
+
#
|
30
|
+
# For TextMate
|
31
|
+
#*.tmproj
|
32
|
+
#tmtags
|
33
|
+
#
|
34
|
+
# For emacs:
|
35
|
+
#*~
|
36
|
+
#\#*
|
37
|
+
#.\#*
|
38
|
+
#
|
39
|
+
# For vim:
|
40
|
+
#*.swp
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
This program is free software: you can redistribute it and/or modify
|
2
|
+
it under the terms of the GNU General Public License as published by
|
3
|
+
the Free Software Foundation, either version 3 of the License, or
|
4
|
+
(at your option) any later version.
|
5
|
+
|
6
|
+
This program is distributed in the hope that it will be useful,
|
7
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
8
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
9
|
+
GNU General Public License for more details.
|
10
|
+
|
11
|
+
You should have received a copy of the GNU General Public License
|
12
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/README
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Net::DHCP library for ruby, originally written by etd.
|
2
|
+
Fork to github by syonbori.
|
3
|
+
Additional fork and gemification by mjtko.
|
4
|
+
|
5
|
+
Here is original README:
|
6
|
+
The svn repository for Net::DHCP contains the project files to use with NetBeans IDE.
|
7
|
+
|
8
|
+
Use "rake" in the /lib folder to generate rdoc documentation.
|
9
|
+
|
10
|
+
Expect lots of changes in the near future both to the folder structure and the project architecture :)
|
11
|
+
|
12
|
+
Have fun,
|
13
|
+
|
14
|
+
etd
|
data/README.etd.original
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
The svn repository for Net::DHCP contains the project files to use with NetBeans IDE.
|
2
|
+
|
3
|
+
Use "rake" in the /lib folder to generate rdoc documentation.
|
4
|
+
|
5
|
+
Expect lots of changes in the near future both to the folder structure and the project architecture :)
|
6
|
+
|
7
|
+
Have fun,
|
8
|
+
|
9
|
+
etd
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler'
|
5
|
+
rescue LoadError
|
6
|
+
$stderr.puts "You must install bundler - run `gem install bundler`"
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
Bundler.setup
|
11
|
+
rescue Bundler::BundlerError => e
|
12
|
+
$stderr.puts e.message
|
13
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
14
|
+
exit e.status_code
|
15
|
+
end
|
16
|
+
require 'rake'
|
17
|
+
|
18
|
+
require 'bueller'
|
19
|
+
Bueller::Tasks.new
|
20
|
+
|
21
|
+
require 'rspec/core/rake_task'
|
22
|
+
RSpec::Core::RakeTask.new(:examples) do |examples|
|
23
|
+
examples.rspec_opts = '-Ispec'
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
27
|
+
spec.rspec_opts = '-Ispec'
|
28
|
+
spec.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
task :default => :examples
|
32
|
+
|
33
|
+
require 'rdoc/task'
|
34
|
+
Rake::RDocTask.new do |rdoc|
|
35
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
36
|
+
|
37
|
+
rdoc.main = 'README.rdoc'
|
38
|
+
rdoc.rdoc_dir = 'rdoc'
|
39
|
+
rdoc.title = "net-dhcp #{version}"
|
40
|
+
rdoc.rdoc_files.include('README*')
|
41
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
42
|
+
end
|
data/bin/net-dhcp
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# main.rb
|
2
|
+
# 4 de octubre de 2007
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'dhcp'
|
6
|
+
require 'socket'
|
7
|
+
require 'pcaplet'
|
8
|
+
|
9
|
+
server_thread = Thread.new do
|
10
|
+
s = "Packets received by the filter:\n"
|
11
|
+
s << '-'*s.size + "\n"
|
12
|
+
|
13
|
+
dhcpdump = Pcaplet.new('-s 4096')
|
14
|
+
|
15
|
+
DHCP_PACKET = Pcap::Filter.new('port 67 or port 68', dhcpdump.capture)
|
16
|
+
|
17
|
+
dhcpdump.add_filter(DHCP_PACKET)
|
18
|
+
dhcpdump.each_packet {|pkt|
|
19
|
+
msg = DHCP::Message.from_udp_payload(pkt.udp_data)
|
20
|
+
|
21
|
+
s << "#{pkt.src}:#{pkt.sport} > #{pkt.dst}:#{pkt.dport}\n"
|
22
|
+
s << msg.to_s
|
23
|
+
puts s if s
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
discover = DHCP::Discover.new
|
28
|
+
payload = discover.pack
|
29
|
+
|
30
|
+
|
31
|
+
sckt = UDPSocket.new
|
32
|
+
sckt.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST,true)
|
33
|
+
sckt.bind('', 68)
|
34
|
+
sckt.send(payload, 0, "<broadcast>", 67)
|
35
|
+
|
36
|
+
trap('INT') {server_thread.kill}
|
37
|
+
server_thread.join
|
data/lib/net-dhcp.rb
ADDED
data/lib/net/dhcp.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
=begin
|
2
|
+
**
|
3
|
+
** dhcp.rb
|
4
|
+
** 31/OCT/2007
|
5
|
+
** ETD-Software
|
6
|
+
** - Daniel Martin Gomez <etd[-at-]nomejortu.com>
|
7
|
+
**
|
8
|
+
** Desc:
|
9
|
+
** This package provides a set of classes to work with the DHCP protocol. They
|
10
|
+
** provide low level access to all the fields and internals of the protocol.
|
11
|
+
**
|
12
|
+
** See the provided rdoc comments for further information.
|
13
|
+
**
|
14
|
+
** More information in:
|
15
|
+
** - rfc2131: Dynamic Host Configuration Protocol
|
16
|
+
** - rfc2132: DHCP Options and BOOTP Vendor Extensions
|
17
|
+
** - rfc2563: DHCP Option to Disable Stateless Auto-Configuration in
|
18
|
+
** IPv4 Clients
|
19
|
+
** - rfc4578: DHCP Options for the Intel Preboot eXecution Environment (PXE)
|
20
|
+
** - rfc4702: The DHCP Client Fully Qualified Domain Name (FQDN) Option
|
21
|
+
**
|
22
|
+
** Version:
|
23
|
+
** v1.0 [31/October/2007]: first released
|
24
|
+
**
|
25
|
+
** License:
|
26
|
+
** This program is free software: you can redistribute it and/or modify
|
27
|
+
** it under the terms of the GNU General Public License as published by
|
28
|
+
** the Free Software Foundation, either version 3 of the License, or
|
29
|
+
** (at your option) any later version.
|
30
|
+
**
|
31
|
+
** This program is distributed in the hope that it will be useful,
|
32
|
+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
33
|
+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
34
|
+
** GNU General Public License for more details.
|
35
|
+
**
|
36
|
+
** You should have received a copy of the GNU General Public License
|
37
|
+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
38
|
+
**
|
39
|
+
=end
|
40
|
+
|
41
|
+
# constants defining the values in the different fields of the protocols
|
42
|
+
require 'net/dhcp/constants'
|
43
|
+
|
44
|
+
# DHCP options as defined in rfc2132 and rfc2563
|
45
|
+
require 'net/dhcp/options'
|
46
|
+
|
47
|
+
# DHCP messages as defined in rfc2131
|
48
|
+
require 'net/dhcp/core'
|
@@ -0,0 +1,182 @@
|
|
1
|
+
=begin
|
2
|
+
**
|
3
|
+
** constants.rb
|
4
|
+
** 04/OCT/2007
|
5
|
+
** ETD-Software
|
6
|
+
** - Daniel Martin Gomez <etd[-at-]nomejortu.com>
|
7
|
+
**
|
8
|
+
** Desc:
|
9
|
+
** This file provides a set of classes to work with the DHCP protocol. They
|
10
|
+
** provide low level access to all the fields and internals of the protocol.
|
11
|
+
**
|
12
|
+
** See the provided rdoc comments for further information.
|
13
|
+
**
|
14
|
+
** More information in:
|
15
|
+
** - rfc2131: Dynamic Host Configuration Protocol
|
16
|
+
** - rfc2132: DHCP Options and BOOTP Vendor Extensions
|
17
|
+
** - rfc2563: DHCP Option to Disable Stateless Auto-Configuration in
|
18
|
+
** IPv4 Clients
|
19
|
+
**
|
20
|
+
** Version:
|
21
|
+
** v1.0 [04/October/2007]: first released
|
22
|
+
**
|
23
|
+
** License:
|
24
|
+
** Please see dhcp.rb or LICENSE.txt for copyright and licensing information.
|
25
|
+
**
|
26
|
+
=end
|
27
|
+
|
28
|
+
# --------------------------------------------------------------- dhcp messages
|
29
|
+
|
30
|
+
# operations ('op' field)
|
31
|
+
$DHCP_OP_REQUEST= 0x01
|
32
|
+
$DHCP_OP_REPLY= 0x02
|
33
|
+
|
34
|
+
# message types
|
35
|
+
$DHCP_MSG_DISCOVER= 0x01
|
36
|
+
$DHCP_MSG_OFFER= 0x02
|
37
|
+
$DHCP_MSG_REQUEST= 0x03
|
38
|
+
$DHCP_MSG_DECLINE= 0x04
|
39
|
+
$DHCP_MSG_ACK= 0x05
|
40
|
+
$DHCP_MSG_NACK= 0x06
|
41
|
+
$DHCP_MSG_RELEASE= 0x07
|
42
|
+
$DHCP_MSG_INFORM= 0x08
|
43
|
+
$DHCP_MSG_NAMES = [
|
44
|
+
'DHCP Discover',
|
45
|
+
'DHCP Offer',
|
46
|
+
'DHCP Request',
|
47
|
+
'DHCP Decline',
|
48
|
+
'DHCP ACK',
|
49
|
+
'DHCP NAK',
|
50
|
+
'DHCP Release',
|
51
|
+
'DHCP Inform'
|
52
|
+
]
|
53
|
+
|
54
|
+
# ---------------------------------------------------------------- other fields
|
55
|
+
|
56
|
+
# hardware types. see "Number Hardware Type (hrd)" in rfc 1700.
|
57
|
+
$DHCP_HTYPE_ETHERNET = 0x01
|
58
|
+
$DHCP_HLEN_ETHERNET = 0x06
|
59
|
+
|
60
|
+
|
61
|
+
$DHCP_MAGIC= 0x63825363
|
62
|
+
$BOOTP_MIN_LEN= 0x12c
|
63
|
+
$DHCP_PAD= 0x00
|
64
|
+
|
65
|
+
# as defined in rfc2132
|
66
|
+
$DHCP_SUBNETMASK= 0x01
|
67
|
+
$DHCP_TIMEOFFSET= 0x02
|
68
|
+
$DHCP_ROUTER= 0x03
|
69
|
+
$DHCP_TIMESERVER= 0x04
|
70
|
+
$DHCP_NAMESERVER= 0x05
|
71
|
+
$DHCP_DNS= 0x06
|
72
|
+
$DHCP_LOGSERV= 0x07
|
73
|
+
#$DHCP_COOKIESERV= 0x08
|
74
|
+
$DHCP_QUOTESSERV= 0x08
|
75
|
+
$DHCP_LPRSERV= 0x09
|
76
|
+
$DHCP_IMPSERV= 0x0a
|
77
|
+
$DHCP_RESSERV= 0x0b
|
78
|
+
$DHCP_HOSTNAME= 0x0c
|
79
|
+
$DHCP_BOOTFILESIZE= 0x0d
|
80
|
+
$DHCP_DUMPFILE= 0x0e
|
81
|
+
$DHCP_DOMAINNAME= 0x0f
|
82
|
+
$DHCP_SWAPSERV= 0x10
|
83
|
+
$DHCP_ROOTPATH= 0x11
|
84
|
+
$DHCP_EXTENPATH= 0x12
|
85
|
+
$DHCP_IPFORWARD= 0x13
|
86
|
+
$DHCP_SRCROUTE= 0x14
|
87
|
+
$DHCP_POLICYFILTER= 0x15
|
88
|
+
$DHCP_MAXASMSIZE= 0x16
|
89
|
+
$DHCP_IPTTL= 0x17
|
90
|
+
$DHCP_MTUTIMEOUT= 0x18
|
91
|
+
$DHCP_MTUTABLE= 0x19
|
92
|
+
$DHCP_MTUSIZE= 0x1a
|
93
|
+
$DHCP_LOCALSUBNETS= 0x1b
|
94
|
+
$DHCP_BROADCASTADDR= 0x1c
|
95
|
+
$DHCP_DOMASKDISCOV= 0x1d
|
96
|
+
$DHCP_MASKSUPPLY= 0x1e
|
97
|
+
$DHCP_DOROUTEDISC= 0x1f
|
98
|
+
$DHCP_ROUTERSOLICIT= 0x20
|
99
|
+
$DHCP_STATICROUTE= 0x21
|
100
|
+
$DHCP_TRAILERENCAP= 0x22
|
101
|
+
$DHCP_ARPTIMEOUT= 0x23
|
102
|
+
$DHCP_ETHERENCAP= 0x24
|
103
|
+
$DHCP_TCPTTL= 0x25
|
104
|
+
$DHCP_TCPKEEPALIVE= 0x26
|
105
|
+
$DHCP_TCPALIVEGARBAGE=0x27
|
106
|
+
$DHCP_NISDOMAIN= 0x28
|
107
|
+
$DHCP_NISSERVERS= 0x29
|
108
|
+
$DHCP_NISTIMESERV= 0x2a
|
109
|
+
$DHCP_VENDSPECIFIC= 0x2b
|
110
|
+
$DHCP_NBNS= 0x2c
|
111
|
+
$DHCP_NBDD= 0x2d
|
112
|
+
$DHCP_NBTCPIP= 0x2e
|
113
|
+
$DHCP_NBTCPSCOPE= 0x2f
|
114
|
+
$DHCP_XFONT= 0x30
|
115
|
+
$DHCP_XDISPLAYMGR= 0x31
|
116
|
+
$DHCP_DISCOVERADDR= 0x32
|
117
|
+
$DHCP_LEASETIME= 0x33
|
118
|
+
$DHCP_OPTIONOVERLOAD= 0x34
|
119
|
+
$DHCP_MESSAGETYPE= 0x35
|
120
|
+
$DHCP_SERVIDENT= 0x36
|
121
|
+
$DHCP_PARAMREQUEST= 0x37
|
122
|
+
$DHCP_MESSAGE= 0x38
|
123
|
+
$DHCP_MAXMSGSIZE= 0x39
|
124
|
+
$DHCP_RENEWTIME= 0x3a
|
125
|
+
$DHCP_REBINDTIME= 0x3b
|
126
|
+
$DHCP_CLASSSID= 0x3c
|
127
|
+
$DHCP_CLIENTID= 0x3d
|
128
|
+
$DHCP_NISPLUSDOMAIN= 0x40
|
129
|
+
$DHCP_NISPLUSSERVERS= 0x41
|
130
|
+
$DHCP_TFTPSERVER= 0x42
|
131
|
+
$DHCP_BOOTFILENAME= 0x43
|
132
|
+
$DHCP_MOBILEIPAGENT= 0x44
|
133
|
+
$DHCP_SMTPSERVER= 0x45
|
134
|
+
$DHCP_POP3SERVER= 0x46
|
135
|
+
$DHCP_NNTPSERVER= 0x47
|
136
|
+
$DHCP_WWWSERVER= 0x48
|
137
|
+
$DHCP_FINGERSERVER= 0x49
|
138
|
+
$DHCP_IRCSERVER= 0x4a
|
139
|
+
$DHCP_STSERVER= 0x4b
|
140
|
+
$DHCP_STDASERVER= 0x4c
|
141
|
+
$DHCP_USERCLASS= 0x4d
|
142
|
+
$DHCP_PRIVATE= 0xaf
|
143
|
+
$DHCP_END= 0xff
|
144
|
+
# / as defined in rfc2132
|
145
|
+
|
146
|
+
# see http://www.bind9.net/bootp-dhcp-parameters
|
147
|
+
|
148
|
+
$DHCP_CLIENTFQDN= 0x51 #rfc4702
|
149
|
+
|
150
|
+
|
151
|
+
$DHCP_CLIENTARCH= 0x5d #rfc4578
|
152
|
+
$DHCP_CLIENTARCH_I386= 0x0000
|
153
|
+
$DHCP_CLIENTARCH_PC98= 0x0001
|
154
|
+
$DHCP_CLIENTARCH_ITANIUM= 0x0002
|
155
|
+
$DHCP_CLIENTARCH_ALPHA= 0x0003
|
156
|
+
$DHCP_CLIENTARCH_X86= 0x0004
|
157
|
+
$DHCP_CLIENTARCH_ILC= 0x0005
|
158
|
+
$DHCP_CLIENTARCH_IA32= 0x0006
|
159
|
+
$DHCP_CLIENTARCH_BC= 0x0007
|
160
|
+
$DHCP_CLIENTARCH_XSCALE= 0x0008
|
161
|
+
$DHCP_CLIENTARCH_X8664= 0x0009
|
162
|
+
$DHCP_CLIENTARCH_NAMES = [
|
163
|
+
'Intel x86PC',
|
164
|
+
'NEC/PC98',
|
165
|
+
'EFI Itanium',
|
166
|
+
'DEC Alpha',
|
167
|
+
'Arc x86',
|
168
|
+
'Intel Lean Client',
|
169
|
+
'EFI IA32',
|
170
|
+
'EFI BC',
|
171
|
+
'EFI Xscale',
|
172
|
+
'EFI x86-64',
|
173
|
+
]
|
174
|
+
|
175
|
+
$DHCP_CLIENTNDI= 0x5e #rfc4578
|
176
|
+
#$DHCP_LDAP= 0x5f
|
177
|
+
$DHCP_UUIDGUID= 0x61 #rfc4578
|
178
|
+
|
179
|
+
$DHCP_AUTOCONF= 0x74 #rfc2563
|
180
|
+
$DHCP_AUTOCONF_NO= 0x00 #rfc2563
|
181
|
+
$DHCP_AUTOCONF_YES= 0x01 #rfc2563
|
182
|
+
|
@@ -0,0 +1,322 @@
|
|
1
|
+
=begin
|
2
|
+
**
|
3
|
+
** core.rb
|
4
|
+
** 02/OCT/2007
|
5
|
+
** ETD-Software
|
6
|
+
** - Daniel Martin Gomez <etd[-at-]nomejortu.com>
|
7
|
+
**
|
8
|
+
** Desc:
|
9
|
+
** This file provides a set of classes to work with the DHCP protocol. They
|
10
|
+
** provide low level access to all the fields and internals of the protocol.
|
11
|
+
**
|
12
|
+
** See the provided rdoc comments for further information.
|
13
|
+
**
|
14
|
+
** Version:
|
15
|
+
** v1.0 [02/October/2007]: first released
|
16
|
+
** v1.1 [31/October/2007]: file moved under /dhcp/ directory and renamed to
|
17
|
+
** core.rb. Now it only contains core classes to
|
18
|
+
** encapsulate DHCP messages
|
19
|
+
**
|
20
|
+
** License:
|
21
|
+
** Please see dhcp.rb or LICENSE.txt for copyright and licensing information.
|
22
|
+
**
|
23
|
+
=end
|
24
|
+
|
25
|
+
module DHCP
|
26
|
+
# -------------------------------------------------------------- dhcp messages
|
27
|
+
class Message
|
28
|
+
attr_accessor :op, :htype, :hlen, :hops
|
29
|
+
attr_accessor :xid
|
30
|
+
attr_accessor :secs, :flags
|
31
|
+
attr_accessor :ciaddr, :yiaddr, :siaddr, :giaddr, :chaddr
|
32
|
+
attr_accessor :options
|
33
|
+
|
34
|
+
alias == eql?
|
35
|
+
|
36
|
+
def Message.from_udp_payload(data)
|
37
|
+
values = data.unpack('C4Nn2N4C16C192NC*')
|
38
|
+
|
39
|
+
params = {
|
40
|
+
:op => values.shift,
|
41
|
+
:htype => values.shift,
|
42
|
+
:hlen => values.shift,
|
43
|
+
:hops => values.shift,
|
44
|
+
|
45
|
+
:xid => values.shift,
|
46
|
+
:secs => values.shift,
|
47
|
+
:flags => values.shift,
|
48
|
+
:ciaddr => values.shift,
|
49
|
+
:yiaddr => values.shift,
|
50
|
+
:siaddr => values.shift,
|
51
|
+
:giaddr => values.shift,
|
52
|
+
:chaddr => values.slice!(0..15)
|
53
|
+
}
|
54
|
+
|
55
|
+
# sname and file
|
56
|
+
not_used = values.slice!(0..191)
|
57
|
+
|
58
|
+
return nil unless ($DHCP_MAGIC == values.shift)
|
59
|
+
|
60
|
+
#default message class
|
61
|
+
msg_class = Message
|
62
|
+
#default option class
|
63
|
+
opt_class = Option
|
64
|
+
|
65
|
+
params[:options] = []
|
66
|
+
|
67
|
+
next_opt = values.shift
|
68
|
+
while(next_opt != $DHCP_END)
|
69
|
+
p = {
|
70
|
+
:type => next_opt,
|
71
|
+
:len => values.shift
|
72
|
+
}
|
73
|
+
p[:payload] = values.slice!(0..p[:len]-1)
|
74
|
+
|
75
|
+
# check what is the type of dhcp option
|
76
|
+
opt_class = $DHCP_MSG_OPTIONS[p[:type]]
|
77
|
+
if(opt_class.nil?)
|
78
|
+
puts '-------------------- please further investigate!!'
|
79
|
+
puts p[:type]
|
80
|
+
puts '-------------------- /'
|
81
|
+
opt_class == Option
|
82
|
+
end
|
83
|
+
if (opt_class == MessageTypeOption)
|
84
|
+
msg_class = $DHCP_MSG_CLASSES[p[:payload].first]
|
85
|
+
end
|
86
|
+
params[:options] << opt_class.new(p)
|
87
|
+
next_opt = values.shift
|
88
|
+
end
|
89
|
+
|
90
|
+
if(msg_class.nil?)
|
91
|
+
puts '-------------------- please further investigate!!'
|
92
|
+
p params[:options]
|
93
|
+
puts '-------------------- /'
|
94
|
+
opt_class == Option
|
95
|
+
end
|
96
|
+
msg_class.new(params)
|
97
|
+
end
|
98
|
+
|
99
|
+
def initialize(params = {})
|
100
|
+
|
101
|
+
# message operation and options. We need at least an operation and a
|
102
|
+
# MessageTypeOption to create a DHCP message!!
|
103
|
+
if (([:op, :options] & params.keys).size != 2)
|
104
|
+
raise ArgumentError('you need to specify at least values for :op and :options')
|
105
|
+
end
|
106
|
+
|
107
|
+
self.op = params[:op]
|
108
|
+
|
109
|
+
self.options = params[:options]
|
110
|
+
found = false
|
111
|
+
self.options.each do |opt|
|
112
|
+
next unless opt.class == MessageTypeOption
|
113
|
+
found = true
|
114
|
+
end
|
115
|
+
raise ArgumentError(':options must include a MessageTypeOption') unless found
|
116
|
+
|
117
|
+
#hardware type and length of the hardware address
|
118
|
+
self.htype = params.fetch(:htype, $DHCP_HTYPE_ETHERNET)
|
119
|
+
self.hlen = params.fetch(:hlen, $DHCP_HLEN_ETHERNET)
|
120
|
+
|
121
|
+
# client sets to zero. relay agents may modify
|
122
|
+
self.hops = params.fetch(:hops, 0x00)
|
123
|
+
|
124
|
+
# initialize a random transaction ID
|
125
|
+
self.xid = params.fetch(:xid, rand(2**32))
|
126
|
+
|
127
|
+
# seconds elapsed, flags
|
128
|
+
self.secs = params.fetch(:secs, 0x0000)
|
129
|
+
self.flags = params.fetch(:flags, 0x0000)
|
130
|
+
|
131
|
+
# client, you, next server and relay agent addresses
|
132
|
+
self.ciaddr = params.fetch(:ciaddr, 0x00000000)
|
133
|
+
self.yiaddr = params.fetch(:yiaddr, 0x00000000)
|
134
|
+
self.siaddr = params.fetch(:siaddr, 0x00000000)
|
135
|
+
self.giaddr = params.fetch(:giaddr, 0x00000000)
|
136
|
+
|
137
|
+
if (params.key?(:chaddr))
|
138
|
+
self.chaddr = params[:chaddr]
|
139
|
+
raise 'chaddr field should be of 16 bytes' unless self.chaddr.size == 16
|
140
|
+
else
|
141
|
+
mac = `/sbin/ifconfig | grep HWaddr | cut -c39- | head -1`.chomp.strip.gsub(/:/,'')
|
142
|
+
self.chaddr = [mac].pack('H*').unpack('CCCCCC')
|
143
|
+
self.chaddr += [0x00]*(16-self.chaddr.size)
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
def pack()
|
150
|
+
out = [
|
151
|
+
self.op, self.htype, self.hlen, self.hops,
|
152
|
+
self.xid,
|
153
|
+
self.secs, self.flags,
|
154
|
+
self.ciaddr,
|
155
|
+
self.yiaddr,
|
156
|
+
self.siaddr,
|
157
|
+
self.giaddr
|
158
|
+
].pack('C4Nn2N4')
|
159
|
+
|
160
|
+
out << self.chaddr.pack('C*')
|
161
|
+
|
162
|
+
|
163
|
+
# sname and file
|
164
|
+
out << ([0x00]*192).pack('C192')
|
165
|
+
|
166
|
+
out << [$DHCP_MAGIC].pack('N')
|
167
|
+
self.options.each do |option|
|
168
|
+
out << option.pack
|
169
|
+
end
|
170
|
+
out << [$DHCP_END].pack('C')
|
171
|
+
|
172
|
+
# add padding up to 300 bytes
|
173
|
+
if out.size < 300
|
174
|
+
out << ([$DHCP_PAD]*(300-out.size)).pack('C*')
|
175
|
+
end
|
176
|
+
return out
|
177
|
+
end
|
178
|
+
|
179
|
+
def eql?(obj)
|
180
|
+
# objects must be of the same class
|
181
|
+
return false unless (self.class == obj.class)
|
182
|
+
|
183
|
+
vars1 = self.instance_variables
|
184
|
+
|
185
|
+
# first make sure that the :options var is equal
|
186
|
+
opt1 = self.instance_variable_get('@options')
|
187
|
+
opt2 = obj.instance_variable_get('@options')
|
188
|
+
|
189
|
+
return false unless opt1.eql?(opt2)
|
190
|
+
vars1.delete('@options')
|
191
|
+
|
192
|
+
# check all the other instance vairables
|
193
|
+
vars1.each do |var|
|
194
|
+
return false unless (self.instance_variable_get(var) == obj.instance_variable_get(var))
|
195
|
+
end
|
196
|
+
|
197
|
+
return true
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
def to_s
|
203
|
+
out = "DHCP Message\r\n"
|
204
|
+
out << "\tFIELDS:\r\n"
|
205
|
+
out << "\t\tTransaction ID = #{self.xid}\r\n"
|
206
|
+
out << "\t\tClient IP address = #{[self.ciaddr].pack('N').unpack('C4').join('.')}\r\n"
|
207
|
+
out << "\t\tYour IP address = #{[self.yiaddr].pack('N').unpack('C4').join('.')}\r\n"
|
208
|
+
out << "\t\tNext server IP address = #{[self.siaddr].pack('N').unpack('C4').join('.')}\r\n"
|
209
|
+
out << "\t\tRelay agent IP address = #{[self.giaddr].pack('N').unpack('C4').join('.')}\r\n"
|
210
|
+
out << "\t\tHardware address = #{self.chaddr.slice(0..(self.hlen-1)).collect do |b| b.to_s(16).upcase.rjust(2,'0') end.join(':')}\r\n"
|
211
|
+
out << "\tOPT:\r\n"
|
212
|
+
self.options.each do |opt|
|
213
|
+
out << "\t\t #{opt.to_s}\r\n"
|
214
|
+
end
|
215
|
+
return out
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Client broadcast to locate available servers.
|
220
|
+
class Discover < Message
|
221
|
+
def initialize(params={})
|
222
|
+
params[:op] = $DHCP_OP_REQUEST
|
223
|
+
# if an :options field is provided, we use it, otherwise, a default is set
|
224
|
+
params[:options] = params.fetch(:options, [MessageTypeOption.new, ParameterRequestListOption.new])
|
225
|
+
super(params)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Server to client in response to DHCPDISCOVER with offer of configuration
|
230
|
+
# parameters.
|
231
|
+
#
|
232
|
+
# By default an ACK message will contain a Server Identifier (0.0.0.0) and
|
233
|
+
# a Domain Name ('nomejortu.com') option.
|
234
|
+
class Offer < Message
|
235
|
+
def initialize(params={})
|
236
|
+
params[:op] = $DHCP_OP_REPLY
|
237
|
+
params[:options] = params.fetch(:options, [
|
238
|
+
MessageTypeOption.new({:payload=>$DHCP_MSG_OFFER}),
|
239
|
+
ServerIdentifierOption.new,
|
240
|
+
DomainNameOption.new
|
241
|
+
])
|
242
|
+
super(params)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Client message to servers either (a) requesting offered parameters from one
|
247
|
+
# server and implicitly declining offers from all others, (b) confirming
|
248
|
+
# correctness of previously allocated address after, e.g., system reboot, or
|
249
|
+
# (c) extending the lease on a particular network address.
|
250
|
+
class Request < Message
|
251
|
+
def initialize(params={})
|
252
|
+
params[:op] = $DHCP_OP_REQUEST
|
253
|
+
params[:options] = params.fetch(:options, [MessageTypeOption.new({:payload=>$DHCP_MSG_REQUEST}), ParameterRequestListOption.new])
|
254
|
+
super(params)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
#
|
259
|
+
# DHCPDECLINE - Client to server indicating network address is already
|
260
|
+
# in use.
|
261
|
+
|
262
|
+
# Server to client with configuration parameters, including committed network
|
263
|
+
# address.
|
264
|
+
#
|
265
|
+
# By default an ACK message will contain a Server Identifier (0.0.0.0) and
|
266
|
+
# a Domain Name ('nomejortu.com') option.
|
267
|
+
class ACK < Message
|
268
|
+
def initialize(params={})
|
269
|
+
params[:op] = $DHCP_OP_REPLY
|
270
|
+
params[:options] = params.fetch(:options, [
|
271
|
+
MessageTypeOption.new({:payload=>$DHCP_MSG_ACK}),
|
272
|
+
ServerIdentifierOption.new,
|
273
|
+
DomainNameOption.new
|
274
|
+
])
|
275
|
+
super(params)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# DHCPNAK - Server to client indicating client's notion of network
|
280
|
+
# address is incorrect (e.g., client has moved to new
|
281
|
+
# subnet) or client's lease as expired
|
282
|
+
|
283
|
+
# Client to server relinquishing network address and cancelling remaining
|
284
|
+
# lease.
|
285
|
+
#
|
286
|
+
# By default an ACK message will contain a Server Identifier (0.0.0.0)
|
287
|
+
class Release < Message
|
288
|
+
def initialize(params={})
|
289
|
+
params[:op] = $DHCP_OP_REQUEST
|
290
|
+
params[:options] = params.fetch(:options, [
|
291
|
+
MessageTypeOption.new({:payload=>$DHCP_MSG_RELEASE}),
|
292
|
+
ServerIdentifierOption.new
|
293
|
+
])
|
294
|
+
super(params)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Client to server, asking only for local configuration parameters; client
|
299
|
+
# already has externally configured network address.
|
300
|
+
class Inform < Message
|
301
|
+
def initialize(params={})
|
302
|
+
params[:op] = $DHCP_OP_REQUEST
|
303
|
+
params[:options] = params.fetch(:options, [MessageTypeOption.new({:payload=>$DHCP_MSG_INFORM}), ParameterRequestListOption.new])
|
304
|
+
super(params)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
# ------------------------------------ map from values of fields to class names
|
309
|
+
|
310
|
+
$DHCP_MSG_CLASSES = {
|
311
|
+
$DHCP_MSG_DISCOVER => Discover,
|
312
|
+
$DHCP_MSG_OFFER => Offer,
|
313
|
+
$DHCP_MSG_REQUEST => Request,
|
314
|
+
# $DHCP_MSG_DECLINE= 0x04
|
315
|
+
$DHCP_MSG_ACK => ACK,
|
316
|
+
# $DHCP_MSG_NACK= 0x06
|
317
|
+
$DHCP_MSG_RELEASE => Release,
|
318
|
+
$DHCP_MSG_INFORM => Inform
|
319
|
+
}
|
320
|
+
|
321
|
+
|
322
|
+
end
|