iana-data 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ccc684f77c372ae813ac2a6d6618bf93fe23dc58
4
- data.tar.gz: 0f77640e7ff7b7a4a443b61077293c4cae300aa9
3
+ metadata.gz: a732c3eecaaa5d69c11766b2566566cdb6b780ce
4
+ data.tar.gz: ad5edb9e28796712e1f675aa3c7d7b0ce0f5ee54
5
5
  SHA512:
6
- metadata.gz: 2752d111927c4ccebb353e05dd67d06f31cf3f71b759bb50416e1f7d7ede11491388c352e7fb4c1dd4b46f8d739822a3117714bc27d97c02eac11c0de2a7ae39
7
- data.tar.gz: e93ec9eb7e3a7a0d9d7501e5cd235fc64c8947962b4ff5bb5bc433a3a1bbb7ab76369715fe8805c9a2d20956908edd2f95a7efedddc34747d27b4e9e447841ab
6
+ metadata.gz: 087a3b8f4aee08a82c12e9395ab8cc4c09fc0d3728652fd319e2c70903597216768f93b3738a54c31847a5f9653fce623f13cecc6878c8b0a74c2f3cc272ca8b
7
+ data.tar.gz: f1f414f6e5d6a113b4a49b8288257c151134189e8c8b04f0c9918440dfd766c317a890baa32abd691ed8f2a18b8397f67edb5192aa00cf7da4c79b6263090406
data/Gemfile.lock CHANGED
@@ -1,13 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- iana-data (1.1.2)
4
+ iana-data (1.1.3)
5
+ nokogiri (~> 1.6)
5
6
  open-uri-cached (= 0.0.5)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
11
  diff-lcs (1.2.5)
12
+ mini_portile2 (2.0.0)
13
+ nokogiri (1.6.7.2)
14
+ mini_portile2 (~> 2.0.0.rc2)
11
15
  open-uri-cached (0.0.5)
12
16
  rake (10.5.0)
13
17
  rspec (3.4.0)
@@ -33,7 +37,7 @@ DEPENDENCIES
33
37
  iana-data!
34
38
  rake (~> 10.0)
35
39
  rspec (~> 3.0)
36
- yard (~> 0.8, >= 0.8.7)
40
+ yard (~> 0.8)
37
41
 
38
42
  BUNDLED WITH
39
43
  1.11.2
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ## What
2
- IANA Ruby module version 1.1.2
2
+ IANA Ruby module version 1.1.3
3
3
 
4
4
  Look up TCP/IP port numbers, protocols, top-level domains, et al.
5
5
 
@@ -8,25 +8,58 @@ available to your programs.
8
8
 
9
9
  ## Install
10
10
 
11
- gem 'iana', github: 'ringe/iana'
11
+ gem install iana-data
12
+
13
+ In your Gemfile
14
+
15
+ gem 'iana-data'
12
16
 
13
17
  ## Usage
14
18
 
15
19
  ```ruby
16
- require 'iana'
20
+ require 'iana'
21
+
22
+ IANA::TLD.valid?("com")
23
+ => true
24
+ IANA::TLD.valid?(".com")
25
+ => true
26
+ IANA::TLD.valid?("isthisforreal")
27
+ => false
28
+
29
+ prot = IANA::Protocol[25]
30
+ => #<IANA::Protocol:0x00563e8bdd18a8 @protocol=25, @name="LEAF-1", @description="Leaf-1", @references=["Barry_Boehm"]>
31
+ prot.number
32
+ => 25
33
+
34
+ port = IANA::Port[25]
35
+ => [#<IANA::Port:0x00556cba04b600 @port=25, @keyword="smtp", @protocol="tcp", @description="Simple Mail Transfer">, #<IANA::Port:0x00556cba04b1a0 @port=25, @keyword="smtp", @protocol="udp", @description="Simple Mail Transfer">]
36
+ port.map(&:protocol)
37
+ => ["tcp", "udp"]
38
+
39
+ IANA::Port.select port: 25, protocol: "udp"
40
+ => {25=>[#<IANA::Port:0x00556cba1f3d90 @port=25, @keyword="smtp", @protocol="udp", @description="Simple Mail Transfer">]}
41
+
42
+ IANA::Port::DCCP[25]
43
+ => []
44
+ IANA::Port::DCCP[8282]
45
+ => [#<IANA::Port:0x00556cb9bc7840 @port=8282, @keyword="", @protocol="dccp", @description="Reserved">]
46
+
47
+ IANA::Port::UDP[443]
48
+ => [#<IANA::Port:0x00556cba1a43a8 @port=443, @keyword="https", @protocol="udp", @description="http protocol over TLS/SSL">]
49
+
17
50
  ```
18
51
 
52
+ You still need to download some data files manually, while the IANA module is
53
+ rewritten to make use of open-uri everywhere.
54
+
19
55
  The IANA Ruby module loads the data into conveniently searchable data
20
56
  structures. The flat files the IANA Ruby module consume as data are hosted at
21
57
  iana.org. You will need to fetch them so you can process the content locally.
