dhcp 0.0.3 → 0.0.4
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 +4 -4
- data/lib/dhcp/s.rb +7 -0
- data/lib/dhcp/server.rb +69 -31
- data/lib/dhcp/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff27859168efaca20656a202f252e830519f8fc1
|
4
|
+
data.tar.gz: 8491c7a8772ac71b6fd6e37ca96f58b320fa1c2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b47973dfb41fb5839a987d5c35ac2aa779258db03496a25c2f3a4be7f12d0be67e81253d6fe122345ea80803257d787b095183ba7975ba40361279e8eea740b
|
7
|
+
data.tar.gz: 186e766fcb5b3e7134fee72dae11666b556560e0b460233008b22b39c74ec2ddbeee608cbbc13768b36b8f11f3231f5999bcc6c18ce4819512fd18962c6be97f
|
data/lib/dhcp/s.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative 'server'
|
4
|
+
require 'syslog'
|
5
|
+
#Syslog.open('dhcp-server')
|
6
|
+
s = DHCP::Server.new(:ip => '209.33.249.130', :debug => true, :log => Class.new do ; def err(x) ; STDERR.puts x ; end ; def info(x) ; STDERR.puts x ; end ; def warn(x) ; STDERR.puts x ; end ; def debug(x) ; STDERR.puts x ; end ; end.new)
|
7
|
+
s.run
|
data/lib/dhcp/server.rb
CHANGED
@@ -1,34 +1,72 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: ASCII-8BIT
|
3
3
|
|
4
|
+
require 'socket'
|
5
|
+
require 'syslog'
|
4
6
|
require_relative 'packet'
|
5
7
|
|
6
8
|
module DHCP # :nodoc:
|
7
9
|
class Server
|
10
|
+
ZERO_IP = IPAddress('0.0.0.0')
|
11
|
+
|
8
12
|
def initialize(opt={})
|
9
|
-
@
|
10
|
-
@
|
13
|
+
@interval = opt[:interval] || 0.5 ## Sleep (seconds) if no data
|
14
|
+
@log = opt[:log] || Syslog ## Logging object (should be open already)
|
15
|
+
@server_ip = opt[:ip] || '0.0.0.0' ## Listen on this IP
|
16
|
+
@server_port = opt[:port] || 67 ## Listen on this UDP port
|
17
|
+
@debug = opt[:debug] || false
|
18
|
+
|
19
|
+
## Bind to UDP server port:
|
20
|
+
@log.info("Starting DHCP on [#{@server_ip}]:#{@server_port} server at #{Time.now}")
|
21
|
+
@sock = UDPSocket.new
|
22
|
+
@sock.do_not_reverse_lookup = true
|
23
|
+
@sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true) ## Permit sending to broadcast address
|
24
|
+
unless @sock.bind(@server_ip, 67)
|
25
|
+
raise "Failed to bind"
|
26
|
+
end
|
11
27
|
end
|
12
|
-
attr_reader :socket
|
13
28
|
|
14
|
-
## Main server event
|
29
|
+
## Main server event single-iteration function (non-blocking):
|
15
30
|
def run_once
|
31
|
+
r,w,e = IO.select([@sock], nil, [@sock], 0)
|
32
|
+
if !r.nil? && r.size == 1
|
33
|
+
data, src = @sock.recvfrom_nonblock(1500)
|
34
|
+
if data.bytesize < 300
|
35
|
+
@log.debug("Ignoring packet smaller than BOOTP minimum size") if @debug
|
36
|
+
else
|
37
|
+
dispatch_packet(data, src[3], src[1])
|
38
|
+
end
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
if !e.nil? && e.size == 1
|
42
|
+
## TODO: Handle errors...
|
43
|
+
raise "Unhandled error on socket"
|
44
|
+
end
|
45
|
+
return false
|
16
46
|
end
|
17
47
|
|
18
48
|
## Main server event loop (blocking):
|
19
49
|
def run
|
20
50
|
loop do
|
21
|
-
|
51
|
+
result = run_once
|
22
52
|
sleep @interval if !result ## Sleep if no data was received and no errors occured
|
23
53
|
end
|
24
54
|
end
|
25
55
|
|
56
|
+
def show_packet(pk)
|
57
|
+
@log.debug(">>> PACKET: #{pk.type} '#{pk.type_name}' at #{Time.now} >>>")
|
58
|
+
pk.to_s.gsub(/\\/,'\\\\').gsub(/[^\x20-\x7e\n]/){|x| '\x' + x.unpack('H2')[0].upcase}.split("\n").each do |i|
|
59
|
+
@log.debug("..." + i)
|
60
|
+
end
|
61
|
+
@log.debug("<<< END OF PACKET <<<")
|
62
|
+
end
|
63
|
+
|
26
64
|
## Hand off raw UDP packet data here for parsing and dispatch:
|
27
65
|
def dispatch_packet(data, source_ip, source_port)
|
28
66
|
now = Time.now
|
29
|
-
|
67
|
+
@log.debug("Packet (#{data.size} bytes) from [#{source_ip}]:#{source_port} received at #{now}")
|
30
68
|
if data.size < 300
|
31
|
-
|
69
|
+
@log.debug("Ignoring small packet (less than BOOTP minimum size.") if @debug
|
32
70
|
return
|
33
71
|
end
|
34
72
|
|
@@ -36,8 +74,8 @@ module DHCP # :nodoc:
|
|
36
74
|
begin
|
37
75
|
packet = DHCP::Packet.new(data)
|
38
76
|
rescue => e
|
39
|
-
show_packet(packet)
|
40
|
-
|
77
|
+
show_packet(packet) if @debug
|
78
|
+
@log.debug("Error parsing DHCP packet.") if @debug
|
41
79
|
return
|
42
80
|
end
|
43
81
|
|
@@ -46,36 +84,36 @@ module DHCP # :nodoc:
|
|
46
84
|
relay = true
|
47
85
|
|
48
86
|
## Quick relay sanity-check on GIADDR:
|
49
|
-
if packet.giaddr ==
|
50
|
-
|
87
|
+
if packet.giaddr == ZERO_IP
|
88
|
+
@log.debug("Packet from relay (port 67) has no GIADDR address set. Ignoring.") if @debug
|
51
89
|
return
|
52
90
|
end
|
53
91
|
|
54
92
|
unless relay_authorized?(source_ip, packet.giaddr)
|
55
|
-
|
93
|
+
@log.debug("Ignoring DHCP packet from unauthorized relay [#{source_ip}].") if @debug
|
56
94
|
return
|
57
95
|
end
|
58
96
|
elsif source_port == 68 ## DHCP on directly attached subnet
|
59
97
|
relay = false
|
60
98
|
|
61
99
|
## Quick relay sanity-check on GIADDR:
|
62
|
-
if packet.giaddr !=
|
63
|
-
|
100
|
+
if packet.giaddr != ZERO_IP
|
101
|
+
@log.debug("Direct (non-relay) packet has set GIADDR to [#{packet.giaddr}] in violation of RFC. Ignoring.") if @debug
|
64
102
|
return
|
65
103
|
end
|
66
104
|
else
|
67
|
-
|
105
|
+
@log.debug("Ignoring packet from UDP port other than 67 (relay) or 68 (direct)") if @debug
|
68
106
|
return
|
69
107
|
end
|
70
108
|
|
71
109
|
## Ethernet hardware type sanity check:
|
72
110
|
if packet.htype != DHCP::HTYPE[:htype_10mb_ethernet][0] || packet.hlen != DHCP::HTYPE[:htype_10mb_ethernet][1]
|
73
|
-
|
111
|
+
@log.debug("Request hardware type or length doesn't match ETHERNET type and length. Ignoring.") if @debug
|
74
112
|
return
|
75
113
|
end
|
76
114
|
|
77
115
|
if packet.op != DHCP::BOOTREQUEST
|
78
|
-
|
116
|
+
@log.debug("Recived a non-BOOTREQUEST packet. Ignoring.") if @debug
|
79
117
|
return
|
80
118
|
end
|
81
119
|
|
@@ -94,11 +132,11 @@ module DHCP # :nodoc:
|
|
94
132
|
when DHCP::DHCPLEASEQUERY
|
95
133
|
handle_leasequery(packet, source_ip, relay)
|
96
134
|
when DHCP::DHCPOFFER, DHCP::DHCPACK, DHCP::DHCPNAK, DHCP::DHCPFORCERENEW, DHCP::DHCPLEASEUNASSIGNED, DHCP::DHCPLEASEACTIVE, DHCP::DHCPLEASEUNKNOWN
|
97
|
-
show_packet(packet)
|
98
|
-
|
135
|
+
show_packet(packet) if @debug
|
136
|
+
@log.debug("Packet type #{packet.type_name} in a BOOTREQUEST is invalid.") if @debug
|
99
137
|
else
|
100
|
-
show_packet(packet)
|
101
|
-
|
138
|
+
show_packet(packet) if @debug
|
139
|
+
@log.debug("Invalid, unknown, or unhandled DHCP packet type received.") if @debug
|
102
140
|
end
|
103
141
|
end
|
104
142
|
|
@@ -108,32 +146,32 @@ module DHCP # :nodoc:
|
|
108
146
|
|
109
147
|
## Handle DHCPDISCOVER packet:
|
110
148
|
def handle_discover(packet, source_ip, relay)
|
111
|
-
show_packet(packet)
|
112
|
-
|
149
|
+
show_packet(packet) if @debug
|
150
|
+
@log.debug("handle_discover") if @debug
|
113
151
|
end
|
114
152
|
|
115
153
|
## Handle DHCPREQUEST packet:
|
116
154
|
def handle_request(packet, source_ip, relay)
|
117
|
-
show_packet(packet)
|
118
|
-
|
155
|
+
show_packet(packet) if @debug
|
156
|
+
@log.debug("handle_request") if @debug
|
119
157
|
end
|
120
158
|
|
121
159
|
## Handle DHCPINFORM packet:
|
122
160
|
def handle_inform(packet, source_ip, relay)
|
123
|
-
show_packet(packet)
|
124
|
-
|
161
|
+
show_packet(packet) if @debug
|
162
|
+
@log.debug("handle_inform") if @debug
|
125
163
|
end
|
126
164
|
|
127
165
|
## Handle DHCPDECLINE packet:
|
128
166
|
def handle_decline(packet, source_ip, relay)
|
129
|
-
show_packet(packet)
|
130
|
-
|
167
|
+
show_packet(packet) if @debug
|
168
|
+
@log.debug("handle_decline") if @debug
|
131
169
|
end
|
132
170
|
|
133
171
|
## Handle DHCPLEASEQUERY packet:
|
134
172
|
def handle_leasequery(packet, source_ip, relay)
|
135
|
-
show_packet(packet)
|
136
|
-
|
173
|
+
show_packet(packet) if @debug
|
174
|
+
@log.debug("handle_leasequery") if @debug
|
137
175
|
end
|
138
176
|
end
|
139
177
|
|
data/lib/dhcp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dhcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron D. Gifford
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ipaddress
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- lib/dhcp/dhcp.rb
|
41
41
|
- lib/dhcp/options.rb
|
42
42
|
- lib/dhcp/packet.rb
|
43
|
+
- lib/dhcp/s.rb
|
43
44
|
- lib/dhcp/server.rb
|
44
45
|
- lib/dhcp/version.rb
|
45
46
|
homepage: http://www.aarongifford.com/computers/dhcp/
|
@@ -65,5 +66,5 @@ rubyforge_project: dhcp
|
|
65
66
|
rubygems_version: 2.4.5
|
66
67
|
signing_key:
|
67
68
|
specification_version: 4
|
68
|
-
summary: dhcp-0.0.
|
69
|
+
summary: dhcp-0.0.4
|
69
70
|
test_files: []
|