DNS query

From Rosetta Code
Revision as of 20:53, 17 May 2011 by rosettacode>Markhobley ({{omit from|ZX Spectrum Basic}})
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.

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 SOCK_DGRAM addresses from getaddrinfo(). Else * we would get both SOCK_DGRAM and SOCK_STREAM addresses, 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;

/* * 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>

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")

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>

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