Project

General

Profile

Download (4.77 KB) Statistics
| Branch: | Tag: | Revision:
module Proxy::DHCP
# Represents Microsoft DHCP Server
# requires the help of a CGI like script running on a MS IIS Server
class MS < Server

def initialize(options = {})
super options[:server]
@username = options[:username]
@password = options[:password]
@gateway = options[:gateway]
end

def loadSubnets
super
cmd = "ListScopeDetailed"
operand = "enumerate the scopes on #{@name}"

response = query cmd, operand

response.each do |line|
line.chomp
break if line.match(/^Command completed/)

# 172.29.216.0 - 255.255.254.0 -Active -DC BRS -
if line =~ /^\s*([\d\.]+)\s*-\s*([\d\.]+)\s*-\s*(Active|Disabled)/
network = $1
netmask = $2
subnet = Proxy::DHCP::Subnet.new(self, network, netmask)
end
end
end

def loadSubnetData subnet
raise "invalid Subnet" unless subnet.is_a? Proxy::DHCP::Subnet
cmd = "ListReservation" + "&ScopeIpAddress=#{subnet.network}"
operand = "enumerate #{subnet.network} on #{@name}"

response = query cmd, operand

subnet.clear

# Extract the data
response.each do |line|
line.chomp
break if line.match(/^Command completed/)
# 172.29.216.6 - 00-a0-e7-21-41-00-
if line =~ /^\s+([\w\.]+)\s+-\s+([-a-f\d]+)/
ip = $1
mac = $2.gsub(/-/,":").match(/^(.*?).$/)[1]
Proxy::DHCP::Record.new(subnet, ip, mac) unless ip.nil? or mac.nil?
end
end
super subnet
end


def loadSubnetOptions subnet
raise "invalid Subnet" unless subnet.is_a? Proxy::DHCP::Subnet
cmd = "ShowOptionValue&ScopeIPAddress=#{subnet.network}"
response = query cmd

subnet.options = parse_options response
super subnet
end

def loadRecordOptions record
raise "invalid Record" unless record.is_a? Proxy::DHCP::Record
subnet = record.subnet
raise "unable to find subnet for #{record}" if subnet.nil?
cmd = "ShowReservedOptionValue&ScopeIPAddress=#{subnet.network}&ReservedIP=#{record.ip}"
response = query cmd

record.options = parse_options response
end

def delRecordFor record
subnet = find_subnet record
mac = record.mac.gsub(/:/,"")
entry = "ScopeIpAddress=#{subnet.network}&ReservedIP=#{record.ip}"
cmd = "DeleteReservation&#{entry}&MAC_Address=#{mac}"

response = query cmd
logger.info "removed Proxy::DHCP reservation for #{entry}/#{mac}"
subnet.delete(record)
end

private
def query cmd, operand = nil
response = invoke cmd
validate_response cmd, operand, response
return response
end

def invoke cmd
userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727; InfoPath.1; MS-RTC LM 8)'
header = "https://#{@gateway}/NetShManager/NetShManager.aspx?ServerName=#{@name}&"
cmd = "CommandName=/" + cmd
command = "curl -q -k --silent --user '#{@username}:#{@password}' --user-agent '#{userAgent}' '#{header}#{cmd}'; "
filtered = command.gsub(@password,"FILTERED")
puts "Invoking #{filtered}" if @@debug

response = %x{#{command}}
puts response if @@debug
raise Proxy::DHCP::Error, "invalid Response - curl return error code #{$?} - while executing #{filtered}" unless $? == 0
return $? == 0 ? response.split(/\r\n/) : false
end

def validate_response cmd, operand, response
unless response[-3..-2].join=~/Command completed successfully/
logger.error "Invoke failed:\n" + response.join("\n")
scopeIpAddress, ip = cmd.match(/ScopeIpAddress=([^&]+)&ReservedIP=([^&]+)/)[1..2]

case operand
when /^create|^delete/
msg = "Failed to #{operand} for #{ip} in #{scopeIpAddress}"
when /^enumerate|install/
msg = "Failed to #{operand}"
when /^query/
return response if response[2] =~ /not a reserved client/
else
if cmd.match(/Add/)
msg = "Failed to set #{operand} for #{ip} in #{scopeIpAddress}"
else
msg = "Failed to get option values for #{ip} in #{scopeIpAddress}"
end
end
end
raise Proxy::DHCP::Error.new msg if msg
rescue
raise Proxy::DHCP::Error.new "Unknown error while processing #{msg} - #{response}"
end

def parse_options response
optionId = nil
options = {}
response.each do |line|
line.chomp
break if line.match(/^Command completed/)

case line
when /OptionId : (\d+)/
optionId = $1
when /Option Element Value = (\S+)/
options[optionId] = $1
end
end
return options
end

end
end
(2-2/4)