Module: LanScanner

Defined in:
lib/lan_scanner.rb,
lib/lan_scanner/device.rb,
lib/lan_scanner/version.rb

Defined Under Namespace

Classes: Device

Constant Summary collapse

VERSION =
'0.0.5'.freeze

Class Method Summary collapse

Class Method Details

.my_ip_addressesObject



83
84
85
# File 'lib/lan_scanner.rb', line 83

def self.my_ip_addresses
  Socket.ip_address_list.select { |ai| ai.ipv4? && !ai.ipv4_loopback? }.map(&:ip_address).uniq
end

.my_networksObject



73
74
75
76
77
78
79
80
81
# File 'lib/lan_scanner.rb', line 73

def self.my_networks
  my_ip_addresses.map do |a|
    if a.include?('.')
      a.split('.')[0..2].join('.') + '.0/24'
    else
      raise "No support for IPv6 devices"
    end
  end
end

.scan_device_states(addresses, expensive: false) ⇒ Object

get states of given addresses

Parameters:

  • expensive (Boolean) (defaults to: false)

    make expensive check for devices which were not found by fast check already



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/lan_scanner.rb', line 53

def self.scan_device_states addresses, expensive: false
  addresses = [addresses] unless addresses.is_a? Array
  tmp_file = "#{Dir.tmpdir}/nmap_scan_#{Random.random_number}.xml"
  nmap_scan_option = if expensive
                 '-Pn'
               else
                 '-sn'
               end
  `nmap -sn #{addresses.join(' ')} -oX "#{tmp_file}"`
  online_hosts = _parse_nmap_xml [File.read(tmp_file)]
  offline_addresses = addresses.reject { |a| online_hosts.map(&:remote_address).include?(a) }
  # check offline addresses again with expensive check
  if expensive
    `nmap -sP #{offline_addresses.join(' ')} -oX "#{tmp_file}"`
    online_hosts += _parse_nmap_xml [File.read(tmp_file)]
    offline_addresses = addresses.reject { |a| online_hosts.map(&:remote_address).include?(a) }
  end
  online_hosts + offline_addresses.map { |a| OpenStruct.new(remote_address: a, host_name: nil, state: 'down') }
end

.scan_devices(network: nil) ⇒ Array<LanScanner::Device>

Returns list of devices.

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/lan_scanner.rb', line 15

def self.scan_devices(network: nil)
  _ensure_nmap_available
  if network.nil?
    network = my_networks
  end
  network = [network] unless network.is_a? Array
  sn_xml_results = []
  tmp_file = "#{Dir.tmpdir}/nmap_scan_#{Random.random_number}.xml"
  # first we do an -sL scan, which also receives addresses from router/network cache,
  # that are not found by -sn scan when scanning for the complete network, but are found
  # with -sn scan, when scanning for this addresses explicitly
  #
  # so after this scan we scan for this addresses beneath the networks with -sn
  sl_xml_results = []
  network.each do |n|
    ['-sL'].each do |nmap_type|
      `nmap #{nmap_type} #{n} -oX "#{tmp_file}"`
      sl_xml_results.push File.read tmp_file
      File.delete tmp_file
    end
  end
  # here we scan for the received ip addresses from network cache
  sl_ips = _parse_nmap_xml sl_xml_results
  `nmap -sn #{sl_ips.map(&:remote_address).join(' ')} -oX "#{tmp_file}"`
  sn_xml_results.push File.read tmp_file
  # here we ping the networks (fast ping which does not detect all)
  network.each do |n|
    ['-sn'].each do |nmap_type|
      `nmap #{nmap_type} #{n} -oX "#{tmp_file}"`
      sn_xml_results.push File.read tmp_file
      File.delete tmp_file
    end
  end
  _parse_nmap_xml sn_xml_results
end