facter 4.0.49 → 4.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/lib/facter/config.rb +20 -7
  3. data/lib/facter/custom_facts/core/execution/base.rb +3 -2
  4. data/lib/facter/custom_facts/core/execution/popen3.rb +47 -0
  5. data/lib/facter/custom_facts/util/fact.rb +2 -2
  6. data/lib/facter/facts/alpine/os/release.rb +29 -0
  7. data/lib/facter/facts/amzn/os/release.rb +29 -0
  8. data/lib/facter/facts/devuan/os/distro/release.rb +36 -0
  9. data/lib/facter/facts/devuan/os/release.rb +29 -0
  10. data/lib/facter/facts/gentoo/os/release.rb +29 -0
  11. data/lib/facter/facts/linuxmint/os/name.rb +18 -0
  12. data/lib/facter/facts/linuxmint/os/release.rb +35 -0
  13. data/lib/facter/facts/mageia/os/release.rb +36 -0
  14. data/lib/facter/facts/meego/os/release.rb +29 -0
  15. data/lib/facter/facts/oel/os/release.rb +29 -0
  16. data/lib/facter/facts/ol/os/release.rb +29 -0
  17. data/lib/facter/facts/openwrt/os/release.rb +35 -0
  18. data/lib/facter/facts/ovs/os/release.rb +29 -0
  19. data/lib/facter/facts/photon/os/release.rb +45 -0
  20. data/lib/facter/facts/rhel/os/release.rb +1 -8
  21. data/lib/facter/facts/slackware/os/release.rb +35 -0
  22. data/lib/facter/framework/config/config_reader.rb +7 -0
  23. data/lib/facter/framework/config/fact_groups.rb +3 -0
  24. data/lib/facter/framework/core/fact_loaders/external_fact_loader.rb +0 -4
  25. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +2 -0
  26. data/lib/facter/framework/detector/os_detector.rb +7 -0
  27. data/lib/facter/resolvers/aio_agent_version.rb +1 -1
  28. data/lib/facter/resolvers/aix/architecture.rb +1 -1
  29. data/lib/facter/resolvers/aix/disks.rb +1 -1
  30. data/lib/facter/resolvers/aix/ffi/ffi.rb +63 -0
  31. data/lib/facter/resolvers/aix/ffi/ffi_helper.rb +146 -20
  32. data/lib/facter/resolvers/aix/ffi/structs.rb +69 -0
  33. data/lib/facter/resolvers/aix/filesystem.rb +1 -1
  34. data/lib/facter/resolvers/aix/hardware.rb +1 -1
  35. data/lib/facter/resolvers/aix/load_averages.rb +2 -2
  36. data/lib/facter/resolvers/aix/memory.rb +1 -1
  37. data/lib/facter/resolvers/aix/mountpoints.rb +1 -1
  38. data/lib/facter/resolvers/aix/networking.rb +9 -16
  39. data/lib/facter/resolvers/aix/nim.rb +1 -1
  40. data/lib/facter/resolvers/aix/os_level.rb +1 -1
  41. data/lib/facter/resolvers/aix/partitions.rb +1 -1
  42. data/lib/facter/resolvers/aix/processors.rb +1 -1
  43. data/lib/facter/resolvers/aix/serialnumber.rb +1 -1
  44. data/lib/facter/resolvers/augeas.rb +1 -1
  45. data/lib/facter/resolvers/base_resolver.rb +4 -4
  46. data/lib/facter/resolvers/bsd/processors.rb +1 -1
  47. data/lib/facter/resolvers/cloud.rb +1 -1
  48. data/lib/facter/resolvers/containers.rb +1 -1
  49. data/lib/facter/resolvers/debian_version.rb +1 -1
  50. data/lib/facter/resolvers/disk.rb +1 -1
  51. data/lib/facter/resolvers/dmi.rb +1 -1
  52. data/lib/facter/resolvers/dmi_decode.rb +1 -1
  53. data/lib/facter/resolvers/ec2.rb +1 -1
  54. data/lib/facter/resolvers/eos_release.rb +1 -1
  55. data/lib/facter/resolvers/facterversion.rb +1 -1
  56. data/lib/facter/resolvers/filesystems.rb +1 -1
  57. data/lib/facter/resolvers/fips_enabled.rb +1 -1
  58. data/lib/facter/resolvers/freebsd/dmi.rb +1 -1
  59. data/lib/facter/resolvers/freebsd/freebsd_version.rb +1 -1
  60. data/lib/facter/resolvers/freebsd/geom.rb +1 -1
  61. data/lib/facter/resolvers/freebsd/processors.rb +1 -1
  62. data/lib/facter/resolvers/freebsd/swap_memory.rb +1 -1
  63. data/lib/facter/resolvers/freebsd/system_memory.rb +1 -1
  64. data/lib/facter/resolvers/freebsd/virtual.rb +1 -1
  65. data/lib/facter/resolvers/gce.rb +1 -1
  66. data/lib/facter/resolvers/hostname.rb +1 -1
  67. data/lib/facter/resolvers/identity.rb +1 -1
  68. data/lib/facter/resolvers/linux/docker_uptime.rb +1 -1
  69. data/lib/facter/resolvers/linux/load_averages.rb +1 -1
  70. data/lib/facter/resolvers/load_averages.rb +1 -1
  71. data/lib/facter/resolvers/lpar.rb +1 -1
  72. data/lib/facter/resolvers/lsb_release.rb +1 -1
  73. data/lib/facter/resolvers/lspci.rb +1 -1
  74. data/lib/facter/resolvers/macosx/dmi.rb +1 -1
  75. data/lib/facter/resolvers/macosx/filesystems.rb +1 -1
  76. data/lib/facter/resolvers/macosx/load_averages.rb +1 -1
  77. data/lib/facter/resolvers/macosx/mountpoints.rb +1 -1
  78. data/lib/facter/resolvers/macosx/processor.rb +1 -1
  79. data/lib/facter/resolvers/macosx/swap_memory.rb +1 -1
  80. data/lib/facter/resolvers/macosx/system_memory.rb +1 -1
  81. data/lib/facter/resolvers/macosx/system_profiler.rb +1 -1
  82. data/lib/facter/resolvers/memory.rb +1 -1
  83. data/lib/facter/resolvers/mountpoints.rb +1 -1
  84. data/lib/facter/resolvers/networking.rb +1 -1
  85. data/lib/facter/resolvers/networking_linux.rb +1 -1
  86. data/lib/facter/resolvers/open_vz.rb +1 -1
  87. data/lib/facter/resolvers/os_release.rb +1 -1
  88. data/lib/facter/resolvers/partitions.rb +1 -1
  89. data/lib/facter/resolvers/path.rb +1 -1
  90. data/lib/facter/resolvers/processors.rb +1 -1
  91. data/lib/facter/resolvers/redhat_release.rb +1 -1
  92. data/lib/facter/resolvers/release_from_first_line.rb +41 -0
  93. data/lib/facter/resolvers/ruby.rb +1 -1
  94. data/lib/facter/resolvers/selinux.rb +1 -1
  95. data/lib/facter/resolvers/solaris/disks.rb +1 -1
  96. data/lib/facter/resolvers/solaris/dmi.rb +1 -1
  97. data/lib/facter/resolvers/solaris/dmi_sparc.rb +1 -1
  98. data/lib/facter/resolvers/solaris/filesystems.rb +1 -1
  99. data/lib/facter/resolvers/solaris/ipaddress.rb +1 -1
  100. data/lib/facter/resolvers/solaris/ldom.rb +1 -1
  101. data/lib/facter/resolvers/solaris/memory.rb +1 -1
  102. data/lib/facter/resolvers/solaris/mountpoints.rb +1 -1
  103. data/lib/facter/resolvers/solaris/networking.rb +1 -1
  104. data/lib/facter/resolvers/solaris/os_release.rb +1 -1
  105. data/lib/facter/resolvers/solaris/processors.rb +1 -1
  106. data/lib/facter/resolvers/solaris/zone.rb +1 -1
  107. data/lib/facter/resolvers/solaris/zone_name.rb +1 -1
  108. data/lib/facter/resolvers/specific_release_file.rb +35 -0
  109. data/lib/facter/resolvers/ssh.rb +1 -1
  110. data/lib/facter/resolvers/suse_release.rb +1 -1
  111. data/lib/facter/resolvers/sw_vers.rb +1 -1
  112. data/lib/facter/resolvers/timezone.rb +1 -1
  113. data/lib/facter/resolvers/uname.rb +1 -1
  114. data/lib/facter/resolvers/uptime.rb +1 -1
  115. data/lib/facter/resolvers/virt_what.rb +1 -1
  116. data/lib/facter/resolvers/vmware.rb +1 -1
  117. data/lib/facter/resolvers/windows/aio_agent_version.rb +1 -1
  118. data/lib/facter/resolvers/windows/dmi_bios.rb +1 -1
  119. data/lib/facter/resolvers/windows/dmi_computersystem.rb +1 -1
  120. data/lib/facter/resolvers/windows/ffi/network_utils.rb +1 -2
  121. data/lib/facter/resolvers/windows/fips.rb +1 -1
  122. data/lib/facter/resolvers/windows/hardware_architecture.rb +1 -1
  123. data/lib/facter/resolvers/windows/identity.rb +1 -1
  124. data/lib/facter/resolvers/windows/kernel.rb +1 -1
  125. data/lib/facter/resolvers/windows/memory.rb +1 -1
  126. data/lib/facter/resolvers/windows/netkvm.rb +1 -1
  127. data/lib/facter/resolvers/windows/networking.rb +8 -4
  128. data/lib/facter/resolvers/windows/processors.rb +1 -1
  129. data/lib/facter/resolvers/windows/product_release.rb +1 -1
  130. data/lib/facter/resolvers/windows/ssh.rb +1 -1
  131. data/lib/facter/resolvers/windows/system32.rb +1 -1
  132. data/lib/facter/resolvers/windows/uptime.rb +1 -1
  133. data/lib/facter/resolvers/windows/virtualization.rb +1 -1
  134. data/lib/facter/resolvers/windows/win_os_description.rb +1 -1
  135. data/lib/facter/resolvers/wpar.rb +1 -1
  136. data/lib/facter/resolvers/xen.rb +1 -1
  137. data/lib/facter/resolvers/zfs.rb +1 -1
  138. data/lib/facter/resolvers/zpool.rb +1 -1
  139. data/lib/facter/util/facts/facts_utils.rb +17 -0
  140. data/lib/facter/util/facts/unit_converter.rb +11 -4
  141. data/lib/facter/util/utils.rb +0 -4
  142. data/lib/facter/version.rb +1 -1
  143. metadata +22 -2
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Ol
5
+ module Os
6
+ class Release
7
+ FACT_NAME = 'os.release'
8
+ ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
+
10
+ def call_the_resolver
11
+ version = determine_release_version
12
+
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless version
14
+
15
+ [Facter::ResolvedFact.new(FACT_NAME, version),
16
+ Facter::ResolvedFact.new(ALIASES.first, version['major'], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES.last, version['full'], :legacy)]
18
+ end
19
+
20
+ def determine_release_version
21
+ version = Facter::Resolvers::ReleaseFromFirstLine.resolve(:release, release_file: '/etc/oracle-release')
22
+ version ||= Facter::Resolvers::OsRelease.resolve(:version_id)
23
+
24
+ Facter::Util::Facts.release_hash_from_string(version)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Openwrt
5
+ module Os
6
+ class Release
7
+ FACT_NAME = 'os.release'
8
+ ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
+
10
+ def call_the_resolver
11
+ version = from_specific_file || from_os_release
12
+
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless version
14
+
15
+ [Facter::ResolvedFact.new(FACT_NAME, version),
16
+ Facter::ResolvedFact.new(ALIASES.first, version['major'], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES.last, version['full'], :legacy)]
18
+ end
19
+
20
+ def from_specific_file
21
+ version = Facter::Resolvers::SpecificReleaseFile.resolve(:release,
22
+ { release_file: '/etc/openwrt_version',
23
+ regex: /^(\d+.\d+.*)/ })
24
+ Facter::Util::Facts.release_hash_from_matchdata(version)
25
+ end
26
+
27
+ def from_os_release
28
+ version = Facter::Resolvers::OsRelease.resolve(:version_id)
29
+
30
+ Facter::Util::Facts.release_hash_from_string(version)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Ovs
5
+ module Os
6
+ class Release
7
+ FACT_NAME = 'os.release'
8
+ ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
+
10
+ def call_the_resolver
11
+ version = determine_release_version
12
+
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless version
14
+
15
+ [Facter::ResolvedFact.new(FACT_NAME, version),
16
+ Facter::ResolvedFact.new(ALIASES.first, version['major'], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES.last, version['full'], :legacy)]
18
+ end
19
+
20
+ def determine_release_version
21
+ version = Facter::Resolvers::ReleaseFromFirstLine.resolve(:release, release_file: '/etc/ovs-release')
22
+ version ||= Facter::Resolvers::OsRelease.resolve(:version_id)
23
+
24
+ Facter::Util::Facts.release_hash_from_string(version)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Photon
5
+ module Os
6
+ class Release
7
+ FACT_NAME = 'os.release'
8
+ ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
+
10
+ def call_the_resolver
11
+ version = from_specific_file || from_os_release
12
+
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless version
14
+
15
+ [Facter::ResolvedFact.new(FACT_NAME, version),
16
+ Facter::ResolvedFact.new(ALIASES.first, version['major'], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES.last, version['full'], :legacy)]
18
+ end
19
+
20
+ def from_specific_file
21
+ version = Facter::Resolvers::SpecificReleaseFile.resolve(:release,
22
+ { release_file: '/etc/lsb-release',
23
+ regex: /DISTRIB_RELEASE="(\d+)\.(\d+)/ })
24
+ return if version.nil? || version[1].nil? || version[2].nil?
25
+
26
+ major = version[1].to_s
27
+ minor = version[2].to_s
28
+ version_data = major + '.' + minor
29
+
30
+ {
31
+ 'full' => version_data,
32
+ 'major' => major,
33
+ 'minor' => minor
34
+ }
35
+ end
36
+
37
+ def from_os_release
38
+ version = Facter::Resolvers::OsRelease.resolve(:version_id)
39
+
40
+ Facter::Util::Facts.release_hash_from_string(version)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -21,14 +21,7 @@ module Facts
21
21
  version = Facter::Resolvers::RedHatRelease.resolve(:version)
22
22
  version ||= Facter::Resolvers::OsRelease.resolve(:version_id)
23
23
 
24
- return unless version
25
-
26
- versions = version.split('.')
27
- fact_value = {}
28
- fact_value['full'] = version
29
- fact_value['major'] = versions[0]
30
- fact_value['minor'] = versions[1] if versions[1]
31
- fact_value
24
+ Facter::Util::Facts.release_hash_from_string(version)
32
25
  end
33
26
  end
34
27
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Slackware
5
+ module Os
6
+ class Release
7
+ FACT_NAME = 'os.release'
8
+ ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
9
+
10
+ def call_the_resolver
11
+ version = from_specific_file || from_os_release
12
+
13
+ return Facter::ResolvedFact.new(FACT_NAME, nil) unless version
14
+
15
+ [Facter::ResolvedFact.new(FACT_NAME, version),
16
+ Facter::ResolvedFact.new(ALIASES.first, version['major'], :legacy),
17
+ Facter::ResolvedFact.new(ALIASES.last, version['full'], :legacy)]
18
+ end
19
+
20
+ def from_specific_file
21
+ version = Facter::Resolvers::SpecificReleaseFile.resolve(:release,
22
+ { release_file: '/etc/slackware-version',
23
+ regex: /Slackware ([0-9.]+)/ })
24
+ Facter::Util::Facts.release_hash_from_matchdata(version)
25
+ end
26
+
27
+ def from_os_release
28
+ version = Facter::Resolvers::OsRelease.resolve(:version_id)
29
+
30
+ Facter::Util::Facts.release_hash_from_string(version)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -33,10 +33,17 @@ module Facter
33
33
 
34
34
  def refresh_config(config_path)
35
35
  @conf = File.readable?(config_path) ? Hocon.load(config_path) : {}
36
+ rescue StandardError => e
37
+ log.warn("Facter failed to read config file #{config_path} with the following error: #{e.message}")
38
+ @conf = {}
36
39
  end
37
40
 
38
41
  private
39
42
 
43
+ def log
44
+ @log ||= Log.new(self)
45
+ end
46
+
40
47
  def default_path
41
48
  os = OsDetector.instance.identifier
42
49
 
@@ -24,6 +24,9 @@ module Facter
24
24
  fact_list = []
25
25
 
26
26
  @block_list.each do |group_name|
27
+ # legacy is a special group and does not need to be broken into facts
28
+ next if group_name == 'legacy'
29
+
27
30
  facts_for_block = @groups[group_name]
28
31
 
29
32
  fact_list += facts_for_block || [group_name]
@@ -10,10 +10,6 @@ module Facter
10
10
  @external_facts = load_external_facts
11
11
  end
12
12
 
13
- def all_facts
14
- @all_facts ||= Utils.deep_copy(custom_facts + external_facts)
15
- end
16
-
17
13
  private
18
14
 
19
15
  def load_custom_facts
@@ -83,6 +83,8 @@ module Facter
83
83
  def block_facts(facts, options)
84
84
  blocked_facts = options[:blocked_facts] || []
85
85
 
86
+ facts.reject! { |fact| fact.type == :legacy } if options[:block_list]&.include?('legacy')
87
+
86
88
  reject_list_core, reject_list_legacy = construct_reject_lists(blocked_facts, facts)
87
89
 
88
90
  facts = facts.reject do |fact|
@@ -64,7 +64,14 @@ class OsDetector
64
64
  Facter::Resolvers::OsRelease.resolve(:id_like)
65
65
  end
66
66
 
67
+ def detect_based_on_release_file
68
+ @identifier = :devuan if File.readable?('/etc/devuan_version')
69
+ end
70
+
67
71
  def detect_distro
72
+ detect_based_on_release_file
73
+ return @identifier if @identifier
74
+
68
75
  [Facter::Resolvers::OsRelease,
69
76
  Facter::Resolvers::RedHatRelease,
70
77
  Facter::Resolvers::SuseRelease].each do |resolver|
@@ -8,7 +8,7 @@ module Facter
8
8
  class << self
9
9
  private
10
10
 
11
- def post_resolve(fact_name)
11
+ def post_resolve(fact_name, _options)
12
12
  @fact_list.fetch(fact_name) { read_agent_version }
13
13
  end
14
14
 
@@ -9,7 +9,7 @@ module Facter
9
9
  class << self
10
10
  private
11
11
 
12
- def post_resolve(fact_name)
12
+ def post_resolve(fact_name, _options)
13
13
  @fact_list.fetch(fact_name) { read_architecture(fact_name) }
14
14
  end
15
15
 
@@ -9,7 +9,7 @@ module Facter
9
9
  class << self
10
10
  private
11
11
 
12
- def post_resolve(fact_name)
12
+ def post_resolve(fact_name, _options)
13
13
  @fact_list.fetch(fact_name) { execute_lspv(fact_name) }
14
14
  end
15
15
 
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facter
4
+ module Resolvers
5
+ module Aix
6
+ module FFI
7
+ RTM_IFINFO = 0xe
8
+ RTM_NEWADDR = 0xc
9
+
10
+ RTAX_DST = 0
11
+ RTAX_GATEWAY = 1
12
+ RTAX_NETMASK = 2
13
+ RTAX_GENMASK = 3
14
+ RTAX_IFP = 4
15
+ RTAX_IFA = 5
16
+ RTAX_AUTHOR = 6
17
+ RTAX_BRD = 7
18
+ RTAX_MAX = 8
19
+
20
+ RTA_DST = 0x1
21
+ RTA_GATEWAY = 0x2
22
+ RTA_NETMASK = 0x4
23
+ RTA_GENMASK = 0x8
24
+ RTA_IFP = 0x10
25
+ RTA_IFA = 0x20
26
+ RTA_AUTHOR = 0x40
27
+ RTA_BRD = 0x80
28
+ RTA_DOWNSTREAM = 0x100
29
+
30
+ AF_UNSPEC = 0
31
+ AF_INET = 2
32
+ AF_INET6 = 24
33
+ AF_MAX = 30
34
+
35
+ INET_ADDRSTRLEN = 16
36
+ INET6_ADDRSTRLEN = 46
37
+
38
+ RTAX_LIST = [
39
+ RTAX_DST,
40
+ RTAX_GATEWAY,
41
+ RTAX_NETMASK,
42
+ RTAX_GENMASK,
43
+ RTAX_IFP,
44
+ RTAX_IFA,
45
+ RTAX_AUTHOR,
46
+ RTAX_BRD
47
+ ].freeze
48
+
49
+ RTA_LIST = [
50
+ RTA_DST,
51
+ RTA_GATEWAY,
52
+ RTA_NETMASK,
53
+ RTA_GENMASK,
54
+ RTA_IFP,
55
+ RTA_IFA,
56
+ RTA_AUTHOR,
57
+ RTA_BRD,
58
+ RTA_DOWNSTREAM
59
+ ].freeze
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,34 +1,160 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ffi'
4
-
4
+ require_relative 'structs'
5
+ require_relative 'ffi'
5
6
  module Facter
6
- module Aix
7
- module FfiHelper
8
- KINFO_GET_AVENRUN = 1
9
- KINFO_READ = 8 << 8
7
+ module Resolvers
8
+ module Aix
9
+ module FfiHelper
10
+ KINFO_GET_AVENRUN = 1
11
+ KINFO_READ = 8 << 8
12
+ KINFO_RT = 1 << 8
13
+ KINFO_RT_IFLIST = KINFO_RT | 3
10
14
 
11
- module Libc
12
- extend FFI::Library
15
+ module Libc
16
+ extend ::FFI::Library
13
17
 
14
- RTLD_LAZY = 0x00000004
15
- RTLD_GLOBAL = 0x00010000
16
- RTLD_MEMBER = 0x00040000
18
+ RTLD_LAZY = 0x00000004
19
+ RTLD_GLOBAL = 0x00010000
20
+ RTLD_MEMBER = 0x00040000
17
21
 
18
- @ffi_lib_flags = RTLD_LAZY | RTLD_GLOBAL | RTLD_MEMBER
19
- ffi_lib 'libc.a(shr.o)'
22
+ @ffi_lib_flags = RTLD_LAZY | RTLD_GLOBAL | RTLD_MEMBER
23
+ ffi_lib 'libc.a(shr.o)'
20
24
 
21
- attach_function :getkerninfo, %i[int pointer pointer int], :int
22
- end
25
+ attach_function :getkerninfo, %i[int pointer pointer int], :int
26
+ attach_function :inet_ntop, %i[int pointer pointer uint], :string
27
+ end
28
+
29
+ def self.read_load_averages
30
+ averages = ::FFI::MemoryPointer.new(:long_long, 3)
31
+ averages_size = ::FFI::MemoryPointer.new(:int, 1)
32
+ averages_size.write_int(averages.size)
33
+
34
+ return if Libc.getkerninfo(KINFO_READ | KINFO_GET_AVENRUN, averages, averages_size, 0).negative?
35
+
36
+ averages.read_array_of_long_long(3).map { |x| (x / 65_536.0).round(5) }
37
+ end
38
+
39
+ def self.read_interfaces
40
+ ksize = Libc.getkerninfo(KINFO_RT_IFLIST, nil, nil, 0)
41
+
42
+ log.debug('getkerninfo call was unsuccessful') if ksize.zero?
43
+
44
+ ksize_ptr = ::FFI::MemoryPointer.new(:int, ksize.size)
45
+ ksize_ptr.write_int(ksize)
46
+
47
+ result_ptr = ::FFI::MemoryPointer.new(:char, ksize)
48
+
49
+ res = Libc.getkerninfo(KINFO_RT_IFLIST, result_ptr, ksize_ptr, 0)
50
+ log.debug('getkerninfo call was unsuccessful') if res == -1
51
+
52
+ cursor = 0
53
+
54
+ interfaces = {}
55
+ while cursor < ksize_ptr.read_int
56
+ hdr = FFI::IfMsghdr.new(result_ptr + cursor)
57
+
58
+ case hdr[:ifm_type]
59
+ when FFI::RTM_IFINFO
60
+ link_addr = FFI::SockaddrDl.new(hdr.to_ptr + hdr.size)
61
+
62
+ interface_name = link_addr[:sdl_data].to_s[0, link_addr[:sdl_nlen]]
63
+ interfaces[interface_name] ||= {}
64
+
65
+ when FFI::RTM_NEWADDR
66
+ addresses = {}
67
+ addr_cursor = cursor + hdr.size
68
+ FFI::RTAX_LIST.each do |key|
69
+ xand = hdr[:ifm_addrs] & FFI::RTA_LIST[key]
70
+ next unless xand != 0
71
+
72
+ sockaddr = FFI::Sockaddr.new(result_ptr + addr_cursor)
73
+ addresses[key] = sockaddr
74
+ roundup_nr = roundup(sockaddr)
75
+ addr_cursor += roundup_nr
76
+ end
77
+
78
+ family = FFI::AF_UNSPEC
79
+
80
+ addresses.each do |_k, addr|
81
+ if family != FFI::AF_UNSPEC &&
82
+ addr[:sa_family] != FFI::AF_UNSPEC &&
83
+ family != addr[:sa_family]
84
+ family = FFI::AF_MAX
85
+ break
86
+ end
87
+ family = addr[:sa_family]
88
+ end
89
+
90
+ if addresses[FFI::RTAX_NETMASK][:sa_len]
91
+ addresses[FFI::RTAX_NETMASK][:sa_family] = family
92
+ netmask = address_to_string(addresses[FFI::RTAX_NETMASK])
93
+ end
94
+
95
+ address = address_to_string(addresses[FFI::RTAX_IFA]) if addresses[FFI::RTAX_IFA][:sa_len]
96
+
97
+ if addresses[FFI::RTAX_NETMASK][:sa_len] && addresses[FFI::RTAX_IFA][:sa_len]
98
+ network = address_to_string(addresses[FFI::RTAX_IFA], addresses[FFI::RTAX_NETMASK])
99
+ end
100
+
101
+ bindings = family == FFI::AF_INET ? :bindings : :bindings6
102
+ interfaces[interface_name][bindings] ||= []
103
+ interfaces[interface_name][bindings] << {
104
+ netmask: netmask.read_string,
105
+ address: address.read_string,
106
+ network: network.read_string
107
+ }
108
+ else
109
+ log.debug("got an unknown RT_IFLIST message: #{hdr[:ifm_type]}")
110
+ end
111
+
112
+ cursor += hdr[:ifm_msglen]
113
+ end
114
+
115
+ interfaces
116
+ end
117
+
118
+ def self.roundup(sockaddr)
119
+ if sockaddr[:sa_len].positive?
120
+ 1 + ((sockaddr[:sa_len] - 1) | (1.size - 1))
121
+ else
122
+ 1.size
123
+ end
124
+ end
125
+
126
+ def self.address_to_string(sockaddr, mask = nil)
127
+ if sockaddr[:sa_family] == FFI::AF_INET
128
+ in_addr_ip = FFI::SockaddrIn.new(sockaddr.to_ptr)
129
+
130
+ if mask && sockaddr[:sa_family] == mask[:sa_family]
131
+ in_addr_mask = FFI::SockaddrIn.new(mask.to_ptr)
132
+ in_addr_ip[:sin_addr][:s_addr] &= in_addr_mask[:sin_addr][:s_addr]
133
+ end
134
+
135
+ buffer = ::FFI::MemoryPointer.new(:char, FFI::INET_ADDRSTRLEN)
136
+ Libc.inet_ntop(FFI::AF_INET, in_addr_ip[:sin_addr].to_ptr, buffer, 16)
137
+
138
+ buffer
139
+ elsif sockaddr[:sa_family] == FFI::AF_INET6
140
+ in_addr_ip = FFI::SockaddrIn6.new(sockaddr.to_ptr)
141
+ if mask && sockaddr[:sa_family] == mask[:sa_family]
142
+ in_addr_mask = FFI::SockaddrIn6.new(sockaddr.to_ptr)
143
+ 16.times do |i|
144
+ in_addr_ip[:sin6_addr][:u6_addr8][i] &= in_addr_mask[:sin6_addr][:u6_addr8][i]
145
+ end
146
+ end
23
147
 
24
- def self.read_load_averages
25
- averages = FFI::MemoryPointer.new(:long_long, 3)
26
- averages_size = FFI::MemoryPointer.new(:int, 1)
27
- averages_size.write_int(averages.size)
148
+ buffer = ::FFI::MemoryPointer.new(:char, FFI::INET6_ADDRSTRLEN)
149
+ Libc.inet_ntop(FFI::AF_INET6, in_addr_ip[:sin6_addr].to_ptr, buffer, 16)
28
150
 
29
- return if Libc.getkerninfo(KINFO_READ | KINFO_GET_AVENRUN, averages, averages_size, 0).negative?
151
+ buffer
152
+ end
153
+ end
30
154
 
31
- averages.read_array_of_long_long(3).map { |x| (x / 65_536.0).round(5) }
155
+ def self.log
156
+ @log ||= Log.new(self)
157
+ end
32
158
  end
33
159
  end
34
160
  end