aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@google.com>2010-08-10 12:18:09 +0100
committerWilmer van der Gaast <wilmer@google.com>2010-08-10 12:18:09 +0100
commitffdf2e71d9e67980727aa994b77fca36ef5246c6 (patch)
tree59277a71581915c3203f879b4bf8276fdb001dbf /lib
parentf32c14c649e854fbfb7b8e495e2ebc8459ee5b6f (diff)
When doing SRV lookups, return an array with all RRs instead of just the
first one. The first isn't always the best one and this is currently causing GTalk issues when talk2.l.google.com (which is currently dead) is first.
Diffstat (limited to 'lib')
-rw-r--r--lib/misc.c80
-rw-r--r--lib/misc.h3
2 files changed, 52 insertions, 31 deletions
diff --git a/lib/misc.c b/lib/misc.c
index fda19c19..b696b8c4 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -507,16 +507,17 @@ int bool2int( char *value )
return 0;
}
-struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain )
+struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain )
{
- struct ns_srv_reply *reply = NULL;
+ struct ns_srv_reply **replies = NULL;
#ifdef HAVE_RESOLV_A
+ struct ns_srv_reply *reply = NULL;
char name[1024];
unsigned char querybuf[1024];
const unsigned char *buf;
ns_msg nsh;
ns_rr rr;
- int i, len, size;
+ int i, n, len, size;
g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain );
@@ -526,37 +527,56 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain )
if( ns_initparse( querybuf, size, &nsh ) != 0 )
return NULL;
- if( ns_parserr( &nsh, ns_s_an, 0, &rr ) != 0 )
- return NULL;
-
- size = ns_rr_rdlen( rr );
- buf = ns_rr_rdata( rr );
-
- len = 0;
- for( i = 6; i < size && buf[i]; i += buf[i] + 1 )
- len += buf[i] + 1;
-
- if( i > size )
- return NULL;
-
- reply = g_malloc( sizeof( struct ns_srv_reply ) + len );
- memcpy( reply->name, buf + 7, len );
-
- for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 )
- reply->name[i] = '.';
-
- if( i > len )
+ n = 0;
+ while( ns_parserr( &nsh, ns_s_an, n, &rr ) == 0 )
{
- g_free( reply );
- return NULL;
+ size = ns_rr_rdlen( rr );
+ buf = ns_rr_rdata( rr );
+
+ len = 0;
+ for( i = 6; i < size && buf[i]; i += buf[i] + 1 )
+ len += buf[i] + 1;
+
+ if( i > size )
+ break;
+
+ reply = g_malloc( sizeof( struct ns_srv_reply ) + len );
+ memcpy( reply->name, buf + 7, len );
+
+ for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 )
+ reply->name[i] = '.';
+
+ if( i > len )
+ {
+ g_free( reply );
+ break;
+ }
+
+ reply->prio = ( buf[0] << 8 ) | buf[1];
+ reply->weight = ( buf[2] << 8 ) | buf[3];
+ reply->port = ( buf[4] << 8 ) | buf[5];
+
+ n ++;
+ replies = g_renew( struct ns_srv_reply *, replies, n + 1 );
+ replies[n-1] = reply;
}
-
- reply->prio = ( buf[0] << 8 ) | buf[1];
- reply->weight = ( buf[2] << 8 ) | buf[3];
- reply->port = ( buf[4] << 8 ) | buf[5];
+ if( replies )
+ replies[n] = NULL;
#endif
- return reply;
+ return replies;
+}
+
+void srv_free( struct ns_srv_reply **srv )
+{
+ int i;
+
+ if( srv == NULL )
+ return;
+
+ for( i = 0; srv[i]; i ++ )
+ g_free( srv[i] );
+ g_free( srv );
}
/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */
diff --git a/lib/misc.h b/lib/misc.h
index 12a9edff..83ba9e67 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -60,7 +60,8 @@ G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count );
G_MODULE_EXPORT int is_bool( char *value );
G_MODULE_EXPORT int bool2int( char *value );
-G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain );
+G_MODULE_EXPORT struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain );
+G_MODULE_EXPORT void srv_free( struct ns_srv_reply **srv );
G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len );