[icecast-dev] src/net/resolver.c patches for better IPv6 resolution

BOUWSMA Beery beerstream at ipv6.netscum.dyndns.dk
Sun Sep 29 11:32:15 PDT 2002



[caution: this is an IPv6 e-mail address.  if you don't have
 IPv6-capable mail then best keep replies on the list only]

> >existing getipnodebyname() call fails with IPv4 on my machine)...
> Well, if you can make it work properly - send your patches in, please.

The following enhancements to src/net/resolver.c (which looks identical
across icecast, ices, libshout, and who knows what all) suffice here to
get the test_resolver.c program to produce useful output on my FreeBSD
machine -- if it's true that (some) Linux doesn't have getipnodebyname()
then a different solution might be needed.

The results when built with -DHAVE_IPV6=1 -DHAVE_GETIPNODEBYNAME=1
added to the Makefile DEFS on my FreeBSD 4.x:
I got 172.27.72.27, when looking up stable.netscum.dyndns.dk.
I got 2002:50da:100d:0:250:daff:fe21:edca, when looking up ipv6.netscum.dyndns.d
k.
I got 2002:50da:100d:0:250:daff:fe21:edca, when looking up netscum.dyndns.dk.
I got ::1, when looking up localhost.
I got news-feed02.inet.tele.dk, when looking up 193.162.153.122.
I got swi6netCE1-A2-0-1.switch.ch, when looking up 2001:620:0:39::1.
I got localhost, when looking up ::1.
Much more satisfying than before.

The results without the above added DEFS:
I got (null), when looking up ipv6.netscum.dyndns.dk.
I got 80.218.16.13, when looking up netscum.dyndns.dk.
I got news-feed02.inet.tele.dk, when looking up 193.162.153.122.
I got (null), when looking up 10.0.2.53.
I got 2001:620:0:39::1, when looking up 2001:620:0:39::1.

Now the question, for which I started to hack a bit:
On an IPv6-aware system, _isip("2001:620:0:39::1") is true.
On a non-IPv6-aware system, it's false, even though that's an IP
of the IPv6 family.  Should it be true?

And if it's false, as you can see, it's interpreted as a hostname,
and returned by resolver_getname(), instead of returning (null).
Should I bother with this at all?  (For example, should resolver_getname()
verify that what it's returning is in fact a hostname and not garbage?)

<p>Anyway, the patch.  I'm sure there's a better way to do this, as
I don't know what I'm doing, so I'd like to know what IPv6-capable
OSen aren't able to get proper results -- it appears to work on my
FreeBSD machine...  Did I say I have no clue what I'm doing yet?

<p>--- resolver.c-ORIG	Mon Aug  5 16:48:03 2002
+++ resolver.c	Sun Sep 29 19:43:54 2002
@@ -42,6 +42,13 @@
 static mutex_t _resolver_mutex;
 static int _initialized = 0;
 
+/* ugly hacks */
+struct in_addr inp;
+union {
+	struct in_addr v4addr;
+	struct in6_addr v6addr;
+} addr_u;
+
 char *resolver_getname(const char *ip, char *buff, int len)
 {
         if (!_isip(ip)) {
@@ -65,18 +72,11 @@
 static int _isip(const char *what)
 {
 #ifdef HAVE_IPV6
-	union {
-		struct in_addr v4addr;
-		struct in6_addr v6addr;
-	} addr_u;
-
         if (inet_pton(AF_INET, what, &addr_u.v4addr) <= 0)
                 return inet_pton(AF_INET6, what, &addr_u.v6addr) > 0 ? 1 : 0;
 
         return 1;
 #else
-	struct in_addr inp;
-
         return inet_aton(what, &inp);
 #endif
 }
@@ -87,27 +87,56 @@
 #ifdef HAVE_GETIPNODEBYNAME
         int err;
 #else
-	struct in_addr inp;
+	char *temp;
 #endif
         struct hostent *host = NULL;
-	char *temp;
 
         /* do a little sanity checking */
         if (what == NULL || buff == NULL || len <= 0)
                 return NULL;
 
 #ifdef HAVE_GETIPNODEBYNAME
-	host = getipnodebyname(what, AF_INET6, AI_DEFAULT, &err);
-	if (host) {
-		if (_isip(what))
+	if (_isip(what)) {
+		/* According to FreeBSD's man page, getipnodebyname and such
+		 * aren't threadsafe either */
+		_lock_resolver();
+		host = getipnodebyaddr(&addr_u.v4addr, sizeof(struct in_addr),
+		    AF_INET, &err);
+		_unlock_resolver();
+		if (host == NULL) {
+			_lock_resolver();
+			host = getipnodebyaddr(&addr_u.v6addr,
+			    sizeof(struct in6_addr), AF_INET6, &err);
+			_unlock_resolver();
+		}
+		if (host == NULL) {
+			buff = NULL;
+		} else {
                         strncpy(buff, host->h_name, len);
-		else
-			inet_ntop(host->h_addrtype, host->h_addr_list[0], buff, len);
-		
-		freehostent(host);
-	} else
-		buff = NULL;
-#else
+			freehostent(host);
+		}
+	} else {
+		/* According to FreeBSD's man page, getipnodebyname and such
+		 * aren't threadsafe either */
+		_lock_resolver();
+		/* Try IPv6 if available and configured; else try IPv4 */
+		host = getipnodebyname(what, AF_INET6, AI_ADDRCONFIG, &err);
+		_unlock_resolver();
+		if (host == NULL) {
+			_lock_resolver();
+			host = getipnodebyname(what, AF_INET, AI_ADDRCONFIG,
+			    &err);
+			_unlock_resolver();
+		}
+		if (host) {
+			inet_ntop(host->h_addrtype, host->h_addr_list[0],
+			    buff, len);
+			freehostent(host);
+		} else {
+			buff = NULL;
+		}
+	}
+#else  /* HAVE_GETIPNODEBYNAME */
         if (_isip(what)) {
                 /* gotta lock calls for now, since gethostbyname and such
                  * aren't threadsafe */
@@ -133,7 +162,7 @@
                 }
         }
 
-#endif
+#endif  /* HAVE_GETIPNODEBYNAME */
         return buff;
 }

 

thanks,
barry bouwsma, beer streamer

--- >8 ----
List archives:  http://www.xiph.org/archives/
icecast project homepage: http://www.icecast.org/
To unsubscribe from this list, send a message to 'icecast-dev-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the Icecast-dev mailing list