22
58
  I grab these files with with curl (but you can use wget or whatever if you
23
59
  don't use curl):
24
60
 
25
- curl -L -O http://www.iana.org/assignments/port-numbers
26
- curl -L -O http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml
27
61
  curl -L -O http://www.iana.org/assignments/ethernet-numbers
28
62
 
29
- TLD data is downloaded automatically using open-uri, so no need to fetch yourself.
30
63
 
31
64
  ## Examples
32
65
  When you run the example programs, do it like so:
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "iana"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/examples/ports.rb CHANGED
@@ -3,30 +3,11 @@
3
3
  # vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
4
4
 
5
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"
6
+ require 'iana'
26
7
 
27
8
  # lookup port 22
28
9
  port = 22
29
- result = IANA_PORT[port]
10
+ result = IANA::Port[port]
30
11
  puts "#{result.size} matches for port #{port}:"
31
12
  result.each do |p|
32
13
  puts "=> #{p.keyword} #{port}/#{p.protocol} \"#{p.description}\""
@@ -3,34 +3,10 @@
3
3
  # vim: expandtab tabstop=2 softtabstop=2 shiftwidth=2
4
4
 
5
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"
6
+ require 'iana'
26
7
 
27
8
  # 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
9
+ result = IANA::Protocol[22]
10
+ puts "protocol 22 => #{result.name} \"#{result.description}\""
35
11
 
36
12
  exit 0
data/iana.gemspec CHANGED
@@ -29,7 +29,8 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "bundler", "~> 1.11"
30
30
  spec.add_development_dependency "rake", "~> 10.0"
31
31
  spec.add_development_dependency "rspec", "~> 3.0"
32
- spec.add_development_dependency 'yard', '~> 0.8', '>= 0.8.7'
32
+ spec.add_development_dependency 'yard', '~> 0.8'
33
33
 
34
34
  spec.add_dependency "open-uri-cached", "= 0.0.5"
35
+ spec.add_dependency "nokogiri", '~> 1.6'
35
36
  end
data/lib/iana/port.rb CHANGED
@@ -5,74 +5,109 @@
5
5
  # lib/iana/port.rb
6
6
 
7
7
  module IANA
8
- module Port
9
- Port = Struct.new('PORT', :keyword, :protocol, :description)
8
+ class Port
9
+ attr_reader :port, :keyword, :protocol, :description
10
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?
11
+ def initialize(port, keyword, protocol, description)
12
+ @port, @keyword, @protocol, @description = port, keyword, protocol, description
13
+ end
14
+
15
+ def port; @port; end
16
+ def number; @port; end
17
+ def keyword; @keyword; end
18
+ def protocol; @protocol; end
19
+ def description; @description; end
17
20
 
18
- # TODO: better error checking for files with incorrect content
21
+ # Download IANA ports list in XML format, return list
22
+ # http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
23
+ def self.iana_list
24
+ source = open("http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.csv").
25
+ read
26
+
27
+ # concatenate multiline strings, then split on newline
28
+ lines = source.gsub(/(?<!\r)\n/, ' ').split(/\r\n/)
19
29
 
20
30
  ports = {}
21
- updated = nil
22
31
 
23
32
  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
33
+ while (line = lines.shift)
34
+ # skip lines which do not contain the ,proto, pattern
35
+ if line !~ /\d,(tcp|udp|sctp|dccp),/
31
36
  next
32
37
  end
33
38
 
34
- # skip commented lines
35
- next if line =~ /^#/
39
+ proto = line.split(/,(?=(?:[^"]|"[^"]*")*$)/)
40
+ name = proto[0]
41
+ num = proto[1].to_i
42
+ protocol = proto[2]
43
+ desc = proto[3]
36
44
 
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
45
+ ports[num] ||= Array.new
46
+ ports[num] << Port.new(num, name, protocol, desc)
47
+ end
48
+ end
42
49
 
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
50
+ return ports
51
+ end
56
52
 
57
- # remainder of tokens serves as the description
58
- desc = tokens.join(' ')
53
+ # Look up port definition in iana_list by number
54
+ def self.[](num, protocol=nil)
55
+ raise ArgumentError, 'port number must be an Fixnum' if num.class != Fixnum
56
+ raise ArgumentError, 'protocol must be tcp, udp, sctp or dccp' unless [nil, 'tcp', 'udp', 'sctp', 'dccp'].include?(protocol)
59
57
 
60
- p = Port.new(name, proto, desc)
58
+ if protocol.nil?
59
+ iana_list[num]
60
+ else
61
+ iana_list[num].select {|p| p.protocol == protocol }
62
+ end
63
+ end
61
64
 
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
65
+ # Select Ports by properties and values
66
+ def self.select(properties)
67
+ portlist = iana_list.collect do |num, ports|
68
+ list = ports.select do |p|
69
+ properties.collect {|key, val|
70
+ p.send(key) == val
71
+ }.all?
70
72
  end
71
- ensure
72
- f.close if !f.nil?
73
+ list.empty? ? nil : [num, list]
73
74
  end
75
+ Hash[*portlist.compact.flatten(1)]
76
+ end
77
+
78
+ # Methods to query IANA Ports within a namespace, like IANA::Port::TCP
79
+ class PortQuerying
80
+
81
+ # Return the Port's protocol name in lower case
82
+ def self.protocol
83
+ name.sub(/.*::/,'').downcase
84
+ end
85
+
86
+ # List all Ports by this protocol
87
+ def self.list
88
+ IANA::Port.select protocol: protocol
89
+ end
90
+
91
+ # Look up given Port number under this protocol
92
+ def self.[](num)
93
+ IANA::Port[num, protocol]
94
+ end
95
+ end
96
+
97
+ # Look up DCCP port definition in iana_list
98
+ class DCCP < PortQuerying
99
+ end
100
+
101
+ # Look up SCTP port definition in iana_list
102
+ class SCTP < PortQuerying
103
+ end
104
+
105
+ # Look up UDP port definition in iana_list
106
+ class UDP < PortQuerying
107
+ end
74
108
 
75
- return ports, updated
109
+ # Look up TCP port definition in iana_list
110
+ class TCP < PortQuerying
76
111
  end
77
112
  end
78
113
  end
data/lib/iana/protocol.rb CHANGED
@@ -8,22 +8,29 @@
8
8
  require 'nokogiri'
9
9
 
10
10
  module IANA
11
- module Protocol
12
- Protocol = Struct.new('PROTOCOL', :name, :description, :references)
11
+ class Protocol
12
+ attr_reader :protocol, :name, :description, :references
13
13
 
14
- # load IANA protocols list from XML file:
14
+ def initialize(protocol, name, description, xref)
15
+ @protocol, @name, @description, @references = protocol, name, description, xref
16
+ end
17
+
18
+ def protocol; @protocol; end
19
+ def number; @protocol; end
20
+ def name; @name; end
21
+ def description; @description; end
22
+ def references; @references; end
23
+
24
+ # Download IANA protocols list in XML format, return list
15
25
  # 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?
26
+ def self.iana_list
27
+ source = open("http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml").read
20
28
 
21
29
  protocols = {}
22
30
  updated = nil
23
31
 
24
32
  begin
25
- f = File.new(pathname, 'r')
26
- doc = Nokogiri::XML(f)
33
+ doc = Nokogiri::XML(source)
27
34
  updated = doc.css('registry/updated').text
28
35
  doc.css('registry/registry/record').each do |r|
29
36
  # range
@@ -51,19 +58,23 @@ module IANA
51
58
  end
52
59
 
53
60
  if low == high then
54
- protocols[low] = Protocol.new(name, description, xref)
61
+ protocols[low] = Protocol.new(low, name, description, xref)
55
62
  else
56
63
  # create an entry for each range element
57
64
  (high-low+1).times do |i|
58
- protocols[low+i] = Protocol.new(name, description, xref)
65
+ protocols[low+i] = Protocol.new(low+i, name, description, xref)
59
66
  end
60
67
  end
61
68
  end
62
- ensure
63
- f.close if !f.nil?
64
69
  end
65
70
 
66
- return protocols, updated
71
+ return protocols
72
+ end
73
+
74
+ # Look up protocol definition in iana_list
75
+ def self.[](arg)
76
+ raise ArgumentError, 'protocol number must be an Fixnum' if arg.class != Fixnum
77
+ iana_list[arg]
67
78
  end
68
79
  end
69
80
  end
data/lib/iana/tld.rb CHANGED
@@ -16,7 +16,7 @@ module IANA
16
16
 
17
17
  # is specified tld a valid IANA Top Level Domain?
18
18
  def self.valid?(tld)
19
- iana_list.include?(tld.to_s.upcase)
19
+ iana_list.include?(tld.to_s.upcase.sub('.',''))
20
20
  end
21
21
 
22
22
  # is specified domain name a TLD?
data/lib/iana/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Iana
2
- VERSION = "1.1.3"
2
+ VERSION = "1.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iana-data
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Runar Ingebrigtsen
@@ -60,9 +60,6 @@ dependencies:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0.8'
63
- - - ">="
64
- - !ruby/object:Gem::Version
65
- version: 0.8.7
66
63
  type: :development
67
64
  prerelease: false
68
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -70,9 +67,6 @@ dependencies:
70
67
  - - "~>"
71
68
  - !ruby/object:Gem::Version
72
69
  version: '0.8'
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: 0.8.7
76
70
  - !ruby/object:Gem::Dependency
77
71
  name: open-uri-cached
78
72
  requirement: !ruby/object:Gem::Requirement
@@ -87,6 +81,20 @@ dependencies:
87
81
  - - '='
88
82
  - !ruby/object:Gem::Version
89
83
  version: 0.0.5
84
+ - !ruby/object:Gem::Dependency
85
+ name: nokogiri
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.6'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.6'
90
98
  description:
91
99
  email:
92
100
  - runar@rin.no,
@@ -102,6 +110,8 @@ files:
102
110
  - LICENSE
103
111
  - README.md
104
112
  - Rakefile
113
+ - bin/console
114
+ - bin/setup
105
115
  - example-data/lsr.txt
106
116
  - examples/ethertypes.rb
107
117
  - examples/ports.rb