resolv 0.4.0 → 0.5.0

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
  SHA256:
3
- metadata.gz: 56680c64e918a60193f43e3ca4a7093db20bbe66f516da79a159d9a3c05860d8
4
- data.tar.gz: f017a2c89fbcdf946b69ce57d41a67537b73f54ec6e99d18cc62865fd6ec1633
3
+ metadata.gz: f3c2610a9201afa7c69fdadb89357cfe4c44e0bec4f52c430ef6328897ebda0a
4
+ data.tar.gz: 06f9f301afe24165dd53683dd11c503a69cb367cc76f5885709552bab7444d61
5
5
  SHA512:
6
- metadata.gz: d57f866a30bc2b8da6dbcdb8c65d0a5db4630af4ec0244aa490e37370ba7b27c3031e153e76055e7f4f63114bd477944326b05dbb7319f97bf59478f8518d76a
7
- data.tar.gz: f07e85287b3bb9973c90900c1fbdc272e193d91493e63b407e696cc9f52de29fc0716f2ec11aba56d37d89a12b6d3fec55d21bd8ce756f02d56577940c454b06
6
+ metadata.gz: 15dafa5ebe1d4ba98fb40a1bec5d700beee853090230b08fcfc0a8c4ebd6cebf2657e4618c6de664a17a1b0ae0c8fa183c27dd0739957389140a5d001fc2d92a
7
+ data.tar.gz: e930fb5af7be91b0342d855486979f070aaf04c02ca054dd8a6dfb70313dcc2fe8037f52e0d9e61b31df21a7452c841e5c3f48889c85532155285ad7100948eb
@@ -0,0 +1,7 @@
1
+ # This is a file used by GitHub to ignore the following commits on `git blame`.
2
+ #
3
+ # You can also do the same thing in your local repository with:
4
+ # $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
5
+
6
+ # Expand tabs
7
+ 9ae210665a8524554e7c868d3ec67af54b0958bb
@@ -0,0 +1,46 @@
1
+ name: Publish gem to rubygems.org
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ push:
13
+ if: github.repository == 'ruby/resolv'
14
+ runs-on: ubuntu-latest
15
+
16
+ environment:
17
+ name: rubygems.org
18
+ url: https://rubygems.org/gems/resolv
19
+
20
+ permissions:
21
+ contents: write
22
+ id-token: write
23
+
24
+ steps:
25
+ - name: Harden Runner
26
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
27
+ with:
28
+ egress-policy: audit
29
+
30
+ - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
31
+
32
+ - name: Set up Ruby
33
+ uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
34
+ with:
35
+ bundler-cache: true
36
+ ruby-version: ruby
37
+
38
+ - name: Publish to RubyGems
39
+ uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1
40
+
41
+ - name: Create GitHub release
42
+ run: |
43
+ tag_name="$(git describe --tags --abbrev=0)"
44
+ gh release create "${tag_name}" --verify-tag --generate-notes
45
+ env:
46
+ GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}
@@ -19,6 +19,9 @@ jobs:
19
19
  include:
20
20
  - ruby: mswin
21
21
  os: windows-latest
22
+ exclude:
23
+ - ruby: 2.5
24
+ os: macos-latest
22
25
  runs-on: ${{ matrix.os }}
23
26
  steps:
24
27
  - uses: actions/checkout@v4
@@ -4,10 +4,10 @@ Redistribution and use in source and binary forms, with or without
4
4
  modification, are permitted provided that the following conditions
5
5
  are met:
6
6
  1. Redistributions of source code must retain the above copyright
7
- notice, this list of conditions and the following disclaimer.
7
+ notice, this list of conditions and the following disclaimer.
8
8
  2. Redistributions in binary form must reproduce the above copyright
9
- notice, this list of conditions and the following disclaimer in the
10
- documentation and/or other materials provided with the distribution.
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
11
 
12
12
  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
