nicinfo 1.1.1 → 1.2.0.pre.alpha

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: 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: