lib/ronin/extensions/ip_addr.rb in ronin-support-0.2.0 vs lib/ronin/extensions/ip_addr.rb in ronin-support-0.3.0

- old
+ new

@@ -15,69 +15,75 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Ronin Support. If not, see <http://www.gnu.org/licenses/>. # +require 'ronin/extensions/resolv' +require 'ronin/extensions/regexp' + require 'ipaddr' -require 'resolv' require 'strscan' require 'combinatorics/list_comprehension' class IPAddr include Enumerable - # A regular expression for matching IPv4 Addresses. - IPV4_REGEXP = /[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}/ + # Socket families and IP address masks + MASKS = { + Socket::AF_INET => IN4MASK, + Socket::AF_INET6 => IN6MASK + } - # A regular expression for matching IPv6 Addresses. - IPV6_REGEXP = /:(:[0-9a-f]{1,4}){1,7}|([0-9a-f]{1,4}::?){1,7}[0-9a-f]{1,4}(:#{IPV4_REGEXP})?/ - - # A regular expression for matching IP Addresses. - REGEXP = /#{IPV4_REGEXP}|#{IPV6_REGEXP}/ - # # Extracts IP Addresses from text. # # @param [String] text # The text to scan for IP Addresses. # - # @param [Symbol] version - # The version of IP Address to scan for (`:ipv4` or `:ipv6`). + # @param [Integer, Symbol] version + # The version of IP Address to scan for (`4`, `6`, `:v4` or `:v6`). # # @yield [ip] # The given block will be passed each extracted IP Address. # # @yieldparam [String] ip # An IP Address from the text. # # @return [Array<String>] # The IP Addresses found in the text. # + # @example + # IPAddr.extract("Host: 127.0.0.1\n\rHost: 10.1.1.1\n\r") + # # => ["127.0.0.1", "10.1.1.1"] + # + # @example Extract only IPv4 addresses from a large amount of text. + # IPAddr.extract(text,:v4) do |ip| + # puts ip + # end + # # @api public # def IPAddr.extract(text,version=nil,&block) + return enum_for(:extract,text,version).to_a unless block_given? + regexp = case version - when :ipv4 - IPV4_REGEXP - when :ipv6 - IPV6_REGEXP + when :ipv4, :v4, 4 + Regexp::IPv4 + when :ipv6, :v6, 6 + Regexp::IPv6 else - REGEXP + Regexp::IP end - parser = StringScanner.new(text) + scanner = StringScanner.new(text) - if block_given? - yield parser.matched while parser.skip_until(regexp) - return nil - else - ips = [] - - ips << parser.matched while parser.skip_until(regexp) - return ips + while scanner.skip_until(regexp) + yield scanner.matched end + + return nil end # # Iterates over each IP address within the IP Address range. Supports # both IPv4 and IPv6 address ranges. @@ -118,32 +124,31 @@ end return enum_for(:each,cidr_or_glob) unless block if cidr_or_glob.include?('::') - prefix = if cidr_or_glob[0,2] == '::' + separator = '::' + base = 16 + + prefix = if cidr_or_glob.start_with?('::') '::' else '' end - separator = '::' - base = 16 - format = lambda { |address| prefix + address.map { |i| '%.2x' % i }.join('::') } else separator = '.' - base = 10 - - format = lambda { |address| address.join('.') } + base = 10 + format = lambda { |address| address.join('.') } end # split the address segments = cidr_or_glob.split(separator) - ranges = [] + ranges = [] # map the components of the address to numeric ranges segments.each do |segment| next if segment.empty? @@ -157,27 +162,27 @@ segment.to_i(base) end end # cycle through the address ranges - ranges.comprehension do |address| - yield format[address] - end - + ranges.comprehension { |address| yield format[address] } return nil end # # Resolves the host-names for the IP address. # + # @param [String] nameserver + # The optional nameserver to query. + # # @return [Array<String>] # The host-names for the IP address. # # @api public # - def lookup - Resolv.getnames(self.to_s) + def lookup(nameserver=nil) + Resolv.resolver(nameserver).getnames(self.to_s) end # # Iterates over each IP address that is included in the addresses # netmask. Supports both IPv4 and IPv6 addresses. @@ -199,15 +204,10 @@ # @api public # def each return enum_for(:each) unless block_given? - case @family - when Socket::AF_INET - family_mask = IN4MASK - when Socket::AF_INET6 - family_mask = IN6MASK - end + family_mask = MASKS[@family] (0..((~@mask_addr) & family_mask)).each do |i| yield _to_string(@addr | i) end