nicinfo 1.1.1 → 1.2.0.pre.alpha

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9fe43f67516f7e82fea869dcb8167a552789d6d4
4
- data.tar.gz: daf03f198d085f28af10fdb7ea6b6730d602bb66
3
+ metadata.gz: 365e2ef8d017dd58dbad28feae2d9c7e4fc127fb
4
+ data.tar.gz: d786b1c62e861fb92565f7fd51f1153a1e8113bd
5
5
  SHA512:
6
- metadata.gz: 0518bde9d95ae4db5bcf334369aba47d7a289e43ada10dc71e3caebc37abca25e144900e103e227a49101069bcde3f5a380a84bfc52cf01507ef9dce64b582ff
7
- data.tar.gz: c52ebfc1ddc66bfa4fe31434fdef86a3b3d9d9904cfb3424181a194c154a31e2d0c574166a4098d9f7b9fcff386866863fac1ed63324c9aa42f9aff222923506
6
+ metadata.gz: 656a29e4095c55658c3d38c8a530a7d4d6de10b2ea81951ef14fca5bb158445e6639232c8197180dbabaa828cf8fec4be5d1dbe16fa21a1f01783c3614ff3c7c
7
+ data.tar.gz: d3cbc99dfa055432fcd08038feeda30143c29b55e121ff8ec4ed3b6f84c8e0c6a5741835425a82b57bf9144a963d1fd05777577e7ebad731e04fb8ae7f559ade
data/bin/nicinfo CHANGED
@@ -17,7 +17,7 @@ require 'rubygems'
17
17
  begin
18
18
  require 'nicinfo'
19
19
  rescue LoadError
20
- lib = File.expand_path("../lib",File.dirname(__FILE__))
20
+ lib = File.expand_path("../lib",File.dirname(File.realdirpath(__FILE__)))
21
21
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
22
22
  require 'nicinfo'
23
23
  end
