Giter Club home page Giter Club logo

rubydns's Introduction

RubyDNS

RubyDNS is a high-performance DNS server which can be easily integrated into other projects or used as a stand-alone daemon. By default it uses rule-based pattern matching. Results can be hard-coded, computed, fetched from a remote DNS server or fetched from a local cache, depending on requirements.

Build Status Code Climate Coverage Status Gitter

RubyDNS Introduction

Installation

Add this line to your application's Gemfile:

gem 'rubydns'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rubydns

Usage

There are lots of examples available in the examples/ directory.

Basic DNS Server

Here is the code from examples/basic-dns.rb:

#!/usr/bin/env ruby
require 'rubydns'

INTERFACES = [
	[:udp, "0.0.0.0", 5300],
	[:tcp, "0.0.0.0", 5300],
]

IN = Resolv::DNS::Resource::IN

# Use upstream DNS for name resolution.
UPSTREAM = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])

# Start the RubyDNS server
RubyDNS::run_server(INTERFACES) do
	match(%r{test.local}, IN::A) do |transaction|
		transaction.respond!("10.0.0.80")
	end

	# Default DNS handler
	otherwise do |transaction|
		transaction.passthrough!(UPSTREAM)
	end
end

Start the server using RUBYOPT=-w ./examples/basic-dns.rb. You can then test it using dig:

$ dig @localhost -p 5300 test.local
$ dig @localhost -p 5300 google.com

File Handle Limitations

On some platforms (e.g. Mac OS X) the number of file descriptors is relatively low by default and should be increased by calling ulimit -n 10000 before running tests or even before starting a server which expects a large number of concurrent incoming connections.

Custom Servers

It is possible to create and integrate your own custom servers, however this functionality has now moved to Async::DNS::Server.

class MyServer < Async::DNS::Server
	def process(name, resource_class, transaction)
		transaction.fail!(:NXDomain)
	end
end

Async::Reactor.run do
	task = MyServer.new.run
	
	# ... do other things, e.g. run specs/tests
	
	# Shut down the server manually if required, otherwise it will run indefinitely.
	# task.stop
end

This is the best way to integrate with other projects.

Performance

Due to changes in the underlying code, there have been some very minor performance regressions. The numbers below will be updated in due course.

We welcome additional benchmarks and feedback regarding RubyDNS performance. To check the current performance results, consult the travis build job output.

Server

The performance is on the same magnitude as bind9. Some basic benchmarks resolving 1000 names concurrently, repeated 5 times, using RubyDNS::Resolver gives the following:

                           user     system      total        real
RubyDNS::Server        4.280000   0.450000   4.730000 (  4.854862)
Bind9                  4.970000   0.520000   5.490000 (  5.541213)

These benchmarks are included in the unit tests. To test bind9 performance, it must be installed and which named must return the executable.

Resolver

The RubyDNS::Resolver is highly concurrent and can resolve individual names as fast as the built in Resolv::DNS resolver. Because the resolver is asynchronous, when dealing with multiple names, it can work more efficiently:

                           user     system      total        real
RubyDNS::Resolver      0.020000   0.010000   0.030000 (  0.030507)
Resolv::DNS            0.070000   0.010000   0.080000 (  1.465975)

These benchmarks are included in the unit tests.

DNSSEC support

DNSSEC is currently not supported and is unlikely to be supported in the future.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Desired Features

  • Support for more features of DNS such as zone transfer.
  • Support reverse records more easily.
  • Some kind of system level integration, e.g. registering a DNS server with the currently running system resolver.

See Also

The majority of this gem is now implemented by async-dns.

  • async-io — Asynchronous networking and sockets.
  • async-dns — Asynchronous DNS resolver and server.
  • async-rspec — Shared contexts for running async specs.

License

Released under the MIT license.

Copyright, 2017, by Samuel G. D. Williams.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

rubydns's People

Contributors

drizzt avatar erran avatar gitter-badger avatar ioquatix avatar jccyr01 avatar jjb avatar justfalter avatar kalemail avatar klarrimore avatar mikz avatar olleolleolle avatar petergoldstein avatar robfors avatar taqtiqa-mark avatar zsprackett avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rubydns's Issues

flakey-dns.rb example is incorrect

flakey-dns.rb example is using false to pass control to otherwise handler which is not working. Actually it needs using next! method. Thus, example is wrong.

For example, if I request microt.com it is not resolving.

This is classical and loved by everybody wrong example case. I expect arrogant response like "it was just an example", like many ruby coders love to say.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

IPv6 Support

Hi,

I see that you have "excluded" IPv6 support. Which is really bad.

When I've used :: as bind host in your example,

INTERFACES = [
    [:udp, "::", 5300],
    [:tcp, "::", 5300]
]

it gave me this error :

  Errno::EAFNOSUPPORT: Address family not supported by protocol - bind(2) for "::" port 5300

Quick look at rubydns-0.9.1/lib/rubydns/handler.rb

shows @126

 def initialize(server, host, port)
      socket = UDPSocket.new

      socket.bind(host, port)

      super(server, socket)
    end

now changing line 127 to :

      socket = UDPSocket.new Socket::AF_INET6

Gets it running like a charm :

