nochowderforyou / clams

Clam Project
MIT License
61 stars 58 forks source link

clamd can't connect to its own rpc interface (in some cases) #272

Open haraldg opened 8 years ago

haraldg commented 8 years ago

This is a minor issue as it probably only happens in rare configurations and can easily be worked around. Nevertheless it is somewhat strange:

The machine is an amd64 linux 3.16.0 with only IPv6 connectivity. DNS is also using IPv6 - no problems there so far. Locally there is a loop back interface with 127.0.0.1

If I try to connect to clamd, eg: "clamd help" I get an error: error: resolve: Host not found (authoritative)

The same error is also reported with "clamd -rpcconnect=127.0.0.1 help" so why is it trying to do a host lookup?

Oddly enough "clamd -rpcconnect=::1 help" works fine.

I tried to strace clamd and had a look at the source but couldn't find anything wrong, so maybe this is an issue with an underlying library. OTOH clamd is the only program I have had trouble with on this machine so far, so thought I should mention this anyway.

tryphe commented 8 years ago

I've never used a v6-only machine, but it looks like GetLocalAddress() does a host lookup of 0.0.0.0(v4 wildcard address) which should return all of your addresses for every interface. However, since your loopback interface is a logical interface, it may not be bound to 0.0.0.0, so nothing is returned since there is no endpoint for the wildcard. Just a hunch.

Does it work with bitcoin? Maybe something needs to be changed.

tryphe commented 8 years ago

I seem to remember the v6 wildcard taking precedence over the v4 one on one of my machines. I'm thinking this might be intended so people stop using the v4 wildcard. Shrugs.

When you listen on ::1, can you see if the port is also open on 127.0.0.1?

dooglus commented 8 years ago

What do you see if you use netstat to check where clamd's RPC interface is listening?

$ netstat -lnt | grep 30174
tcp        0      0 127.0.0.1:30174         0.0.0.0:*               LISTEN     
tcp6       0      0 ::1:30174               :::*                    LISTEN     
haraldg commented 8 years ago

Sorry for the delayed replies, I'm somewhat busy ATM.

Yes, clamd is listening on the v4 address, but it doesn't matter: It fails before it even tries to connect to the rpc port.

I don't have bitcoind running on that machine, so will need a while before I can report back.

I don't think GetLocalAddress() is called when connecting to the rpc interface. I think this is the responsible code (rpcprotocol.h):

bool connect(const std::string& server, const std::string& port)
    {
        boost::asio::ip::tcp::resolver resolver(stream.get_io_service());
        boost::asio::ip::tcp::resolver::query query(server.c_str(), port.c_str());
        boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        boost::asio::ip::tcp::resolver::iterator end;
        boost::system::error_code error = boost::asio::error::host_not_found;
        while (error && endpoint_iterator != end)
        {
            stream.lowest_layer().close();
            stream.lowest_layer().connect(*endpoint_iterator++, error);
        }
haraldg commented 7 years ago

Finally stumbled upon the explanation for this: The behaviour is controlled by AI_ADDRCONFIG. See this post for example: http://stackoverflow.com/questions/5971242/how-does-boost-asios-hostname-resolution-work-on-linux-is-it-possible-to-use-n

I expect changing in the above code the line

boost::asio::ip::tcp::resolver::query query(server.c_str(), port.c_str());

to

boost::asio::ip::tcp::resolver::query query(server.c_str(), port.c_str(),  boost::asio::ip::resolver_query_base::numeric_service);

will fix the problem.

I can test this and submit a PR. However against which branch should the PR be?