DNS query: Difference between revisions

From Rosetta Code
(removed my (wrrong) implementation)
(No difference)

Revision as of 15:18, 27 August 2011

Task
DNS query
You are encouraged to solve this task according to the task description, using any language you may know.

DNS is an internet service that maps domain names, like rosettacode.org, to IP addresses, like 66.220.0.231.

Use DNS to resolve www.kame.net to both IPv4 and IPv6 addresses. Print these addresses.

Ada

Works with: GNAT GPL version Any - package Gnat.Sockets supports only IPv4 as of Jun 2011

<lang Ada>with Ada.Text_IO; use Ada.Text_IO; with GNAT.Sockets; use GNAT.Sockets;

procedure DNSQuerying is

  Host         : Host_Entry_Type (1, 1);
  Inet_Addr_V4 : Inet_Addr_Type (Family_Inet);

begin

  Host         := Get_Host_By_Name (Name => "www.kame.net");
  Inet_Addr_V4 := Addresses (Host);
  Put ("IPv4: " & Image (Value => Inet_Addr_V4));

end DNSQuerying;</lang>

C

This solution uses getaddrinfo(), a standard function from RFC 3493. This code resembles an example from getaddrinfo(3), the BSD manual page. Whereas the man page code connects to www.kame.net, this code only prints the numeric addresses.

<lang c>#include <sys/types.h>

  1. include <sys/socket.h>
  2. include <netdb.h> /* getaddrinfo, getnameinfo */
  3. include <stdio.h> /* fprintf, printf */
  4. include <stdlib.h> /* exit */
  5. include <string.h> /* memset */

int main() { struct addrinfo hints, *res, *res0; int error; char host[NI_MAXHOST];

/* * Request only one socket type from getaddrinfo(). Else we * would get both SOCK_DGRAM and SOCK_STREAM, and print two * copies of each numeric address. */ memset(&hints, 0, sizeof hints); hints.ai_family = PF_UNSPEC; /* IPv4, IPv6, or anything */ hints.ai_socktype = SOCK_DGRAM; /* Dummy socket type */

/* * Use getaddrinfo() to resolve "www.kame.net" and allocate * a linked list of addresses. */ error = getaddrinfo("www.kame.net", NULL, &hints, &res0); if (error) { fprintf(stderr, "%s\n", gai_strerror(error)); exit(1); }

/* Iterate the linked list. */ for (res = res0; res; res = res->ai_next) { /* * Use getnameinfo() to convert res->ai_addr to a * printable string. * * NI_NUMERICHOST means to present the numeric address * without doing reverse DNS to get a domain name. */ error = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof host, NULL, 0, NI_NUMERICHOST);

if (error) { fprintf(stderr, "%s\n", gai_strerror(error)); } else { /* Print the numeric address. */ printf("%s\n", host); } }

/* Free the linked list. */ freeaddrinfo(res0);

return 0; }</lang>

C#

Implementation takes a host name string as a parameter, and returns the IP addresses in a comma-delimited string. Note that a failed lookup throws a SocketException. <lang csharp>

       private string LookupDns(string s)
       {
           try
           {
               System.Net.IPHostEntry ip = System.Net.Dns.GetHostEntry(s);
               string result = ip.AddressList[0].ToString();
               for (int i = 1; i < ip.AddressList.Length; ++i)
                   result += ", " + ip.AddressList[i].ToString();
               return result;
           }
           catch (System.Net.Sockets.SocketException se)
           {
               return se.Message;
           }
       }

</lang>

Delphi

The included Indy components wrap GetAddressInfo.

<lang Delphi>program DNSQuerying;

{$APPTYPE CONSOLE}

uses

 IdGlobal, IdStackWindows;

const

 DOMAIN_NAME = 'www.kame.net';

var

 lStack: TIdStackWindows;

begin

 lStack := TIdStackWindows.Create;
 try
   Writeln(DOMAIN_NAME);
   Writeln('IPv4: ' + lStack.ResolveHost(DOMAIN_NAME));
   Writeln('IPv6: ' + lStack.ResolveHost(DOMAIN_NAME, Id_IPv6));
 finally
   lStack.Free;
 end;

end.</lang>

Output:

www.kame.net
IPv4: 203.178.141.194
IPv6: 2001:200:DFF:FFF1:216:3EFF:FEB1:44D7

Go

<lang go>package main

import (

   "fmt"
   "net"

)

func main() {

   if addrs, err := net.LookupHost("www.kame.net"); err == nil {
       fmt.Println(addrs)
   } else {
       fmt.Println(err)
   }

}</lang> Output:

[203.178.141.194 2001:200:dff:fff1:216:3eff:feb1:44d7]

Java

<lang java>import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.UnknownHostException;