13
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
data/COPYING ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a. place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b. use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c. give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d. make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a. distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b. accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c. give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d. make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+ if have_library('iphlpapi', 'GetNetworkParams')
3
+ create_makefile('win32/resolv')
4
+ else
5
+ File.write('Makefile', "all clean install:\n\t@echo Done: $(@)\n")
6
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: false
2
+ =begin
3
+ = Win32 DNS and DHCP I/F
4
+
5
+ =end
6
+
7
+ require 'win32/registry'
8
+
9
+ module Win32
10
+ module Resolv
11
+ API = Registry::API
12
+ Error = Registry::Error
13
+
14
+ def self.get_hosts_path
15
+ path = get_hosts_dir
16
+ path = File.expand_path('hosts', path)
17
+ File.exist?(path) ? path : nil
18
+ end
19
+
20
+ def self.get_resolv_info
21
+ search, nameserver = get_info
22
+ if search.empty?
23
+ search = nil
24
+ else
25
+ search.delete("")
26
+ search.uniq!
27
+ end
28
+ if nameserver.empty?
29
+ nameserver = nil
30
+ else
31
+ nameserver.delete("")
32
+ nameserver.delete("0.0.0.0")
33
+ nameserver.uniq!
34
+ end
35
+ [ search, nameserver ]
36
+ end
37
+ end
38
+ end
39
+
40
+ begin
41
+ require 'win32/resolv.so'
42
+ rescue LoadError
43
+ end
44
+
45
+ module Win32
46
+ #====================================================================
47
+ # Windows NT
48
+ #====================================================================
49
+ module Resolv
50
+ module SZ
51
+ refine Registry do
52
+ # ad hoc workaround for broken registry
53
+ def read_s(key)
54
+ type, str = read(key)
55
+ unless type == Registry::REG_SZ
56
+ warn "Broken registry, #{name}\\#{key} was #{Registry.type2name(type)}, ignored"
57
+ return String.new
58
+ end
59
+ str
60
+ end
61
+ end
62
+ end
63
+ using SZ
64
+
65
+ TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
66
+
67
+ class << self
68
+ private
69
+ def get_hosts_dir
70
+ Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
71
+ reg.read_s_expand('DataBasePath')
72
+ end
73
+ end
74
+
75
+ def get_info
76
+ search = nil
77
+ nameserver = get_dns_server_list
78
+ Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
79
+ begin
80
+ slist = reg.read_s('SearchList')
81
+ search = slist.split(/,\s*/) unless slist.empty?
82
+ rescue Registry::Error
83
+ end
84
+
85
+ if add_search = search.nil?
86
+ search = []
87
+ begin
88
+ nvdom = reg.read_s('NV Domain')
89
+ unless nvdom.empty?
90
+ @search = [ nvdom ]
91
+ if reg.read_i('UseDomainNameDevolution') != 0
92
+ if /^\w+\./ =~ nvdom
93
+ devo = $'
94
+ end
95
+ end
96
+ end
97
+ rescue Registry::Error
98
+ end
99
+ end
100
+
101
+ reg.open('Interfaces') do |h|
102
+ h.each_key do |iface, |
103
+ h.open(iface) do |regif|
104
+ next unless ns = %w[NameServer DhcpNameServer].find do |key|
105
+ begin
106
+ ns = regif.read_s(key)
107
+ rescue Registry::Error
108
+ else
109
+ break ns.split(/[,\s]\s*/) unless ns.empty?
110
+ end
111
+ end
112
+ next if (nameserver & ns).empty?
113
+
114
+ if add_search
115
+ begin
116
+ [ 'Domain', 'DhcpDomain' ].each do |key|
117
+ dom = regif.read_s(key)
118
+ unless dom.empty?
119
+ search.concat(dom.split(/,\s*/))
120
+ break
121
+ end
122
+ end
123
+ rescue Registry::Error
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ search << devo if add_search and devo
130
+ end
131
+ [ search.uniq, nameserver.uniq ]
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,65 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include <windows.h>
4
+ #ifndef NTDDI_VERSION
5
+ #define NTDDI_VERSION 0x06000000
6
+ #endif
7
+ #include <iphlpapi.h>
8
+
9
+ static VALUE
10
+ w32error_make_error(DWORD e)
11
+ {
12
+ VALUE code = ULONG2NUM(e);
13
+ return rb_class_new_instance(1, &code, rb_path2class("Win32::Resolv::Error"));
14
+ }
15
+
16
+ static void
17
+ w32error_raise(DWORD e)
18
+ {
19
+ rb_exc_raise(w32error_make_error(e));
20
+ }
21
+
22
+ static VALUE
23
+ get_dns_server_list(VALUE self)
24
+ {
25
+ FIXED_INFO *fixedinfo = NULL;
26
+ ULONG buflen = 0;
27
+ DWORD ret;
28
+ VALUE buf, nameservers = Qnil;
29
+
30
+ ret = GetNetworkParams(NULL, &buflen);
31
+ if (ret != NO_ERROR && ret != ERROR_BUFFER_OVERFLOW) {
32
+ w32error_raise(ret);
33
+ }
34
+ fixedinfo = ALLOCV(buf, buflen);
35
+ ret = GetNetworkParams(fixedinfo, &buflen);
36
+ if (ret == NO_ERROR) {
37
+ const IP_ADDR_STRING *ipaddr = &fixedinfo->DnsServerList;
38
+ nameservers = rb_ary_new();
39
+ do {
40
+ const char *s = ipaddr->IpAddress.String;
41
+ if (!*s) continue;
42
+ if (strcmp(s, "0.0.0.0") == 0) continue;
43
+ rb_ary_push(nameservers, rb_str_new_cstr(s));
44
+ } while ((ipaddr = ipaddr->Next) != NULL);
45
+ }
46
+ ALLOCV_END(buf);
47
+ if (ret != NO_ERROR) w32error_raise(ret);
48
+
49
+ return nameservers;
50
+ }
51
+
52
+ void
53
+ InitVM_resolv(void)
54
+ {
55
+ VALUE mWin32 = rb_define_module("Win32");
56
+ VALUE resolv = rb_define_module_under(mWin32, "Resolv");
57
+ VALUE singl = rb_singleton_class(resolv);
58
+ rb_define_private_method(singl, "get_dns_server_list", get_dns_server_list, 0);
59
+ }
60
+
61
+ void
62
+ Init_resolv(void)
63
+ {
64
+ InitVM(resolv);
65
+ }
data/lib/resolv.rb CHANGED
@@ -37,7 +37,7 @@ end
37
37
 
38
38
  class Resolv
39
39
 
40
- VERSION = "0.4.0"
40
+ VERSION = "0.5.0"
41
41
 
42
42
  ##
43
43
  # Looks up the first IP address for +name+.
@@ -396,13 +396,15 @@ class Resolv
396
396
  # be a Resolv::IPv4 or Resolv::IPv6
397
397
 
398
398
  def each_address(name)
399
- each_resource(name, Resource::IN::A) {|resource| yield resource.address}
400
399
  if use_ipv6?
401
400
  each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
402
401
  end
402
+ each_resource(name, Resource::IN::A) {|resource| yield resource.address}
403
403
  end
404
404
 
405
405
  def use_ipv6? # :nodoc:
406
+ @config.lazy_initialize unless @config.instance_variable_get(:@initialized)
407
+
406
408
  use_ipv6 = @config.use_ipv6?
407
409
  unless use_ipv6.nil?
408
410
  return use_ipv6
@@ -513,35 +515,40 @@ class Resolv
513
515
 
514
516
  def fetch_resource(name, typeclass)
515
517
  lazy_initialize
516
- begin
517
- requester = make_udp_requester
518
+ truncated = {}
519
+ requesters = {}
520
+ udp_requester = begin
521
+ make_udp_requester
518
522
  rescue Errno::EACCES
519
523
  # fall back to TCP
520
524
  end
521
525
  senders = {}
526
+
522
527
  begin
523
- @config.resolv(name) {|candidate, tout, nameserver, port|
524
- requester ||= make_tcp_requester(nameserver, port)
528
+ @config.resolv(name) do |candidate, tout, nameserver, port|
525
529
  msg = Message.new
526
530
  msg.rd = 1
527
531
  msg.add_question(candidate, typeclass)
528
- unless sender = senders[[candidate, nameserver, port]]
532
+
533
+ requester = requesters.fetch([nameserver, port]) do
534
+ if !truncated[candidate] && udp_requester
535
+ udp_requester
536
+ else
537
+ requesters[[nameserver, port]] = make_tcp_requester(nameserver, port)
538
+ end
539
+ end
540
+
541
+ unless sender = senders[[candidate, requester, nameserver, port]]
529
542
  sender = requester.sender(msg, candidate, nameserver, port)
530
543
  next if !sender
531
- senders[[candidate, nameserver, port]] = sender
544
+ senders[[candidate, requester, nameserver, port]] = sender
532
545
  end
533
546
  reply, reply_name = requester.request(sender, tout)
534
547
  case reply.rcode
535
548
  when RCode::NoError
536
549
  if reply.tc == 1 and not Requester::TCP === requester
537
- requester.close
538
550
  # Retry via TCP:
539
- requester = make_tcp_requester(nameserver, port)
540
- senders = {}
541
- # This will use TCP for all remaining candidates (assuming the
542
- # current candidate does not already respond successfully via
543
- # TCP). This makes sense because we already know the full
544
- # response will not fit in an untruncated UDP packet.
551
+ truncated[candidate] = true
545
552
  redo
546
553
  else
547
554
  yield(reply, reply_name)
@@ -552,9 +559,10 @@ class Resolv
552
559
  else
553
560
  raise Config::OtherResolvError.new(reply_name.to_s)
554
561
  end
555
- }
562
+ end
556
563
  ensure
557
- requester&.close
564
+ udp_requester&.close
565
+ requesters.each_value { |requester| requester&.close }
558
566
  end
559
567
  end
560
568
 
@@ -569,6 +577,11 @@ class Resolv
569
577
 
570
578
  def make_tcp_requester(host, port) # :nodoc:
571
579
  return Requester::TCP.new(host, port)
580
+ rescue Errno::ECONNREFUSED
581
+ # Treat a refused TCP connection attempt to a nameserver like a timeout,
582
+ # as Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a
583
+ # hint to try the next nameserver:
584
+ raise ResolvTimeout
572
585
  end
573
586
 
574
587
  def extract_resources(msg, name, typeclass) # :nodoc:
@@ -1800,7 +1813,6 @@ class Resolv
1800
1813
  end
1801
1814
  end
1802
1815
 
1803
-
1804
1816
  ##
1805
1817
  # Base class for SvcParam. [RFC9460]
1806
1818
 
@@ -2499,7 +2511,6 @@ class Resolv
2499
2511
 
2500
2512
  attr_reader :altitude
2501
2513
 
2502
-
2503
2514
  def encode_rdata(msg) # :nodoc:
2504
2515
  msg.put_bytes(@version)
2505
2516
  msg.put_bytes(@ssize.scalar)
@@ -3439,4 +3450,3 @@ class Resolv
3439
3450
  AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
3440
3451
 
3441
3452
  end
3442
-
data/resolv.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.homepage = "https://github.com/ruby/resolv"
17
17
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
18
18
  spec.licenses = ["Ruby", "BSD-2-Clause"]
19
+ spec.extensions << "ext/win32/resolv/extconf.rb"
19
20
 
20
21
  spec.metadata["homepage_uri"] = spec.homepage
21
22
  spec.metadata["source_code_uri"] = spec.homepage
metadata CHANGED
@@ -1,30 +1,38 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resolv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanaka Akira
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 2024-03-19 00:00:00.000000000 Z
11
+ date: 2024-11-11 00:00:00.000000000 Z
11
12
  dependencies: []
12
13
  description: Thread-aware DNS resolver library in Ruby.
13
14
  email:
14
15
  - akr@fsij.org
15
16
  executables: []
16
- extensions: []
17
+ extensions:
18
+ - ext/win32/resolv/extconf.rb
17
19
  extra_rdoc_files: []
18
20
  files:
21
+ - ".git-blame-ignore-revs"
19
22
  - ".github/dependabot.yml"
23
+ - ".github/workflows/push_gem.yml"
20
24
  - ".github/workflows/test.yml"
21
25
  - ".gitignore"
26
+ - BSDL
27
+ - COPYING
22
28
  - Gemfile
23
- - LICENSE.txt
24
29
  - README.md
25
30
  - Rakefile
26
31
  - bin/console
27
32
  - bin/setup
33
+ - ext/win32/resolv/extconf.rb
34
+ - ext/win32/resolv/lib/win32/resolv.rb
35
+ - ext/win32/resolv/resolv.c
28
36
  - lib/resolv.rb
29
37
  - resolv.gemspec
30
38
  homepage: https://github.com/ruby/resolv
@@ -34,6 +42,7 @@ licenses:
34
42
  metadata:
35
43
  homepage_uri: https://github.com/ruby/resolv
36
44
  source_code_uri: https://github.com/ruby/resolv
45
+ post_install_message:
37
46
  rdoc_options: []
38
47
  require_paths:
39
48
  - lib
@@ -48,7 +57,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
48
57
  - !ruby/object:Gem::Version
49
58
  version: '0'
50
59
  requirements: []
51
- rubygems_version: 3.6.0.dev
60
+ rubygems_version: 3.5.11
61
+ signing_key:
52
62
  specification_version: 4
53
63
  summary: Thread-aware DNS resolver library in Ruby.
54
64
  test_files: []