@@ -1,7 +1,24 @@
1
1
  {
2
2
  "description": "RDAP bootstrap file for Domain Name System registrations",
3
- "publication": "2016-03-22T15:40:01Z",
3
+ "publication": "2017-10-05T15:42:56Z",
4
4
  "services": [
5
+ [
6
+ [
7
+ "com",
8
+ "net"
9
+ ],
10
+ [
11
+ "https://rdap-pilot.verisignlabs.com"
12
+ ]
13
+ ],
14
+ [
15
+ [
16
+ "ar"
17
+ ],
18
+ [
19
+ "https://rdap.nic.ar"
20
+ ]
21
+ ],
5
22
  [
6
23
  [
7
24
  "cz"
@@ -9,6 +26,14 @@
9
26
  [
10
27
  "https://rdap.nic.cz"
11
28
  ]
29
+ ],
30
+ [
31
+ [
32
+ "br"
33
+ ],
34
+ [
35
+ "https://rdap.registro.br/"
36
+ ]
12
37
  ]
13
38
  ],
14
39
  "version": "1.0"
@@ -0,0 +1,96 @@
1
+ require('ipaddr')
2
+
3
+ def split_range(s, e, pfx)
4
+ diff = e - s
5
+ pfx += 1
6
+ return [[s, s + diff / 2, pfx], [s + diff/2 + 1, e, pfx]]
7
+ end
8
+
9
+ def cidr_to_str(ip, mask, type)
10
+ ip = IPAddr.new(ip, type)
11
+ return "%s/%i" % [ip.to_s, mask]
12
+ end
13
+
14
+ def find_start_cidrs(r, start)
15
+ s = r[0]
16
+ e = r[1]
17
+ pfx = r[2]
18
+ if s >= start
19
+ return [r]
20
+ elsif start > e
21
+ return []
22
+ else
23
+ nr1, nr2 = split_range(s, e, pfx)
24
+ return find_start_cidrs(nr1, start) + find_start_cidrs(nr2, start)
25
+ end
26
+ end
27
+
28
+ def find_end_cidrs(r, end_val)
29
+ s = r[0]
30
+ e = r[1]
31
+ pfx = r[2]
32
+ if e <= end_val
33
+ return [r]
34
+ elsif end_val < s
35
+ return []
36
+ else
37
+ nr1, nr2 = split_range(s, e, pfx)
38
+ return find_end_cidrs(nr1, end_val) + find_end_cidrs(nr2, end_val)
39
+ end
40
+ end
41
+
42
+ def clean_ip(ip)
43
+ if ip.include? '.'
44
+ ip = ip.split('.').map(&:to_i).join('.')
45
+ end
46
+ return ip
47
+ end
48
+
49
+ def find_cidrs(lower, upper)
50
+
51
+ lower = clean_ip(lower)
52
+ upper = clean_ip(upper)
53
+
54
+ s = IPAddr.new lower
55
+ e = IPAddr.new upper
56
+
57
+ maxlen = 128
58
+ type = Socket::AF_INET6
59
+ if s.ipv4?
60
+ maxlen = 32
61
+ type = Socket::AF_INET
62
+ end
63
+
64
+ s = s.to_i
65
+ e = e.to_i
66
+
67
+ if s > e
68
+ tmp = e
69
+ e = s
70
+ s = tmp
71
+ end
72
+
73
+ mask = e ^ s
74
+ i = 0
75
+ while mask != 0
76
+ i += 1
77
+ mask = mask >> 1
78
+ end
79
+
80
+ r_start = s - (s % 2**i)
81
+ r_end = r_start + (2**i) - 1
82
+
83
+ rs = []
84
+ if r_start == s and r_end == e
85
+ rs = [[s, e, maxlen - i]]
86
+ else
87
+ r1, r2 = split_range(r_start, r_end, maxlen - i)
88
+ rs = find_start_cidrs(r1, s) + find_end_cidrs(r2, e)
89
+ end
90
+
91
+ ret = []
92
+ for r in rs
93
+ ret.push(cidr_to_str(r[0], r[2], type))
94
+ end
95
+ return ret
96
+ end
@@ -18,9 +18,9 @@
18
18
 
19
19
  module NicInfo
20
20
 
21
- VERSION = "1.1.1"
21
+ VERSION = "1.2.0-alpha"
22
22
  VERSION_LABEL = "NicInfo v." + VERSION
23
- COPYRIGHT = "Copyright (c) 2011-2016 American Registry for Internet Numbers (ARIN)"
23
+ COPYRIGHT = "Copyright (c) 2011-2017 American Registry for Internet Numbers (ARIN)"
24
24
  CONFIG_VERSION = 3
25
25
 
26
26
  # regular expressions
data/lib/nicinfo/ip.rb CHANGED
@@ -12,12 +12,15 @@
12
12
  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
13
13
  # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
14
 
15
+ require 'netaddr'
16
+
15
17
  require 'nicinfo/config'
16
18
  require 'nicinfo/nicinfo_logger'
17
19
  require 'nicinfo/utils'
18
20
  require 'nicinfo/common_json'
19
21
  require 'nicinfo/entity'
20
22
  require 'nicinfo/data_tree'
23
+ require 'nicinfo/cidrs'
21
24
 
22
25
  module NicInfo
23
26
 
@@ -51,6 +54,7 @@ module NicInfo
51
54
  @config.logger.extra "Object Class Name", NicInfo::get_object_class_name( @objectclass )
52
55
  @config.logger.terse "Start Address", NicInfo.get_startAddress( @objectclass )
53
56
  @config.logger.terse "End Address", NicInfo.get_endAddress( @objectclass )
57
+ @config.logger.terse "CIDRs", get_CIDRs
54
58
  @config.logger.datum "IP Version", @objectclass[ "ipVersion" ]
55
59
  @config.logger.extra "Name", NicInfo.get_name( @objectclass )
56
60
  @config.logger.terse "Country", NicInfo.get_country( @objectclass )
@@ -77,6 +81,21 @@ module NicInfo
77
81
  return "(unidentifiable network #{object_id})"
78
82
  end
79
83
 
84
+ def get_CIDRs
85
+ startAddress = NicInfo.get_startAddress @objectclass
86
+ endAddress = NicInfo.get_endAddress @objectclass
87
+ if startAddress and endAddress
88
+ cidrs = find_cidrs(startAddress, endAddress)
89
+ return cidrs.join(', ')
90
+ elsif startAddress
91
+ return NetAddr::CIDR.create(startAddress).to_s
92
+ elsif endAddress
93
+ return NetAddr::CIDR.create(endAddress).to_s
94
+ else
95
+ return ""
96
+ end
97
+ end
98
+
80
99
  def to_node
81
100
  DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) )
82
101
  end
@@ -32,6 +32,7 @@ require 'nicinfo/autnum'
32
32
  require 'nicinfo/error_code'
33
33
  require 'ipaddr'
34
34
  require 'nicinfo/data_tree'
35
+ require 'nicinfo/traceroute'
35
36
  begin
36
37
  require 'json'
37
38
  rescue LoadError
@@ -61,6 +62,7 @@ module NicInfo
61
62
  QueryType.add_item :SRCH_NS, "NAMESERVERS"
62
63
  QueryType.add_item :SRCH_NS_BY_NAME, "NSBYNAME"
63
64
  QueryType.add_item :SRCH_NS_BY_IP, "NSBYIP"
65
+ QueryType.add_item :TRACE, "TRACE"
64
66
  QueryType.add_item :BY_SERVER_HELP, "HELP"
65
67
  QueryType.add_item :BY_URL, "URL"
66
68
 
@@ -104,6 +106,7 @@ module NicInfo
104
106
  " dsbynsip - domain search by nameserver IP address",
105
107
  " nsbyname - nameserver search by nameserver name",
106
108
  " nsbyip - nameserver search by IP address",
109
+ " trace - trace route",
107
110
  " url - RDAP URL",
108
111
  " help - server help") do |type|
109
112
  uptype = type.upcase
@@ -421,6 +424,20 @@ module NicInfo
421
424
  end
422
425
  end
423
426
 
427
+ if @config.options.argv[0] == '.'
428
+ @config.logger.mesg( "Obtaining current IP Address...")
429
+ data = get("https://stat.ripe.net/data/whats-my-ip/data.json", 0)
430
+ json_data = JSON.load(data)
431
+
432
+ if json_data["data"] == nil || json_data["data"]["ip"] == nil
433
+ @config.logger.mesg("Server repsonded with unknown JSON")
434
+ @config.logger.mesg("Unable to determine your IP Address. You must specify it.")
435
+ exit
436
+ elsif
437
+ @config.options.argv[0] = json_data["data"]["ip"]
438
+ end
439
+ end
440
+
424
441
  if @config.options.query_type == nil
425
442
  @config.options.query_type = guess_query_value_type(@config.options.argv)
426
443
  if (@config.options.query_type == QueryType::BY_IP4_ADDR ||
@@ -462,6 +479,28 @@ module NicInfo
462
479
  end
463
480
  end
464
481
 
482
+ #determine if this will be a single query or multiple
483
+ qtype = @config.options.query_type
484
+ case qtype
485
+ when QueryType::TRACE
486
+ ips = NicInfo.traceroute @config.options.argv[ 0 ], @config
487
+ if ips.empty?
488
+ @config.logger.mesg "Trace route yeilded no data"
489
+ else
490
+ ips.each do |ip|
491
+ @config.options.query_type = QueryType::BY_IP4_ADDR
492
+ @config.options.argv[ 0 ] = ip
493
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = nil
494
+ json_data = do_rdap_query
495
+ display_rdap_query( json_data, false )
496
+ end
497
+ end
498
+ else
499
+ json_data = do_rdap_query
500
+ display_rdap_query( json_data, true )
501
+ end
502
+
503
+ =begin
465
504
  if @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] == nil && !@config.options.url
466
505
  bootstrap = Bootstrap.new( @config )
467
506
  qtype = @config.options.query_type
@@ -626,9 +665,180 @@ module NicInfo
626
665
  end
627
666
  @config.logger.trace("Server response code was " + e.response.code)
628
667
  end
668
+ =end
629
669
 
630
670
  end
631
671
 
672
+ def do_rdap_query
673
+ if @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] == nil && !@config.options.url
674
+ bootstrap = Bootstrap.new( @config )
675
+ qtype = @config.options.query_type
676
+ if qtype == QueryType::BY_SERVER_HELP
677
+ qtype = guess_query_value_type( @config.options.argv )
678
+ end
679
+ case qtype
680
+ when QueryType::BY_IP4_ADDR
681
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_ip( @config.options.argv[ 0 ] )
682
+ when QueryType::BY_IP6_ADDR
683
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_ip( @config.options.argv[ 0 ] )
684
+ when QueryType::BY_IP4_CIDR
685
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_ip( @config.options.argv[ 0 ] )
686
+ when QueryType::BY_IP6_CIDR
687
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_ip( @config.options.argv[ 0 ] )
688
+ when QueryType::BY_AS_NUMBER
689
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_as( @config.options.argv[ 0 ] )
690
+ when QueryType::BY_DOMAIN
691
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_domain( @config.options.argv[ 0 ] )
692
+ when QueryType::BY_NAMESERVER
693
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_domain( @config.options.argv[ 0 ] )
694
+ when QueryType::BY_ENTITY_HANDLE
695
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_entity( @config.options.argv[ 0 ] )
696
+ when QueryType::SRCH_ENTITY_BY_NAME
697
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::ENTITY_ROOT_URL ]
698
+ when QueryType::SRCH_DOMAIN_BY_NAME
699
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_domain( @config.options.argv[ 0 ] )
700
+ when QueryType::SRCH_DOMAIN_BY_NSNAME
701
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_domain( @config.options.argv[ 0 ] )
702
+ when QueryType::SRCH_DOMAIN_BY_NSIP
703
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::DOMAIN_ROOT_URL ]
704
+ when QueryType::SRCH_NS_BY_NAME
705
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_domain( @config.options.argv[ 0 ] )
706
+ when QueryType::SRCH_NS_BY_IP
707
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = bootstrap.find_url_by_ip( @config.options.argv[ 0 ] )
708
+ else
709
+ @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::BOOTSTRAP_URL ] = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::HELP_ROOT_URL ]
710
+ end
711
+ end
712
+ begin
713
+ rdap_url = nil
714
+ unless @config.options.url
715
+ path = create_resource_url(@config.options.argv, @config.options.query_type)
716
+ rdap_url = make_rdap_url(@config.config[NicInfo::BOOTSTRAP][NicInfo::BOOTSTRAP_URL], path)
717
+ else
718
+ rdap_url = @config.options.argv[0]
719
+ end
720
+ data = get( rdap_url, 0 )
721
+ json_data = JSON.load data
722
+ if (ec = json_data[ NicInfo::NICINFO_DEMO_ERROR ]) != nil
723
+ res = MyHTTPResponse.new( "1.1", ec, "Demo Exception" )
724
+ res["content-type"] = NicInfo::RDAP_CONTENT_TYPE
725
+ res.body=data
726
+ raise Net::HTTPServerException.new( "Demo Exception", res )
727
+ end
728
+ inspect_rdap_compliance json_data
729
+ cache_self_references json_data
730
+ json_data
731
+ rescue JSON::ParserError => a
732
+ @config.logger.mesg( "Server returned invalid JSON!" )
733
+ rescue SocketError => a
734
+ @config.logger.mesg(a.message)
735
+ rescue ArgumentError => a
736
+ @config.logger.mesg(a.message)
737
+ rescue Net::HTTPServerException => e
738
+ case e.response.code
739
+ when "200"
740
+ @config.logger.mesg( e.message )
741
+ when "401"
742
+ @config.logger.mesg("Authorization is required.")
743
+ handle_error_response e.response
744
+ when "404"
745
+ @config.logger.mesg("Query yielded no results.")
746
+ handle_error_response e.response
747
+ else
748
+ @config.logger.mesg("Error #{e.response.code}.")
749
+ handle_error_response e.response
750
+ end
751
+ @config.logger.trace("Server response code was " + e.response.code)
752
+ rescue Net::HTTPFatalError => e
753
+ case e.response.code
754
+ when "500"
755
+ @config.logger.mesg("RDAP server is reporting an internal error.")
756
+ handle_error_response e.response
757
+ when "501"
758
+ @config.logger.mesg("RDAP server does not implement the query.")
759
+ handle_error_response e.response
760
+ when "503"
761
+ @config.logger.mesg("RDAP server is reporting that it is unavailable.")
762
+ handle_error_response e.response
763
+ else
764
+ @config.logger.mesg("Error #{e.response.code}.")
765
+ handle_error_response e.response
766
+ end
767
+ @config.logger.trace("Server response code was " + e.response.code)
768
+ end
769
+ end
770
+
771
+ def display_rdap_query json_data, show_help = true
772
+ if @config.options.output_json
773
+ @config.logger.raw( DataAmount::TERSE_DATA, json_data, false )
774
+ elsif @config.options.json_values
775
+ @config.options.json_values.each do |value|
776
+ @config.logger.raw( DataAmount::TERSE_DATA, eval_json_value( value, json_data), false )
777
+ end
778
+ else
779
+ Notices.new.display_notices json_data, @config, @config.options.query_type == QueryType::BY_SERVER_HELP
780
+ if @config.options.query_type != QueryType::BY_SERVER_HELP
781
+ result_type = get_query_type_from_result( json_data )
782
+ if result_type != nil
783
+ if result_type != @config.options.query_type
784
+ @config.logger.mesg( "Query type is " + @config.options.query_type + ". Result type is " + result_type + "." )
785
+ else
786
+ @config.logger.mesg( "Result type is " + result_type + "." )
787
+ end
788
+ @config.options.query_type = result_type
789
+ elsif json_data[ "errorCode" ] == nil
790
+ @config.conf_msgs << "Response has no result type."
791
+ end
792
+ data_tree = DataTree.new( )
793
+ case @config.options.query_type
794
+ when QueryType::BY_IP4_ADDR
795
+ NicInfo::display_ip( json_data, @config, data_tree )
796
+ when QueryType::BY_IP6_ADDR
797
+ NicInfo::display_ip( json_data, @config, data_tree )
798
+ when QueryType::BY_IP4_CIDR
799
+ NicInfo::display_ip( json_data, @config, data_tree )
800
+ when QueryType::BY_IP6_CIDR
801
+ NicInfo::display_ip( json_data, @config, data_tree )
802
+ when QueryType::BY_IP
803
+ NicInfo::display_ip( json_data, @config, data_tree )
804
+ when QueryType::BY_AS_NUMBER
805
+ NicInfo::display_autnum( json_data, @config, data_tree )
806
+ when "NicInfo::DsData"
807
+ NicInfo::display_ds_data( json_data, @config, data_tree )
808
+ when "NicInfo::KeyData"
809
+ NicInfo::display_key_data( json_data, @config, data_tree )
810
+ when QueryType::BY_DOMAIN
811
+ NicInfo::display_domain( json_data, @config, data_tree )
812
+ when QueryType::BY_NAMESERVER
813
+ NicInfo::display_ns( json_data, @config, data_tree )
814
+ when QueryType::BY_ENTITY_HANDLE
815
+ NicInfo::display_entity( json_data, @config, data_tree )
816
+ when QueryType::SRCH_DOMAINS
817
+ NicInfo::display_domains( json_data, @config, data_tree )
818
+ when QueryType::SRCH_DOMAIN_BY_NAME
819
+ NicInfo::display_domains( json_data, @config, data_tree )
820
+ when QueryType::SRCH_DOMAIN_BY_NSNAME
821
+ NicInfo::display_domains( json_data, @config, data_tree )
822
+ when QueryType::SRCH_DOMAIN_BY_NSIP
823
+ NicInfo::display_domains( json_data, @config, data_tree )
824
+ when QueryType::SRCH_ENTITY_BY_NAME
825
+ NicInfo::display_entities( json_data, @config, data_tree )
826
+ when QueryType::SRCH_NS
827
+ NicInfo::display_nameservers( json_data, @config, data_tree )
828
+ when QueryType::SRCH_NS_BY_NAME
829
+ NicInfo::display_nameservers( json_data, @config, data_tree )
830
+ when QueryType::SRCH_NS_BY_IP
831
+ NicInfo::display_nameservers( json_data, @config, data_tree )
832
+ end
833
+ @config.save_as_yaml( NicInfo::LASTTREE_YAML, data_tree ) if !data_tree.empty?
834
+ show_search_results_truncated json_data
835
+ show_conformance_messages
836
+ show_helpful_messages json_data, data_tree if show_help
837
+ end
838
+ end
839
+ @config.logger.end_run
840
+ end
841
+
632
842
  def handle_error_response (res)
633
843
  if res["content-type"] == NicInfo::RDAP_CONTENT_TYPE && res.body && res.body.to_s.size > 0
634
844
  json_data = JSON.load( res.body )
@@ -0,0 +1,125 @@
1
+ # Copyright (C) 2009 Original Author Unknown
2
+ # Copyright (C) 2016 American Registry for Internet Numbers
3
+ # Adopted from https://code.google.com/archive/p/rubyroute/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification, are permitted
6
+ # provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this list of
9
+ # conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice, this list
12
+ # of conditions and the following disclaimer in the documentation and/or other materials
13
+ # provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors may be used to
16
+ # endorse or promote products derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
19
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20
+ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
+ # THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
+ # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+
29
+ require 'timeout'
30
+ require 'socket'
31
+ require 'nicinfo/config'
32
+ require 'nicinfo/nicinfo_logger'
33
+
34
+ module NicInfo
35
+
36
+ def NicInfo.random_port
37
+ 1024 + rand(64511)
38
+ end
39
+
40
+ def NicInfo.traceroute host, config
41
+ ips = Array.new
42
+
43
+ begin
44
+ myname = Socket.gethostname
45
+ rescue SocketError => err_msg
46
+ config.logger.mesg "Can't get my own host name (#{err_msg})."
47
+ exit 1
48
+ end
49
+
50
+ config.logger.mesg "Tracing route to #{host}"
51
+
52
+ ttl = 1
53
+ max_ttl = 255
54
+ max_contiguaous_timeout = 16
55
+ localport = random_port
56
+ dgram_sock = UDPSocket::new
57
+
58
+ begin
59
+ dgram_sock.bind( myname, localport )
60
+ rescue
61
+ localport = random_port
62
+ retry
63
+ end
64
+
65
+ begin
66
+ icmp_sock = Socket.open( Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP )
67
+ icmp_sockaddr = Socket.pack_sockaddr_in( localport, myname )
68
+ icmp_sock.bind( icmp_sockaddr )
69
+ rescue SystemCallError => socket_error
70
+ config.logger.mesg "Error with ICMP socket. You probably need to be root: #{socket_error}"
71
+ exit 1
72
+ end
73
+
74
+
75
+ begin
76
+ dgram_sock.connect( host, 999 )
77
+ rescue SocketError => err_msg
78
+ config.logger.mesg "Can't connect to remote host (#{err_msg})."
79
+ exit 1
80
+ end
81
+
82
+ stop_tracing = false
83
+ continguous_timeout = 0
84
+ until stop_tracing
85
+ dgram_sock.setsockopt( 0, Socket::IP_TTL, ttl )
86
+ dgram_sock.send( "RubyRoute says hello!", 0 )
87
+
88
+ begin
89
+ Timeout::timeout( 1 ) {
90
+ data, sender = icmp_sock.recvfrom( 8192 )
91
+ # 20th and 21th bytes of IP+ICMP datagram carry the ICMP type and code resp.
92
+ icmp_type = data.unpack( '@20C' )[0]
93
+ icmp_code = data.unpack( '@21C' )[0]
94
+ # Extract the ICMP sender from response.
95
+ ip = Socket.unpack_sockaddr_in( sender )[1].to_s
96
+ ips << ip
97
+ config.logger.mesg "TTL = #{ttl}: " + ip
98
+ continguous_timeout = 0
99
+ if ( icmp_type == 3 and icmp_code == 13 )
100
+ config.logger.mesg "'Communication Administratively Prohibited' from this hop."
101
+ # ICMP 3/3 is port unreachable and usually means that we've hit the target.
102
+ elsif ( icmp_type == 3 and icmp_code == 3 )
103
+ config.logger.mesg "Destination reached. Trace complete."
104
+ stop_tracing = true
105
+ end
106
+ }
107
+ rescue Timeout::Error
108
+ config.logger.mesg "Timeout error with TTL = #{ttl}!"
109
+ continguous_timeout += 1
110
+ end
111
+
112
+ ttl += 1
113
+ stop_tracing = true if ttl > max_ttl
114
+ if continguous_timeout > max_contiguaous_timeout
115
+ stop_tracing = true
116
+ config.logger.mesg "Getting a lot of contiguous timeouts. Prematurely terminating trace."
117
+ end
118
+ end
119
+
120
+ ips
121
+ end
122
+
123
+ end
124
+
125
+
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nicinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-03 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2017-10-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: netaddr
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.5.1
13
33
  description: A command-line RDAP client.
14
34
  email: andy@arin.net
15
35
  executables:
@@ -27,6 +47,7 @@ files:
27
47
  - lib/nicinfo/bsfiles/ipv4.json
28
48
  - lib/nicinfo/bsfiles/ipv6.json
29
49
  - lib/nicinfo/cache.rb
50
+ - lib/nicinfo/cidrs.rb
30
51
  - lib/nicinfo/common_json.rb
31
52
  - lib/nicinfo/common_names.rb
32
53
  - lib/nicinfo/config.rb
@@ -62,6 +83,7 @@ files:
62
83
  - lib/nicinfo/nicinfo_main.rb
63
84
  - lib/nicinfo/notices.rb
64
85
  - lib/nicinfo/ns.rb
86
+ - lib/nicinfo/traceroute.rb
65
87
  - lib/nicinfo/utils.rb
66
88
  homepage: https://github.com/arinlabs/nicinfo
67
89
  licenses:
@@ -73,19 +95,18 @@ require_paths:
73
95
  - lib
74
96
  required_ruby_version: !ruby/object:Gem::Requirement
75
97
  requirements:
76
- - - '>='
98
+ - - ">="
77
99
  - !ruby/object:Gem::Version
78
100
  version: '0'
79
101
  required_rubygems_version: !ruby/object:Gem::Requirement
80
102
  requirements:
81
- - - '>='
103
+ - - ">"
82
104
  - !ruby/object:Gem::Version
83
- version: '0'
105
+ version: 1.3.1
84
106
  requirements: []
85
107
  rubyforge_project:
86
- rubygems_version: 2.4.5
108
+ rubygems_version: 2.6.14
87
109
  signing_key:
88
110
  specification_version: 4
89
111
  summary: RDAP Client
90
112
  test_files: []
91
- has_rdoc: