louis 1.1.0 → 1.1.1
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.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/Rakefile +11 -0
- data/data/processed_data.json +1 -0
- data/lib/louis/helpers.rb +50 -0
- data/lib/louis/version.rb +1 -1
- data/lib/louis.rb +7 -47
- data/louis.gemspec +4 -1
- data/spec/louis_spec.rb +6 -2
- metadata +3 -2
- data/data/mac_oui_manuf.txt +0 -25491
@@ -0,0 +1,50 @@
|
|
1
|
+
module Louis
|
2
|
+
module Helpers
|
3
|
+
# Calculate the bit mask for testing whether or not a mac_prefix matches.
|
4
|
+
# This returns an integer with the upper X bits set where X is the mask
|
5
|
+
# length.
|
6
|
+
#
|
7
|
+
# @param [String] prefix
|
8
|
+
# @param [String] mask
|
9
|
+
# @return [Fixnum]
|
10
|
+
def calculate_mask(prefix, mask)
|
11
|
+
mask_base = mask.nil? ? (clean_mac(prefix).length * 4) : mask.to_i
|
12
|
+
(2 ** 48 - 1) - (2 ** (48 - mask_base) - 1)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the hex representing a full or partial MAC address with the
|
16
|
+
# 'connecting' characters removed. Does nothing to ensure length.
|
17
|
+
#
|
18
|
+
# @param [String] mac
|
19
|
+
# @return [String]
|
20
|
+
def clean_mac(mac)
|
21
|
+
mac.gsub(/[:-]/, '')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Converts a hexidecimal version of a full or partial (prefix) MAC address
|
25
|
+
# into it's integer representation.
|
26
|
+
#
|
27
|
+
# @param [String] mac
|
28
|
+
def mac_to_num(mac)
|
29
|
+
clean_mac(mac).ljust(12, '0').to_i(16)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Handle parsing a line from the raw OUI file into it's associated lookup
|
33
|
+
# table format. This will return nil if the line is poorly formatted, empty
|
34
|
+
# or a comment.
|
35
|
+
#
|
36
|
+
# @param [String]
|
37
|
+
# @return [Hash<String=>Object>]
|
38
|
+
def line_parser(line)
|
39
|
+
return unless (matches = OUI_FORMAT_REGEX.match(line))
|
40
|
+
result = Hash[matches.names.zip(matches.captures)]
|
41
|
+
|
42
|
+
{
|
43
|
+
'mask' => calculate_mask(result['prefix'], result['mask']),
|
44
|
+
'prefix' => mac_to_num(result['prefix']),
|
45
|
+
'short_vendor' => result['short_vendor'],
|
46
|
+
'long_vendor' => result['long_vendor']
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/louis/version.rb
CHANGED
data/lib/louis.rb
CHANGED
@@ -1,27 +1,11 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
require 'louis/const'
|
4
|
+
require 'louis/helpers'
|
2
5
|
require 'louis/version'
|
3
6
|
|
4
7
|
module Louis
|
5
|
-
|
6
|
-
# This returns an integer with the upper X bits set where X is the mask
|
7
|
-
# length.
|
8
|
-
#
|
9
|
-
# @param [String] prefix
|
10
|
-
# @param [String] mask
|
11
|
-
# @return [Fixnum]
|
12
|
-
def self.calculate_mask(prefix, mask)
|
13
|
-
mask_base = mask.nil? ? (clean_mac(prefix).length * 4) : mask.to_i
|
14
|
-
(2 ** 48 - 1) - (2 ** (48 - mask_base) - 1)
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns the hex representing a full or partial MAC address with the
|
18
|
-
# 'connecting' characters removed. Does nothing to ensure length.
|
19
|
-
#
|
20
|
-
# @param [String] mac
|
21
|
-
# @return [String]
|
22
|
-
def self.clean_mac(mac)
|
23
|
-
mac.gsub(/[:-]/, '')
|
24
|
-
end
|
8
|
+
extend Helpers
|
25
9
|
|
26
10
|
# Search through the OUI lookup table and return all the entries in the
|
27
11
|
# lookup table that match the provided MAC.
|
@@ -29,27 +13,13 @@ module Louis
|
|
29
13
|
# @param [String] mac
|
30
14
|
# @return [Array<Hash<String=>Object>>]
|
31
15
|
def self.find_matches(mac)
|
32
|
-
|
16
|
+
lookup_table.select { |m| mac_matches_prefix?(mac, m['prefix'], m['mask']) }
|
33
17
|
end
|
34
18
|
|
35
19
|
# Loads the lookup table, parsing out the uncommented non-blank lines into
|
36
20
|
# objects we can compare MACs against to find their vendor.
|
37
|
-
def self.
|
38
|
-
|
39
|
-
@lookup_table = []
|
40
|
-
|
41
|
-
File.open(ORIGINAL_OUI_FILE).each_line do |line|
|
42
|
-
if (matches = OUI_FORMAT_REGEX.match(line))
|
43
|
-
result = Hash[matches.names.zip(matches.captures)]
|
44
|
-
|
45
|
-
@lookup_table.push({
|
46
|
-
'mask' => calculate_mask(result['prefix'], result['mask']),
|
47
|
-
'prefix' => mac_to_num(result['prefix']),
|
48
|
-
'short_vendor' => result['short_vendor'],
|
49
|
-
'long_vendor' => result['long_vendor']
|
50
|
-
})
|
51
|
-
end
|
52
|
-
end
|
21
|
+
def self.lookup_table
|
22
|
+
@lookup_table ||= JSON.parse(File.read(Louis::PARSED_DATA_FILE))
|
53
23
|
end
|
54
24
|
|
55
25
|
# Returns the name of the vendor that has the most specific prefix
|
@@ -58,8 +28,6 @@ module Louis
|
|
58
28
|
# @param [String] mac
|
59
29
|
# @return [String]
|
60
30
|
def self.lookup(mac)
|
61
|
-
load_lookup_table
|
62
|
-
|
63
31
|
o = find_matches(mac).sort_by { |m| m['prefix'] }.first
|
64
32
|
o ||= {'long_vendor' => 'Unknown', 'short_vendor' => 'Unknown'}
|
65
33
|
|
@@ -75,12 +43,4 @@ module Louis
|
|
75
43
|
def self.mac_matches_prefix?(mac, prefix, mask)
|
76
44
|
(mac_to_num(mac) & mask) == prefix
|
77
45
|
end
|
78
|
-
|
79
|
-
# Converts a hexidecimal version of a full or partial (prefix) MAC address
|
80
|
-
# into it's integer representation.
|
81
|
-
#
|
82
|
-
# @param [String] mac
|
83
|
-
def self.mac_to_num(mac)
|
84
|
-
clean_mac(mac).ljust(12, '0').to_i(16)
|
85
|
-
end
|
86
46
|
end
|
data/louis.gemspec
CHANGED
@@ -15,7 +15,10 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.homepage = ""
|
16
16
|
spec.license = "AGPLv3"
|
17
17
|
|
18
|
-
|
18
|
+
file_list = `git ls-files -z`.split("\x0")
|
19
|
+
file_list.delete('data/mac_oui_manuf.txt')
|
20
|
+
|
21
|
+
spec.files = file_list
|
19
22
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
23
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
24
|
spec.require_paths = ["lib"]
|
data/spec/louis_spec.rb
CHANGED
@@ -5,11 +5,15 @@ RSpec.describe Louis do
|
|
5
5
|
expect(Louis::VERSION).not_to be nil
|
6
6
|
end
|
7
7
|
|
8
|
-
it "it should have it's data file" do
|
8
|
+
it "it should have it's source data file" do
|
9
9
|
expect(File.readable?(Louis::ORIGINAL_OUI_FILE)).to be(true)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
it "it should have it's parsed data file" do
|
13
|
+
expect(File.readable?(Louis::PARSED_DATA_FILE)).to be(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'Original OUI format regex' do
|
13
17
|
subject { Louis::OUI_FORMAT_REGEX }
|
14
18
|
|
15
19
|
it "should ignore comment lines" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: louis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Stelfox
|
@@ -141,9 +141,10 @@ files:
|
|
141
141
|
- LICENSE.txt
|
142
142
|
- README.md
|
143
143
|
- Rakefile
|
144
|
-
- data/
|
144
|
+
- data/processed_data.json
|
145
145
|
- lib/louis.rb
|
146
146
|
- lib/louis/const.rb
|
147
|
+
- lib/louis/helpers.rb
|
147
148
|
- lib/louis/version.rb
|
148
149
|
- louis.gemspec
|
149
150
|
- spec/louis_spec.rb
|