dhcp 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|