Subject: DNS-SD in getaddrinfo()
To: NetBSD-network <tech-net@NetBSD.org>
From: Pelle Johansson <morth@morth.org>
List: tech-net
Date: 06/01/2004 20:24:46
Hello list, my first post (and a big one), but I believe I'm in the 
right place. I'm sure someone will tell me if I'm not. :)

I have developed an extension to getaddrinfo() implementing DNS service 
discovery as defined in RFC 2782. I believe this falls into the scope 
of that function since it's defined by RFC 3493 as this:

"The getaddrinfo() function translates the name of a service location
    (for example, a host name) and/or a service name and returns a set of
    socket addresses and associated information to be used in creating a
    socket with which to address the specified service."

I realise it won't be accepted at least without some discussion, but I 
wanted it for myself, so I did it. If NetBSD accepts it it's a plus. :)

The patch is rather big so I decided to not put it in the email. 
Instead you can find it at 
<http://www.morth.org/getaddrinfo-dns-sd.patch>. I'm not completely 
sure if it totally follows the coding standards, but I tried my best 
and it does satisfy lint. It doesn't call any functions that weren't 
already called during dns lookups, and should be completely thread safe 
by itself.

There's some things to consider:
1) There should probably be a way to turn of the SD. Either a flag or 
perhaps a nodename enclosed in brackets should be looked up directly 
(as postfix does), or both.
2) The descreptive error message for a rejected service is "No address 
associated with hostname". This is not completely correct, and perhaps 
should be changed. EAI_NONAME might be a better error code than 
EAI_NODATA (or not).

Here are some sample runs to show how the code is working (this is the 
last part of the mail if you get tired of reading). It prints canonical 
name, ip, port and protocol for the results from getaddrinfo():

# ./tai srvtest.morth.org http
kaninen.morth.org: 3ffe:bc0:c93:2::1 80/tcp
kaninen.morth.org: 130.236.227.234 80/tcp

matches:
_http._tcp      IN      SRV     1       0       80      
kaninen.morth.org.
_http._udp      IN      SRV     1       0       80      .

rejecting UDP and giving the TCP location for this service as 
kaninen.morth.org, port 80.


# ./tai srvtest.morth.org www
kaninen.morth.org: 3ffe:bc0:c93:2::1 80/tcp
kaninen.morth.org: 130.236.227.234 80/tcp

Just an example to show that service name aliases works (it's still 
_http._tcp that's looked up).


# ./tai srvtest.morth.org smtp
mail.morth.org: 3ffe:bc0:c93:2::1 10025/tcp
mail2.morth.org: 213.64.222.43 25/tcp
mail.cynisk.net: 194.237.241.78 25/tcp

matches:
_smtp._tcp      IN      SRV     1       0       10025   mail.morth.org.
                 IN      SRV     5       0       25      mail2.morth.org.
                 IN      SRV     10      0       25      mail.cynisk.net.

Here we have several hosts with different priority, and they'll always 
be returned in the correct order. smtp is only given for tcp in 
/etc/services and udp is therefore not returned. Notice also the 
nonstandard port.


# ./tai srvtest.morth.org ssh
srvtest.morth.org: 130.236.227.127 22/udp
kaninen.morth.org: 3ffe:bc0:c93:2::1 22/tcp
kaninen.morth.org: 130.236.227.234 22/tcp

matches:
@               IN      A       130.236.227.127
_ssh._tcp       IN      SRV     1       0       22      
kaninen.morth.org.

Since no UDP SRV record is found, a normal lookup is done instead.


# ./tai srvtest.morth.org telnet
gettaddrinfo: No address associated with hostname

matches:
_telnet._tcp    IN      SRV     1       0       23      .

Since telnet is only defined for tcp, and rejected by dns, the whole 
lookup is rejected.

# ./tai srvtest.morth.org qotd
kaninen.morth.org: 3ffe:bc0:c93:2::1 17/tcp
kaninen.morth.org: 130.236.227.234 17/tcp
mail2.morth.org: 213.64.222.43 17/tcp
srvtest.morth.org: 130.236.227.127 17/tcp
www.netbsd.org: 2001:4f8:4:7:290:27ff:feab:19a7 17/tcp
www.netbsd.org: 204.152.184.116 17/tcp
ftp.netbsd.org: 2001:4f8:4:7:2e0:81ff:fe21:6563 17/tcp
ftp.netbsd.org: 204.152.184.75 17/tcp
www.sunet.se: 192.36.125.18 17/tcp
ftp.sunet.se: 2001:6b0:19::64 17/tcp
ftp.sunet.se: 194.71.11.70 17/tcp

matches:
_qotd._tcp      IN      SRV     1       10      17      
kaninen.morth.org.
                 IN      SRV     1       5       17      
srvtest.morth.org.
                 IN      SRV     1       0       17      mail2.morth.org.
                 IN      SRV     2       1       17      www.netbsd.org.
                 IN      SRV     2       1       17      ftp.netbsd.org.
                 IN      SRV     3       0       17      www.sunet.se.
                 IN      SRV     3       0       17      ftp.sunet.se.

Showing how priorities are honored and weights are randomised.
-- 
Pelle Johansson
<morth@morth.org>