oui-offline 1.2.3 → 1.2.5
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +6 -0
- data/README.md +12 -1
- data/bin/oui +29 -21
- data/data/oui.txt +128306 -0
- data/db/oui.sqlite3 +0 -0
- data/lib/oui.rb +177 -59
- data/oui-offline.gemspec +11 -5
- metadata +18 -5
- metadata.gz.sig +0 -0
- data/ext/mkrf_conf.rb +0 -22
data/db/oui.sqlite3
CHANGED
Binary file
|
data/lib/oui.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
autoload :FileUtils, 'fileutils'
|
2
|
+
autoload :JSON, 'json'
|
3
|
+
require 'monitor'
|
3
4
|
require 'open-uri'
|
5
|
+
|
4
6
|
require 'sequel'
|
5
7
|
|
6
8
|
# Organizationally Unique Identifier
|
@@ -9,29 +11,93 @@ module OUI
|
|
9
11
|
|
10
12
|
private
|
11
13
|
|
14
|
+
DEBUGGING_DEFAULT = false
|
12
15
|
TABLE = :ouis
|
13
16
|
# import data/oui.txt instead of fetching remotely
|
14
|
-
|
17
|
+
IMPORT_LOCAL_TXT_FILE_DEFAULT = false
|
15
18
|
# use in-memory instead of persistent file
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
OUI_URL = 'http://standards.ieee.org/develop/regauth/oui/oui.txt'
|
23
|
-
end
|
19
|
+
IN_MEMORY_ONLY_DEFAULT = false
|
20
|
+
ROOT = File.expand_path(File.join('..', '..'), __FILE__)
|
21
|
+
LOCAL_DB_DEFAULT = File.join(ROOT, 'db', 'oui.sqlite3')
|
22
|
+
LOCAL_TXT_FILE = File.join(ROOT, 'data', 'oui.txt')
|
23
|
+
REMOTE_TXT_URI = 'http://standards.ieee.org/develop/regauth/oui/oui.txt'
|
24
|
+
LOCAL_MANUAL_FILE = File.join(ROOT, 'data', 'oui-manual.json')
|
24
25
|
FIRST_LINE_INDEX = 7
|
25
26
|
EXPECTED_DUPLICATES = [0x0001C8, 0x080030]
|
26
27
|
LINE_LENGTH = 22
|
28
|
+
HEX_BEGINNING_REGEX = /\A[[:space:]]{2}[[:xdigit:]]{2}-/
|
29
|
+
ERASE_LINE = "\b" * LINE_LENGTH
|
30
|
+
BLANK_LINE = ' ' * LINE_LENGTH
|
31
|
+
|
32
|
+
MISSING_COUNTRIES = [
|
33
|
+
0x000052,
|
34
|
+
0x002142,
|
35
|
+
0x684CA8
|
36
|
+
]
|
37
|
+
|
38
|
+
COUNTRY_OVERRIDES = {
|
39
|
+
0x000052 => 'UNITED STATES',
|
40
|
+
0x002142 => 'SERBIA',
|
41
|
+
0x684CA8 => 'CHINA'
|
42
|
+
}
|
27
43
|
|
28
44
|
public
|
29
45
|
|
46
|
+
@@local_db = LOCAL_DB_DEFAULT
|
47
|
+
|
48
|
+
def local_db
|
49
|
+
@@local_db
|
50
|
+
end
|
51
|
+
|
52
|
+
def local_db=(v)
|
53
|
+
@@local_db = v || LOCAL_DB_DEFAULT
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
@@debugging = DEBUGGING_DEFAULT
|
58
|
+
|
59
|
+
def debugging
|
60
|
+
@@debugging
|
61
|
+
end
|
62
|
+
|
63
|
+
def debugging=(v)
|
64
|
+
@@debugging = (v.nil?) ? DEBUGGING_DEFAULT : v
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
@@import_local_txt_file = IMPORT_LOCAL_TXT_FILE_DEFAULT
|
69
|
+
|
70
|
+
def import_local_txt_file
|
71
|
+
@@import_local_txt_file
|
72
|
+
end
|
73
|
+
|
74
|
+
def import_local_txt_file=(v)
|
75
|
+
@@import_local_txt_file = (v.nil?) ? IMPORT_LOCAL_TXT_FILE_DEFAULT : v
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
@@in_memory_only = IN_MEMORY_ONLY_DEFAULT
|
80
|
+
|
81
|
+
def in_memory_only
|
82
|
+
@@in_memory_only
|
83
|
+
end
|
84
|
+
|
85
|
+
def in_memory_only=(v)
|
86
|
+
if v != @@in_memory_only
|
87
|
+
@@in_memory_only = (v.nil?) ? IN_MEMORY_ONLY_DEFAULT : v
|
88
|
+
close_db
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
30
92
|
# @param oui [String,Integer] hex or numeric OUI to find
|
31
93
|
# @return [Hash,nil]
|
32
94
|
def find(oui)
|
33
|
-
|
34
|
-
|
95
|
+
semaphore.synchronize do
|
96
|
+
update_db unless table? && table.count > 0
|
97
|
+
r = table.where(id: self.to_i(oui)).first
|
98
|
+
r.delete :create_table if r # not sure why this is here, but nuking it
|
99
|
+
r
|
100
|
+
end
|
35
101
|
end
|
36
102
|
|
37
103
|
# Converts an OUI string to an integer of equal value
|
@@ -41,8 +107,9 @@ module OUI
|
|
41
107
|
def to_i(oui)
|
42
108
|
return oui if oui.is_a? Integer
|
43
109
|
oui = oui.strip.gsub(/[:\- .]/, '')
|
44
|
-
|
45
|
-
|
110
|
+
if oui =~ /([[:xdigit:]]{6})/
|
111
|
+
$1.to_i(16)
|
112
|
+
end
|
46
113
|
end
|
47
114
|
|
48
115
|
# Convert an id to OUI
|
@@ -56,62 +123,98 @@ module OUI
|
|
56
123
|
format('%06x', id).scan(/../).join(sep)
|
57
124
|
end
|
58
125
|
|
126
|
+
@@db = nil
|
59
127
|
# Release backend resources
|
60
128
|
def close_db
|
61
|
-
|
129
|
+
semaphore.synchronize do
|
130
|
+
debug 'Closing database'
|
131
|
+
if @@db
|
132
|
+
@@db.disconnect
|
133
|
+
@@db = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def clear_table
|
139
|
+
debug 'clear_table'
|
140
|
+
table.delete_sql
|
62
141
|
end
|
63
142
|
|
64
143
|
# Update database from fetched URL
|
144
|
+
# @param [Boolean] whether to connect to the network or not
|
65
145
|
# @return [Integer] number of unique records loaded
|
66
|
-
def update_db
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
146
|
+
def update_db(local = nil, db_file = nil)
|
147
|
+
semaphore.synchronize do
|
148
|
+
debug "update_db(local = #{local}, db_file = #{db_file})"
|
149
|
+
close_db
|
150
|
+
old_import_local_txt_file = self.import_local_txt_file
|
151
|
+
self.import_local_txt_file = local
|
152
|
+
old_local_db = self.local_db
|
153
|
+
self.local_db = db_file
|
154
|
+
## Sequel
|
155
|
+
debug '--- close db ---'
|
156
|
+
debug '--- close db ---'
|
157
|
+
debug '--- drop table ---'
|
158
|
+
drop_table
|
159
|
+
# debug '--- drop table ---'
|
160
|
+
# debug '--- create table ---'
|
161
|
+
create_table
|
162
|
+
# debug '--- create table ---'
|
163
|
+
db.transaction do
|
164
|
+
debug '--- clear table ---'
|
165
|
+
clear_table
|
166
|
+
debug '--- clear table ---'
|
167
|
+
debug '--- install manual ---'
|
168
|
+
install_manual
|
169
|
+
debug '--- install manual ---'
|
170
|
+
debug '--- install updates ---'
|
171
|
+
install_updates
|
172
|
+
debug '--- install updates ---'
|
173
|
+
end
|
174
|
+
debug '--- close db ---'
|
175
|
+
close_db
|
176
|
+
debug '--- close db ---'
|
177
|
+
|
178
|
+
self.local_db = old_local_db
|
179
|
+
self.import_local_txt_file = old_import_local_txt_file
|
180
|
+
## AR
|
181
|
+
# self.transaction do
|
182
|
+
# self.delete_all
|
183
|
+
# self.install_manual
|
184
|
+
# self.install_updates
|
185
|
+
# end
|
186
|
+
debug "update_db(local = #{local}, db_file = #{db_file}) finish"
|
75
187
|
end
|
76
|
-
## AR
|
77
|
-
# self.transaction do
|
78
|
-
# self.delete_all
|
79
|
-
# self.install_manual
|
80
|
-
# self.install_updates
|
81
|
-
# end
|
82
188
|
end
|
83
|
-
|
84
189
|
|
85
190
|
private
|
86
191
|
|
87
|
-
HEX_BEGINNING_REGEX = /\A[[:space:]]{2}[[:xdigit:]]{2}-/
|
88
|
-
ERASE_LINE = "\b" * LINE_LENGTH
|
89
|
-
BLANK_LINE = ' ' * LINE_LENGTH
|
90
|
-
|
91
192
|
def connect_file_db(f)
|
92
193
|
FileUtils.mkdir_p(File.dirname(f))
|
93
194
|
if RUBY_PLATFORM == 'java'
|
94
|
-
|
195
|
+
u = 'jdbc:sqlite:'+f
|
95
196
|
else
|
96
|
-
|
197
|
+
u = 'sqlite:'+f
|
97
198
|
end
|
199
|
+
debug "Connecting to db file #{u}"
|
200
|
+
Sequel.connect(u)
|
98
201
|
end
|
99
202
|
|
100
203
|
def connect_db
|
101
|
-
if
|
204
|
+
if in_memory_only
|
205
|
+
debug 'Connecting to in-memory database'
|
102
206
|
if RUBY_PLATFORM == 'java'
|
103
207
|
Sequel.connect('jdbc:sqlite::memory:')
|
104
208
|
else
|
105
209
|
Sequel.sqlite # in-memory sqlite database
|
106
210
|
end
|
107
211
|
else
|
108
|
-
|
109
|
-
connect_file_db LOCAL_DB
|
212
|
+
connect_file_db local_db
|
110
213
|
end
|
111
214
|
end
|
112
215
|
|
113
216
|
def db
|
114
|
-
|
217
|
+
@@db ||= connect_db
|
115
218
|
end
|
116
219
|
|
117
220
|
def table?
|
@@ -123,10 +226,12 @@ module OUI
|
|
123
226
|
end
|
124
227
|
|
125
228
|
def drop_table
|
229
|
+
debug 'drop_table'
|
126
230
|
db.drop_table(TABLE) if table?
|
127
231
|
end
|
128
232
|
|
129
233
|
def create_table
|
234
|
+
# debug 'create_table'
|
130
235
|
db.create_table TABLE do
|
131
236
|
primary_key :id
|
132
237
|
String :organization, null: false
|
@@ -164,18 +269,6 @@ module OUI
|
|
164
269
|
g[1].split(' ')[0].to_i(16)
|
165
270
|
end
|
166
271
|
|
167
|
-
MISSING_COUNTRIES = [
|
168
|
-
0x000052,
|
169
|
-
0x002142,
|
170
|
-
0x684CA8
|
171
|
-
]
|
172
|
-
|
173
|
-
COUNTRY_OVERRIDES = {
|
174
|
-
0x000052 => 'UNITED STATES',
|
175
|
-
0x002142 => 'SERBIA',
|
176
|
-
0x684CA8 => 'CHINA'
|
177
|
-
}
|
178
|
-
|
179
272
|
def parse_address1(g)
|
180
273
|
g[2] if g.length >= 4
|
181
274
|
end
|
@@ -208,23 +301,26 @@ module OUI
|
|
208
301
|
end
|
209
302
|
|
210
303
|
def fetch
|
211
|
-
|
212
|
-
|
304
|
+
uri = oui_uri
|
305
|
+
$stderr.puts "Fetching #{uri}"
|
306
|
+
open(uri).read
|
213
307
|
end
|
214
308
|
|
215
309
|
def install_manual
|
310
|
+
debug 'install_manual'
|
216
311
|
JSON.load(File.read(LOCAL_MANUAL_FILE)).each do |g|
|
217
312
|
# convert keys to symbols
|
218
313
|
g = g.map { |k, v| [k.to_sym, v] }
|
219
314
|
g = Hash[g]
|
220
315
|
# convert OUI octets to integers
|
221
|
-
g[:id] =
|
316
|
+
g[:id] = self.to_i(g[:id])
|
222
317
|
create_unless_present(g)
|
223
318
|
end
|
224
319
|
rescue Errno::ENOENT
|
225
320
|
end
|
226
321
|
|
227
322
|
def install_updates
|
323
|
+
debug 'install_updates'
|
228
324
|
lines = fetch.split("\n").map { |x| x.sub(/\r$/, '') }
|
229
325
|
parse_lines_into_groups(lines).each_with_index do |group, idx|
|
230
326
|
create_from_line_group(group)
|
@@ -240,11 +336,23 @@ module OUI
|
|
240
336
|
|
241
337
|
# Has a particular id been added yet?
|
242
338
|
def added
|
243
|
-
|
339
|
+
@@added ||= {}
|
340
|
+
end
|
341
|
+
|
342
|
+
def debug?
|
343
|
+
$DEBUG || debugging || ENV['DEBUG_OUI']
|
244
344
|
end
|
245
345
|
|
246
346
|
def debug(*args)
|
247
|
-
$stderr.puts(*args) if
|
347
|
+
$stderr.puts(*args) if debug?
|
348
|
+
end
|
349
|
+
|
350
|
+
def debug_print(*args)
|
351
|
+
$stderr.print(*args) if debug?
|
352
|
+
end
|
353
|
+
|
354
|
+
def semaphore
|
355
|
+
@@semaphore ||= Monitor.new
|
248
356
|
end
|
249
357
|
|
250
358
|
def create_unless_present(opts)
|
@@ -259,4 +367,14 @@ module OUI
|
|
259
367
|
added[id] = true
|
260
368
|
end
|
261
369
|
end
|
370
|
+
|
371
|
+
def oui_uri
|
372
|
+
if import_local_txt_file
|
373
|
+
debug 'oui_uri = local'
|
374
|
+
LOCAL_TXT_FILE
|
375
|
+
else
|
376
|
+
debug 'oui_uri = remote'
|
377
|
+
REMOTE_TXT_URI
|
378
|
+
end
|
379
|
+
end
|
262
380
|
end
|
data/oui-offline.gemspec
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
Gem::Specification::new do |s|
|
2
2
|
s.name = 'oui-offline'
|
3
|
-
s.version = '1.2.
|
4
|
-
s.platform = Gem::Platform::RUBY
|
3
|
+
s.version = '1.2.5'
|
5
4
|
s.summary = 'Organizationally Unique Idenitfiers (OUI)'
|
6
5
|
s.description = 'Organizationally Unique Idenitfiers (OUI) offline database'
|
7
6
|
s.license = 'MIT'
|
@@ -12,10 +11,11 @@ Gem::Specification::new do |s|
|
|
12
11
|
'bin/oui',
|
13
12
|
'data/oui-manual.json',
|
14
13
|
'db/oui.sqlite3',
|
15
|
-
'ext/mkrf_conf.rb',
|
16
14
|
'lib/oui.rb',
|
17
15
|
'oui-offline.gemspec',
|
18
|
-
]
|
16
|
+
]
|
17
|
+
s.files << 'data/oui.txt' if File.exist?('data/oui.txt')
|
18
|
+
|
19
19
|
s.required_ruby_version = '>= 1.9.3'
|
20
20
|
|
21
21
|
s.require_path = 'lib'
|
@@ -27,7 +27,13 @@ Gem::Specification::new do |s|
|
|
27
27
|
s.post_install_message = 'Oui!'
|
28
28
|
|
29
29
|
s.add_dependency 'sequel', '~> 4'
|
30
|
-
|
30
|
+
if RUBY_PLATFORM == 'java'
|
31
|
+
s.platform = 'java'
|
32
|
+
s.add_dependency 'jdbc-sqlite3'
|
33
|
+
else
|
34
|
+
s.platform = Gem::Platform::RUBY
|
35
|
+
s.add_dependency 'sqlite3', '~> 1'
|
36
|
+
end
|
31
37
|
s.add_development_dependency 'rake', '~> 10'
|
32
38
|
s.add_development_dependency 'minitest', '~> 5'
|
33
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oui-offline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Barry Allard
|
@@ -41,7 +41,7 @@ cert_chain:
|
|
41
41
|
TE/ChTQStrIVMKgW+FbU3E6AmrM6HcwTi7mwsDM8S36y2NZ5DVaZPCpvkiTDgPSW
|
42
42
|
t/HWh1yhriCUe/y8+De8M87btOs=
|
43
43
|
-----END CERTIFICATE-----
|
44
|
-
date: 2015-01-
|
44
|
+
date: 2015-01-27 00:00:00.000000000 Z
|
45
45
|
dependencies:
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: sequel
|
@@ -57,6 +57,20 @@ dependencies:
|
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: '4'
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: sqlite3
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '1'
|
60
74
|
- !ruby/object:Gem::Dependency
|
61
75
|
name: rake
|
62
76
|
requirement: !ruby/object:Gem::Requirement
|
@@ -89,16 +103,15 @@ description: Organizationally Unique Idenitfiers (OUI) offline database
|
|
89
103
|
email: barry.allard@gmail.com
|
90
104
|
executables:
|
91
105
|
- oui
|
92
|
-
extensions:
|
93
|
-
- ext/mkrf_conf.rb
|
106
|
+
extensions: []
|
94
107
|
extra_rdoc_files: []
|
95
108
|
files:
|
96
109
|
- Gemfile
|
97
110
|
- README.md
|
98
111
|
- bin/oui
|
99
112
|
- data/oui-manual.json
|
113
|
+
- data/oui.txt
|
100
114
|
- db/oui.sqlite3
|
101
|
-
- ext/mkrf_conf.rb
|
102
115
|
- lib/oui.rb
|
103
116
|
- oui-offline.gemspec
|
104
117
|
homepage: https://github.com/steakknife/oui
|
metadata.gz.sig
CHANGED
Binary file
|