Skip to content

Commit 606dd03

Browse files
[Bug #20208] Revert "Set AI_ADDRCONFIG when making getaddrinfo(3) calls for outgoi… (ruby#9791)
Revert "Set AI_ADDRCONFIG when making getaddrinfo(3) calls for outgoing conns" This reverts commit 673ed41.
1 parent 53f0c5a commit 606dd03

File tree

3 files changed

+2
-175
lines changed

3 files changed

+2
-175
lines changed

ext/socket/extconf.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,6 @@ def %(s) s || self end
607607
EOS
608608
end
609609

610-
have_const('AI_ADDRCONFIG', headers)
611-
612610
case with_config("lookup-order-hack", "UNSPEC")
613611
when "INET"
614612
$defs << "-DLOOKUP_ORDER_HACK_INET"

ext/socket/ipsocket.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,15 @@ init_inetsock_internal(VALUE v)
5454
VALUE connect_timeout = arg->connect_timeout;
5555
struct timeval tv_storage;
5656
struct timeval *tv = NULL;
57-
int remote_addrinfo_hints = 0;
5857

5958
if (!NIL_P(connect_timeout)) {
6059
tv_storage = rb_time_interval(connect_timeout);
6160
tv = &tv_storage;
6261
}
6362

64-
if (type == INET_SERVER) {
65-
remote_addrinfo_hints |= AI_PASSIVE;
66-
}
67-
#ifdef HAVE_CONST_AI_ADDRCONFIG
68-
remote_addrinfo_hints |= AI_ADDRCONFIG;
69-
#endif
70-
7163
arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv,
72-
family, SOCK_STREAM, remote_addrinfo_hints);
64+
family, SOCK_STREAM,
65+
(type == INET_SERVER) ? AI_PASSIVE : 0);
7366

7467

7568
/*

test/socket/test_tcp.rb

Lines changed: 0 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -140,168 +140,4 @@ def test_accept_multithread
140140
server_threads.each(&:join)
141141
end
142142
end
143-
144-
def test_ai_addrconfig
145-
# This test verifies that we pass AI_ADDRCONFIG to the DNS resolver when making
146-
# an outgoing connection.
147-
# The verification of this is unfortunately incredibly convoluted. We perform the
148-
# test by setting up a fake DNS server to receive queries. Then, we construct
149-
# an environment which has only IPv4 addresses and uses that fake DNS server. We
150-
# then attempt to make an outgoing TCP connection. Finally, we verify that we
151-
# only received A and not AAAA queries on our fake resolver.
152-
# This test can only possibly work on Linux, and only when run as root. If either
153-
# of these conditions aren't met, the test will be skipped.
154-
155-
# The construction of our IPv6-free environment must happen in a child process,
156-
# which we can put in its own network & mount namespaces.
157-
158-
omit "This test is disabled. It is retained to show the original intent of [ruby-core:110870]"
159-
160-
IO.popen("-") do |test_io|
161-
if test_io.nil?
162-
begin
163-
# Child program
164-
require 'fiddle'
165-
require 'resolv'
166-
require 'open3'
167-
168-
libc = Fiddle.dlopen(nil)
169-
begin
170-
unshare = Fiddle::Function.new(libc['unshare'], [Fiddle::TYPE_INT], Fiddle::TYPE_INT)
171-
rescue Fiddle::DLError
172-
# Test can't run because we don't have unshare(2) in libc
173-
# This will be the case on not-linux, and also on very old glibc versions (or
174-
# possibly other libc's that don't expose this syscall wrapper)
175-
$stdout.write(Marshal.dump({result: :skip, reason: "unshare(2) or mount(2) not in libc"}))
176-
exit
177-
end
178-
179-
# Move our test process into a new network & mount namespace.
180-
# This environment will be configured to be IPv6 free and point DNS resolution
181-
# at a fake DNS server.
182-
# (n.b. these flags are CLONE_NEWNS | CLONE_NEWNET)
183-
ret = unshare.call(0x00020000 | 0x40000000)
184-
errno = Fiddle.last_error
185-
if ret == -1 && errno == Errno::EPERM::Errno
186-
# Test can't run because we're not root.
187-
$stdout.write(Marshal.dump({result: :skip, reason: "insufficient permissions to unshare namespaces"}))
188-
exit
189-
elsif ret == -1 && (errno == Errno::ENOSYS::Errno || errno == Errno::EINVAL::Errno)
190-
# No unshare(2) in the kernel (or kernel too old to know about this namespace type)
191-
$stdout.write(Marshal.dump({result: :skip, reason: "errno #{errno} calling unshare(2)"}))
192-
exit
193-
elsif ret == -1
194-
# Unexpected failure
195-
raise "errno #{errno} calling unshare(2)"
196-
end
197-
198-
# Set up our fake DNS environment. Clean out /etc/hosts...
199-
fake_hosts_file = Tempfile.new('ruby_test_hosts')
200-
fake_hosts_file.write <<~HOSTS
201-
127.0.0.1 localhost
202-
::1 localhost
203-
HOSTS
204-
fake_hosts_file.flush
205-
206-
# Have /etc/resolv.conf point to 127.0.0.1...
207-
fake_resolv_conf = Tempfile.new('ruby_test_resolv')
208-
fake_resolv_conf.write <<~RESOLV
209-
nameserver 127.0.0.1
210-
RESOLV
211-
fake_resolv_conf.flush
212-
213-
# Also stub out /etc/nsswitch.conf; glibc can have other resolver modules
214-
# (like systemd-resolved) configured in there other than just using dns,
215-
# so rewrite it to remove any `hosts:` lines and add one which just uses
216-
# dns.
217-
real_nsswitch_conf = File.read('/etc/nsswitch.conf') rescue ""
218-
fake_nsswitch_conf = Tempfile.new('ruby_test_nsswitch')
219-
real_nsswitch_conf.lines.reject { _1 =~ /^\s*hosts:/ }.each do |ln|
220-
fake_nsswitch_conf.puts ln
221-
end
222-
fake_nsswitch_conf.puts "hosts: files myhostname dns"
223-
fake_nsswitch_conf.flush
224-
225-
# This is needed to make sure our bind-mounds aren't visible outside this process.
226-
system 'mount', '--make-rprivate', '/', exception: true
227-
# Bind-mount the fake files over the top of the real files.
228-
system 'mount', '--bind', '--make-private', fake_hosts_file.path, '/etc/hosts', exception: true
229-
system 'mount', '--bind', '--make-private', fake_resolv_conf.path, '/etc/resolv.conf', exception: true
230-
system 'mount', '--bind', '--make-private', fake_nsswitch_conf.path, '/etc/nsswitch.conf', exception: true
231-
232-
# Create a dummy interface with only an IPv4 address
233-
system 'ip', 'link', 'add', 'dummy0', 'type', 'dummy', exception: true
234-
system 'ip', 'addr', 'add', '192.168.1.2/24', 'dev', 'dummy0', exception: true
235-
system 'ip', 'link', 'set', 'dummy0', 'up', exception: true
236-
system 'ip', 'link', 'set', 'lo', 'up', exception: true
237-
238-
# Disable IPv6 on this interface (this is needed to disable the link-local
239-
# IPv6 address)
240-
File.open('/proc/sys/net/ipv6/conf/dummy0/disable_ipv6', 'w') do |f|
241-
f.puts "1"
242-
end
243-
244-
# Create a fake DNS server which will receive the DNS queries triggered by TCPSocket.new
245-
fake_dns_server_socket = UDPSocket.new
246-
fake_dns_server_socket.bind('127.0.0.1', 53)
247-
received_dns_queries = []
248-
fake_dns_server_thread = Thread.new do
249-
Socket.udp_server_loop_on([fake_dns_server_socket]) do |msg, msg_src|
250-
request = Resolv::DNS::Message.decode(msg)
251-
received_dns_queries << request
252-
response = request.dup.tap do |r|
253-
r.qr = 0
254-
r.rcode = 3 # NXDOMAIN
255-
end
256-
msg_src.reply response.encode
257-
end
258-
end
259-
260-
# Make a request which will hit our fake DNS swerver - this needs to be in _another_
261-
# process because glibc will cache resolver info across the fork otherwise.
262-
load_path_args = $LOAD_PATH.flat_map { ['-I', _1] }
263-
Open3.capture3('/proc/self/exe', *load_path_args, '-rsocket', '-e', <<~RUBY)
264-
TCPSocket.open('www.example.com', 4444)
265-
RUBY
266-
267-
fake_dns_server_thread.kill
268-
fake_dns_server_thread.join
269-
270-
have_aaaa_qs = received_dns_queries.any? do |query|
271-
query.question.any? do |question|
272-
question[1] == Resolv::DNS::Resource::IN::AAAA
273-
end
274-
end
275-
276-
have_a_q = received_dns_queries.any? do |query|
277-
query.question.any? do |question|
278-
question[0].to_s == "www.example.com"
279-
end
280-
end
281-
282-
if have_aaaa_qs
283-
$stdout.write(Marshal.dump({result: :fail, reason: "got AAAA queries, expected none"}))
284-
elsif !have_a_q
285-
$stdout.write(Marshal.dump({result: :fail, reason: "got no A query for example.com"}))
286-
else
287-
$stdout.write(Marshal.dump({result: :success}))
288-
end
289-
rescue => ex
290-
$stdout.write(Marshal.dump({result: :fail, reason: ex.full_message}))
291-
ensure
292-
# Make sure the child process does not transfer control back into the test runner.
293-
exit!
294-
end
295-
else
296-
test_result = Marshal.load(test_io.read)
297-
298-
case test_result[:result]
299-
when :skip
300-
omit test_result[:reason]
301-
when :fail
302-
fail test_result[:reason]
303-
end
304-
end
305-
end
306-
end
307143
end if defined?(TCPSocket)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy