resolv 0.2.1 → 0.3.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: 1bf3ba9bb88ab06a53d2e20d8349c226de8a53bcdf67b2c29072857d691d1a12
4
- data.tar.gz: e260ec02eacdb6ea69505dd272afd8292f03af269a215792425c33dfc89a7b6f
3
+ metadata.gz: d76dc1156c60da694ce1f0a96165e6d5a7e29d662ad7140b443e9aa735082f31
4
+ data.tar.gz: 7b532fc449aff2e5a63cb6a31892a45da5b41b6090d454f94d3c3e5165c94271
5
5
  SHA512:
6
- metadata.gz: 608c379803d480eddb1f48858d7ac1a79d02bfa54499b8ac47c58aef390e7ec4c611ee48034146668644bc5873cfd4f7c41302a6b686ff7ac774c0d1e15fa9eb
7
- data.tar.gz: bf6e669b18e58754ace2258dd0dad1d6bae791e1e361b72e2151d24b91adfd3df277ad6cefba3cb37b52c6ef6874b56a83e16bc3df0e24d129a840ae1cec6433
6
+ metadata.gz: 685ce620cc9c83f1d5827de0a374d71f98fbff7629256d2ab7ed65d66eee062a5bc081a869caba31aeb67b4c292ca6dfc53fa4d71180ce15dd82f39d6fb5992b
7
+ data.tar.gz: 9897929fbfc67bc3a8133d3d9b2f99e7c9350802cf86d4cc0d8f061f397393f91308d6d1d6d35e46d497a3beb7fcf6424dc47ae92d5f7f39e572ac04b2677409
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -3,20 +3,26 @@ name: test
3
3
  on: [push, pull_request]
4
4
 
5
5
  jobs:
6
+ ruby-versions:
7
+ uses: ruby/actions/.github/workflows/ruby_versions.yml@master
8
+ with:
9
+ engine: cruby
10
+ min_version: 2.5
11
+
6
12
  build:
13
+ needs: ruby-versions
7
14
  name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
15
  strategy:
9
16
  matrix:
10
- ruby: [ '3.0', 2.7, 2.6, 2.5, head ]
17
+ ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
11
18
  os: [ ubuntu-latest, macos-latest ]
12
19
  runs-on: ${{ matrix.os }}
13
20
  steps:
14
- - uses: actions/checkout@v2
21
+ - uses: actions/checkout@v4
15
22
  - name: Set up Ruby
16
23
  uses: ruby/setup-ruby@v1
17
24
  with:
18
25
  ruby-version: ${{ matrix.ruby }}
19
- - name: Install dependencies
20
- run: bundle install
26
+ bundler-cache: true
21
27
  - name: Run test
22
- run: rake test
28
+ run: bundle exec rake test
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+
10
+ Gemfile.lock
data/Gemfile CHANGED
@@ -1,4 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
+ gemspec
4
+
3
5
  gem "rake"
4
6
  gem "test-unit"
7
+ gem "test-unit-ruby-core"
data/lib/resolv.rb CHANGED
@@ -37,6 +37,8 @@ end
37
37
 
38
38
  class Resolv
39
39
 
40
+ VERSION = "0.3.0"
41
+
40
42
  ##
41
43
  # Looks up the first IP address for +name+.
42
44
 
@@ -82,8 +84,8 @@ class Resolv
82
84
  ##
83
85
  # Creates a new Resolv using +resolvers+.
84
86
 
85
- def initialize(resolvers=[Hosts.new, DNS.new])
86
- @resolvers = resolvers
87
+ def initialize(resolvers=nil, use_ipv6: nil)
88
+ @resolvers = resolvers || [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(use_ipv6: use_ipv6))]
87
89
  end
88
90
 
89
91
  ##
@@ -196,7 +198,7 @@ class Resolv
196
198
  next unless addr
197
199
  @addr2name[addr] = [] unless @addr2name.include? addr
198
200
  @addr2name[addr] << hostname
199
- @addr2name[addr] += aliases
201
+ @addr2name[addr].concat(aliases)
200
202
  @name2addr[hostname] = [] unless @name2addr.include? hostname
201
203
  @name2addr[hostname] << addr
202
204
  aliases.each {|n|
@@ -310,6 +312,8 @@ class Resolv
310
312
  # String:: Path to a file using /etc/resolv.conf's format.
311
313
  # Hash:: Must contain :nameserver, :search and :ndots keys.
312
314
  # :nameserver_port can be used to specify port number of nameserver address.
315
+ # :raise_timeout_errors can be used to raise timeout errors
316
+ # as exceptions instead of treating the same as an NXDOMAIN response.
313
317
  #
314
318
  # The value of :nameserver should be an address string or
315
319
  # an array of address strings.
@@ -406,6 +410,11 @@ class Resolv
406
410
  end
407
411
 
408
412
  def use_ipv6? # :nodoc:
413
+ use_ipv6 = @config.use_ipv6?
414
+ unless use_ipv6.nil?
415
+ return use_ipv6
416
+ end
417
+
409
418
  begin
410
419
  list = Socket.ip_address_list
411
420
  rescue NotImplementedError
@@ -748,7 +757,7 @@ class Resolv
748
757
  next if @socks_hash[bind_host]
749
758
  begin
750
759
  sock = UDPSocket.new(af)
751
- rescue Errno::EAFNOSUPPORT
760
+ rescue Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT
752
761
  next # The kernel doesn't support the address family.
753
762
  end
754
763
  @socks << sock
@@ -965,7 +974,7 @@ class Resolv
965
974
  next unless keyword
966
975
  case keyword
967
976
  when 'nameserver'
968
- nameserver += args
977
+ nameserver.concat(args)
969
978
  when 'domain'
970
979
  next if args.empty?
971
980
  search = [args[0]]
@@ -1004,6 +1013,7 @@ class Resolv
1004
1013
  @mutex.synchronize {
1005
1014
  unless @initialized
1006
1015
  @nameserver_port = []
1016
+ @use_ipv6 = nil
1007
1017
  @search = nil
1008
1018
  @ndots = 1
1009
1019
  case @config_info
@@ -1028,8 +1038,12 @@ class Resolv
1028
1038
  if config_hash.include? :nameserver_port
1029
1039
  @nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] }
1030
1040
  end
1041
+ if config_hash.include? :use_ipv6
1042
+ @use_ipv6 = config_hash[:use_ipv6]
1043
+ end
1031
1044
  @search = config_hash[:search] if config_hash.include? :search
1032
1045
  @ndots = config_hash[:ndots] if config_hash.include? :ndots
1046
+ @raise_timeout_errors = config_hash[:raise_timeout_errors]
1033
1047
 
1034
1048
  if @nameserver_port.empty?
1035
1049
  @nameserver_port << ['0.0.0.0', Port]
@@ -1083,6 +1097,10 @@ class Resolv
1083
1097
  @nameserver_port
1084
1098
  end
1085
1099
 
1100
+ def use_ipv6?
1101
+ @use_ipv6
1102
+ end
1103
+
1086
1104
  def generate_candidates(name)
1087
1105
  candidates = nil
1088
1106
  name = Name.create(name)
@@ -1116,6 +1134,7 @@ class Resolv
1116
1134
  def resolv(name)
1117
1135
  candidates = generate_candidates(name)
1118
1136
  timeouts = @timeouts || generate_timeouts
1137
+ timeout_error = false
1119
1138
  begin
1120
1139
  candidates.each {|candidate|
1121
1140
  begin
@@ -1127,11 +1146,13 @@ class Resolv
1127
1146
  end
1128
1147
  }
1129
1148
  }
1149
+ timeout_error = true
1130
1150
  raise ResolvError.new("DNS resolv timeout: #{name}")
1131
1151
  rescue NXDomain
1132
1152
  end
1133
1153
  }
1134
1154
  rescue ResolvError
1155
+ raise if @raise_timeout_errors && timeout_error
1135
1156
  end
1136
1157
  end
1137
1158
 
@@ -1487,14 +1508,14 @@ class Resolv
1487
1508
  }
1488
1509
  end
1489
1510
 
1490
- def put_name(d)
1491
- put_labels(d.to_a)
1511
+ def put_name(d, compress: true)
1512
+ put_labels(d.to_a, compress: compress)
1492
1513
  end
1493
1514
 
1494
- def put_labels(d)
1515
+ def put_labels(d, compress: true)
1495
1516
  d.each_index {|i|
1496
1517
  domain = d[i..-1]
1497
- if idx = @names[domain]
1518
+ if compress && idx = @names[domain]
1498
1519
  self.put_pack("n", 0xc000 | idx)
1499
1520
  return
1500
1521
  else
@@ -1518,13 +1539,15 @@ class Resolv
1518
1539
  id, flag, qdcount, ancount, nscount, arcount =
1519
1540
  msg.get_unpack('nnnnnn')
1520
1541
  o.id = id
1542
+ o.tc = (flag >> 9) & 1
1543
+ o.rcode = flag & 15
1544
+ return o unless o.tc.zero?
1545
+
1521
1546
  o.qr = (flag >> 15) & 1
1522
1547
  o.opcode = (flag >> 11) & 15
1523
1548
  o.aa = (flag >> 10) & 1
1524
- o.tc = (flag >> 9) & 1
1525
1549
  o.rd = (flag >> 8) & 1
1526
1550
  o.ra = (flag >> 7) & 1
1527
- o.rcode = flag & 15
1528
1551
  (1..qdcount).each {
1529
1552
  name, typeclass = msg.get_question
1530
1553
  o.add_question(name, typeclass)
@@ -1616,6 +1639,14 @@ class Resolv
1616
1639
  strings
1617
1640
  end
1618
1641
 
1642
+ def get_list
1643
+ [].tap do |values|
1644
+ while @index < @limit
1645
+ values << yield
1646
+ end
1647
+ end
1648
+ end
1649
+
1619
1650
  def get_name
1620
1651
  return Name.new(self.get_labels)
1621
1652
  end
@@ -1676,6 +1707,378 @@ class Resolv
1676
1707
  end
1677
1708
  end
1678
1709
 
1710
+ ##
1711
+ # SvcParams for service binding RRs. [RFC9460]
1712
+
1713
+ class SvcParams
1714
+ include Enumerable
1715
+
1716
+ ##
1717
+ # Create a list of SvcParams with the given initial content.
1718
+ #
1719
+ # +params+ has to be an enumerable of +SvcParam+s.
1720
+ # If its content has +SvcParam+s with the duplicate key,
1721
+ # the one appears last takes precedence.
1722
+
1723
+ def initialize(params = [])
1724
+ @params = {}
1725
+
1726
+ params.each do |param|
1727
+ add param
1728
+ end
1729
+ end
1730
+
1731
+ ##
1732
+ # Get SvcParam for the given +key+ in this list.
1733
+
1734
+ def [](key)
1735
+ @params[canonical_key(key)]
1736
+ end
1737
+
1738
+ ##
1739
+ # Get the number of SvcParams in this list.
1740
+
1741
+ def count
1742
+ @params.count
1743
+ end
1744
+
1745
+ ##
1746
+ # Get whether this list is empty.
1747
+
1748
+ def empty?
1749
+ @params.empty?
1750
+ end
1751
+
1752
+ ##
1753
+ # Add the SvcParam +param+ to this list, overwriting the existing one with the same key.
1754
+
1755
+ def add(param)
1756
+ @params[param.class.key_number] = param
1757
+ end
1758
+
1759
+ ##
1760
+ # Remove the +SvcParam+ with the given +key+ and return it.
1761
+
1762
+ def delete(key)
1763
+ @params.delete(canonical_key(key))
1764
+ end
1765
+
1766
+ ##
1767
+ # Enumerate the +SvcParam+s in this list.
1768
+
1769
+ def each(&block)
1770
+ return enum_for(:each) unless block
1771
+ @params.each_value(&block)
1772
+ end
1773
+
1774
+ def encode(msg) # :nodoc:
1775
+ @params.keys.sort.each do |key|
1776
+ msg.put_pack('n', key)
1777
+ msg.put_length16 do
1778
+ @params.fetch(key).encode(msg)
1779
+ end
1780
+ end
1781
+ end
1782
+
1783
+ def self.decode(msg) # :nodoc:
1784
+ params = msg.get_list do
1785
+ key, = msg.get_unpack('n')
1786
+ msg.get_length16 do
1787
+ SvcParam::ClassHash[key].decode(msg)
1788
+ end
1789
+ end
1790
+
1791
+ return self.new(params)
1792
+ end
1793
+
1794
+ private
1795
+
1796
+ def canonical_key(key) # :nodoc:
1797
+ case key
1798
+ when Integer
1799
+ key
1800
+ when /\Akey(\d+)\z/
1801
+ Integer($1)
1802
+ when Symbol
1803
+ SvcParam::ClassHash[key].key_number
1804
+ else
1805
+ raise TypeError, 'key must be either String or Symbol'
1806
+ end
1807
+ end
1808
+ end
1809
+
1810
+
1811
+ ##
1812
+ # Base class for SvcParam. [RFC9460]
1813
+
1814
+ class SvcParam
1815
+
1816
+ ##
1817
+ # Get the presentation name of the SvcParamKey.
1818
+
1819
+ def self.key_name
1820
+ const_get(:KeyName)
1821
+ end
1822
+
1823
+ ##
1824
+ # Get the registered number of the SvcParamKey.
1825
+
1826
+ def self.key_number
1827
+ const_get(:KeyNumber)
1828
+ end
1829
+
1830
+ ClassHash = Hash.new do |h, key| # :nodoc:
1831
+ case key
1832
+ when Integer
1833
+ Generic.create(key)
1834
+ when /\Akey(?<key>\d+)\z/
1835
+ Generic.create(key.to_int)
1836
+ when Symbol
1837
+ raise KeyError, "unknown key #{key}"
1838
+ else
1839
+ raise TypeError, 'key must be either String or Symbol'
1840
+ end
1841
+ end
1842
+
1843
+ ##
1844
+ # Generic SvcParam abstract class.
1845
+
1846
+ class Generic < SvcParam
1847
+
1848
+ ##
1849
+ # SvcParamValue in wire-format byte string.
1850
+
1851
+ attr_reader :value
1852
+
1853
+ ##
1854
+ # Create generic SvcParam
1855
+
1856
+ def initialize(value)
1857
+ @value = value
1858
+ end
1859
+
1860
+ def encode(msg) # :nodoc:
1861
+ msg.put_bytes(@value)
1862
+ end
1863
+
1864
+ def self.decode(msg) # :nodoc:
1865
+ return self.new(msg.get_bytes)
1866
+ end
1867
+
1868
+ def self.create(key_number)
1869
+ c = Class.new(Generic)
1870
+ key_name = :"key#{key_number}"
1871
+ c.const_set(:KeyName, key_name)
1872
+ c.const_set(:KeyNumber, key_number)
1873
+ self.const_set(:"Key#{key_number}", c)
1874
+ ClassHash[key_name] = ClassHash[key_number] = c
1875
+ return c
1876
+ end
1877
+ end
1878
+
1879
+ ##
1880
+ # "mandatory" SvcParam -- Mandatory keys in service binding RR
1881
+
1882
+ class Mandatory < SvcParam
1883
+ KeyName = :mandatory
1884
+ KeyNumber = 0
1885
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1886
+
1887
+ ##
1888
+ # Mandatory keys.
1889
+
1890
+ attr_reader :keys
1891
+
1892
+ ##
1893
+ # Initialize "mandatory" ScvParam.
1894
+
1895
+ def initialize(keys)
1896
+ @keys = keys.map(&:to_int)
1897
+ end
1898
+
1899
+ def encode(msg) # :nodoc:
1900
+ @keys.sort.each do |key|
1901
+ msg.put_pack('n', key)
1902
+ end
1903
+ end
1904
+
1905
+ def self.decode(msg) # :nodoc:
1906
+ keys = msg.get_list { msg.get_unpack('n')[0] }
1907
+ return self.new(keys)
1908
+ end
1909
+ end
1910
+
1911
+ ##
1912
+ # "alpn" SvcParam -- Additional supported protocols
1913
+
1914
+ class ALPN < SvcParam
1915
+ KeyName = :alpn
1916
+ KeyNumber = 1
1917
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1918
+
1919
+ ##
1920
+ # Supported protocol IDs.
1921
+
1922
+ attr_reader :protocol_ids
1923
+
1924
+ ##
1925
+ # Initialize "alpn" ScvParam.
1926
+
1927
+ def initialize(protocol_ids)
1928
+ @protocol_ids = protocol_ids.map(&:to_str)
1929
+ end
1930
+
1931
+ def encode(msg) # :nodoc:
1932
+ msg.put_string_list(@protocol_ids)
1933
+ end
1934
+
1935
+ def self.decode(msg) # :nodoc:
1936
+ return self.new(msg.get_string_list)
1937
+ end
1938
+ end
1939
+
1940
+ ##
1941
+ # "no-default-alpn" SvcParam -- No support for default protocol
1942
+
1943
+ class NoDefaultALPN < SvcParam
1944
+ KeyName = :'no-default-alpn'
1945
+ KeyNumber = 2
1946
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1947
+
1948
+ def encode(msg) # :nodoc:
1949
+ # no payload
1950
+ end
1951
+
1952
+ def self.decode(msg) # :nodoc:
1953
+ return self.new
1954
+ end
1955
+ end
1956
+
1957
+ ##
1958
+ # "port" SvcParam -- Port for alternative endpoint
1959
+
1960
+ class Port < SvcParam
1961
+ KeyName = :port
1962
+ KeyNumber = 3
1963
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1964
+
1965
+ ##
1966
+ # Port number.
1967
+
1968
+ attr_reader :port
1969
+
1970
+ ##
1971
+ # Initialize "port" ScvParam.
1972
+
1973
+ def initialize(port)
1974
+ @port = port.to_int
1975
+ end
1976
+
1977
+ def encode(msg) # :nodoc:
1978
+ msg.put_pack('n', @port)
1979
+ end
1980
+
1981
+ def self.decode(msg) # :nodoc:
1982
+ port, = msg.get_unpack('n')
1983
+ return self.new(port)
1984
+ end
1985
+ end
1986
+
1987
+ ##
1988
+ # "ipv4hint" SvcParam -- IPv4 address hints
1989
+
1990
+ class IPv4Hint < SvcParam
1991
+ KeyName = :ipv4hint
1992
+ KeyNumber = 4
1993
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
1994
+
1995
+ ##
1996
+ # Set of IPv4 addresses.
1997
+
1998
+ attr_reader :addresses
1999
+
2000
+ ##
2001
+ # Initialize "ipv4hint" ScvParam.
2002
+
2003
+ def initialize(addresses)
2004
+ @addresses = addresses.map {|address| IPv4.create(address) }
2005
+ end
2006
+
2007
+ def encode(msg) # :nodoc:
2008
+ @addresses.each do |address|
2009
+ msg.put_bytes(address.address)
2010
+ end
2011
+ end
2012
+
2013
+ def self.decode(msg) # :nodoc:
2014
+ addresses = msg.get_list { IPv4.new(msg.get_bytes(4)) }
2015
+ return self.new(addresses)
2016
+ end
2017
+ end
2018
+
2019
+ ##
2020
+ # "ipv6hint" SvcParam -- IPv6 address hints
2021
+
2022
+ class IPv6Hint < SvcParam
2023
+ KeyName = :ipv6hint
2024
+ KeyNumber = 6
2025
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
2026
+
2027
+ ##
2028
+ # Set of IPv6 addresses.
2029
+
2030
+ attr_reader :addresses
2031
+
2032
+ ##
2033
+ # Initialize "ipv6hint" ScvParam.
2034
+
2035
+ def initialize(addresses)
2036
+ @addresses = addresses.map {|address| IPv6.create(address) }
2037
+ end
2038
+
2039
+ def encode(msg) # :nodoc:
2040
+ @addresses.each do |address|
2041
+ msg.put_bytes(address.address)
2042
+ end
2043
+ end
2044
+
2045
+ def self.decode(msg) # :nodoc:
2046
+ addresses = msg.get_list { IPv6.new(msg.get_bytes(16)) }
2047
+ return self.new(addresses)
2048
+ end
2049
+ end
2050
+
2051
+ ##
2052
+ # "dohpath" SvcParam -- DNS over HTTPS path template [RFC9461]
2053
+
2054
+ class DoHPath < SvcParam
2055
+ KeyName = :dohpath
2056
+ KeyNumber = 7
2057
+ ClassHash[KeyName] = ClassHash[KeyNumber] = self # :nodoc:
2058
+
2059
+ ##
2060
+ # URI template for DoH queries.
2061
+
2062
+ attr_reader :template
2063
+
2064
+ ##
2065
+ # Initialize "dohpath" ScvParam.
2066
+
2067
+ def initialize(template)
2068
+ @template = template.encode('utf-8')
2069
+ end
2070
+
2071
+ def encode(msg) # :nodoc:
2072
+ msg.put_bytes(@template)
2073
+ end
2074
+
2075
+ def self.decode(msg) # :nodoc:
2076
+ template = msg.get_bytes.force_encoding('utf-8')
2077
+ return self.new(template)
2078
+ end
2079
+ end
2080
+ end
2081
+
1679
2082
  ##
1680
2083
  # A DNS query abstract class.
1681
2084
 
@@ -2328,7 +2731,7 @@ class Resolv
2328
2731
  msg.put_pack("n", @priority)
2329
2732
  msg.put_pack("n", @weight)
2330
2733
  msg.put_pack("n", @port)
2331
- msg.put_name(@target)
2734
+ msg.put_name(@target, compress: false)
2332
2735
  end
2333
2736
 
2334
2737
  def self.decode_rdata(msg) # :nodoc:
@@ -2339,6 +2742,84 @@ class Resolv
2339
2742
  return self.new(priority, weight, port, target)
2340
2743
  end
2341
2744
  end
2745
+
2746
+ ##
2747
+ # Common implementation for SVCB-compatible resource records.
2748
+
2749
+ class ServiceBinding
2750
+
2751
+ ##
2752
+ # Create a service binding resource record.
2753
+
2754
+ def initialize(priority, target, params = [])
2755
+ @priority = priority.to_int
2756
+ @target = Name.create(target)
2757
+ @params = SvcParams.new(params)
2758
+ end
2759
+
2760
+ ##
2761
+ # The priority of this target host.
2762
+ #
2763
+ # The range is 0-65535.
2764
+ # If set to 0, this RR is in AliasMode. Otherwise, it is in ServiceMode.
2765
+
2766
+ attr_reader :priority
2767
+
2768
+ ##
2769
+ # The domain name of the target host.
2770
+
2771
+ attr_reader :target
2772
+
2773
+ ##
2774
+ # The service paramters for the target host.
2775
+
2776
+ attr_reader :params
2777
+
2778
+ ##
2779
+ # Whether this RR is in AliasMode.
2780
+
2781
+ def alias_mode?
2782
+ self.priority == 0
2783
+ end
2784
+
2785
+ ##
2786
+ # Whether this RR is in ServiceMode.
2787
+
2788
+ def service_mode?
2789
+ !alias_mode?
2790
+ end
2791
+
2792
+ def encode_rdata(msg) # :nodoc:
2793
+ msg.put_pack("n", @priority)
2794
+ msg.put_name(@target, compress: false)
2795
+ @params.encode(msg)
2796
+ end
2797
+
2798
+ def self.decode_rdata(msg) # :nodoc:
2799
+ priority, = msg.get_unpack("n")
2800
+ target = msg.get_name
2801
+ params = SvcParams.decode(msg)
2802
+ return self.new(priority, target, params)
2803
+ end
2804
+ end
2805
+
2806
+ ##
2807
+ # SVCB resource record [RFC9460]
2808
+
2809
+ class SVCB < ServiceBinding
2810
+ TypeValue = 64
2811
+ ClassValue = IN::ClassValue
2812
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2813
+ end
2814
+
2815
+ ##
2816
+ # HTTPS resource record [RFC9460]
2817
+
2818
+ class HTTPS < ServiceBinding
2819
+ TypeValue = 65
2820
+ ClassValue = IN::ClassValue
2821
+ ClassHash[[TypeValue, ClassValue]] = self # :nodoc:
2822
+ end
2342
2823
  end
2343
2824
  end
2344
2825
  end
@@ -2464,7 +2945,7 @@ class Resolv
2464
2945
  Regex_8HexLinkLocal = /\A
2465
2946
  [Ff][Ee]80
2466
2947
  (?::[0-9A-Fa-f]{1,4}){7}
2467
- %[0-9A-Za-z]+
2948
+ %[-0-9A-Za-z._~]+
2468
2949
  \z/x
2469
2950
 
2470
2951
  ##
@@ -2478,7 +2959,7 @@ class Resolv
2478
2959
  |
2479
2960
  :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
2480
2961
  )?
2481
- :[0-9A-Fa-f]{1,4}%[0-9A-Za-z.]+
2962
+ :[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+
2482
2963
  \z/x
2483
2964
 
2484
2965
  ##
@@ -2558,11 +3039,7 @@ class Resolv
2558
3039
  attr_reader :address
2559
3040
 
2560
3041
  def to_s # :nodoc:
2561
- address = sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *@address.unpack("nnnnnnnn"))
2562
- unless address.sub!(/(^|:)0(:0)+(:|$)/, '::')
2563
- address.sub!(/(^|:)0(:|$)/, '::')
2564
- end
2565
- return address
3042
+ sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *@address.unpack("nnnnnnnn")).sub(/(^|:)0(:0)+(:|$)/, '::')
2566
3043
  end
2567
3044
 
2568
3045
  def inspect # :nodoc:
data/resolv.gemspec CHANGED
@@ -1,6 +1,13 @@
1
+ name = File.basename(__FILE__, ".gemspec")
2
+ version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir|
3
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
4
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
5
+ end rescue nil
6
+ end
7
+
1
8
  Gem::Specification.new do |spec|
2
- spec.name = "resolv"
3
- spec.version = "0.2.1"
9
+ spec.name = name
10
+ spec.version = version
4
11
  spec.authors = ["Tanaka Akira"]
5
12
  spec.email = ["akr@fsij.org"]
6
13
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resolv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanaka Akira
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2023-12-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Thread-aware DNS resolver library in Ruby.
14
14
  email:
@@ -17,6 +17,7 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - ".github/dependabot.yml"
20
21
  - ".github/workflows/test.yml"
21
22
  - ".gitignore"
22
23
  - Gemfile
@@ -49,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
50
  - !ruby/object:Gem::Version
50
51
  version: '0'
51
52
  requirements: []
52
- rubygems_version: 3.3.0.dev
53
+ rubygems_version: 3.5.0.dev
53
54
  signing_key:
54
55
  specification_version: 4
55
56
  summary: Thread-aware DNS resolver library in Ruby.