Question about host, gethostbyname and getaddress

Hi *,

Could you pleas help me with following problem ?

I need to get FQDN of host as well as it's IP. So I need same result as
"host" command gives me in *nix OSes. I found out these (suitable) functions:

Socket.getaddrinfo
IPSocket.getaddress
TCPSocket.gethostbyname

which can do the job (partialy). My problem is that non of them gives me
back FQDN. Eg. let's say that I have myserver.mydomain.com which is FQDN and
it's alias is myserver.

My problem is that when I use any of those functions with "myserver"
attribiute I always get as set of aliases ["myserver"] array only (e.g. no
myserver.mydomain.com).

Is there any way how to find out FQDN via some ruby function ? Thanks!

Regards,

  V.

gethostbyname and gethostbyaddr both return the "canonical name" in the first
element of the output array. If you are dealing with IP addresses gethostbyaddr
can do a reverse lookup for you (but not gethostbyname).

One tricky bit is that gethostbyaddr expects a struct in_addr packed into a
Ruby string. See inet_ntoa below to help with that.

Examples:

require 'socket'
def inet_aton(ip)
    ip.split('.').inject(String.new) { |str, q| str << q.to_i }
end

p Socket.gethostbyname('www.google.com')[0]
p Socket.gethostbyaddr(inet_aton("127.0.0.1"))[0]

···

On Wed, Nov 19, 2008 at 8:43 AM, Vladimir Fekete <fekete@melkor.dnp.fmph.uniba.sk> wrote:

Hi *,

Could you pleas help me with following problem ?

I need to get FQDN of host as well as it's IP. So I need same result as
"host" command gives me in *nix OSes. I found out these (suitable) functions:

Socket.getaddrinfo
IPSocket.getaddress
TCPSocket.gethostbyname

which can do the job (partialy). My problem is that non of them gives me
back FQDN. Eg. let's say that I have myserver.mydomain.com which is FQDN and
it's alias is myserver.

My problem is that when I use any of those functions with "myserver"
attribiute I always get as set of aliases ["myserver"] array only (e.g. no
myserver.mydomain.com).

Is there any way how to find out FQDN via some ruby function ? Thanks!

Regards,

V.

Hello Alan,

I think we don't understand each other. I don't need reverse DNS (I would use
resolv.rb for it instead). What I need is:

you have machine with fully qualified domain name (FQDN)
  a.b.c.d.e
It's hostname is
  a
It's IP is
  v.x.y.z

I'm looking for function which could give me back fully qualified domain
name and IP when I pass hostname as argument.

Probably I don't understand what is canonical name I thought it should be FQDN
but it is not.

because this code:

puts "getaddress : " + IPSocket.getaddress("a").inspect
puts "gethostbyname : " + TCPSocket.gethostbyname("a").inspect

has result:

getaddress : "10.0.2.1"
gethostbyname : ["a", , 2, "10.0.2.1"]

and what i need is result like this:

gethostbyname : ["a.b.c.d.e", ["a"], 2, "10.0.2.1"]

I hope it's more clear now. (or maybe I completely did not get what you
wanted to tell me)

Cheers,

V.

···

On Thu, Nov 20, 2008 at 05:23:20AM +0900, Alan Johnson wrote:

On Wed, Nov 19, 2008 at 8:43 AM, Vladimir Fekete > <fekete@melkor.dnp.fmph.uniba.sk> wrote:
>
> Hi *,
>
> Could you pleas help me with following problem ?
>
> I need to get FQDN of host as well as it's IP. So I need same result as
> "host" command gives me in *nix OSes. I found out these (suitable) functions:
>
> Socket.getaddrinfo
> IPSocket.getaddress
> TCPSocket.gethostbyname
>
> which can do the job (partialy). My problem is that non of them gives me
> back FQDN. Eg. let's say that I have myserver.mydomain.com which is FQDN and
> it's alias is myserver.
>
> My problem is that when I use any of those functions with "myserver"
> attribiute I always get as set of aliases ["myserver"] array only (e.g. no
> myserver.mydomain.com).
>
> Is there any way how to find out FQDN via some ruby function ? Thanks!
>
> Regards,
>
> V.
>

gethostbyname and gethostbyaddr both return the "canonical name" in the first
element of the output array. If you are dealing with IP addresses gethostbyaddr
can do a reverse lookup for you (but not gethostbyname).

One tricky bit is that gethostbyaddr expects a struct in_addr packed into a
Ruby string. See inet_ntoa below to help with that.

Examples:

require 'socket'
def inet_aton(ip)
    ip.split('.').inject(String.new) { |str, q| str << q.to_i }
end

p Socket.gethostbyname('www.google.com')[0]
p Socket.gethostbyaddr(inet_aton("127.0.0.1"))[0]

TCPSocket.gethostbyname is confusingly inconsistent with Socket.gethostbyname.
I suggest always using the Socket version. I think it will work the way you
want it to.

Alternatively, the getaddrinfo method may do what you are looking for.
Technically getaddrinfo obsoletes gethostbyname, anyway. It looks like:
Socket.getaddrinfo(host, port [, family] [, socktype] [, protocol] [,
flags]) => resultsArray

The rules for using it are pretty complicated but you'll probably want to do
something like:

include Socket::Constants
p Socket.getaddrinfo('myhost', nil, AF_INET, SOCK_STREAM)

Note that in either case your reverse DNS lookup must be configured correctly
or all you will get is an ip address. You can test this using the nslookup
command from a command prompt in Linux or Windows.

···

On Wed, Nov 19, 2008 at 3:44 PM, Vladimir Fekete <fekete@melkor.dnp.fmph.uniba.sk> wrote:

Hello Alan,

I think we don't understand each other. I don't need reverse DNS (I would use
resolv.rb for it instead). What I need is:

you have machine with fully qualified domain name (FQDN)
       a.b.c.d.e
It's hostname is
       a
It's IP is
       v.x.y.z

I'm looking for function which could give me back fully qualified domain
name and IP when I pass hostname as argument.

Probably I don't understand what is canonical name I thought it should be FQDN
but it is not.

because this code:

puts "getaddress : " + IPSocket.getaddress("a").inspect
puts "gethostbyname : " + TCPSocket.gethostbyname("a").inspect

has result:

getaddress : "10.0.2.1"
gethostbyname : ["a", , 2, "10.0.2.1"]

and what i need is result like this:

gethostbyname : ["a.b.c.d.e", ["a"], 2, "10.0.2.1"]

I hope it's more clear now. (or maybe I completely did not get what you
wanted to tell me)

Cheers,

V.

--
Alan

Hello Alan,

  I have to say you are not right. And if you are, then there is somwhere
huge problem, because it behaves in completely different way as it should.
  I tried to use getaddrinfo aswell, but the result was same (no canonical
name). Performance was terrible (17 times slower than getaddress and approx.
4 times slower than gethostbyname).

  Next thing is, that I don't have to have reverse dns set up, in fact I
don't. Reason why I believe this is true is, that "host" command works
perfectly withouth correct reverse dns. I thought that it is due to line in
/etc/hosts where I assigned IP to conanical name and aliases, but when I
commented out this line it worked as good as before.

result of command host a :
a.b.c.d.e.f.g has address 10.0.2.1

result of nslookup 10.0.2.1 :

Server: v.x.y.z
Address: v.x.y.z#53

** server can't find 1.2.0.10.in-addr.arpa: NXDOMAIN

So if "host" command works and all ruby's functions don't I assume there is
some problem in ruby.

Regards,

   V.

···

On Thu, Nov 20, 2008 at 09:21:44AM +0900, Alan Johnson wrote:

On Wed, Nov 19, 2008 at 3:44 PM, Vladimir Fekete > <fekete@melkor.dnp.fmph.uniba.sk> wrote:
> Hello Alan,
>
> I think we don't understand each other. I don't need reverse DNS (I would use
> resolv.rb for it instead). What I need is:
>
> you have machine with fully qualified domain name (FQDN)
> a.b.c.d.e
> It's hostname is
> a
> It's IP is
> v.x.y.z
>
> I'm looking for function which could give me back fully qualified domain
> name and IP when I pass hostname as argument.
>
> Probably I don't understand what is canonical name I thought it should be FQDN
> but it is not.
>
> because this code:
>
> puts "getaddress : " + IPSocket.getaddress("a").inspect
> puts "gethostbyname : " + TCPSocket.gethostbyname("a").inspect
>
> has result:
>
> getaddress : "10.0.2.1"
> gethostbyname : ["a", , 2, "10.0.2.1"]
>
> and what i need is result like this:
>
> gethostbyname : ["a.b.c.d.e", ["a"], 2, "10.0.2.1"]
>
> I hope it's more clear now. (or maybe I completely did not get what you
> wanted to tell me)
>
> Cheers,
>
> V.
>

TCPSocket.gethostbyname is confusingly inconsistent with Socket.gethostbyname.
I suggest always using the Socket version. I think it will work the way you
want it to.

Alternatively, the getaddrinfo method may do what you are looking for.
Technically getaddrinfo obsoletes gethostbyname, anyway. It looks like:
Socket.getaddrinfo(host, port [, family] [, socktype] [, protocol] [,
flags]) => resultsArray

The rules for using it are pretty complicated but you'll probably want to do
something like:

include Socket::Constants
p Socket.getaddrinfo('myhost', nil, AF_INET, SOCK_STREAM)

Note that in either case your reverse DNS lookup must be configured correctly
or all you will get is an ip address. You can test this using the nslookup
command from a command prompt in Linux or Windows.

--
Alan

# ... why I believe this is true is, that "host" command works
# perfectly withouth correct reverse dns....

try resolv.

eg,

require 'resolv'

=> true

Resolv.getname "10.2.10.123"

=> "bg-mis-pbot.delmonte-phil.com"

i believe that is my pc :wink:

Resolv.getname "10.2.10.23"

=> "bgmissappm00.delmonte-phil.com"

not mine :wink:

···

From: Vladimir Fekete [mailto:fekete@melkor.dnp.fmph.uniba.sk]

Ugh. I am very sorry. I've discovered why we are getting different results.
I submitted a patch last night that changes the way gethostbyname/gethostbyaddr
work. You see, right now they use a combination of several calls to functions
in the underlying OS and combine the output of them into the results you see.
I changed them to just faithfully call the underlying OS version of
gethostbyname/gethostbyaddr. See http://redmine.ruby-lang.org/issues/show/743
if you care about more details.

Somewhere along the way this patched version worked its way ahead of the stock
version in my path. I name the executables differently to avoid this sort of
confusion, but apparently I messed up somewhere.

So, the bad news is once I fixed the error and tested with ruby 1.8, I'm
getting similar results to you. The good news is that if that patch is
accepted then this problem will go away in the future (not that that helps you
any right now).

Apologies for any frustrations I've caused you.

···

On Thu, Nov 20, 2008 at 1:12 AM, Vladimir Fekete <fekete@melkor.dnp.fmph.uniba.sk> wrote:

Hello Alan,

I have to say you are not right.

--
Alan

Hi,

From: Vladimir Fekete [mailto:fekete@melkor.dnp.fmph.uniba.sk]
# ... why I believe this is true is, that "host" command works
# perfectly withouth correct reverse dns....

try resolv.

eg,

> require 'resolv'
=> true

> Resolv.getname "10.2.10.123"
=> "bg-mis-pbot.delmonte-phil.com"

i believe that is my pc :wink:

> Resolv.getname "10.2.10.23"
=> "bgmissappm00.delmonte-phil.com"

this does not work either.
Code:
#!/usr/bin/env ruby

require 'resolv'

puts Resolv.getname("10.0.2.1").to_s

result:

/usr/lib/ruby/1.8/resolv.rb:128:in `getname': no name for 10.0.2.1
/(Resolv::ResolvError)
        from /usr/lib/ruby/1.8/resolv.rb:64:in `getname'
        from ./test.rb:6

so as I said before, I don't have reverse dns (e.g. to get in-addr.arpa
from dns) and host command works, rubys' commands dont. :frowning: I guess I will
have to use `host` insted of pure ruby code.

regards,

  V.

···

On Thu, Nov 20, 2008 at 06:56:08PM +0900, Pe?a, Botp wrote:

not mine :wink:

# so as I said before, I don't have reverse dns (e.g. to get
# in-addr.arpa from dns)

oops, yes, just read the thread sorry.

try,

  Socket.do_not_reverse_lookup=true

···

From: Vladimir Fekete [mailto:fekete@melkor.dnp.fmph.uniba.sk]

Hi,

From: Vladimir Fekete [mailto:fekete@melkor.dnp.fmph.uniba.sk]
# so as I said before, I don't have reverse dns (e.g. to get
# in-addr.arpa from dns)

oops, yes, just read the thread sorry.

try,

  Socket.do_not_reverse_lookup=true

no, not helped, result is still same - no canonical name in array :frowning:

V.

···

On Thu, Nov 20, 2008 at 07:24:39PM +0900, Pe?a, Botp wrote:

that is weird. mine still works.
btw, i used that together with resolv.rb

thanks -botp

···

On Thu, Nov 20, 2008 at 6:36 PM, Vladimir Fekete <fekete@melkor.dnp.fmph.uniba.sk> wrote:

no, not helped, result is still same - no canonical name in array :frowning: