resolv 0.6.2 → 0.7.2
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 +4 -4
- data/.document +4 -0
- data/ext/win32/resolv/extconf.rb +2 -1
- data/ext/win32/resolv/lib/resolv.rb +47 -85
- data/ext/win32/resolv/resolv.c +203 -10
- data/lib/resolv.rb +130 -26
- metadata +3 -12
- data/.git-blame-ignore-revs +0 -7
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/push_gem.yml +0 -46
- data/.github/workflows/test.yml +0 -52
- data/.gitignore +0 -11
- data/Gemfile +0 -8
- data/Rakefile +0 -18
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/resolv.gemspec +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 38de4f14ddb183350d35593550caa34f9694644fb9d2fc79bd275d92d17ee338
|
|
4
|
+
data.tar.gz: 00d4977e89fb7cd8ec4a772c481d63e49fd4441b90c7ec5be42a79294ab3da19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 175ca63aa1f82ebabc499bbcd8eedf17c33ff220c439187a1c5778ca2e74926d15651a720c0bb5f615a698747252d8f9cd82c5db5fb25d28a4d1e63cb696acf1
|
|
7
|
+
data.tar.gz: 8789721febc5b7a96a8bcfdc51dd503afefa648a6d7057e6951b77d1fb514c613e35524ef9680e4ef6d4ad49e310a0fa2d1e92a972eae0e8f23969519c7db1d9
|
data/.document
ADDED
data/ext/win32/resolv/extconf.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'mkmf'
|
|
2
|
-
if RUBY_ENGINE == "ruby" and have_library('iphlpapi', 'GetNetworkParams')
|
|
2
|
+
if RUBY_ENGINE == "ruby" and have_library('iphlpapi', 'GetNetworkParams', ['windows.h', 'iphlpapi.h'])
|
|
3
|
+
have_library('advapi32', 'RegGetValueW', ['windows.h'])
|
|
3
4
|
create_makefile('win32/resolv')
|
|
4
5
|
else
|
|
5
6
|
File.write('Makefile', "all clean install:\n\t@echo Done: $(@)\n")
|
|
@@ -4,8 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
=end
|
|
6
6
|
|
|
7
|
+
require 'win32/resolv.so'
|
|
8
|
+
|
|
7
9
|
module Win32
|
|
8
10
|
module Resolv
|
|
11
|
+
# Error at Win32 API
|
|
12
|
+
class Error < StandardError
|
|
13
|
+
# +code+ Win32 Error code
|
|
14
|
+
# +message+ Formatted message for +code+
|
|
15
|
+
def initialize(code, message)
|
|
16
|
+
super(message)
|
|
17
|
+
@code = code
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Win32 error code
|
|
21
|
+
attr_reader :code
|
|
22
|
+
end
|
|
23
|
+
|
|
9
24
|
def self.get_hosts_path
|
|
10
25
|
path = get_hosts_dir
|
|
11
26
|
path = File.expand_path('hosts', path)
|
|
@@ -29,115 +44,62 @@ module Win32
|
|
|
29
44
|
end
|
|
30
45
|
[ search, nameserver ]
|
|
31
46
|
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
begin
|
|
36
|
-
require 'win32/resolv.so'
|
|
37
|
-
rescue LoadError
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
module Win32
|
|
41
|
-
#====================================================================
|
|
42
|
-
# Windows NT
|
|
43
|
-
#====================================================================
|
|
44
|
-
module Resolv
|
|
45
|
-
begin
|
|
46
|
-
require 'win32/registry'
|
|
47
|
-
module SZ
|
|
48
|
-
refine Registry do
|
|
49
|
-
# ad hoc workaround for broken registry
|
|
50
|
-
def read_s(key)
|
|
51
|
-
type, str = read(key)
|
|
52
|
-
unless type == Registry::REG_SZ
|
|
53
|
-
warn "Broken registry, #{name}\\#{key} was #{Registry.type2name(type)}, ignored"
|
|
54
|
-
return String.new
|
|
55
|
-
end
|
|
56
|
-
str
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
using SZ
|
|
61
|
-
rescue LoadError
|
|
62
|
-
require "open3"
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
|
|
66
47
|
|
|
67
48
|
class << self
|
|
68
49
|
private
|
|
69
50
|
def get_hosts_dir
|
|
70
|
-
|
|
51
|
+
tcpip_params do |params|
|
|
52
|
+
params.value('DataBasePath')
|
|
53
|
+
end
|
|
71
54
|
end
|
|
72
55
|
|
|
73
56
|
def get_info
|
|
74
57
|
search = nil
|
|
75
58
|
nameserver = get_dns_server_list
|
|
76
59
|
|
|
77
|
-
|
|
78
|
-
|
|
60
|
+
tcpip_params do |params|
|
|
61
|
+
slist = params.value('SearchList')
|
|
62
|
+
search = slist.split(/,\s*/) if slist and !slist.empty?
|
|
79
63
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
64
|
+
if add_search = search.nil?
|
|
65
|
+
search = []
|
|
66
|
+
domain = params.value('Domain')
|
|
83
67
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
68
|
+
if domain and !domain.empty?
|
|
69
|
+
search = [ domain ]
|
|
70
|
+
udmnd = params.value('UseDomainNameDevolution')
|
|
71
|
+
if udmnd&.nonzero?
|
|
72
|
+
if /^\w+\./ =~ domain
|
|
73
|
+
devo = $'
|
|
74
|
+
end
|
|
90
75
|
end
|
|
91
76
|
end
|
|
92
77
|
end
|
|
93
|
-
end
|
|
94
78
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
end
|
|
101
|
-
else
|
|
102
|
-
cmd = "Get-ChildItem 'HKLM:\\#{TCPIP_NT}\\Interfaces' | ForEach-Object { $_.PSChildName }"
|
|
103
|
-
output, _ = Open3.capture2('powershell', '-Command', cmd)
|
|
104
|
-
output.split(/\n+/)
|
|
79
|
+
params.open('Interfaces') do |reg|
|
|
80
|
+
reg.each_key do |iface|
|
|
81
|
+
next unless ns = %w[NameServer DhcpNameServer].find do |key|
|
|
82
|
+
ns = iface.value(key)
|
|
83
|
+
break ns.split(/[,\s]\s*/) if ns and !ns.empty?
|
|
105
84
|
end
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
next unless ns = %w[NameServer DhcpNameServer].find do |key|
|
|
109
|
-
ns = get_item_property(TCPIP_NT + '\Interfaces' + "\\#{iface}", key)
|
|
110
|
-
break ns.split(/[,\s]\s*/) unless ns.empty?
|
|
111
|
-
end
|
|
86
|
+
next if (nameserver & ns).empty?
|
|
112
87
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
88
|
+
if add_search
|
|
89
|
+
[ 'Domain', 'DhcpDomain' ].each do |key|
|
|
90
|
+
dom = iface.value(key)
|
|
91
|
+
if dom and !dom.empty?
|
|
92
|
+
search.concat(dom.split(/,\s*/))
|
|
93
|
+
break
|
|
94
|
+
end
|
|
95
|
+
end
|
|
121
96
|
end
|
|
122
97
|
end
|
|
123
98
|
end
|
|
124
|
-
end
|
|
125
|
-
search << devo if add_search and devo
|
|
126
|
-
[ search.uniq, nameserver.uniq ]
|
|
127
|
-
end
|
|
128
99
|
|
|
129
|
-
|
|
130
|
-
if defined?(Win32::Registry)
|
|
131
|
-
Registry::HKEY_LOCAL_MACHINE.open(path) do |reg|
|
|
132
|
-
expand ? reg.read_s_expand(name) : reg.read_s(name)
|
|
133
|
-
rescue Registry::Error
|
|
134
|
-
""
|
|
135
|
-
end
|
|
136
|
-
else
|
|
137
|
-
cmd = "Get-ItemProperty -Path 'HKLM:\\#{path}' -Name '#{name}' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty '#{name}'"
|
|
138
|
-
output, _ = Open3.capture2('powershell', '-Command', cmd)
|
|
139
|
-
output.strip
|
|
100
|
+
search << devo if add_search and devo
|
|
140
101
|
end
|
|
102
|
+
[ search.uniq, nameserver.uniq ]
|
|
141
103
|
end
|
|
142
104
|
end
|
|
143
105
|
end
|
data/ext/win32/resolv/resolv.c
CHANGED
|
@@ -1,24 +1,56 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
#include <ruby/encoding.h>
|
|
3
3
|
#include <windows.h>
|
|
4
|
+
#include <windns.h>
|
|
4
5
|
#ifndef NTDDI_VERSION
|
|
5
6
|
#define NTDDI_VERSION 0x06000000
|
|
6
7
|
#endif
|
|
7
8
|
#include <iphlpapi.h>
|
|
8
9
|
|
|
10
|
+
#ifndef numberof
|
|
11
|
+
#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
|
|
12
|
+
#endif
|
|
13
|
+
|
|
9
14
|
static VALUE
|
|
10
15
|
w32error_make_error(DWORD e)
|
|
11
16
|
{
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
char buffer[512], *p;
|
|
18
|
+
DWORD source = 0;
|
|
19
|
+
VALUE args[2];
|
|
20
|
+
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
|
21
|
+
FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
|
|
22
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
|
23
|
+
buffer, sizeof(buffer), NULL)) {
|
|
24
|
+
snprintf(buffer, sizeof(buffer), "Unknown Error %lu", (unsigned long)e);
|
|
25
|
+
}
|
|
26
|
+
p = buffer;
|
|
27
|
+
while ((p = strpbrk(p, "\r\n")) != NULL) {
|
|
28
|
+
memmove(p, p + 1, strlen(p));
|
|
29
|
+
if (!p[1]) {
|
|
30
|
+
p[0] = '\0';
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
args[0] = ULONG2NUM(e);
|
|
35
|
+
args[1] = rb_str_new_cstr(buffer);
|
|
36
|
+
return rb_class_new_instance(2, args, rb_path2class("Win32::Resolv::Error"));
|
|
14
37
|
}
|
|
15
38
|
|
|
16
|
-
NORETURN(static void w32error_raise(DWORD e));
|
|
17
|
-
|
|
18
39
|
static void
|
|
19
|
-
|
|
40
|
+
w32error_check(DWORD e)
|
|
41
|
+
{
|
|
42
|
+
if (e != NO_ERROR) {
|
|
43
|
+
rb_exc_raise(w32error_make_error(e));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static VALUE
|
|
48
|
+
wchar_to_utf8(const WCHAR *w, int n)
|
|
20
49
|
{
|
|
21
|
-
|
|
50
|
+
int clen = WideCharToMultiByte(CP_UTF8, 0, w, n, NULL, 0, NULL, NULL);
|
|
51
|
+
VALUE str = rb_enc_str_new(NULL, clen, rb_utf8_encoding());
|
|
52
|
+
WideCharToMultiByte(CP_UTF8, 0, w, n, RSTRING_PTR(str), clen, NULL, NULL);
|
|
53
|
+
return str;
|
|
22
54
|
}
|
|
23
55
|
|
|
24
56
|
static VALUE
|
|
@@ -30,9 +62,7 @@ get_dns_server_list(VALUE self)
|
|
|
30
62
|
VALUE buf, nameservers = Qnil;
|
|
31
63
|
|
|
32
64
|
ret = GetNetworkParams(NULL, &buflen);
|
|
33
|
-
if (ret !=
|
|
34
|
-
w32error_raise(ret);
|
|
35
|
-
}
|
|
65
|
+
if (ret != ERROR_BUFFER_OVERFLOW) w32error_check(ret);
|
|
36
66
|
fixedinfo = ALLOCV(buf, buflen);
|
|
37
67
|
ret = GetNetworkParams(fixedinfo, &buflen);
|
|
38
68
|
if (ret == NO_ERROR) {
|
|
@@ -46,18 +76,181 @@ get_dns_server_list(VALUE self)
|
|
|
46
76
|
} while ((ipaddr = ipaddr->Next) != NULL);
|
|
47
77
|
}
|
|
48
78
|
ALLOCV_END(buf);
|
|
49
|
-
|
|
79
|
+
w32error_check(ret);
|
|
50
80
|
|
|
51
81
|
return nameservers;
|
|
52
82
|
}
|
|
53
83
|
|
|
84
|
+
|
|
85
|
+
static const WCHAR TCPIP_Params[] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
|
|
86
|
+
|
|
87
|
+
static void
|
|
88
|
+
hkey_finalize(void *p)
|
|
89
|
+
{
|
|
90
|
+
RegCloseKey((HKEY)p);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static const rb_data_type_t hkey_type = {
|
|
94
|
+
"RegKey",
|
|
95
|
+
{0, hkey_finalize},
|
|
96
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
static VALUE
|
|
100
|
+
hkey_close(VALUE self)
|
|
101
|
+
{
|
|
102
|
+
RegCloseKey((HKEY)DATA_PTR(self));
|
|
103
|
+
DATA_PTR(self) = 0;
|
|
104
|
+
return self;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static VALUE reg_key_class;
|
|
108
|
+
|
|
109
|
+
static VALUE
|
|
110
|
+
reg_open_key(VALUE klass, HKEY hkey, const WCHAR *wname)
|
|
111
|
+
{
|
|
112
|
+
VALUE k = TypedData_Wrap_Struct(klass, &hkey_type, NULL);
|
|
113
|
+
DWORD e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
|
|
114
|
+
if (e == ERROR_FILE_NOT_FOUND) return Qnil;
|
|
115
|
+
w32error_check(e);
|
|
116
|
+
return rb_ensure(rb_yield, k, hkey_close, k);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static VALUE
|
|
120
|
+
tcpip_params_open(VALUE klass)
|
|
121
|
+
{
|
|
122
|
+
return reg_open_key(reg_key_class, HKEY_LOCAL_MACHINE, TCPIP_Params);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static int
|
|
126
|
+
to_wname(VALUE *name, WCHAR *wname, int wlen)
|
|
127
|
+
{
|
|
128
|
+
const char *n = StringValueCStr(*name);
|
|
129
|
+
int nlen = RSTRING_LEN(*name);
|
|
130
|
+
int len = MultiByteToWideChar(CP_UTF8, 0, n, nlen, wname, wlen - 1);
|
|
131
|
+
if (len == 0) w32error_check(GetLastError());
|
|
132
|
+
if (len >= wlen) rb_raise(rb_eArgError, "too long name");
|
|
133
|
+
wname[len] = L'\0';
|
|
134
|
+
return len;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static VALUE
|
|
138
|
+
reg_open(VALUE self, VALUE name)
|
|
139
|
+
{
|
|
140
|
+
HKEY hkey = DATA_PTR(self);
|
|
141
|
+
WCHAR wname[256];
|
|
142
|
+
to_wname(&name, wname, numberof(wname));
|
|
143
|
+
return reg_open_key(CLASS_OF(self), hkey, wname);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
static VALUE
|
|
148
|
+
reg_each_key(VALUE self)
|
|
149
|
+
{
|
|
150
|
+
WCHAR wname[256];
|
|
151
|
+
HKEY hkey = DATA_PTR(self);
|
|
152
|
+
VALUE k = TypedData_Wrap_Struct(CLASS_OF(self), &hkey_type, NULL);
|
|
153
|
+
DWORD i, e, n;
|
|
154
|
+
for (i = 0; n = numberof(wname), (e = RegEnumKeyExW(hkey, i, wname, &n, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS; i++) {
|
|
155
|
+
e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
|
|
156
|
+
w32error_check(e);
|
|
157
|
+
rb_ensure(rb_yield, k, hkey_close, k);
|
|
158
|
+
}
|
|
159
|
+
if (e != ERROR_NO_MORE_ITEMS) w32error_check(e);
|
|
160
|
+
return self;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static inline DWORD
|
|
164
|
+
swap_dw(DWORD x)
|
|
165
|
+
{
|
|
166
|
+
#if defined(_MSC_VER)
|
|
167
|
+
return _byteswap_ulong(x);
|
|
168
|
+
#else
|
|
169
|
+
return __builtin_bswap32(x);
|
|
170
|
+
#endif
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static VALUE
|
|
174
|
+
reg_value(VALUE self, VALUE name)
|
|
175
|
+
{
|
|
176
|
+
HKEY hkey = DATA_PTR(self);
|
|
177
|
+
DWORD type = 0, size = 0, e;
|
|
178
|
+
VALUE result, value_buffer;
|
|
179
|
+
void *buffer;
|
|
180
|
+
WCHAR wname[256];
|
|
181
|
+
to_wname(&name, wname, numberof(wname));
|
|
182
|
+
e = RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type, NULL, &size);
|
|
183
|
+
if (e == ERROR_FILE_NOT_FOUND) return Qnil;
|
|
184
|
+
w32error_check(e);
|
|
185
|
+
# define get_value_2nd(data, dsize) do { \
|
|
186
|
+
DWORD type2 = type; \
|
|
187
|
+
w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type2, data, dsize)); \
|
|
188
|
+
if (type != type2) { \
|
|
189
|
+
rb_raise(rb_eRuntimeError, "registry value type changed %lu -> %lu", \
|
|
190
|
+
(unsigned long)type, (unsigned long)type2); \
|
|
191
|
+
} \
|
|
192
|
+
} while (0)
|
|
193
|
+
|
|
194
|
+
switch (type) {
|
|
195
|
+
case REG_DWORD: case REG_DWORD_BIG_ENDIAN:
|
|
196
|
+
{
|
|
197
|
+
DWORD d;
|
|
198
|
+
if (size != sizeof(d)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
|
|
199
|
+
w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_DWORD, &type, &d, &size));
|
|
200
|
+
if (type == REG_DWORD_BIG_ENDIAN) d = swap_dw(d);
|
|
201
|
+
return ULONG2NUM(d);
|
|
202
|
+
}
|
|
203
|
+
case REG_QWORD:
|
|
204
|
+
{
|
|
205
|
+
QWORD q;
|
|
206
|
+
if (size != sizeof(q)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
|
|
207
|
+
w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_QWORD, &type, &q, &size));
|
|
208
|
+
return ULL2NUM(q);
|
|
209
|
+
}
|
|
210
|
+
case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ:
|
|
211
|
+
if (size % sizeof(WCHAR)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
|
|
212
|
+
buffer = ALLOCV_N(char, value_buffer, size);
|
|
213
|
+
get_value_2nd(buffer, &size);
|
|
214
|
+
if (type == REG_MULTI_SZ) {
|
|
215
|
+
const WCHAR *w = (WCHAR *)buffer;
|
|
216
|
+
result = rb_ary_new();
|
|
217
|
+
size /= sizeof(WCHAR);
|
|
218
|
+
size -= 1;
|
|
219
|
+
for (size_t i = 0; i < size; ++i) {
|
|
220
|
+
int n = lstrlenW(w+i);
|
|
221
|
+
rb_ary_push(result, wchar_to_utf8(w+i, n));
|
|
222
|
+
i += n;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
result = wchar_to_utf8((WCHAR *)buffer, lstrlenW((WCHAR *)buffer));
|
|
227
|
+
}
|
|
228
|
+
ALLOCV_END(value_buffer);
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
result = rb_str_new(0, size);
|
|
232
|
+
get_value_2nd(RSTRING_PTR(result), &size);
|
|
233
|
+
rb_str_set_len(result, size);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
|
|
54
239
|
void
|
|
55
240
|
InitVM_resolv(void)
|
|
56
241
|
{
|
|
57
242
|
VALUE mWin32 = rb_define_module("Win32");
|
|
58
243
|
VALUE resolv = rb_define_module_under(mWin32, "Resolv");
|
|
59
244
|
VALUE singl = rb_singleton_class(resolv);
|
|
245
|
+
VALUE regkey = rb_define_class_under(resolv, "registry key", rb_cObject);
|
|
246
|
+
|
|
247
|
+
reg_key_class = regkey;
|
|
248
|
+
rb_undef_alloc_func(regkey);
|
|
60
249
|
rb_define_private_method(singl, "get_dns_server_list", get_dns_server_list, 0);
|
|
250
|
+
rb_define_private_method(singl, "tcpip_params", tcpip_params_open, 0);
|
|
251
|
+
rb_define_method(regkey, "open", reg_open, 1);
|
|
252
|
+
rb_define_method(regkey, "each_key", reg_each_key, 0);
|
|
253
|
+
rb_define_method(regkey, "value", reg_value, 1);
|
|
61
254
|
}
|
|
62
255
|
|
|
63
256
|
void
|
data/lib/resolv.rb
CHANGED
|
@@ -4,6 +4,7 @@ require 'socket'
|
|
|
4
4
|
require 'timeout'
|
|
5
5
|
require 'io/wait'
|
|
6
6
|
require 'securerandom'
|
|
7
|
+
require 'rbconfig'
|
|
7
8
|
|
|
8
9
|
# Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can
|
|
9
10
|
# handle multiple DNS requests concurrently without blocking the entire Ruby
|
|
@@ -33,7 +34,8 @@ require 'securerandom'
|
|
|
33
34
|
|
|
34
35
|
class Resolv
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
# The version string
|
|
38
|
+
VERSION = "0.7.2"
|
|
37
39
|
|
|
38
40
|
##
|
|
39
41
|
# Looks up the first IP address for +name+.
|
|
@@ -173,21 +175,19 @@ class Resolv
|
|
|
173
175
|
|
|
174
176
|
class ResolvTimeout < Timeout::Error; end
|
|
175
177
|
|
|
176
|
-
WINDOWS = /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
|
|
177
|
-
private_constant :WINDOWS
|
|
178
|
-
|
|
179
178
|
##
|
|
180
179
|
# Resolv::Hosts is a hostname resolver that uses the system hosts file.
|
|
181
180
|
|
|
182
181
|
class Hosts
|
|
183
|
-
if
|
|
182
|
+
if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
|
|
184
183
|
begin
|
|
185
184
|
require 'win32/resolv' unless defined?(Win32::Resolv)
|
|
186
|
-
|
|
185
|
+
hosts = Win32::Resolv.get_hosts_path || IO::NULL
|
|
187
186
|
rescue LoadError
|
|
188
187
|
end
|
|
189
188
|
end
|
|
190
|
-
|
|
189
|
+
# The default file name for host names
|
|
190
|
+
DefaultFileName = hosts || '/etc/hosts'
|
|
191
191
|
|
|
192
192
|
##
|
|
193
193
|
# Creates a new Resolv::Hosts, using +filename+ for its data source.
|
|
@@ -487,13 +487,18 @@ class Resolv
|
|
|
487
487
|
# * Resolv::DNS::Resource::IN::A
|
|
488
488
|
# * Resolv::DNS::Resource::IN::AAAA
|
|
489
489
|
# * Resolv::DNS::Resource::IN::ANY
|
|
490
|
+
# * Resolv::DNS::Resource::IN::CAA
|
|
490
491
|
# * Resolv::DNS::Resource::IN::CNAME
|
|
491
492
|
# * Resolv::DNS::Resource::IN::HINFO
|
|
493
|
+
# * Resolv::DNS::Resource::IN::HTTPS
|
|
494
|
+
# * Resolv::DNS::Resource::IN::LOC
|
|
492
495
|
# * Resolv::DNS::Resource::IN::MINFO
|
|
493
496
|
# * Resolv::DNS::Resource::IN::MX
|
|
494
497
|
# * Resolv::DNS::Resource::IN::NS
|
|
495
498
|
# * Resolv::DNS::Resource::IN::PTR
|
|
496
499
|
# * Resolv::DNS::Resource::IN::SOA
|
|
500
|
+
# * Resolv::DNS::Resource::IN::SRV
|
|
501
|
+
# * Resolv::DNS::Resource::IN::SVCB
|
|
497
502
|
# * Resolv::DNS::Resource::IN::TXT
|
|
498
503
|
# * Resolv::DNS::Resource::IN::WKS
|
|
499
504
|
#
|
|
@@ -525,6 +530,8 @@ class Resolv
|
|
|
525
530
|
}
|
|
526
531
|
end
|
|
527
532
|
|
|
533
|
+
# :stopdoc:
|
|
534
|
+
|
|
528
535
|
def fetch_resource(name, typeclass)
|
|
529
536
|
lazy_initialize
|
|
530
537
|
truncated = {}
|
|
@@ -719,7 +726,8 @@ class Resolv
|
|
|
719
726
|
begin
|
|
720
727
|
reply, from = recv_reply(select_result[0])
|
|
721
728
|
rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
|
|
722
|
-
Errno::ECONNRESET # Windows
|
|
729
|
+
Errno::ECONNRESET, # Windows
|
|
730
|
+
EOFError
|
|
723
731
|
# No name server running on the server?
|
|
724
732
|
# Don't wait anymore.
|
|
725
733
|
raise ResolvTimeout
|
|
@@ -928,8 +936,11 @@ class Resolv
|
|
|
928
936
|
end
|
|
929
937
|
|
|
930
938
|
def recv_reply(readable_socks)
|
|
931
|
-
|
|
939
|
+
len_data = readable_socks[0].read(2)
|
|
940
|
+
raise EOFError if len_data.nil? || len_data.bytesize != 2
|
|
941
|
+
len = len_data.unpack('n')[0]
|
|
932
942
|
reply = @socks[0].read(len)
|
|
943
|
+
raise EOFError if reply.nil? || reply.bytesize != len
|
|
933
944
|
return reply, nil
|
|
934
945
|
end
|
|
935
946
|
|
|
@@ -1021,8 +1032,7 @@ class Resolv
|
|
|
1021
1032
|
def Config.default_config_hash(filename="/etc/resolv.conf")
|
|
1022
1033
|
if File.exist? filename
|
|
1023
1034
|
Config.parse_resolv_conf(filename)
|
|
1024
|
-
elsif
|
|
1025
|
-
require 'win32/resolv' unless defined?(Win32::Resolv)
|
|
1035
|
+
elsif defined?(Win32::Resolv)
|
|
1026
1036
|
search, nameserver = Win32::Resolv.get_resolv_info
|
|
1027
1037
|
config_hash = {}
|
|
1028
1038
|
config_hash[:nameserver] = nameserver if nameserver
|
|
@@ -1243,6 +1253,13 @@ class Resolv
|
|
|
1243
1253
|
|
|
1244
1254
|
class Str # :nodoc:
|
|
1245
1255
|
def initialize(string)
|
|
1256
|
+
# A label is limited to 63 octets. [RFC 1035 2.3.4] Checking it here
|
|
1257
|
+
# makes it an invariant of the object: every label, however it was
|
|
1258
|
+
# built, fits in its length octet and cannot wrap it. Callers turn
|
|
1259
|
+
# this into the error their own contract promises.
|
|
1260
|
+
if string.bytesize > 63
|
|
1261
|
+
raise ArgumentError, "DNS label is too long (#{string.bytesize} bytes, max 63): #{string.inspect}"
|
|
1262
|
+
end
|
|
1246
1263
|
@string = string
|
|
1247
1264
|
# case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
|
|
1248
1265
|
# This assumes @string is given in ASCII compatible encoding.
|
|
@@ -1288,7 +1305,26 @@ class Resolv
|
|
|
1288
1305
|
when Name
|
|
1289
1306
|
return arg
|
|
1290
1307
|
when String
|
|
1291
|
-
|
|
1308
|
+
# A hostname is runtime data rather than a programming mistake, so
|
|
1309
|
+
# both size limits surface as ResolvError to stay rescuable alongside
|
|
1310
|
+
# the rest of name resolution. The type check below is a caller
|
|
1311
|
+
# mistake and keeps raising ArgumentError.
|
|
1312
|
+
begin
|
|
1313
|
+
labels = Label.split(arg)
|
|
1314
|
+
rescue ArgumentError => e
|
|
1315
|
+
raise ResolvError.new(e.message)
|
|
1316
|
+
end
|
|
1317
|
+
# Label::Str enforces the per-label limit. Only the total is knowable
|
|
1318
|
+
# here, and it counts the encoded form, so size starts at 1 for the
|
|
1319
|
+
# root label's terminating zero octet. [RFC 1035 2.3.4, 3.1]
|
|
1320
|
+
size = 1
|
|
1321
|
+
labels.each do |label|
|
|
1322
|
+
size += 1 + label.string.bytesize
|
|
1323
|
+
if size > 255
|
|
1324
|
+
raise ResolvError.new("DNS name is too long (#{size} octets, max 255): #{arg.inspect}")
|
|
1325
|
+
end
|
|
1326
|
+
end
|
|
1327
|
+
return Name.new(labels, /\.\z/ =~ arg ? true : false)
|
|
1292
1328
|
else
|
|
1293
1329
|
raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
|
|
1294
1330
|
end
|
|
@@ -1410,12 +1446,24 @@ class Resolv
|
|
|
1410
1446
|
@rd == other.rd &&
|
|
1411
1447
|
@ra == other.ra &&
|
|
1412
1448
|
@rcode == other.rcode &&
|
|
1413
|
-
|
|
1449
|
+
question_equal?(other.question) &&
|
|
1414
1450
|
@answer == other.answer &&
|
|
1415
1451
|
@authority == other.authority &&
|
|
1416
1452
|
@additional == other.additional
|
|
1417
1453
|
end
|
|
1418
1454
|
|
|
1455
|
+
# A question holds the resource class itself, and decoding creates a fresh
|
|
1456
|
+
# class for each unknown type, so the classes cannot be compared by
|
|
1457
|
+
# identity alone.
|
|
1458
|
+
private def question_equal?(other_question) # :nodoc:
|
|
1459
|
+
return false unless @question.length == other_question.length
|
|
1460
|
+
@question.zip(other_question) {|(name, typeclass), (o_name, o_typeclass)|
|
|
1461
|
+
return false unless name == o_name &&
|
|
1462
|
+
Resource::Generic.type_class_equal?(typeclass, o_typeclass)
|
|
1463
|
+
}
|
|
1464
|
+
return true
|
|
1465
|
+
end
|
|
1466
|
+
|
|
1419
1467
|
def add_question(name, typeclass)
|
|
1420
1468
|
@question << [Name.create(name), typeclass]
|
|
1421
1469
|
end
|
|
@@ -1522,8 +1570,15 @@ class Resolv
|
|
|
1522
1570
|
end
|
|
1523
1571
|
|
|
1524
1572
|
def put_string(d)
|
|
1525
|
-
|
|
1526
|
-
|
|
1573
|
+
s = d.to_s
|
|
1574
|
+
# A character-string is prefixed by a single length octet, so it can
|
|
1575
|
+
# hold at most 255 octets. [RFC 1035 3.3] Reject anything longer to
|
|
1576
|
+
# avoid silently truncating the length to its low 8 bits (mod 256).
|
|
1577
|
+
if s.bytesize > 255
|
|
1578
|
+
raise ArgumentError, "character-string is too long (#{s.bytesize} bytes, max 255): #{s.inspect}"
|
|
1579
|
+
end
|
|
1580
|
+
self.put_pack("C", s.bytesize)
|
|
1581
|
+
@data << s
|
|
1527
1582
|
end
|
|
1528
1583
|
|
|
1529
1584
|
def put_string_list(ds)
|
|
@@ -1553,7 +1608,17 @@ class Resolv
|
|
|
1553
1608
|
end
|
|
1554
1609
|
|
|
1555
1610
|
def put_label(d)
|
|
1556
|
-
|
|
1611
|
+
s = d.to_s
|
|
1612
|
+
# Label::Str applies this limit when a label is built, so what is left
|
|
1613
|
+
# for here is a raw string handed straight to put_labels. The two ways
|
|
1614
|
+
# an over-long label goes wrong differ: 64 to 255 octets write a length
|
|
1615
|
+
# octet in the reserved or compression pointer range, and 256 or more
|
|
1616
|
+
# wrap it mod 256. Either way the encoded name stops being the name the
|
|
1617
|
+
# caller asked for. [RFC 1035 2.3.4, 4.1.4]
|
|
1618
|
+
if s.bytesize > 63
|
|
1619
|
+
raise ArgumentError, "DNS label is too long (#{s.bytesize} bytes, max 63): #{s.inspect}"
|
|
1620
|
+
end
|
|
1621
|
+
self.put_string(s)
|
|
1557
1622
|
end
|
|
1558
1623
|
end
|
|
1559
1624
|
|
|
@@ -1679,7 +1744,9 @@ class Resolv
|
|
|
1679
1744
|
prev_index = @index
|
|
1680
1745
|
save_index = nil
|
|
1681
1746
|
d = []
|
|
1682
|
-
size
|
|
1747
|
+
# size counts the encoded form, so it starts at 1 for the root
|
|
1748
|
+
# label's terminating zero octet. [RFC 1035 3.1]
|
|
1749
|
+
size = 1
|
|
1683
1750
|
while true
|
|
1684
1751
|
raise DecodeError.new("limit exceeded") if @limit <= @index
|
|
1685
1752
|
case @data.getbyte(@index)
|
|
@@ -1710,6 +1777,11 @@ class Resolv
|
|
|
1710
1777
|
|
|
1711
1778
|
def get_label
|
|
1712
1779
|
return Label::Str.new(self.get_string)
|
|
1780
|
+
rescue ArgumentError => e
|
|
1781
|
+
# A length octet of 64..191 is reserved rather than a label length,
|
|
1782
|
+
# but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
|
|
1783
|
+
# the way the rest of a malformed message is reported.
|
|
1784
|
+
raise DecodeError.new(e.message)
|
|
1713
1785
|
end
|
|
1714
1786
|
|
|
1715
1787
|
def get_question
|
|
@@ -1897,8 +1969,9 @@ class Resolv
|
|
|
1897
1969
|
key_name = :"key#{key_number}"
|
|
1898
1970
|
c.const_set(:KeyName, key_name)
|
|
1899
1971
|
c.const_set(:KeyNumber, key_number)
|
|
1900
|
-
|
|
1901
|
-
|
|
1972
|
+
# Not registered in a constant or in ClassHash. ClassHash creates a
|
|
1973
|
+
# class for every unknown SvcParamKey, so registering them
|
|
1974
|
+
# permanently would let a malicious response exhaust memory.
|
|
1902
1975
|
return c
|
|
1903
1976
|
end
|
|
1904
1977
|
end
|
|
@@ -2205,12 +2278,28 @@ class Resolv
|
|
|
2205
2278
|
return self.new(msg.get_bytes)
|
|
2206
2279
|
end
|
|
2207
2280
|
|
|
2281
|
+
# create makes a fresh class for each decoded resource, so the type and
|
|
2282
|
+
# class values have to be compared instead of the class itself.
|
|
2283
|
+
def self.type_class_equal?(klass, other) # :nodoc:
|
|
2284
|
+
return true if klass.equal?(other)
|
|
2285
|
+
Generic > klass && Generic > other &&
|
|
2286
|
+
klass::TypeValue == other::TypeValue &&
|
|
2287
|
+
klass::ClassValue == other::ClassValue
|
|
2288
|
+
end
|
|
2289
|
+
|
|
2290
|
+
def ==(other) # :nodoc:
|
|
2291
|
+
return other.is_a?(Generic) &&
|
|
2292
|
+
Generic.type_class_equal?(self.class, other.class) &&
|
|
2293
|
+
@data == other.data
|
|
2294
|
+
end
|
|
2295
|
+
|
|
2208
2296
|
def self.create(type_value, class_value) # :nodoc:
|
|
2209
2297
|
c = Class.new(Generic)
|
|
2210
2298
|
c.const_set(:TypeValue, type_value)
|
|
2211
2299
|
c.const_set(:ClassValue, class_value)
|
|
2212
|
-
|
|
2213
|
-
|
|
2300
|
+
# Not registered in a constant or in ClassHash. get_class creates a
|
|
2301
|
+
# class for every unknown (type, class) pair, so registering them
|
|
2302
|
+
# permanently would let a malicious response exhaust memory.
|
|
2214
2303
|
return c
|
|
2215
2304
|
end
|
|
2216
2305
|
end
|
|
@@ -2926,15 +3015,21 @@ class Resolv
|
|
|
2926
3015
|
|
|
2927
3016
|
class IPv4
|
|
2928
3017
|
|
|
2929
|
-
##
|
|
2930
|
-
# Regular expression IPv4 addresses must match.
|
|
2931
|
-
|
|
2932
3018
|
Regex256 = /0
|
|
2933
3019
|
|1(?:[0-9][0-9]?)?
|
|
2934
3020
|
|2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
|
|
2935
|
-
|[3-9][0-9]?/x
|
|
3021
|
+
|[3-9][0-9]?/x # :nodoc:
|
|
3022
|
+
|
|
3023
|
+
##
|
|
3024
|
+
# Regular expression IPv4 addresses must match.
|
|
2936
3025
|
Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
|
|
2937
3026
|
|
|
3027
|
+
##
|
|
3028
|
+
# Creates a new IPv4 address from +arg+ which may be:
|
|
3029
|
+
#
|
|
3030
|
+
# IPv4:: returns +arg+.
|
|
3031
|
+
# String:: +arg+ must match the IPv4::Regex constant
|
|
3032
|
+
|
|
2938
3033
|
def self.create(arg)
|
|
2939
3034
|
case arg
|
|
2940
3035
|
when IPv4
|
|
@@ -3243,13 +3338,15 @@ class Resolv
|
|
|
3243
3338
|
|
|
3244
3339
|
end
|
|
3245
3340
|
|
|
3246
|
-
module LOC
|
|
3341
|
+
module LOC # :nodoc:
|
|
3247
3342
|
|
|
3248
3343
|
##
|
|
3249
3344
|
# A Resolv::LOC::Size
|
|
3250
3345
|
|
|
3251
3346
|
class Size
|
|
3252
3347
|
|
|
3348
|
+
# Regular expression LOC size must match.
|
|
3349
|
+
|
|
3253
3350
|
Regex = /^(\d+\.*\d*)[m]$/
|
|
3254
3351
|
|
|
3255
3352
|
##
|
|
@@ -3275,6 +3372,7 @@ class Resolv
|
|
|
3275
3372
|
end
|
|
3276
3373
|
end
|
|
3277
3374
|
|
|
3375
|
+
# Internal use; use self.create.
|
|
3278
3376
|
def initialize(scalar)
|
|
3279
3377
|
@scalar = scalar
|
|
3280
3378
|
end
|
|
@@ -3312,6 +3410,8 @@ class Resolv
|
|
|
3312
3410
|
|
|
3313
3411
|
class Coord
|
|
3314
3412
|
|
|
3413
|
+
# Regular expression LOC Coord must match.
|
|
3414
|
+
|
|
3315
3415
|
Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
|
|
3316
3416
|
|
|
3317
3417
|
##
|
|
@@ -3341,6 +3441,7 @@ class Resolv
|
|
|
3341
3441
|
end
|
|
3342
3442
|
end
|
|
3343
3443
|
|
|
3444
|
+
# Internal use; use self.create.
|
|
3344
3445
|
def initialize(coordinates,orientation)
|
|
3345
3446
|
unless coordinates.kind_of?(String)
|
|
3346
3447
|
raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
|
|
@@ -3403,6 +3504,8 @@ class Resolv
|
|
|
3403
3504
|
|
|
3404
3505
|
class Alt
|
|
3405
3506
|
|
|
3507
|
+
# Regular expression LOC Alt must match.
|
|
3508
|
+
|
|
3406
3509
|
Regex = /^([+-]*\d+\.*\d*)[m]$/
|
|
3407
3510
|
|
|
3408
3511
|
##
|
|
@@ -3428,6 +3531,7 @@ class Resolv
|
|
|
3428
3531
|
end
|
|
3429
3532
|
end
|
|
3430
3533
|
|
|
3534
|
+
# Internal use; use self.create.
|
|
3431
3535
|
def initialize(altitude)
|
|
3432
3536
|
@altitude = altitude
|
|
3433
3537
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: resolv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tanaka Akira
|
|
@@ -17,23 +17,14 @@ extensions:
|
|
|
17
17
|
- ext/win32/resolv/extconf.rb
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
-
- ".
|
|
21
|
-
- ".github/dependabot.yml"
|
|
22
|
-
- ".github/workflows/push_gem.yml"
|
|
23
|
-
- ".github/workflows/test.yml"
|
|
24
|
-
- ".gitignore"
|
|
20
|
+
- ".document"
|
|
25
21
|
- BSDL
|
|
26
22
|
- COPYING
|
|
27
|
-
- Gemfile
|
|
28
23
|
- README.md
|
|
29
|
-
- Rakefile
|
|
30
|
-
- bin/console
|
|
31
|
-
- bin/setup
|
|
32
24
|
- ext/win32/resolv/extconf.rb
|
|
33
25
|
- ext/win32/resolv/lib/resolv.rb
|
|
34
26
|
- ext/win32/resolv/resolv.c
|
|
35
27
|
- lib/resolv.rb
|
|
36
|
-
- resolv.gemspec
|
|
37
28
|
homepage: https://github.com/ruby/resolv
|
|
38
29
|
licenses:
|
|
39
30
|
- Ruby
|
|
@@ -55,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
55
46
|
- !ruby/object:Gem::Version
|
|
56
47
|
version: '0'
|
|
57
48
|
requirements: []
|
|
58
|
-
rubygems_version: 3.6.
|
|
49
|
+
rubygems_version: 3.6.9
|
|
59
50
|
specification_version: 4
|
|
60
51
|
summary: Thread-aware DNS resolver library in Ruby.
|
|
61
52
|
test_files: []
|
data/.git-blame-ignore-revs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
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
|
data/.github/dependabot.yml
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
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@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
|
27
|
-
with:
|
|
28
|
-
egress-policy: audit
|
|
29
|
-
|
|
30
|
-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
31
|
-
|
|
32
|
-
- name: Set up Ruby
|
|
33
|
-
uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0
|
|
34
|
-
with:
|
|
35
|
-
bundler-cache: true
|
|
36
|
-
ruby-version: ruby
|
|
37
|
-
|
|
38
|
-
- name: Publish to RubyGems
|
|
39
|
-
uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1
|
|
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.GITHUB_TOKEN }}
|
data/.github/workflows/test.yml
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
name: test
|
|
2
|
-
|
|
3
|
-
on: [push, pull_request]
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
ruby-versions:
|
|
7
|
-
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
8
|
-
with:
|
|
9
|
-
engine: cruby-jruby
|
|
10
|
-
min_version: 2.5
|
|
11
|
-
|
|
12
|
-
build:
|
|
13
|
-
needs: ruby-versions
|
|
14
|
-
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
|
15
|
-
strategy:
|
|
16
|
-
matrix:
|
|
17
|
-
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
18
|
-
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
|
19
|
-
include:
|
|
20
|
-
- ruby: mswin
|
|
21
|
-
os: windows-latest
|
|
22
|
-
exclude:
|
|
23
|
-
- ruby: 2.5
|
|
24
|
-
os: macos-latest
|
|
25
|
-
runs-on: ${{ matrix.os }}
|
|
26
|
-
steps:
|
|
27
|
-
- uses: actions/checkout@v4
|
|
28
|
-
- name: Set up Ruby
|
|
29
|
-
uses: ruby/setup-ruby@v1
|
|
30
|
-
with:
|
|
31
|
-
ruby-version: ${{ matrix.ruby }}
|
|
32
|
-
bundler-cache: true
|
|
33
|
-
- name: Run test
|
|
34
|
-
run: bundle exec rake test
|
|
35
|
-
timeout-minutes: 3
|
|
36
|
-
continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }}
|
|
37
|
-
- name: Build package
|
|
38
|
-
id: build
|
|
39
|
-
shell: bash
|
|
40
|
-
run: |
|
|
41
|
-
if ruby -e 'exit RUBY_VERSION>="3.0."'; then
|
|
42
|
-
bundle exec rake build
|
|
43
|
-
set pkg/*.gem
|
|
44
|
-
echo pkg=$1 >> $GITHUB_OUTPUT
|
|
45
|
-
fi
|
|
46
|
-
- name: Install gem
|
|
47
|
-
run: |
|
|
48
|
-
gem install ${{ steps.build.outputs.pkg }}
|
|
49
|
-
ruby -rresolv -e 'puts $LOADED_FEATURES.grep(/resolv/)'
|
|
50
|
-
ruby -rresolv -e 'puts Resolv::VERSION'
|
|
51
|
-
if: ${{ steps.build.outputs.pkg }}
|
|
52
|
-
continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }}
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require "bundler/gem_tasks"
|
|
2
|
-
require "rake/testtask"
|
|
3
|
-
|
|
4
|
-
if RUBY_ENGINE == "ruby"
|
|
5
|
-
require "ruby-core/extensiontask"
|
|
6
|
-
helper = Bundler::GemHelper.instance
|
|
7
|
-
extask = RubyCore::ExtensionTask.new(helper.gemspec)
|
|
8
|
-
task :test => :compile
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
Rake::TestTask.new(:test) do |t|
|
|
12
|
-
t.libs.unshift(*extask.libs) if extask
|
|
13
|
-
t.libs << "test/lib"
|
|
14
|
-
t.ruby_opts << "-rhelper"
|
|
15
|
-
t.test_files = FileList["test/**/test_*.rb"]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
task :default => :test
|
data/bin/console
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "resolv"
|
|
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(__FILE__)
|
data/bin/setup
DELETED
data/resolv.gemspec
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
|
|
8
|
-
Gem::Specification.new do |spec|
|
|
9
|
-
spec.name = name
|
|
10
|
-
spec.version = version
|
|
11
|
-
spec.authors = ["Tanaka Akira"]
|
|
12
|
-
spec.email = ["akr@fsij.org"]
|
|
13
|
-
|
|
14
|
-
spec.summary = %q{Thread-aware DNS resolver library in Ruby.}
|
|
15
|
-
spec.description = %q{Thread-aware DNS resolver library in Ruby.}
|
|
16
|
-
spec.homepage = "https://github.com/ruby/resolv"
|
|
17
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
|
18
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
|
19
|
-
spec.extensions << "ext/win32/resolv/extconf.rb"
|
|
20
|
-
|
|
21
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
22
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
|
23
|
-
|
|
24
|
-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
25
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
-
end
|
|
27
|
-
spec.bindir = "exe"
|
|
28
|
-
spec.executables = []
|
|
29
|
-
spec.require_paths = ["lib"]
|
|
30
|
-
end
|