class DnsQuery {

   public static void main(String[] args) {
       try {
           InetAddress[] ipAddr = InetAddress.getAllByName("www.kame.net");
           for(int i=0; i < ipAddr.length ; i++) {
               if (ipAddr[i] instanceof Inet4Address) {
                   System.out.println("IPv4 : " + ipAddr[i].getHostAddress());
               } else if (ipAddr[i] instanceof Inet6Address) {
                   System.out.println("IPv6 : " + ipAddr[i].getHostAddress());
               }
           }
       } catch (UnknownHostException uhe) {
           System.err.println("unknown host");
       }
   }

} </lang> Output:

IPv4 : 203.178.141.194
IPv6 : 2001:200:dff:fff1:216:3eff:feb1:44d7

NetRexx

<lang netrexx> say InetAddress.getByName('rosettacode.org') </lang>

OCaml

<lang ocaml>let dns_query ~host ~ai_family =

 let opts = [
   Unix.AI_FAMILY ai_family;
   Unix.AI_SOCKTYPE Unix.SOCK_DGRAM;
 ] in
 let addr_infos = Unix.getaddrinfo host "" opts in
 match addr_infos with
 | [] -> failwith "dns_query"
 | ai :: _ ->
   match ai.Unix.ai_addr with
   | Unix.ADDR_INET (addr, _) -> (Unix.string_of_inet_addr addr)
   | Unix.ADDR_UNIX addr -> failwith "addr_unix"

let () =

 let host = "www.kame.net" in
 Printf.printf "primary addresses of %s are:\n" host;
 Printf.printf " IPv4 address: %s\n" (dns_query host Unix.PF_INET);
 Printf.printf " IPv6 address: %s\n" (dns_query host Unix.PF_INET6);
</lang>

Perl

Unfortunately IPv6 was only added to Perl 5.14, a relatively new version. <lang perl>require 5.14; # Older versions can't resolve IPv6 with just core Socket module

use Socket qw(getaddrinfo getnameinfo); my ($err, @res) = getaddrinfo("www.kame.net", 0,

               { protocol=>Socket::IPPROTO_TCP } );

die "getaddrinfo error: $err" if $err;

print getnameinfo($_->{addr}, Socket::NI_NUMERICHOST), "\n" for @res </lang>

PicoLisp

<lang PicoLisp>(make

  (in '(host "www.kame.net")
     (while (from "address ")
        (link (till "^J" T)) ) ) )</lang>

Output:

-> ("203.178.141.194" "2001:200:dff:fff1:216:3eff:feb1:44d7")

Python

<lang python>>>> import socket >>> ips = set(i[4][0] for i in socket.getaddrinfo('www.kame.net', 80)) >>> for ip in ips: print ip ... 2001:200:dff:fff1:216:3eff:feb1:44d7 203.178.141.194</lang>

Ruby

<lang ruby>irb(main):001:0> require 'socket' => true irb(main):002:0> Addrinfo.getaddrinfo("www.kame.net", nil, nil, :DGRAM) \ irb(main):003:0* .map! { |ai| ai.ip_address } => ["203.178.141.194", "2001:200:dff:fff1:216:3eff:feb1:44d7"]</lang>

Scheme

Works with: Guile

<lang scheme>; Query DNS (define n (car (hostent:addr-list (gethost "www.kame.net"))))

Display address as IPv4 and IPv6

(display (inet-ntoa n))(newline) (display (inet-ntop AF_INET n))(newline) (display (inet-ntop AF_INET6 n))(newline)</lang>

Output:

203.178.141.194
203.178.141.194
::203.178.141.194

Tcl

While Tcl does internally do address resolution, it doesn't directly support looking up addresses without actually connecting to them. This is left to support packages to provide. An additional complexity is that while the DNS protocol itself is defined to work with both TCP and UDP as the transport layer, Tcl only supports TCP sockets by default (because they have a stream model) whereas DNS is typically only deployed with UDP enabled.

Library: Tcllib (Package: dns)
Library: udp

<lang tcl>package require udp; # Query by UDP more widely supported, but requires external package package require dns

set host "www.kame.net" set v4 [dns::resolve $host -type A]; # Specifically get IPv4 address set v6 [dns::resolve $host -type AAAA]; # Specifically get IPv6 address while {[dns::status $v4] eq "connect" || [dns::status $v6] eq "connect"} {

   update; # Let queries complete

} puts "primary addresses of $host are:\n\tIPv4» [dns::address $v4]\n\tIPv6» [dns::address $v6]"</lang> Output:

primary addresses of www.kame.net are:
	IPv4» 203.178.141.194
	IPv6» 2001:200:dff:fff1:216:3eff:feb1:44d7