ruby example.rb          
I, [2014-12-13T03:05:39.921812 #16965]  INFO -- : Starting RubyDNS server (v0.9.1)...
I, [2014-12-13T03:05:39.921953 #16965]  INFO -- : <> Listening on udp::::5300
I, [2014-12-13T03:05:39.923565 #16965]  INFO -- : <> Listening on tcp::::5300

with netstat confirming opening right sockets:

udp6       0      0 :::5300                 :::*                                16965/ruby      
tcp6       0      0 :::5300                 :::*                    LISTEN      16965/ruby      

and dig confirming it works as expected :

 dig @localhost -p 5300 test.mydomain.org

; <<>> DiG 9.9.5-3ubuntu0.1-Ubuntu <<>> @localhost -p 5300 test.mydomain.org
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37126
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;test.mydomain.org.     IN  A

;; ANSWER SECTION:
test.mydomain.org.  86400   IN  A   10.0.0.80

;; Query time: 2 msec
;; SERVER: ::1#5300(::1)

with that little change you can have it correctly listening on IPv6 sockets, they are brilliant, because on most systems they also enable IPv4 listening :

same example script running, just query over legacy IPv4

dig -4 @localhost -p 5300 test.mydomain.org

; <<>> DiG 9.9.5-3ubuntu0.1-Ubuntu <<>> -4 @localhost -p 5300 test.mydomain.org
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55503
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;test.mydomain.org.     IN  A

;; ANSWER SECTION:
test.mydomain.org.  86400   IN  A   10.0.0.80

;; Query time: 1 msec
;; SERVER: 127.0.0.1#5300(127.0.0.1)

So the only thing missing would be distinguishing between UDP sockets between IPv6 and IPv4 host, which is darn simple with a regex or IPAddr or even, pass it as an attribute so we can decide.

passing block to transaction.passthrough! no longer returns reply object.

previous examples show transaction.passthrough!(resolver, options: {}, &block)

but attempting

transaction.passthrough!(resolver, options: {}) do |result, result_name|
...
end

has nil value for result\result_name

It would be nice to have a method of getting response address without using -

transaction.response.answer[0][2].address.to_s

I'm happy to attempt a patch if it's not something that can be easily added.

Regexs in example code need fixing

In the example code, you have match(/test.mydomain.org/, IN::A), however this will also match testamydomain.org. Suggest you fix the regexs to it is clear you're not using magical regex syntax :)

call addresses_for for a record(cname message returned) throw NoMethodError exception

hello, when I use addressed for a record, like www.baidu.com which is a cname record, will throw such an exception:

in `block (2 levels) in addresses_for': undefined method `address' for #<Resolv::DNS::Resource::IN::CNAME:0x000000019e4fc0> (NoMethodError)
        from rubydns-0.8.4/lib/rubydns/resolver.rb:70:in `collect'
        from rubydns-0.8.4/lib/rubydns/resolver.rb:70:in `block in addresses_for'
        from rubydns-0.8.4/lib/rubydns/resolver.rb:85:in `block in fetch'
        from eventmachine-1.0.3/lib/em/deferrable.rb:151:in `call'
        from eventmachine-1.0.3/lib/em/deferrable.rb:151:in `set_deferred_status'
        from eventmachine-1.0.3/lib/em/deferrable.rb:191:in `succeed'
        from rubydns-0.8.4/lib/rubydns/resolver.rb:142:in `process_response!'
        from rubydns-0.8.4/lib/rubydns/resolver.rb:219:in `receive_data'
        from eventmachine-1.0.3/lib/eventmachine.rb:187:in `run_machine'
        from eventmachine-1.0.3/lib/eventmachine.rb:187:in `run'

is there a way to get the target ip ?

Thanks

Missing method when using the simple server example

Steps to reproduce :

Result : server crash, because of a missing method. Backtrace :

E, [2012-03-28T10:41:26.881228 #49254] ERROR -- : Exception thrown while processing www.google.com A!
E, [2012-03-28T10:41:26.881403 #49254] ERROR -- : NameError: undefined local variable or method `make_requester' for #<Resolv::DNS:0x007fac98828f10>
E, [2012-03-28T10:41:26.881455 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/resolv.rb:30:in `query'
E, [2012-03-28T10:41:26.881504 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/transaction.rb:159:in `passthrough'
E, [2012-03-28T10:41:26.881571 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/transaction.rb:136:in `passthrough!'
E, [2012-03-28T10:41:26.881611 #49254] ERROR -- : dns_server.rb:16:in `block (2 levels) in <main>'
E, [2012-03-28T10:41:26.881652 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/server.rb:168:in `call'
E, [2012-03-28T10:41:26.881677 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/server.rb:168:in `process'
E, [2012-03-28T10:41:26.881704 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/transaction.rb:125:in `process'
E, [2012-03-28T10:41:26.881728 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/server.rb:192:in `block in receive_data'
E, [2012-03-28T10:41:26.881752 #49254] ERROR -- : /Users/romain/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/resolv.rb:1267:in `block in each_question'
E, [2012-03-28T10:41:26.882033 #49254] ERROR -- : /Users/romain/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/resolv.rb:1266:in `each'
E, [2012-03-28T10:41:26.882072 #49254] ERROR -- : /Users/romain/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/resolv.rb:1266:in `each_question'
E, [2012-03-28T10:41:26.882097 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/server.rb:188:in `receive_data'
E, [2012-03-28T10:41:26.882121 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/handler.rb:37:in `process'
E, [2012-03-28T10:41:26.882146 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns/handler.rb:47:in `receive_data'
E, [2012-03-28T10:41:26.882171 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run_machine'
E, [2012-03-28T10:41:26.882206 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in `run'
E, [2012-03-28T10:41:26.882580 #49254] ERROR -- : /Users/romain/.rvm/gems/ruby-1.9.3-p125/gems/rubydns-0.3.4/lib/rubydns.rb:62:in `run_server'
E, [2012-03-28T10:41:26.882719 #49254] ERROR -- : dns_server.rb:7:in `<main>'

query domains in a for loop

I have tried it but everytime I rub into a different issue.
Can you gimme a simple example where If I had and array of domains how would i query them using a for loop ?

Resolver's IP address question

Hi Samuel,

I just had a very quick question about RubyDNS - which looks like an awesome project btw, congrats.

I am writing a "poor man's CDN" and I'd like to set up a DNS server. RubyDNS looks like it can do the job, but one feature that I would like to write is to do a GeoIP lookup of the client's IP address.

The thing is, I'm not sure if the client's IP address is available in the lookup? (or if it's even part of the DNS protocol!?)

Given that you know far far more about DNS than I do, I just wanted to know if it's possible to get the client's IP address? This would enable us to do funky things like GeoIP lookup and return the IP address of the closest server.

Thanks!

Leo

Unable to handle requests when use-vc is used

When use-vc is used in /etc/resolv.conf, the server is unable to handle client requests

$ strace ping gmail.com

execve("/usr/bin/ping", ["ping", "gmail.com", "-s", "102400"], 0x7ffc229984c8 /* 15 vars */) = 0
brk(NULL)                               = 0x558e12bc6000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe630d3500) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f80463e2000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0  \0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=22456, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f80463e0000
mmap(NULL, 24920, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f80463d9000
mmap(0x7f80463db000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f80463db000
mmap(0x7f80463dd000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f80463dd000
mmap(0x7f80463de000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f80463de000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libidn2.so.4", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0  \0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=120512, ...}) = 0
mmap(NULL, 122904, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f80463ba000
mmap(0x7f80463bc000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f80463bc000
mmap(0x7f80463c0000, 94208, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f80463c0000
mmap(0x7f80463d7000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c000) = 0x7f80463d7000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libcrypto.so.1.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0`\7\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2941552, ...}) = 0
mmap(NULL, 2957160, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f80460e8000
mmap(0x7f804615d000, 1699840, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x75000) = 0x7f804615d000
mmap(0x7f80462fc000, 577536, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x214000) = 0x7f80462fc000
mmap(0x7f8046389000, 188416, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2a0000) = 0x7f8046389000
mmap(0x7f80463b7000, 12136, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f80463b7000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 @\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=88200, ...}) = 0
mmap(NULL, 100512, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f80460cf000
mprotect(0x7f80460d3000, 69632, PROT_NONE) = 0
mmap(0x7f80460d3000, 49152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f80460d3000
mmap(0x7f80460df000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10000) = 0x7f80460df000
mmap(0x7f80460e4000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14000) = 0x7f80460e4000
mmap(0x7f80460e6000, 6304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f80460e6000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000C\2\0\0\0\0\0"..., 832) = 832
lseek(3, 792, SEEK_SET)                 = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2136840, ...}) = 0
lseek(3, 792, SEEK_SET)                 = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
lseek(3, 864, SEEK_SET)                 = 864
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8045f0b000
mprotect(0x7f8045f2d000, 1671168, PROT_NONE) = 0
mmap(0x7f8045f2d000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f8045f2d000
mmap(0x7f8046078000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16d000) = 0x7f8046078000
mmap(0x7f80460c5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b9000) = 0x7f80460c5000
mmap(0x7f80460cb000, 13888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f80460cb000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libunistring.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\17\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1570608, ...}) = 0
mmap(NULL, 3668232, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8045b8b000
mprotect(0x7f8045d07000, 2093056, PROT_NONE) = 0
mmap(0x7f8045f06000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17b000) = 0x7f8045f06000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \20\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=14240, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8045b89000
mmap(NULL, 16528, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8045b84000
mmap(0x7f8045b85000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x7f8045b85000
mmap(0x7f8045b86000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f8045b86000
mmap(0x7f8045b87000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f8045b87000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340f\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=155408, ...}) = 0
lseek(3, 808, SEEK_SET)                 = 808
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
mmap(NULL, 131528, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8045b63000
mmap(0x7f8045b69000, 61440, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f8045b69000
mmap(0x7f8045b78000, 24576, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7f8045b78000
mmap(0x7f8045b7e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a000) = 0x7f8045b7e000
mmap(0x7f8045b80000, 12744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8045b80000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8045b60000
arch_prctl(ARCH_SET_FS, 0x7f8045b60740) = 0
mprotect(0x7f80460c5000, 16384, PROT_READ) = 0
mprotect(0x7f8045b7e000, 4096, PROT_READ) = 0
mprotect(0x7f8045b87000, 4096, PROT_READ) = 0
mprotect(0x7f8045f06000, 16384, PROT_READ) = 0
mprotect(0x7f80460e4000, 4096, PROT_READ) = 0
mprotect(0x7f8046389000, 180224, PROT_READ) = 0
mprotect(0x7f80463d7000, 4096, PROT_READ) = 0
mprotect(0x7f80463de000, 4096, PROT_READ) = 0
mprotect(0x558e12589000, 4096, PROT_READ) = 0
mprotect(0x7f8046440000, 4096, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
set_tid_address(0x7f8045b60a10)         = 13773
set_robust_list(0x7f8045b60a20, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7f8045b69130, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f8045b753c0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7f8045b691d0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f8045b753c0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
brk(NULL)                               = 0x558e12bc6000
brk(0x558e12be7000)                     = 0x558e12be7000
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_CHOWN|1<<CAP_DAC_OVERRIDE|1<<CAP_DAC_READ_SEARCH|1<<CAP_FOWNER|1<<CAP_FSETID|1<<CAP_KILL|1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_SETPCAP|1<<CAP_LINUX_IMMUTABLE|1<<CAP_NET_BIND_SERVICE|1<<CAP_NET_BROADCAST|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_IPC_LOCK|1<<CAP_IPC_OWNER|1<<CAP_SYS_MODULE|1<<CAP_SYS_RAWIO|1<<CAP_SYS_CHROOT|1<<CAP_SYS_PTRACE|1<<CAP_SYS_PACCT|1<<CAP_SYS_ADMIN|1<<CAP_SYS_BOOT|1<<CAP_SYS_NICE|1<<CAP_SYS_RESOURCE|1<<CAP_SYS_TIME|1<<CAP_SYS_TTY_CONFIG|1<<CAP_MKNOD|1<<CAP_LEASE|1<<CAP_AUDIT_WRITE|1<<CAP_AUDIT_CONTROL|1<<CAP_SETFCAP|1<<CAP_MAC_OVERRIDE|1<<CAP_MAC_ADMIN|1<<CAP_SYSLOG|1<<CAP_WAKE_ALARM|1<<CAP_BLOCK_SUSPEND|1<<CAP_AUDIT_READ, permitted=1<<CAP_CHOWN|1<<CAP_DAC_OVERRIDE|1<<CAP_DAC_READ_SEARCH|1<<CAP_FOWNER|1<<CAP_FSETID|1<<CAP_KILL|1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_SETPCAP|1<<CAP_LINUX_IMMUTABLE|1<<CAP_NET_BIND_SERVICE|1<<CAP_NET_BROADCAST|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_IPC_LOCK|1<<CAP_IPC_OWNER|1<<CAP_SYS_MODULE|1<<CAP_SYS_RAWIO|1<<CAP_SYS_CHROOT|1<<CAP_SYS_PTRACE|1<<CAP_SYS_PACCT|1<<CAP_SYS_ADMIN|1<<CAP_SYS_BOOT|1<<CAP_SYS_NICE|1<<CAP_SYS_RESOURCE|1<<CAP_SYS_TIME|1<<CAP_SYS_TTY_CONFIG|1<<CAP_MKNOD|1<<CAP_LEASE|1<<CAP_AUDIT_WRITE|1<<CAP_AUDIT_CONTROL|1<<CAP_SETFCAP|1<<CAP_MAC_OVERRIDE|1<<CAP_MAC_ADMIN|1<<CAP_SYSLOG|1<<CAP_WAKE_ALARM|1<<CAP_BLOCK_SUSPEND|1<<CAP_AUDIT_READ, inheritable=0}) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
prctl(PR_SET_KEEPCAPS, 1)               = 0
getuid()                                = 0
setuid(0)                               = 0
prctl(PR_SET_KEEPCAPS, 0)               = 0
getuid()                                = 0
geteuid()                               = 0
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3346576, ...}) = 0
mmap(NULL, 3346576, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f804582e000
close(3)                                = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_NET_RAW, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = -1 EACCES (Permission denied)
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = -1 EACCES (Permission denied)
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) = 4
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_NET_RAW, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
openat(AT_FDCWD, "/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=56352, ...}) = 0
read(5, "# GNU libc iconv configuration.\n"..., 4096) = 4096
read(5, "1002//\tJUS_I.B1.002//\nmodule\tJUS"..., 4096) = 4096
read(5, "ISO-IR-110//\t\tISO-8859-4//\nalias"..., 4096) = 4096
read(5, "\t\tISO-8859-14//\nalias\tISO_8859-1"..., 4096) = 4096
read(5, "IC-ES//\nalias\tEBCDICES//\t\tEBCDIC"..., 4096) = 4096
read(5, "DIC-CP-ES//\t\tIBM284//\nalias\tCSIB"..., 4096) = 4096
read(5, "\tIBM863//\nalias\tOSF1002035F//\t\tI"..., 4096) = 4096
read(5, "37//\t\tIBM937//\nmodule\tIBM937//\t\t"..., 4096) = 4096
read(5, "JIS//\t\t\tEUC-JP//\nmodule\tEUC-JP//"..., 4096) = 4096
read(5, "ias\tISO2022CN//\t\tISO-2022-CN//\nm"..., 4096) = 4096
read(5, "_5427-EXT//\nalias\tISO_5427EXT//\t"..., 4096) = 4096
read(5, "st\nmodule\tMAC-SAMI//\t\tINTERNAL\t\t"..., 4096) = 4096
read(5, "12//\t\tINTERNAL\t\tIBM1112\t\t1\nmodul"..., 4096) = 4096
brk(0x558e12c08000)                     = 0x558e12c08000
read(5, "\tCP9448//\t\tIBM9448//\nalias\tCSIBM"..., 4096) = 3104
read(5, "", 4096)                       = 0
close(5)                                = 0
futex(0x7f80460ca868, FUTEX_WAKE_PRIVATE, 2147483647) = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5
connect(5, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(5)                                = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5
connect(5, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(5)                                = 0
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=334, ...}) = 0
read(5, "# Name Service Switch configurat"..., 4096) = 334
read(5, "", 4096)                       = 0
close(5)                                = 0
stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=70, ...}) = 0
openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=73, ...}) = 0
read(5, "# Resolver configuration file.\n#"..., 4096) = 73
read(5, "", 4096)                       = 0
close(5)                                = 0
futex(0x7f80460cd744, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=70, ...}) = 0
read(5, "options use-vc single-request\nse"..., 4096) = 70
read(5, "", 4096)                       = 0
close(5)                                = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7f80463e2000
close(5)                                = 0
openat(AT_FDCWD, "/usr/lib/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 0\0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=55200, ...}) = 0
mmap(NULL, 83416, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7f8045819000
mmap(0x7f804581c000, 28672, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x3000) = 0x7f804581c000
mmap(0x7f8045823000, 12288, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0xa000) = 0x7f8045823000
mmap(0x7f8045826000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0xc000) = 0x7f8045826000
mmap(0x7f8045828000, 21976, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8045828000
close(5)                                = 0
mprotect(0x7f8045826000, 4096, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 5
lseek(5, 0, SEEK_CUR)                   = 0
fstat(5, {st_mode=S_IFREG|0644, st_size=150, ...}) = 0
read(5, "127.0.0.1 localhost.localdomain "..., 4096) = 150
lseek(5, 0, SEEK_CUR)                   = 150
read(5, "", 4096)                       = 0
close(5)                                = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7f80463e2000
close(5)                                = 0
openat(AT_FDCWD, "/usr/lib/libnss_mymachines.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 `\0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=282528, ...}) = 0
mmap(NULL, 286848, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7f80457d2000
mmap(0x7f80457d8000, 184320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x6000) = 0x7f80457d8000
mmap(0x7f8045805000, 61440, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x33000) = 0x7f8045805000
mmap(0x7f8045814000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x41000) = 0x7f8045814000
mmap(0x7f8045818000, 128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8045818000
close(5)                                = 0
mprotect(0x7f8045814000, 12288, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
rt_sigprocmask(SIG_BLOCK, [HUP USR1 USR2 PIPE ALRM CHLD TSTP URG VTALRM PROF WINCH IO], [], 8) = 0
openat(AT_FDCWD, "/run/systemd/machines/gmail.com", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7f80463e2000
close(5)                                = 0
openat(AT_FDCWD, "/usr/lib/libnss_myhostname.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0  \0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=75696, ...}) = 0
mmap(NULL, 80168, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7f80457be000
mmap(0x7f80457c0000, 36864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x2000) = 0x7f80457c0000
mmap(0x7f80457c9000, 20480, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0xb000) = 0x7f80457c9000
mmap(0x7f80457ce000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0xf000) = 0x7f80457ce000
close(5)                                = 0
mprotect(0x7f80457ce000, 12288, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
rt_sigprocmask(SIG_BLOCK, [HUP USR1 USR2 PIPE ALRM CHLD TSTP URG VTALRM PROF WINCH IO], [], 8) = 0
uname({sysname="Linux", nodename="macux.apple", ...}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7f80463e2000
close(5)                                = 0
openat(AT_FDCWD, "/usr/lib/libnss_resolve.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 `\0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=282528, ...}) = 0
mmap(NULL, 286848, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7f8045777000
mmap(0x7f804577d000, 184320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x6000) = 0x7f804577d000
mmap(0x7f80457aa000, 61440, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x33000) = 0x7f80457aa000
mmap(0x7f80457b9000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x41000) = 0x7f80457b9000
mmap(0x7f80457bd000, 128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f80457bd000
close(5)                                = 0
mprotect(0x7f80457b9000, 12288, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
rt_sigprocmask(SIG_BLOCK, [HUP USR1 USR2 PIPE ALRM CHLD TSTP URG VTALRM PROF WINCH IO], [], 8) = 0
geteuid()                               = 0
getpid()                                = 13773
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5
getsockopt(5, SOL_SOCKET, SO_RCVBUF, [212992], [4]) = 0
setsockopt(5, SOL_SOCKET, SO_RCVBUF, [8388608], 4) = 0
getsockopt(5, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
setsockopt(5, SOL_SOCKET, SO_SNDBUF, [8388608], 4) = 0
connect(5, {sa_family=AF_UNIX, sun_path="/run/dbus/system_bus_socket"}, 30) = 0
getsockopt(5, SOL_SOCKET, SO_PEERCRED, {pid=1, uid=0, gid=0}, [12]) = 0
getsockopt(5, SOL_SOCKET, SO_PEERSEC, 0x558e12becc90, [64]) = -1 ENOPROTOOPT (Protocol not available)
getsockopt(5, SOL_SOCKET, SO_PEERGROUPS, 0x558e12becce0, [256->0]) = 0
fstat(5, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
getsockopt(5, SOL_SOCKET, SO_ACCEPTCONN, [0], [4]) = 0
getsockname(5, {sa_family=AF_UNIX}, [128->2]) = 0
geteuid()                               = 0
sendmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0AUTH EXTERNAL ", iov_len=15}, {iov_base="30", iov_len=2}, {iov_base="\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n", iov_len=28}], msg_iovlen=3, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 45
gettid()                                = 13773
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="OK ca45efb6900e41870662ea415c727"..., iov_len=256}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 52
sendmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\1\0\1\0\0\0\0\1\0\0\0m\0\0\0\1\1o\0\25\0\0\0/org/fre"..., iov_len=128}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 128
recvmsg(5, {msg_namelen=0}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = -1 EAGAIN (Resource temporarily unavailable)
ppoll([{fd=5, events=POLLIN}], 1, {tv_sec=24, tv_nsec=999798000}, NULL, 8) = 1 ([{fd=5, revents=POLLIN}], left {tv_sec=24, tv_nsec=999244438})
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\2\1\1\f\0\0\0\1\0\0\0=\0\0\0\6\1s\0\7\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base=":1.6626\0\5\1u\0\1\0\0\0\10\1g\0\1s\0\0\7\1s\0\24\0\0\0"..., iov_len=68}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 68
sendmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\1\2\1 \0\0\0\2\0\0\0\242\0\0\0\1\1o\0\31\0\0\0/org/fre"..., iov_len=184}, {iov_base="\0\0\0\0\t\0\0\0gmail.com\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", iov_len=32}], msg_iovlen=2, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 216
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\4\1\1\f\0\0\0\2\0\0\0\215\0\0\0\1\1o\0\25\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="/org/freedesktop/DBus\0\0\0\2\1s\0\24\0\0\0"..., iov_len=148}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 148
recvmsg(5, {msg_namelen=0}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = -1 EAGAIN (Resource temporarily unavailable)
ppoll([{fd=5, events=POLLIN}], 1, {tv_sec=119, tv_nsec=999776000}, NULL, 8) = 1 ([{fd=5, revents=POLLIN}], left {tv_sec=119, tv_nsec=999773749})
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\3\1\0013\0\0\0\3\0\0\0u\0\0\0\6\1s\0\7\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
recvmsg(5, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base=":1.6626\0\4\1s\0)\0\0\0org.freedesktop."..., iov_len=163}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 163
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
close(5)                                = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=215879, ...}) = 0
mmap(NULL, 215879, PROT_READ, MAP_PRIVATE, 5, 0) = 0x7f80463e2000
close(5)                                = 0
openat(AT_FDCWD, "/usr/lib/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 5
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \20\0\0\0\0\0\0"..., 832) = 832
fstat(5, {st_mode=S_IFREG|0755, st_size=26528, ...}) = 0
mmap(NULL, 28688, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 5, 0) = 0x7f804576f000
mmap(0x7f8045770000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x1000) = 0x7f8045770000
mmap(0x7f8045774000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x5000) = 0x7f8045774000
mmap(0x7f8045775000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 5, 0x5000) = 0x7f8045775000
close(5)                                = 0
mprotect(0x7f8045775000, 4096, PROT_READ) = 0
munmap(0x7f80463e2000, 215879)          = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
writev(5, [{iov_base="\0\33", iov_len=2}, {iov_base="\354\372\1\0\0\1\0\0\0\0\0\0\5gmail\3com\0\0\1\0\1", iov_len=27}, {iov_base="\0\33", iov_len=2}, {iov_base="j\17\1\0\0\1\0\0\0\0\0\0\5gmail\3com\0\0\34\0\1", iov_len=27}], 4) = 58
read(5, "\0+", 2)                       = 2
read(5, "\354\372\201\200\0\1\0\1\0\0\0\0\5gmail\3com\0\0\1\0\1\300\f\0\1\0"..., 43) = 43
read(5, 0x7ffe630d1206, 2)              = -1 ECONNRESET (Connection reset by peer)
close(5)                                = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
writev(5, [{iov_base="\0\33", iov_len=2}, {iov_base="\354\372\1\0\0\1\0\0\0\0\0\0\5gmail\3com\0\0\1\0\1", iov_len=27}, {iov_base="\0\33", iov_len=2}, {iov_base="j\17\1\0\0\1\0\0\0\0\0\0\5gmail\3com\0\0\34\0\1", iov_len=27}], 4) = 58
read(5, "\0+", 2)                       = 2
read(5, "\354\372\201\200\0\1\0\1\0\0\0\0\5gmail\3com\0\0\1\0\1\300\f\0\1\0"..., 43) = 43
read(5, 0x7ffe630d1206, 2)              = -1 ECONNRESET (Connection reset by peer)
close(5)                                = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
writev(5, [{iov_base="\0&", iov_len=2}, {iov_base="T`\1\0\0\1\0\0\0\0\0\0\5gmail\3com\6google\3co"..., iov_len=38}, {iov_base="\0&", iov_len=2}, {iov_base="+z\1\0\0\1\0\0\0\0\0\0\5gmail\3com\6google\3co"..., iov_len=38}], 4) = 80
read(5, "\0X", 2)                       = 2
read(5, "T`\201\203\0\1\0\0\0\1\0\0\5gmail\3com\6google\3co"..., 88) = 88
read(5, 0x7ffe630d1206, 2)              = -1 ECONNRESET (Connection reset by peer)
close(5)                                = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
writev(5, [{iov_base="\0&", iov_len=2}, {iov_base="T`\1\0\0\1\0\0\0\0\0\0\5gmail\3com\6google\3co"..., iov_len=38}, {iov_base="\0&", iov_len=2}, {iov_base="+z\1\0\0\1\0\0\0\0\0\0\5gmail\3com\6google\3co"..., iov_len=38}], 4) = 80
read(5, "\0X", 2)                       = 2
read(5, "T`\201\203\0\1\0\0\0\1\0\0\5gmail\3com\6google\3co"..., 88) = 88
read(5, 0x7ffe630d1206, 2)              = -1 ECONNRESET (Connection reset by peer)
close(5)                                = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 5
fstat(5, {st_mode=S_IFREG|0644, st_size=2997, ...}) = 0
read(5, "# Locale name alias data base.\n#"..., 4096) = 2997
read(5, "", 4096)                       = 0
close(5)                                = 0
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "ping: gmail.com: Temporary failu"..., 54ping: gmail.com: Temporary failure in name resolution
) = 54
exit_group(2)                           = ?
+++ exited with 2 +++

How to stop the server?

Thank you for RubyDNS, we are using it to mock DNS lookups in the test suite. To this end we need to stop the server at the end of a test using it, as well as have the ability replace the server with another one with different configuration. Looking through the code, I think task.stop for the task created in https://github.com/socketry/async-dns/blob/master/lib/async/dns/server.rb#L105 is going to stop the server, but the task does not appear to be exposed even in that method not to mention RubyDNS.

What is the recommended way of stopping a RubyDNS server?

Speeding up DNS requests

Hi,

I needed a simple local DNS server to help me resolve internal names like ip-238.32.42.14.*.internal locally to the implied IP address. RubyDNS worked well for this and have a simple script working and resolving the names as expected. I've configured a RubyDNS server as the first entry via network manager / resolv.conf in linux.

However my DNS requests are resolving significantly more slowly when requesting a regular record. I'm no DNS expert but assume that generally on a host some caching mechanism is employed and that's why I'm so much slower when running the script.

Is the caching assumption correct regarding the slowdown? If so should I just use a map and some sort of timer to expire the records in that map? Can you give me other advice regarding my resolver or DNS configuration?

Thanks again for providing this DNS solution!

require 'rubydns'

  INTERFACES = [
      [:udp, "0.0.0.0", 53],
      [:tcp, "0.0.0.0", 53],
  ]

  IN = Resolv::DNS::Resource::IN

# Use upstream DNS for name resolution.

  def getResolver(ipaddress,port)
    return RubyDNS::Resolver.new([[:udp,ipaddress,port],[:tcp,ipaddress,port]])
  end
  
  #GOOGLE_DNS = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
  # TODO: get these from resolv.conf or network manager
  NET_1 = getResolver("101.123.128.20",53)
  #NET_2 = getResolver("101.124.82.144",53)


# Start the RubyDNS server
  RubyDNS::run_server(INTERFACES) do
    single_ip_match_group = /ip-([^.]*).*/ #internal/
    match(single_ip_match_group) do |transaction, match_data|
      logger.info("matched ")
      logger.info(match_data[1].to_s)
      ip = match_data[1].to_s.gsub("-",".")
      transaction.respond!(ip)
    end

    # Default DNS handler
    otherwise do |transaction|
      logger.info("not matched")
      transaction.passthrough!(NET_1)
    end
  end

Please tag v1.x.x

Could you please release and tag a semver v1.x.x?

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
Version 1.0.0 defines the public API. The way in which the version number is incremented after this release is dependent on this public API and how it changes.
— http://semver.org/

No meaningful relationship between v0.x.x releases can be inferred. There's no guarantee that v0.7.4 will be in any way compatible with v0.7.3.

This means library authors need to lock their dependencies to the patch-version, making interoperability painful. For example landrush.gemspec locks to rubydns 0.7.0 while vagrant-dns.gemspec locks to rubydns 0.6.x, so they can't both be loaded at once.

A v1.0.0 release doesn't need to be finished or perfect, it just defines the backwards-compatibility semantics moving forwards, and should be released pretty much as soon as the code is being used in the wild.

Thanks!

otherwise not working after match block returns false

When I use match block and otherwise, I want to skip some addresses in match so they would be caught by otherwise block. But it doesn't go to otherwise block.

RubyDNS.run_server(listen: INTERFACES, asynchronous: false) do
  upstream = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])

  match(/^([\d\.]+)\.in-addr\.arpa$/, IN::PTR) do |transaction, match_data|

    domain = nil # just for test

    if domain
      transaction.respond!(Name.create(domain))
    else
      # Pass the request to the otherwise handler
      # !!! this doesn't work
      false
    end
  end

  otherwise do |transaction|
    transaction.passthrough!(upstream)
  end
end

When I return false from match block - it doesn't go to otherwise block.

What am I doing wrong?

rubydns unexpected quit on windows

the issue happned on both windows7 and win10,
to reproduce the issue: 1. start rubydns 2.run nslookup in the same computer, then the issue happened.
I checked the log and found that endpoint can't bind to socket again if socket error happened.
I checked the code and I don't know how to fix it.

I use ruby2.6-64,
here is my server code:
#!/usr/bin/env ruby
require 'rubydns'

INTERFACES = [
[:udp, "192.168.95.47", 53],
]

IN = Resolv::DNS::Resource::IN

UPSTREAM = RubyDNS::Resolver.new([[:tcp, "8.8.8.8", 53]])

RubyDNS::run_server(INTERFACES) do
match(%r{test.local}, IN::A) do |transaction|
transaction.respond!("10.0.0.80")
end

otherwise do |transaction|
	transaction.passthrough!(UPSTREAM)
end

end

here is the log(on win10-x64):

E:>ruby -d basic-dns.rb
Exception LoadError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/rubygems.rb:1397 - cannot load such file -- rubygems/defaults/ruby Exception LoadError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59 - cannot load such file -- rubydns
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/rubydns-2.0.2/lib/rubydns.rb:31: warning: parentheses after method name is interpreted as an argument list, not a decomposed argument
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/socket.rb:124: warning: shadowing outer local variable - task
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/socket.rb:216: warning: shadowing outer local variable - task
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().autoclose= ^ Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - : syntax error, unexpected end-of-input
().sync=
^
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().pos= ^ Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - : syntax error, unexpected end-of-input
().close_on_exec=
^
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().do_not_reverse_lookup= ^ Exception NameError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/fiddle/import.rb:157 - uninitialized constant Fiddle::Function::STDCALL
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/extensions/resolv.rb:29: warning: parentheses after method name is interpreted as an argument list, not a decomposed argument
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/extensions/resolv.rb:53: warning: method redefined; discarding old to_s
C:/plong/Ruby25-x64/lib/ruby/2.5.0/resolv.rb:1304: warning: previous definition of to_s was here
C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/extensions/resolv.rb:57: warning: method redefined; discarding old inspect
C:/plong/Ruby25-x64/lib/ruby/2.5.0/resolv.rb:1236: warning: previous definition of inspect was here
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().hostname= ^ Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - : syntax error, unexpected end-of-input
().session=
^
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().sync_close= ^ Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - : syntax error, unexpected end-of-input
().close_on_exec=
^
Exception SyntaxError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/forwardable/impl.rb:6 - <compiled>: syntax error, unexpected end-of-input ().reactor= ^ C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/resolver.rb:217: warning: assigned but unused variable - peer C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/handler.rb:124: warning: assigned but unused variable - error C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/transport.rb:80: warning: assigned but unused variable - count 0.2s: Starting Async::DNS server (v1.2.0)... 0.2s: Async::IO::Socket : Binding to #<Addrinfo: 192.168.95.47:53 UDP> 0.21s: <> Listening for datagrams on #<Addrinfo: 192.168.95.47:53 UDP> 4.82s: <> Receiving incoming query (44 bytes) to Async::DNS::DatagramHandler... : <1> Processing question 47.95.168.192.in-addr.arpa Resolv::DNS::Resource::IN::PTR... : <1> Searching for 47.95.168.192.in-addr.arpa Resolv::DNS::Resource::IN::PTR : <1> Checking rule [/test.local/, Resolv::DNS::Resource::IN::A]... 4.82s: <1> Resource class Resolv::DNS::Resource::IN::PTR failed to match Resolv::DNS::Resource::IN::A! 4.82s: [60973] Sending request [[#<Resolv::DNS::Name: 47.95.168.192.in-addr.arpa.>, Resolv::DNS::Resource::IN::PTR]] to address #<Async::IO::HostEndpoint:0x00000000057369f0 @options={}, @specification=["8.8.8.8", 53, nil, 1]> 4.82s: [60973] -> Try address #<Async::IO::HostEndpoint name="8.8.8.8" service=53 family=nil type=1 protocol=nil flags=nil> 4.82s: Async::IO::Socket : Connecting to #<Addrinfo: 8.8.8.8:53 TCP> 6.82s: <> Receiving incoming query (28 bytes) to Async::DNS::DatagramHandler... : <2> Processing question google.com Resolv::DNS::Resource::IN::A... : <2> Searching for google.com Resolv::DNS::Resource::IN::A : <2> Checking rule [/test.local/, Resolv::DNS::Resource::IN::A]... 6.83s: <2> No pattern matched. 6.83s: [3933] Sending request [[#<Resolv::DNS::Name: google.com.>, Resolv::DNS::Resource::IN::A]] to address #<Async::IO::HostEndpoint:0x000000000573ef38 @options={}, @specification=["8.8.8.8", 53, nil, 1]> 6.83s: [3933] -> Try address #<Async::IO::HostEndpoint name="8.8.8.8" service=53 family=nil type=1 protocol=nil flags=nil> 6.83s: Async::IO::Socket : Connecting to #<Addrinfo: 8.8.8.8:53 TCP> 7.17s: [60973] <- Try address #<Async::IO::HostEndpoint name="8.8.8.8" service=53 family=nil type=1 protocol=nil flags=nil> = #<Resolv::DNS::Message:0x000000000573d0c0> 7.17s: [60973] Received valid response with 0 answer(s). : <1> Time to process request: 2.353993s 7.17s: <1> Writing 44 bytes response to client via UDP... Exception Errno::ECONNRESET' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/socket.rb:444 - An existing connection was forcibly closed by the remote host. - recvmsg(2)
7.17s: <Async::Task:0x2b62acc binding to #<Addrinfo: 192.168.95.47:53 UDP> failed>
| Errno::ECONNRESET: An existing connection was forcibly closed by the remote host. - recvmsg(2)
| → C:/plong/Ruby25-x64/lib/ruby/2.5.0/socket.rb 444
| C:/plong/Ruby25-x64/lib/ruby/2.5.0/socket.rb 444
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/generic.rb 128
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/generic.rb 47
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/handler.rb 72
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-dns-1.2.0/lib/async/dns/server.rb 116
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/socket.rb 220
| C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-1.13.0/lib/async/task.rb 198
Exception Async::TimeoutError' at C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-1.13.0/lib/async/task.rb:51 - execution expired Exception Async::TimeoutError' at C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/socket.rb:180 - execution expired
Exception Async::TimeoutError' at C:/plong/Ruby25-x64/lib/ruby/gems/2.5.0/gems/async-io-1.17.2/lib/async/io/host_endpoint.rb:57 - execution expired 11.84s: [3933] Request timed out! : <2> Time to process request: 5.01667s 11.85s: <2> Writing 28 bytes response to client via UDP... Exception IOError' at C:/plong/Ruby25-x64/lib/ruby/2.5.0/socket.rb:321 - closed stream
11.85s: <> UDP response failed: #<IOError: closed stream>!
11.86s: <Async::Reactor:0x2b63260 stopped=false>
: Exiting run-loop because finished.

E:>
log.txt

Assertion failed: (OutboundPages.size() > 0), function Write, file ed.cpp, line 1653.

I have some issues when using RubyDNS, it faild some times, here is the log:

D, [2013-03-14T01:11:53.690315 #62668] DEBUG -- : Checking rule [/^test([0-9]+).mydomain.org$/, Resolv::DNS::Resource::IN::A]...
D, [2013-03-14T01:11:53.690406 #62668] DEBUG -- : No pattern matched.
I, [2013-03-14T01:11:53.690450 #62668]  INFO -- : Passing DNS request upstream...
D, [2013-03-14T01:11:57.063527 #62668] DEBUG -- : Receiving incoming query (28 bytes)...
D, [2013-03-14T01:11:57.063710 #62668] DEBUG -- : Processing question google.com Resolv::DNS::Resource::IN::A...
D, [2013-03-14T01:11:57.063764 #62668] DEBUG -- : Searching for google.com Resolv::DNS::Resource::IN::A
D, [2013-03-14T01:11:57.063800 #62668] DEBUG -- : Checking rule [/dev.mydomain.org/, Resolv::DNS::Resource::IN::ANY]...
D, [2013-03-14T01:11:57.063834 #62668] DEBUG -- : Resource class Resolv::DNS::Resource::IN::A failed to match Resolv::DNS::Resource::IN::ANY!
D, [2013-03-14T01:11:57.063865 #62668] DEBUG -- : Checking rule ["dev.mydomain.org", Resolv::DNS::Resource::IN::A]...
D, [2013-03-14T01:11:57.063892 #62668] DEBUG -- : No pattern matched.
D, [2013-03-14T01:11:57.063920 #62668] DEBUG -- : Checking rule ["80.0.0.10.in-addr.arpa", Resolv::DNS::Resource::IN::PTR]...
D, [2013-03-14T01:11:57.063948 #62668] DEBUG -- : Resource class Resolv::DNS::Resource::IN::A failed to match Resolv::DNS::Resource::IN::PTR!
D, [2013-03-14T01:11:57.063977 #62668] DEBUG -- : Checking rule ["dev.mydomain.org", Resolv::DNS::Resource::IN::MX]...
D, [2013-03-14T01:11:57.064023 #62668] DEBUG -- : Resource class Resolv::DNS::Resource::IN::A failed to match Resolv::DNS::Resource::IN::MX!
D, [2013-03-14T01:11:57.064051 #62668] DEBUG -- : Checking rule [/^test([0-9]+).mydomain.org$/, Resolv::DNS::Resource::IN::A]...
D, [2013-03-14T01:11:57.064080 #62668] DEBUG -- : No pattern matched.
I, [2013-03-14T01:11:57.064106 #62668]  INFO -- : Passing DNS request upstream...
Assertion failed: (OutboundPages.size() > 0), function Write, file ed.cpp, line 1653.

and here is the source code from your example file:

require 'rubygems'
require 'rubydns'
require 'rubydns/system'

# You can specify other DNS servers easily
# $R = Resolv::DNS.new(:nameserver => ["xx.xx.1.1", "xx.xx.2.2"])

R = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
Name = Resolv::DNS::Name
IN = Resolv::DNS::Resource::IN

RubyDNS::run_server do
  # % dig +nocmd +noall +answer @localhost ANY dev.mydomain.org
    # dev.mydomain.org. 16000   IN  A   10.0.0.80
    # dev.mydomain.org. 16000   IN  MX  10 mail.mydomain.org.
    match(/dev.mydomain.org/, IN::ANY) do |match_data, transaction|
        transaction.append_question!

        [IN::A, IN::CNAME, IN::MX].each do |resource_class|
            logger.debug "Appending query for #{resource_class}..."
            transaction.append_query!(transaction.name, resource_class)
        end
    end

    # For this exact address record, return an IP address
    match("dev.mydomain.org", IN::A) do |transaction|
        transaction.respond!("10.0.0.80")
    end

    match("80.0.0.10.in-addr.arpa", IN::PTR) do |transaction|
        transaction.respond!(Name.create("dev.mydomain.org."))
    end

    match("dev.mydomain.org", IN::MX) do |transaction|
        transaction.respond!(10, Name.create("mail.mydomain.org."))
    end

    match(/^test([0-9]+).mydomain.org$/, IN::A) do |match_data, transaction|
        offset = match_data[1].to_i

        if offset > 0 && offset < 10
            logger.info "Responding with address #{"10.0.0." + (90 + offset).to_s}..."
            transaction.respond!("10.0.0." + (90 + offset).to_s)
        else
            logger.info "Address out of range: #{offset}!"
            false
        end
    end

    # Default DNS handler
    otherwise do |transaction|
        logger.info "Passing DNS request upstream..."
        transaction.passthrough!(R)
    end

My Env:

Darwin B612.local 12.2.1 Darwin Kernel Version 12.2.1: Thu Oct 18 12:13:47 PDT 2012; root:xnu-2050.20.9~1/RELEASE_X86_64 x86_64
EM 1.0.0
Ruby 2.0.0

consider releasing a new version (1.0.3 is not possible to be packaged for distributions)

Hey, please consider releasing a new version. The current one (1.0.3) depends on celluloid = 0.16.0 which can't be met for a distribution level of packaging as it ships > 0.17. I have seen you made already adjustments so its able to switch to celluloid libraries from the 0.17 series.
I would highly appreciate if you could consider releasing a new version soon so I could package your library for our distribution (as rubydns its a hard dependency for a program I maintain).

cheers and thx

Tools for Consistent, Parseable Log Formatting

This is intended as a discussion about a potential feature. If we can agree on goals and details I can probably do a PR

In most of RubyDNS' logging, the log message starts with either angle brackets or square brackets, which generally contain either a message id. a response id, or a query id. Some messages start with an empty set of angle brackets, and at least one message (the startup message) has no brackets at all.

I'd like to have a consistent format that is easily parseable by automated tools. Some goals:

  1. The type of data (message id, response id, query id) associated with a log message should be unambiguous
  2. The presence or absence of such data should be unambiguous regardless of the log message (i.e. Even if I start my log message with '<', it should not be possible to confuse the data and message setions)
  3. RubyDNS should include a Logger formatter that makes it easy to format logs in the preferred manner
  4. All examples should use this format

@ioquatix Any thoughts? If you agree with the above goals, do you have preferences for the format?

problem when running on port :53

Hi,

When I launch a rubydns server on port 5330, everything works fine. But when I launch the server at port 53 (to replace my ISP's dns server), the process is blocked: The dig command will exist with "TimeOut" error.

Any ideas?

Append multiple IP to answer

I've tried with this code to append multiple responses to a single request

match(/.*/, IN::A) do |transaction|
    transaction.defer!
    GOOGLE.query(transaction.name, IN::A) do |response|
        logger.debug 'Got response from google servers'
        response.answer.each do |singleResult|
            transaction.append!(singleResult[2])
        end
        transaction.succeed
    end
end

but the problem is that the response is sent after the first ip to be returned, these are the logs:

D, [2013-12-24T15:52:45.535869 #26845] DEBUG -- : Got response from google servers
D, [2013-12-24T15:52:45.535986 #26845] DEBUG -- : add_answer: #<Resolv::DNS::Resource::IN::A:0x007fd131a09718 @address=#<Resolv::IPv4 173.194.113.224>, @ttl=253> 1 1
D, [2013-12-24T15:52:45.536054 #26845] DEBUG -- : Passing answer back to caller...
D, [2013-12-24T15:52:45.536138 #26845] DEBUG -- : Writing response to client (44 bytes) via UDP...
D, [2013-12-24T15:52:45.536209 #26845] DEBUG -- : add_answer: #<Resolv::DNS::Resource::IN::A:0x007fd131a08f70 @address=#<Resolv::IPv4 173.194.113.225>, @ttl=253> 1 1
D, [2013-12-24T15:52:45.536288 #26845] DEBUG -- : add_answer: #<Resolv::DNS::Resource::IN::A:0x007fd131a087c8 @address=#<Resolv::IPv4 173.194.113.230>, @ttl=253> 1 1
D, [2013-12-24T15:52:45.536358 #26845] DEBUG -- : add_answer: #<Resolv::DNS::Resource::IN::A:0x007fd131a13fb0 @address=#<Resolv::IPv4 173.194.113.228>, @ttl=253> 1 1
D, [2013-12-24T15:52:45.536434 #26845] DEBUG -- : add_answer: #<Resolv::DNS::Resource::IN::A:0x007fd131a13808 @address=#<Resolv::IPv4 173.194.113.226>, @ttl=253> 1 1

what should I use to give multiple IPs into the response?

AXFR only first packet gets parsed

shouldn't this result in the same as "dig axfr . @192.228.79.201"?

It's quiet clear what's happening if we do a network dump (e.g. Wireshark). The server responds with two DNS packets, but DNSruby only parses the first.

require 'rubygems'
require 'dnsruby'
include Dnsruby
nameserver = "192.228.79.201"
resolver = Resolver.new(:nameserver => [nameserver])
resolver.use_tcp = true
question = Message.new(".", Types.AXFR)
queue = Queue.new
resolver.send_async(question, queue, 876876876)
id, reply, error = queue.pop
puts reply.answer

DNS NOTIFY support

Does this support receiving DNS notify messages? I did not see it in the code.

Some programs can't resolve

Hi. I'm having an issue with some programs like "svn", "ntpdate", or "telnet". This programs can't resolve any host, while "ping", "host", "dig" or many other can.

My setup is:

  • Debian 7
  • Ruby 1.9.1
  • /etc/resolv.conf nameserver 127.0.0.1
  • passthrough! to our DNS

The script i've created is very simple, I can attach it if needed. Is something like follows:

require 'rubygems'

require 'rexec'
require 'rexec/daemon'

require 'rubydns'
require 'rubydns/system'


if RExec.current_user != "root"
    $stderr.puts "Arracanlo como root!"
    exit 1
end


class DNSMovilidad < RExec::Daemon::Base

    INTERFACES = [
        [:udp, "0.0.0.0", 53],
        [:tcp, "0.0.0.0", 53]
    ]

    JME_DNS = [
        [:tcp, "172.16.22.3", 53]
    ]

    #UPSTREAM_JME = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
    UPSTREAM_JME = RubyDNS::Resolver.new(JME_DNS)

    Name = Resolv::DNS::Name
    IN = Resolv::DNS::Resource::IN

    def self.run
        # Don't buffer output (for debug purposes)
        $stderr.sync = true

        etc_hosts = RubyDNS::System::Hosts.local()
        eh_mtime = File.mtime(RubyDNS::System::HOSTS)

        RubyDNS::run_server(:listen => INTERFACES) do
            on(:start) do
                #@logger.level = Logger::INFO
                #RExec.change_user(RUN_AS)

                @logger = Logger.new('/LOGS/dns.log', 'weekly')
                if ARGV.include?("--debug")
                    @logger.level = Logger::DEBUG
                else
                    @logger.level = Logger::INFO
                end
            end

            match(//) do |transaction| # catch all!!

                if eh_mtime != File.mtime(RubyDNS::System::HOSTS)
                    etc_hosts = RubyDNS::System::Hosts.local()
                    eh_mtime = File.mtime(RubyDNS::System::HOSTS)
                    @logger.info "/etc/hosts cambiado #{eh_mtime}"
                end

                @logger.info "TEST #{transaction}"

                in_local = etc_hosts.lookup(transaction.name())


                if in_local
                    @logger.debug "Dominio en local #{in_local}"
                    transaction.respond!(in_local)


                elsif /^cms\-([a-z]+)\..*/.match(transaction.name())
                    @logger.debug "Dominio clasico lab-id02"
                    transaction.respond!("10.10.22.111") # lab-id02

                elsif /^(.*)\-([a-z]+)(\-([0-9a-z\.]+))?\.mov$/.match(transaction.name())
                    @logger.debug "Dominio nuevo enjuto1"
                    transaction.respond!("10.10.20.48") # enjuto1

# removed some patterns

                else
                    logger.debug "npi, UPSTREAM_JME"
                    transaction.passthrough!(UPSTREAM_JME)
                end
            end

            otherwise do |transaction|
                logger.debug "mmmm? UPSTREAM_JME"
                transaction.passthrough!(UPSTREAM_JME)
            end
        end

    end
end

DNSMovilidad.daemonize

As I said, all works fine except for some programs, I cant understand why "svn" cant resolve and "ping" can.

Thank you!

Warnings on jRuby

Hi!
When running rubydns on jRuby (yes, I know it's actually not supported. But this warning may apply also to other implementations) I get these warning:

$HOME/.rvm/gems/jruby-1.7.4/gems/rubydns-0.6.3/lib/rubydns/server.rb:106 warning: optional boolean argument is obsoleted

It seems that the attr :something, true syntax should not be used anymore.
Bye and thanks for the awesome work.
Shogun

Resolv::DNS::DecodeError: limit exceeded

I've written a really simple rubydns server and put it online to check how it is working. After some time the server stopped to respond with this error:

rubydns@web1:~/rubydns$ ./server.rb
 0.03s     info: Starting Async::DNS server (v1.2.5)... [pid=14308] [2020-04-17 14:11:44 +0200]
 0.03s     info: <> Listening for datagrams on #<Addrinfo: 0.0.0.0:5300 UDP> [pid=14308] [2020-04-17 14:11:44 +0200]
 0.03s     info: <> Listening for connections on #<Addrinfo: 0.0.0.0:5300 TCP> [pid=14308] [2020-04-17 14:11:44 +0200]
 40m9s    error: Async::DNS::DatagramHandler [oid=0x398] [pid=14308] [2020-04-17 14:51:53 +0200]
               |   Resolv::DNS::DecodeError: limit exceeded
               |   → /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1604 in `get_string'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1652 in `get_label'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1646 in `get_labels'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1619 in `get_name'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1656 in `get_question'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1528 in `block (2 levels) in decode'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1527 in `each'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1527 in `block in decode'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1552 in `initialize'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1516 in `new'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/2.7.0/resolv.rb:1516 in `decode'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/async-dns-1.2.5/lib/async/dns/message.rb:43 in `decode_message'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/async-dns-1.2.5/lib/async/dns/handler.rb:58 in `process_query'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/async-dns-1.2.5/lib/async/dns/handler.rb:82 in `respond'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/async-dns-1.2.5/lib/async/dns/handler.rb:76 in `block in run'
               |     /home/rubydns/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/async-1.24.2/lib/async/task.rb:258 in `block in make_fiber'

As the request to my server came from an other DNS server, I can't reproduce it simply. There was already a bug #10 which is similar to this. Maybe you can have a look.

Found an issue in an other project: slack-ruby/slack-ruby-client#66 but it's very old.

I've tried to find an according entry in ruby issue tracker but couldn't find one.

Gemfile.lock as reference:

GEM
  remote: https://rubygems.org/
  specs:
    async (1.24.2)
      console (~> 1.0)
      nio4r (~> 2.3)
      timers (~> 4.1)
    async-dns (1.2.5)
      async-io (~> 1.15)
    async-io (1.28.0)
      async (~> 1.14)
    console (1.8.2)
    minitest (5.14.0)
    nio4r (2.5.2)
    rubydns (2.0.2)
      async-dns (~> 1.0)
    timers (4.3.0)

PLATFORMS
  ruby

DEPENDENCIES
  minitest
  rubydns

BUNDLED WITH
   2.1.4

(UDP|TCP)RequestHandler dies

Message#decode can throw Resolv::DNS::DecodeError while trying to process an incoming request. (UDP|TCP)RequestHandler assumes that all incoming data can be decoded. Simple solution is to clear Message.id in RubyDNS::decode_message when decoding fails. Clearing this field will force an id mismatch in the request handlers.

/usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1465:in `get_string': limit exceeded (Resolv::DNS::DecodeError)
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1509:in `get_label'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1502:in `get_labels'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1480:in `get_name'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1513:in `get_question'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1391:in `block (2 levels) in decode'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1390:in `each'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1390:in `block in decode'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1415:in `initialize'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1379:in `new'
    from /usr/local/rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/resolv.rb:1379:in `decode'
    from /usr/local/rvm/gems/ruby-1.9.2-p320@surf/gems/rubydns-0.5.2/lib/rubydns/message.rb:38:in `decode_message'
    from /usr/local/rvm/gems/ruby-1.9.2-p320@surf/gems/rubydns-0.5.2/lib/rubydns/resolver.rb:177:in `receive_data'
    from /usr/local/rvm/gems/ruby-1.9.2-p320@surf/gems/eventmachine-1.0.0/lib/eventmachine.rb:187:in `run_machine'
    from /usr/local/rvm/gems/ruby-1.9.2-p320@surf/gems/eventmachine-1.0.0/lib/eventmachine.rb:187:in `run'
    from /usr/local/rvm/gems/ruby-1.9.2-p320@surf/gems/rubydns-0.5.2/lib/rubydns.rb:73:in `run_server'

Errno::ECONNRESET: Connection reset by peer

I did simple dns proxy (based on your flakey-dns example), which NXDomain some domains and proxy others. After a while it's crashed with such log message:

E, [2016-05-19T18:36:05.380280 #14018] ERROR -- : Actor crashed!
Errno::ECONNRESET: Connection reset by peer
        <internal:prelude>:76:in `__read_nonblock'
        <internal:prelude>:76:in `read_nonblock'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:41:in `block in sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:389:in `synchronize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:39:in `sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:128:in `readpartial'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/transport.rb:58:in `read_chunk'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/handler.rb:159:in `handle_connection'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'
E, [2016-05-19T18:36:05.380877 #14018] ERROR -- : Actor crashed!
Errno::ECONNRESET: Connection reset by peer
        <internal:prelude>:76:in `__read_nonblock'
        <internal:prelude>:76:in `read_nonblock'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:41:in `block in sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:389:in `synchronize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:39:in `sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:128:in `readpartial'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/transport.rb:58:in `read_chunk'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/handler.rb:159:in `handle_connection'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'
W, [2016-05-19T18:36:05.381014 #14018]  WARN -- : Terminating task: type=:call, meta={:method_name=>:run}, status=:iowait
        Celluloid::TaskFiber backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here.
E, [2016-05-19T18:36:05.382608 #14018] ERROR -- : Actor crashed!
Errno::ECONNRESET: Connection reset by peer
        <internal:prelude>:76:in `__read_nonblock'
        <internal:prelude>:76:in `read_nonblock'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:41:in `block in sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:389:in `synchronize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:39:in `sysread'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-io-0.16.2/lib/celluloid/io/stream.rb:128:in `readpartial'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/transport.rb:58:in `read_chunk'
        /usr/local/lib/ruby/gems/2.3.0/gems/rubydns-1.0.3/lib/rubydns/handler.rb:159:in `handle_connection'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:122:in `dispatch'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
        /usr/local/lib/ruby/gems/2.3.0/gems/celluloid-0.16.0/lib/celluloid/tasks/task_fiber.rb:15:in `block in create'
W, [2016-05-19T18:36:05.383086 #14018]  WARN -- : Terminating task: type=:call, meta={:method_name=>:run}, status=:iowait
        Celluloid::TaskFiber backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here.
=== Daemon Exception Backtrace @ 2016-05-23 12:56:43 +0300 ===
SignalException: SIGTERM
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/notification.rb:52:in `read'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/notification.rb:52:in `wait'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon.rb:134:in `sleep_until_interrupted'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon.rb:143:in `run'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon.rb:157:in `spawn'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/controller.rb:84:in `block in spawn'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/controller.rb:67:in `fork'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/controller.rb:67:in `spawn'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/controller.rb:113:in `start'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon/controller.rb:53:in `daemonize'
/usr/local/lib/ruby/gems/2.3.0/gems/process-daemon-1.0.1/lib/process/daemon.rb:180:in `daemonize'
dns-proxy.rb:50:in `<main>'
=== Daemon Crashed ===
=== Daemon Stopping @ 2016-05-23 12:56:43 +0300 ===

Then daemon remained to be run while dns is not serving (actor is not restarted). Line 50 is match()'s 'end' keyword.

This is obscure. How would you suggest to debug or workaround it? It's possible that uplink dns server temporary returned connection refused, I would like to catch and ignore this exception, but it does not show my script anywhere in stack trace on Errno::ECONNRESET exception.

Opened sockets are not closed.

Hi!
While testing my devdnsd with v 1.0, I noticed that if you try to run twice the same server in a process in asynchronous way, it will not close sockets.

Example:

server = RubyDNS::run_server(asynchronous: true, server_class: MyServer)
# Do something
server.terminate
server = RubyDNS::run_server(asynchronous: true, server_class: MyServer)

The second call will raise bind error as the socket is already in use.

This apparently happens because you never finalize the actors.

This snippet fixed the code in my case:

server.actors.first.links.each(&:terminate)

Maybe you can find a better way in the real implementation. :)
Hope this helps!
Paolo

How to test a server?

I've implemented a basic server that matches specific subdomains, following the examples. Nice and easy, it's a lovely library.

However, I'm uncertain how to approach unit tests to ensure the server's functionality. Do you have any recommendations? (I'm using Minitest, if that matters.)

Getting error Uninitialized contstant IN

I just want an async dns resolver for one time task. I installed 0.5 version n copy pasted the resolver code to test.. But it gave me the error Uninitialized constant IN. Can you gimme a simple example pasted on a gist or tell what possiblly could i b doing wrong?

NoMethodError while running RubyDNS

Hi there,

I'm currently using RubyDNS on Heroku and I sometimes see this error:

/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1510:in `get_labels': undefined method `ord' for nil:NilClass (NoMethodError) 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1503:in `get_name' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1542:in `get_rr' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1418:in `block (2 levels) in decode' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1417:in `each' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1417:in `block in decode' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1438:in `initialize' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1402:in `new' 
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/resolv.rb:1402:in `decode' 
/app/vendor/bundle/ruby/1.9.1/gems/rubydns-0.6.5/lib/rubydns/message.rb:39:in `decode_message' 
/app/vendor/bundle/ruby/1.9.1/gems/rubydns-0.6.5/lib/rubydns/resolver.rb:191:in `receive_data' 

I'm not exactly sure why this happens. I don't know which nameserver or domain name is causing it yet (I'll be finding out shortly). But some insight how we could fix it would be appreciated.

Thanks for making rubydns!

Gem broken by celluloid 0.16.1

It appears that the celluloid authors aren't abiding by sym-versioning rules, as the update to 0.16.0 was released a few days ago and completely breaks your gem. Can you lock to 0.16.0 in your gemspec and release a new version, or fix for the new gem versions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.