mac_vendor 0.0.0

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.
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ # Ignore Emacs backups everywhere.
21
+ *~
22
+
23
+ # Ignore textmate projects
24
+ *.tmproj
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2013 Uceem Idaho, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,38 @@
1
+ = mac_vendor
2
+
3
+ * {Homepage}[https://github.com/uceem/mac_vendor.git]
4
+ * {Email}[mailto:doug at uceem.com]
5
+
6
+ == Description
7
+
8
+ Given a MAC address, lookup the vendor of the interface.
9
+
10
+ Inspired by the Net-MAC-Vendor perl package.
11
+
12
+ == Examples
13
+
14
+ require 'mac_vendor'
15
+
16
+ v = MacVendor.new
17
+ v.lookup '00-11-22-33-44-55'
18
+
19
+ To preload all data up front:
20
+
21
+ v = MacVendor.new
22
+ v.preload_cache
23
+ v.lookup '00:ff:bb:11:22:33'
24
+
25
+ To use a local copy of the data, as of the gem release date:
26
+
27
+ v = MacVendor.new :use_local => true
28
+ v.lookup 'aabbccddeeff'
29
+
30
+ == Install
31
+
32
+ $ gem install mac_vendor
33
+
34
+ == Copyright
35
+
36
+ Copyright (c) 2013 Uceem Idaho, Inc.
37
+
38
+ See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
data/data/oui.txt.gz ADDED
Binary file
data/lib/mac_vendor.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'net/http'
2
+
3
+ class MacVendor
4
+ OUI_FULL_URL = 'http://standards.ieee.org/develop/regauth/oui/oui.txt'
5
+ OUI_SINGLE_URL = 'http://standards.ieee.org/cgi-bin/ouisearch?' # ex: http://standards.ieee.org/cgi-bin/ouisearch?00-11-22
6
+
7
+ def initialize(opts={})
8
+ @prefix_cache = {}
9
+ @preloaded = false
10
+ @network_hits = 0 if opts[:enable_network_tracking]
11
+ preload_cache_via_local_data if opts[:use_local]
12
+ end
13
+
14
+ def lookup(mac)
15
+ prefix = self.normalize_prefix mac
16
+ return @prefix_cache[prefix] if @preloaded or @prefix_cache.has_key?(prefix)
17
+ @prefix_cache[prefix] = fetch_single(prefix)
18
+ end
19
+
20
+ # Attempts to turn anything MAC-like into the first six digits, e.g.: AABBCC
21
+ def normalize_prefix(mac)
22
+ mac.strip.upcase.gsub(/^0[xX]/,'').gsub(/[^0-9A-F]/,'')[0..5]
23
+ end
24
+
25
+ # Converts a normalized prefix into something with hyphens, e.g.: AA-BB-CC
26
+ def hyphen_prefix(p)
27
+ "#{p[0..1]}-#{p[2..3]}-#{p[4..5]}"
28
+ end
29
+
30
+ def get_url(url)
31
+ @network_hits +=1 unless @network_hits.nil?
32
+ Net::HTTP.get URI(url)
33
+ end
34
+
35
+ def fetch_single(prefix)
36
+ single_txt = get_url OUI_SINGLE_URL + hyphen_prefix(prefix)
37
+
38
+ if single_txt =~ /The public OUI listing contains no match for the query/
39
+ return @prefix_cache[prefix] = nil
40
+ end
41
+
42
+ if single_txt.gsub(/[\r\n]/,"\t") =~ /([0-9A-F]+)\s+\(base 16\)(.*?)pre/
43
+ mac_prefix = normalize_prefix $1
44
+ lines = $2.strip.split("\t")
45
+ company_name = lines[0]
46
+ company_address = lines[1..-2].reject {|x| x == ''}
47
+
48
+ return @prefix_cache[prefix] = {:name => company_name, :address => company_address}
49
+ end
50
+ nil
51
+ end
52
+
53
+ def preload_cache_via_string(oui_txt)
54
+ # First entry is a header
55
+ entries = oui_txt.split("\n\n")
56
+
57
+ entries[1..-1].each do |entry|
58
+ base16_fields = entry.strip.split("\n")[1].split("\t")
59
+ mac_prefix = base16_fields[0][0..5]
60
+ company_name = base16_fields[-1]
61
+ company_address = entry.strip.gsub("\t",'').split("\n")[2..-1]
62
+
63
+ # This actually happens three times in the current dataset!
64
+ unless @prefix_cache[mac_prefix].nil?
65
+ #puts "MAC PREFIX COLLISION: #{mac_prefix}"
66
+ #puts "CURRENT = #{@prefix_cache[mac_prefix].inspect}"
67
+ #puts "NEW = #{{:name => company_name, :address => company_address}.inspect}"
68
+ #raise "MAC prefix key collision: #{mac_prefix}"
69
+ next
70
+ end
71
+
72
+ @prefix_cache[mac_prefix] = {:name => company_name, :address => company_address}
73
+ end
74
+ @preloaded = true
75
+ end
76
+
77
+ def preload_cache_via_local_data
78
+ local_path = File.expand_path(File.dirname(__FILE__) + "/../data/oui.txt.gz")
79
+ preload_cache_via_string Zlib::GzipReader.open(local_path).read
80
+ end
81
+
82
+ def preload_cache
83
+ preload_cache_via_string get_url(OUI_FULL_URL)
84
+ end
85
+
86
+ def network_hits
87
+ @network_hits
88
+ end
89
+ end
90
+
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mac_vendor'
3
+ s.version = '0.0.0'
4
+ s.date = '2013-01-09'
5
+ s.license = "MIT"
6
+ s.summary = "MAC address vendor lookup"
7
+ s.description = "Given a MAC address, lookup the vendor of the interface."
8
+ s.authors = ["Doug Wiegley"]
9
+ s.email = 'doug@uceem.com'
10
+
11
+ s.files = `git ls-files`.split($/)
12
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
13
+ s.require_paths = ['lib']
14
+
15
+ s.homepage = 'https://github.com/uceem/mac_vendor.git'
16
+ end
@@ -0,0 +1,57 @@
1
+ require 'test/unit'
2
+ require 'mac_vendor'
3
+
4
+ class MacVendorTest < Test::Unit::TestCase
5
+ def setup
6
+ @x = { :name=> "CIMSYS Inc",
7
+ :address=> ["#301,Sinsung-clean BLDG,140, Nongseo-Ri,Kiheung-Eup",
8
+ "Yongin-City Kyunggi-Do 449-711",
9
+ "KOREA, REPUBLIC OF"] }
10
+ @v = MacVendor.new :enable_network_tracking => true
11
+ end
12
+
13
+ def test_normalize_prefix
14
+ [ 'aa-11-bb', 'aa:11:bb:22:cc:33', 'AA11BBCCDD22', 'aa-11-bb-00-00-00' ].each do |s|
15
+ assert_equal @v.normalize_prefix(s), 'AA11BB'
16
+ end
17
+ assert_equal @v.normalize_prefix('junk'), ''
18
+ assert_equal @v.network_hits, 0
19
+ end
20
+
21
+ def test_hyphen_prefix
22
+ assert_equal @v.hyphen_prefix('AA11BB'), 'AA-11-BB'
23
+ assert_equal @v.hyphen_prefix('junk'), 'ju-nk-'
24
+ assert_equal @v.network_hits, 0
25
+ end
26
+
27
+ def test_fetch_single
28
+ assert_equal @v.lookup('00:11:22:33:44:55'), @x
29
+ assert_equal @v.lookup('00-11-22-33-44-55'), @x
30
+ assert_equal @v.network_hits, 1
31
+ end
32
+
33
+ def test_fetch_single_not_found
34
+ assert_equal @v.lookup('FF:FF:FF:33:44:55'), nil
35
+ assert_equal @v.lookup('FF-FF-FF-33-44-55'), nil
36
+ assert_equal @v.network_hits, 1
37
+ end
38
+
39
+ def test_preloaded_local
40
+ mv = MacVendor.new :enable_network_tracking => true, :use_local => true
41
+ assert_equal mv.network_hits, 0
42
+ assert_equal mv.lookup('00-11-22-33-44-55'), @x
43
+ assert_equal mv.network_hits, 0
44
+ assert_equal mv.lookup('FF-FF-FF-33-44-55'), nil
45
+ assert_equal mv.network_hits, 0
46
+ end
47
+
48
+ def test_preloaded
49
+ @v.preload_cache
50
+ assert_equal @v.network_hits, 1
51
+ assert_equal @v.lookup('00-11-22-33-44-55'), @x
52
+ assert_equal @v.network_hits, 1
53
+ assert_equal @v.lookup('FF-FF-FF-33-44-55'), nil
54
+ assert_equal @v.network_hits, 1
55
+ end
56
+ end
57
+
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mac_vendor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Doug Wiegley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Given a MAC address, lookup the vendor of the interface.
15
+ email: doug@uceem.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - LICENSE.txt
22
+ - README.rdoc
23
+ - Rakefile
24
+ - data/oui.txt.gz
25
+ - lib/mac_vendor.rb
26
+ - mac_vendor.gemspec
27
+ - test/test_mac_vendor.rb
28
+ homepage: https://github.com/uceem/mac_vendor.git
29
+ licenses:
30
+ - MIT
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.17
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: MAC address vendor lookup
53
+ test_files:
54
+ - test/test_mac_vendor.rb