iana-data 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +39 -0
- data/LICENSE +22 -0
- data/README.md +42 -0
- data/Rakefile +56 -0
- data/example-data/lsr.txt +5538 -0
- data/examples/ethertypes.rb +51 -0
- data/examples/ports.rb +35 -0
- data/examples/protocols.rb +36 -0
- data/examples/tlds.rb +20 -0
- data/iana.gemspec +35 -0
- data/iana.tmproj +49 -0
- data/lib/iana/ethertype.rb +99 -0
- data/lib/iana/lsr.rb +145 -0
- data/lib/iana/port.rb +80 -0
- data/lib/iana/protocol.rb +71 -0
- data/lib/iana/tld.rb +29 -0
- data/lib/iana/version.rb +3 -0
- data/lib/iana.rb +24 -0
- metadata +145 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# examples/ethertypes.rb
|
6
|
+
|
7
|
+
require 'pathname'
|
8
|
+
dir = Pathname.new(File.expand_path(__FILE__)).realpath
|
9
|
+
require File.join(File.dirname(dir.to_s), '../lib/iana')
|
10
|
+
|
11
|
+
SCRIPT = File.basename(__FILE__)
|
12
|
+
|
13
|
+
def known_ethertype?(ethertype)
|
14
|
+
|
15
|
+
IANA_ETHERTYPES.include?(ethertype)
|
16
|
+
end
|
17
|
+
|
18
|
+
if ARGV.length == 1
|
19
|
+
begin
|
20
|
+
IANA_ETHERTYPES, IANA_ETHERTYPES_UPDATED = IANA::EtherType::load(ARGV[0])
|
21
|
+
rescue
|
22
|
+
puts "#{SCRIPT}: #{$!}"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
else
|
26
|
+
puts "Usage: #{SCRIPT} <ethernet-numbers>"
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "updated #{IANA_ETHERTYPES_UPDATED} => #{IANA_ETHERTYPES.size} entries"
|
31
|
+
puts
|
32
|
+
IANA_ETHERTYPES.each do |t|
|
33
|
+
print "#{t.begin}"
|
34
|
+
print "-#{t.end}" if t.end != t.begin
|
35
|
+
puts " => #{t.description}"
|
36
|
+
end
|
37
|
+
puts
|
38
|
+
|
39
|
+
# known in :begin => true
|
40
|
+
puts "86dd is known? => #{IANA::EtherType.known?("86dd")}"
|
41
|
+
|
42
|
+
# known in :end => true
|
43
|
+
puts "8a97 is known? => #{IANA::EtherType.known?("8a97")}"
|
44
|
+
|
45
|
+
# known between :begin and :end => true
|
46
|
+
puts "8709 is known? => #{IANA::EtherType.known?("8709")}"
|
47
|
+
|
48
|
+
# unknown => false
|
49
|
+
puts "fefe is known? => #{IANA::EtherType.known?("fefe")}"
|
50
|
+
|
51
|
+
exit 0
|
data/examples/ports.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# examples/ports.rb
|
6
|
+
|
7
|
+
require 'pathname'
|
8
|
+
dir = Pathname.new(File.expand_path(__FILE__)).realpath
|
9
|
+
require File.join(File.dirname(dir.to_s), '../lib/iana')
|
10
|
+
|
11
|
+
SCRIPT = File.basename(__FILE__)
|
12
|
+
|
13
|
+
if ARGV.length == 1
|
14
|
+
begin
|
15
|
+
IANA_PORT, IANA_PORT_UPDATED = IANA::Port::load(ARGV[0])
|
16
|
+
rescue
|
17
|
+
puts "#{SCRIPT}: #{$!}"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
else
|
21
|
+
puts "Usage: #{SCRIPT} <port-numbers>"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "#{IANA_PORT_UPDATED} => #{IANA_PORT.size} entries"
|
26
|
+
|
27
|
+
# lookup port 22
|
28
|
+
port = 22
|
29
|
+
result = IANA_PORT[port]
|
30
|
+
puts "#{result.size} matches for port #{port}:"
|
31
|
+
result.each do |p|
|
32
|
+
puts "=> #{p.keyword} #{port}/#{p.protocol} \"#{p.description}\""
|
33
|
+
end
|
34
|
+
|
35
|
+
exit 0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# examples/protocols.rb
|
6
|
+
|
7
|
+
require 'pathname'
|
8
|
+
dir = Pathname.new(File.expand_path(__FILE__)).realpath
|
9
|
+
require File.join(File.dirname(dir.to_s), '../lib/iana')
|
10
|
+
|
11
|
+
SCRIPT = File.basename(__FILE__)
|
12
|
+
|
13
|
+
if ARGV.length == 1
|
14
|
+
begin
|
15
|
+
IANA_PROTO, IANA_PROTO_UPDATED = IANA::Protocol::load(ARGV[0])
|
16
|
+
rescue
|
17
|
+
puts "#{SCRIPT}: #{$!}"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
else
|
21
|
+
puts "Usage: #{SCRIPT} <protocol-numbers>"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "#{IANA_PROTO_UPDATED} => #{IANA_PROTO.size} entries"
|
26
|
+
|
27
|
+
# lookup protocol 22
|
28
|
+
result = IANA_PROTO[22]
|
29
|
+
print "protocol 22 => #{result.name} \"#{result.description}\""
|
30
|
+
if !result.references.nil? && !result.references.empty? then
|
31
|
+
puts " #{result.references}"
|
32
|
+
else
|
33
|
+
puts
|
34
|
+
end
|
35
|
+
|
36
|
+
exit 0
|
data/examples/tlds.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# examples/tlds.rb
|
6
|
+
require 'iana'
|
7
|
+
|
8
|
+
# is com a TLD?
|
9
|
+
puts "com is a TLD? => #{IANA::TLD.tld?('com')}"
|
10
|
+
|
11
|
+
# how about to?
|
12
|
+
puts "to is a TLD? => #{IANA::TLD.tld?('to')}"
|
13
|
+
|
14
|
+
# grizzlebat is probably not a TLD
|
15
|
+
puts "grizzlebat is a TLD? => #{IANA::TLD.tld?('grizzlebat')}"
|
16
|
+
|
17
|
+
# how about yn?
|
18
|
+
puts "yn is a TLD? => #{IANA::TLD.tld?('yn')}"
|
19
|
+
|
20
|
+
exit 0
|
data/iana.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'iana/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "iana-data"
|
8
|
+
spec.version = Iana::VERSION
|
9
|
+
spec.authors = ["Runar Ingebrigtsen", "Ramsey Dow"]
|
10
|
+
spec.email = %w{runar@rin.no, yesmar@gmail.com}
|
11
|
+
|
12
|
+
spec.summary = %q{Look up official IANA data, replacement for iana gem}
|
13
|
+
spec.homepage = "http://github.com/ringe/iana"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
17
|
+
# delete this section to allow pushing this gem to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
32
|
+
spec.add_development_dependency 'yard', '~> 0.8', '>= 0.8.7'
|
33
|
+
|
34
|
+
spec.add_dependency "open-uri-cached", "= 0.0.5"
|
35
|
+
end
|
data/iana.tmproj
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>documents</key>
|
6
|
+
<array>
|
7
|
+
<dict>
|
8
|
+
<key>filename</key>
|
9
|
+
<string>README</string>
|
10
|
+
</dict>
|
11
|
+
<dict>
|
12
|
+
<key>filename</key>
|
13
|
+
<string>LICENSE</string>
|
14
|
+
</dict>
|
15
|
+
<dict>
|
16
|
+
<key>filename</key>
|
17
|
+
<string>Rakefile</string>
|
18
|
+
</dict>
|
19
|
+
<dict>
|
20
|
+
<key>expanded</key>
|
21
|
+
<true/>
|
22
|
+
<key>name</key>
|
23
|
+
<string>lib</string>
|
24
|
+
<key>regexFolderFilter</key>
|
25
|
+
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
|
26
|
+
<key>sourceDirectory</key>
|
27
|
+
<string>lib</string>
|
28
|
+
</dict>
|
29
|
+
<dict>
|
30
|
+
<key>expanded</key>
|
31
|
+
<true/>
|
32
|
+
<key>name</key>
|
33
|
+
<string>examples</string>
|
34
|
+
<key>regexFolderFilter</key>
|
35
|
+
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
|
36
|
+
<key>sourceDirectory</key>
|
37
|
+
<string>examples</string>
|
38
|
+
</dict>
|
39
|
+
</array>
|
40
|
+
<key>fileHierarchyDrawerWidth</key>
|
41
|
+
<integer>200</integer>
|
42
|
+
<key>metaData</key>
|
43
|
+
<dict/>
|
44
|
+
<key>showFileHierarchyDrawer</key>
|
45
|
+
<true/>
|
46
|
+
<key>windowFrame</key>
|
47
|
+
<string>{{638, 167}, {728, 637}}</string>
|
48
|
+
</dict>
|
49
|
+
</plist>
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# lib/iana/ethertype.rb
|
6
|
+
|
7
|
+
module IANA
|
8
|
+
module EtherType
|
9
|
+
EtherType = Struct.new('ETHERTYPE', :begin, :end, :description)
|
10
|
+
|
11
|
+
# I hate doing it this way, but the inconsistency of IANA data files...
|
12
|
+
LAST_ENTRY = '^ 65535 FFFF - - Reserved \[RFC1701\]$'
|
13
|
+
|
14
|
+
# load IANA Ether types list from flat file:
|
15
|
+
# http://www.iana.org/assignments/ethernet-numbers
|
16
|
+
def self.load(pathname)
|
17
|
+
raise ArgumentError, 'nil pathname' if pathname.nil?
|
18
|
+
raise ArgumentError, 'invalid pathname class' if pathname.class != String
|
19
|
+
raise ArgumentError, 'empty pathname' if pathname.empty?
|
20
|
+
|
21
|
+
# TODO: better error checking for files with incorrect content
|
22
|
+
|
23
|
+
ethertypes = []
|
24
|
+
updated = nil
|
25
|
+
|
26
|
+
begin
|
27
|
+
f = File.new(pathname, 'r')
|
28
|
+
while (line = f.gets)
|
29
|
+
line.chomp!
|
30
|
+
|
31
|
+
# extract update stamp
|
32
|
+
if line =~ /^\(last updated (\d{4}-\d{2}-\d{2})\)\s*$/
|
33
|
+
updated = $1
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
# skip lines that don't have [XXX] or (XXX) at the end
|
38
|
+
next if line !~ /\[\w*\]$/ && line !~ /\([\w\s]*\)$/
|
39
|
+
|
40
|
+
# now skip all lines that don't begin with a space
|
41
|
+
next if line !~ /^[\t\ ]*/
|
42
|
+
|
43
|
+
# skip over decimal Ethertype
|
44
|
+
pos = 0
|
45
|
+
if line =~ /^\t\ /
|
46
|
+
pos = 2
|
47
|
+
else
|
48
|
+
pos = 9
|
49
|
+
end
|
50
|
+
|
51
|
+
# clean up ridiculous IANA formatting
|
52
|
+
line.gsub!(/^\t/, '8') # TODO: investigate this weirdness
|
53
|
+
line.gsub!(/\t -/, ' -')
|
54
|
+
line.gsub!(/\t\t\t /, ' ')
|
55
|
+
line.gsub!(/\t/, ' ')
|
56
|
+
|
57
|
+
tmp = line[pos..-1]
|
58
|
+
|
59
|
+
ethertype = tmp[0..9].strip!
|
60
|
+
low, high = ethertype.split('-')
|
61
|
+
high = low if high.nil?
|
62
|
+
|
63
|
+
description, *junk = tmp[25..-1].split('[')
|
64
|
+
description.strip!
|
65
|
+
|
66
|
+
et = EtherType.new(low, high, description)
|
67
|
+
ethertypes << et
|
68
|
+
|
69
|
+
# short-circuit as soon as we've hit the end of the list
|
70
|
+
break if line =~ /#{LAST_ENTRY}/
|
71
|
+
end
|
72
|
+
ensure
|
73
|
+
f.close if !f.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
return ethertypes, updated
|
77
|
+
end
|
78
|
+
|
79
|
+
# is specified Ether type known
|
80
|
+
def self.known?(ethertype)
|
81
|
+
raise ArgumentError, 'nil ethertype' if ethertype.nil?
|
82
|
+
raise ArgumentError, 'invalid ethertype class' if \
|
83
|
+
ethertype.class != String
|
84
|
+
raise ArgumentError, 'empty ethertype' if ethertype.empty?
|
85
|
+
|
86
|
+
IANA_ETHERTYPES.each do |t|
|
87
|
+
return true if ethertype.upcase == t.begin
|
88
|
+
if t.end != t.begin
|
89
|
+
return true if ethertype.upcase >= t.begin && \
|
90
|
+
ethertype.upcase <= t.end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|
data/lib/iana/lsr.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# NOTE
|
4
|
+
# RFC 4646 described below has been obseleted by RFC5646. Tests still run OK
|
5
|
+
# but I have no idea (yet) what this new RFC has changed in terms of the LSR
|
6
|
+
# file format or langugae tags generally.
|
7
|
+
# See http://tools.ietf.org/html/rfc5646 (particularly section 8).
|
8
|
+
# 2011-04-18
|
9
|
+
module IANA
|
10
|
+
# Get the Language Subtag Registry data from the IANA site or a text file
|
11
|
+
# and load it into an array of hashes for further processing.
|
12
|
+
#
|
13
|
+
# IANA's Language Subtag Registry incorporates multiple standards for the
|
14
|
+
# definition of language- and locale-defining strings, including:
|
15
|
+
# ISO 3166: English country names and code elements
|
16
|
+
# ( http://www.iso.org/iso/english_country_names_and_code_elements )
|
17
|
+
# ISO 639.2: Codes for the Representation of Names of Languages
|
18
|
+
# ( http://www.loc.gov/standards/iso639-2/php/code_list.php )
|
19
|
+
# The registry's format is specified in RFC 4646
|
20
|
+
# ( http://www.ietf.org/rfc/rfc4646.txt )
|
21
|
+
class LanguageSubtagRegistry
|
22
|
+
# Entries always have these keys: Type, [Tag or Subtag], Description, Added
|
23
|
+
# All keys used in the IANA format:
|
24
|
+
Keys = [
|
25
|
+
"Type",
|
26
|
+
"Tag",
|
27
|
+
"Subtag",
|
28
|
+
"Description",
|
29
|
+
"Added",
|
30
|
+
"Preferred-Value",
|
31
|
+
"Deprecated",
|
32
|
+
"Suppress-Script",
|
33
|
+
"Prefix",
|
34
|
+
"Comments" ]
|
35
|
+
IANAHost = 'www.iana.org'
|
36
|
+
IANAPath = '/assignments/language-subtag-registry'
|
37
|
+
IANAFile = File.dirname(__FILE__) + "/../../example-data/lsr.txt"
|
38
|
+
@@tags = []
|
39
|
+
@@file_date = ""
|
40
|
+
|
41
|
+
def self.tags
|
42
|
+
@@tags
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.file_date
|
46
|
+
@@file_date
|
47
|
+
end
|
48
|
+
|
49
|
+
# Load data directly from IANA site
|
50
|
+
def self.get(path=IANAPath, host=IANAHost)
|
51
|
+
require 'net/http'
|
52
|
+
site = Net::HTTP.new host
|
53
|
+
response = site.request_get path
|
54
|
+
self.load(response.body)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Load data from a text file
|
58
|
+
def self.open(filename=IANAFile)
|
59
|
+
file = File.open(filename, 'r')
|
60
|
+
self.load(file.read)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Load data from text string
|
64
|
+
def self.load(text)
|
65
|
+
@@tags = []
|
66
|
+
@@file_date = ""
|
67
|
+
item = {}
|
68
|
+
prev = []
|
69
|
+
text.each do |line|
|
70
|
+
line.chomp!
|
71
|
+
case line
|
72
|
+
when /^%%$/
|
73
|
+
(@@tags << item; item = {}) unless item.empty? # separator; append last entry, if present
|
74
|
+
when /^File-Date: .*/
|
75
|
+
@@file_date = line.gsub('File-Date: ','') # File-date entry
|
76
|
+
when /^ [^ ].*/
|
77
|
+
item[prev].kind_of?(Array) ? item[prev].last += " " + line.strip : item[prev] += " " + line.strip # continuation line
|
78
|
+
else # everything else (the actual key: value pairs)
|
79
|
+
key, val = line.split(':', 2) # the main pair (ie, "Subtag: en")
|
80
|
+
if /\.\./.match val # value specifies a range, not simply a string
|
81
|
+
start, finish = val.strip.split('..', 2)
|
82
|
+
val = Range.new(start, finish)
|
83
|
+
else # otherwise it's just a string
|
84
|
+
val.strip!
|
85
|
+
end
|
86
|
+
if item.has_key?(key) # append to array if this key already exists
|
87
|
+
item[key] = [item[key]] unless item[key].kind_of? Array
|
88
|
+
item[key] << val
|
89
|
+
else # otherwise simply assign the item
|
90
|
+
item[key] = val
|
91
|
+
end
|
92
|
+
prev = key # in case of continuation (wrapped text)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
@@tags << item
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
|
99
|
+
# Dump data to:
|
100
|
+
# IANA's flat text format (String)
|
101
|
+
# YAML (String)
|
102
|
+
# A hash of hashes, with the keys being the tags (Hash)
|
103
|
+
def self.dump(format = "iana")
|
104
|
+
begin
|
105
|
+
format = format.strip.downcase
|
106
|
+
rescue
|
107
|
+
raise ArgumentError, "Invalid argument type; expected String"
|
108
|
+
end
|
109
|
+
case format
|
110
|
+
when "iana"
|
111
|
+
new_text = "File-Date: " + @@file_date + $/ + "%%" + $/
|
112
|
+
new_text << @@tags.map do |item|
|
113
|
+
Keys.map do |key|
|
114
|
+
val = item[key]
|
115
|
+
if val
|
116
|
+
if val.kind_of? Array
|
117
|
+
val.map { |i| key + ": " + i.to_s }.join($/)
|
118
|
+
else
|
119
|
+
key + ": " + val.to_s
|
120
|
+
end
|
121
|
+
else
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
end.compact.join($/) + $/
|
125
|
+
end.join('%%' + $/)
|
126
|
+
when "yaml"
|
127
|
+
require 'yaml'
|
128
|
+
YAML::dump([@@file_date, @@tags])
|
129
|
+
when "hash"
|
130
|
+
taghash = {}
|
131
|
+
@@tags.each do |tag|
|
132
|
+
tag = tag.clone
|
133
|
+
val = tag.delete("Tag") || tag.delete("Subtag")
|
134
|
+
taghash[val.to_s] = tag
|
135
|
+
end
|
136
|
+
taghash
|
137
|
+
else
|
138
|
+
raise ArgumentError, "Invalid format option"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|
data/lib/iana/port.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# lib/iana/port.rb
|
6
|
+
|
7
|
+
module IANA
|
8
|
+
module Port
|
9
|
+
Port = Struct.new('PORT', :keyword, :protocol, :description)
|
10
|
+
|
11
|
+
# load IANA ports list from flat file:
|
12
|
+
# http://www.iana.org/assignments/port-numbers
|
13
|
+
def self.load(pathname)
|
14
|
+
raise ArgumentError, 'nil pathname' if pathname.nil?
|
15
|
+
raise ArgumentError, 'invalid pathname class' if pathname.class != String
|
16
|
+
raise ArgumentError, 'empty pathname' if pathname.empty?
|
17
|
+
|
18
|
+
# TODO: better error checking for files with incorrect content
|
19
|
+
|
20
|
+
ports = {}
|
21
|
+
updated = nil
|
22
|
+
|
23
|
+
begin
|
24
|
+
f = File.new(pathname, 'r')
|
25
|
+
while (line = f.gets)
|
26
|
+
line.chomp!
|
27
|
+
|
28
|
+
# extract update stamp
|
29
|
+
if line =~ /^\(last updated (\d{4}-\d{2}-\d{2})\)\s*$/
|
30
|
+
updated = $1
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
# skip commented lines
|
35
|
+
next if line =~ /^#/
|
36
|
+
|
37
|
+
# skip lines which do not contain the /{proto} pattern
|
38
|
+
if line !~ /\/tcp/ && line !~ /\/udp/ && line !~ /\/sctp/ && \
|
39
|
+
line !~ /\/dccp/
|
40
|
+
next
|
41
|
+
end
|
42
|
+
|
43
|
+
line.strip!
|
44
|
+
tokens = line.split(/[\s]+/)
|
45
|
+
|
46
|
+
# if first token is a port/proto pair then the port is unnamed
|
47
|
+
if tokens[0] =~ /\//
|
48
|
+
name = nil
|
49
|
+
num,proto = tokens[0].split(/\//)
|
50
|
+
tokens.delete_at(0)
|
51
|
+
else
|
52
|
+
name = tokens[0]
|
53
|
+
num,proto = tokens[1].split(/\//)
|
54
|
+
2.times { tokens.delete_at(0) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# remainder of tokens serves as the description
|
58
|
+
desc = tokens.join(' ')
|
59
|
+
|
60
|
+
p = Port.new(name, proto, desc)
|
61
|
+
|
62
|
+
if ports[num.to_i].nil?
|
63
|
+
ports[num.to_i] = p
|
64
|
+
else
|
65
|
+
c = []
|
66
|
+
c << ports[num.to_i]
|
67
|
+
c << p
|
68
|
+
ports[num.to_i] = c.flatten
|
69
|
+
end
|
70
|
+
end
|
71
|
+
ensure
|
72
|
+
f.close if !f.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
return ports, updated
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# lib/iana/protocol.rb
|
6
|
+
|
7
|
+
# rubygems
|
8
|
+
require 'nokogiri'
|
9
|
+
|
10
|
+
module IANA
|
11
|
+
module Protocol
|
12
|
+
Protocol = Struct.new('PROTOCOL', :name, :description, :references)
|
13
|
+
|
14
|
+
# load IANA protocols list from XML file:
|
15
|
+
# http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml
|
16
|
+
def self.load(pathname)
|
17
|
+
raise ArgumentError, 'nil pathname' if pathname.nil?
|
18
|
+
raise ArgumentError, 'invalid pathname class' if pathname.class != String
|
19
|
+
raise ArgumentError, 'empty pathname' if pathname.empty?
|
20
|
+
|
21
|
+
protocols = {}
|
22
|
+
updated = nil
|
23
|
+
|
24
|
+
begin
|
25
|
+
f = File.new(pathname, 'r')
|
26
|
+
doc = Nokogiri::XML(f)
|
27
|
+
updated = doc.css('registry/updated').text
|
28
|
+
doc.css('registry/registry/record').each do |r|
|
29
|
+
# range
|
30
|
+
value = r.css('value').text
|
31
|
+
if value =~ /-/ then
|
32
|
+
low,high = value.split('-').map(&:to_i)
|
33
|
+
else
|
34
|
+
low = value.to_i
|
35
|
+
high = low
|
36
|
+
end
|
37
|
+
|
38
|
+
# name
|
39
|
+
name = r.css('name').text
|
40
|
+
name = nil if !name.nil? && name.empty?
|
41
|
+
|
42
|
+
# description
|
43
|
+
description = r.css('description').text
|
44
|
+
description = nil if !description.nil? && description.empty?
|
45
|
+
|
46
|
+
# references
|
47
|
+
xref = []
|
48
|
+
r.css('xref').each do |x|
|
49
|
+
data = x['data']
|
50
|
+
xref << data if !data.nil? && !data.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
if low == high then
|
54
|
+
protocols[low] = Protocol.new(name, description, xref)
|
55
|
+
else
|
56
|
+
# create an entry for each range element
|
57
|
+
(high-low+1).times do |i|
|
58
|
+
protocols[low+i] = Protocol.new(name, description, xref)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
ensure
|
63
|
+
f.close if !f.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
return protocols, updated
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|
data/lib/iana/tld.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# lib/tld.rb
|
6
|
+
|
7
|
+
module IANA
|
8
|
+
module TLD
|
9
|
+
# Download official IANA Top Level Domain list
|
10
|
+
# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
|
11
|
+
def self.iana_list
|
12
|
+
open("http://data.iana.org/TLD/tlds-alpha-by-domain.txt").read.
|
13
|
+
split("\n").
|
14
|
+
reject {|ln| ln =~ /^#/ }
|
15
|
+
end
|
16
|
+
|
17
|
+
# is specified tld a valid IANA Top Level Domain?
|
18
|
+
def self.valid?(tld)
|
19
|
+
iana_list.include?(tld.to_s.upcase)
|
20
|
+
end
|
21
|
+
|
22
|
+
# is specified domain name a TLD?
|
23
|
+
def self.tld?(tld)
|
24
|
+
valid?(tld)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|
data/lib/iana/version.rb
ADDED
data/lib/iana.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
|
4
|
+
|
5
|
+
# lib/iana.rb
|
6
|
+
module IANA
|
7
|
+
end # IANA
|
8
|
+
|
9
|
+
require 'open-uri'
|
10
|
+
require 'open-uri/cached'
|
11
|
+
|
12
|
+
#require 'consumer'
|
13
|
+
require 'iana/ethertype'
|
14
|
+
require 'iana/port'
|
15
|
+
require 'iana/protocol'
|
16
|
+
require 'iana/tld'
|
17
|
+
require 'iana/lsr'
|
18
|
+
|
19
|
+
# TODO implement consumer model
|
20
|
+
# TODO complete documentaion
|
21
|
+
# TODO implement unit tests
|
22
|
+
# TODO lookup needs to be more flexible
|
23
|
+
|
24
|
+
raise RuntimeError, 'This library is for require only' if $0 == __FILE__
|