#!/usr/bin/env ruby # Version 0.61 #-------------------------------------------------------------------------------------------- # Change log # July 2006 - Alpha version # July 2006 - 0.1 Implemented SimpleIPNetwork # August 2006 - 0.2 Replaced Socket library with Resolv library # October 2006 - 0.3 Tightened code & added comments # October 2006 - 0.4 More code tightening, first & last functions, handling multiple address in Resolv # October 2006 - 0.5 New functions and comments, error handling, long2ip returns nil if lookup fails # October 2006 - 0.6 Added arpa address functionality require 'resolv' class SimpleIP #Convert a IP address string in dotted notation to long integer def ip2long(dotted) begin octets = dotted.split(/\./) return octets[0].to_i << 24 | octets[1].to_i << 16 | octets[2].to_i << 8 | octets[3].to_i rescue return nil end end #---------------------------------------------------------- #Convert an IP address in long integer form to string in dotted notation def long2ip(longint) begin return (longint >> 24).to_s + "." + ((0x00FF0000 & longint) >> 16).to_s + "." + ((0x0000FF00 & longint) >> 8).to_s + "." + (0x000000FF & longint).to_s rescue return nil end end #---------------------------------------------------------- #Perform a host name to dotted IP lookup def SimpleIP.host2ip(fqdn) # to do - handle multiple IPs begin result = Resolv.getaddresses(fqdn).join(", ") return result.empty? ? nil : result rescue Resolv::ResolvError return nil end end #---------------------------------------------------------- #Perform an dotted IP address to host name lookup def SimpleIP.ip2host(ip) begin result = Resolv.getnames(ip).join(", ") return result.empty? ? nil : result rescue Resolv::ResolvError return nil end end #---------------------------------------------------------- def SimpleIP.arpa(dotted) begin octets = dotted.split(/\./) return octets.reverse.join(".") + ".in-addr.arpa" rescue return nil end end end ################################################################## class SimpleIPNetwork < SimpleIP #Intialize the object and optionally create a new range def initialize(*range) @startlong = 0 @endlong = 0 self.set(range.to_s) if range end #Create a new range def set(range) case range when /^\d+\.\d+\.\d+\.\d+$/ # single IP @startlong = self.ip2long(range) @endlong = self.ip2long(range) when /^\d+\.\d+\.\d+\.\d+\-\d+$/ # class C range asplit = range.scan(/(\d+\.\d+\.\d+\.)(\d+)(\-)(\d+)/) @startlong = self.ip2long(asplit[0][0] + asplit[0][1]) @endlong = self.ip2long(asplit[0][0] + asplit[0][3]) when /^\d+\.\d+\.\d+\.\d+\-\d+\.\d$/ # class B range asplit = range.scan(/(\d+\.\d+\.)(\d+\.)(\d+)(\-)(\d+\.\d+)/) @startlong = self.ip2long(asplit[0][0] + asplit[0][1] + asplit[0][2]) @endlong = self.ip2long(asplit[0][0] + asplit[0][4]) when /^\d+\.\d+\.\d+\.\d+\-\d+\.\d+\.\d+\.\d+$/ # IP to IP asplit = range.split(/\-/) @startlong = self.ip2long(asplit[0] ) @endlong = self.ip2long(asplit[1]) when /^\d+\.\d+\.\d+\.\d+\/\d+/ # CIDR asplit = range.split(/\//) @startlong = self.ip2long(asplit[0] ) @endlong = @startlong + (0xFFFFFFFF >> asplit[1].to_i) else # get serious end end #---------------------------------------------------------- #Returns true if the IP address in the range def includes?(ip) (@startlong <= self.ip2long(ip) and self.ip2long(ip) <= @endlong) ? true : false end #---------------------------------------------------------- #Iterate through the entire range def each @startlong.upto(@endlong) { |ip| yield self.long2ip(ip) } end #---------------------------------------------------------- #First IP address def first return self.long2ip(@startlong) end #---------------------------------------------------------- #Last IP address def last() return self.long2ip(@endlong) end #---------------------------------------------------------- #Total number of IP's in the range def count() return (@endlong - @startlong + 1) end end ################################################################## if __FILE__==$0 s = SimpleIP.host2ip("www.pentester.com.au") p s r = SimpleIP.ip2host(s) p r p "Network 1 10.0.0.1-10" t = SimpleIPNetwork.new("10.0.0.1-10") t.each do | ip | p ip end p t.count() p "Network 2 10.0.0.1-1.255" t.set("10.0.0.1-1.255") p t.first() p t.last() p "Network 3 10.0.0.0/28" t.set("10.0.0.0/28") t.each do | ip | p ip end p t.includes?("10.0.0.1") p t.includes?("10.1.1.1") end