diff options
| author | jcopenha <jcopenha@typedef.org> | 2014-07-24 00:51:07 -0300 | 
|---|---|---|
| committer | dequis <dx@dxzone.com.ar> | 2014-07-24 00:51:07 -0300 | 
| commit | 632627e1ead19fc7dc07effe441b2d543a675229 (patch) | |
| tree | 84d8aac19b33ad72e1711a2a88ad6a7958c060ef /lib | |
| parent | 59e66ff766cbef04883c1d7477d66c7e9b515833 (diff) | |
srv_lookup: Portability fixes, handle compressed responses
srv_lookup works on cygwin and openbsd now.
Provide ns_initparse, friends, and types where they aren't provided by
platform.
Use dn_expandname instead of custom parser so compressed DNS responses
are handled correctly.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/misc.c | 27 | ||||
| -rw-r--r-- | lib/misc.h | 81 | ||||
| -rw-r--r-- | lib/ns_parse.c | 217 | 
4 files changed, 309 insertions, 18 deletions
| diff --git a/lib/Makefile b/lib/Makefile index f20b3797..40c03215 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,7 @@ _SRCDIR_ := $(_SRCDIR_)lib/  endif  # [SH] Program variables -objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o json.o json_util.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o +objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o json.o json_util.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ns_parse.o  LFLAGS += -r @@ -524,7 +524,7 @@ struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain )  	const unsigned char *buf;  	ns_msg nsh;  	ns_rr rr; -	int i, n, len, size; +	int n, len, size;  	g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain ); @@ -537,27 +537,20 @@ struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain )  	n = 0;  	while( ns_parserr( &nsh, ns_s_an, n, &rr ) == 0 )  	{ -		size = ns_rr_rdlen( rr ); +		char name[NS_MAXDNAME]; + +		if( ns_rr_rdlen( rr ) < 7) +		    break; +  		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 ) +		if( dn_expand(querybuf, querybuf + size, &buf[6], name, NS_MAXDNAME) == -1 )  			break; + +		len = strlen(name) + 1;  		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; -		} +		memcpy( reply->name, name, len );  		reply->prio = ( buf[0] << 8 ) | buf[1];  		reply->weight = ( buf[2] << 8 ) | buf[3]; @@ -37,6 +37,87 @@ struct ns_srv_reply  	char name[];  }; +#ifndef NAMESER_HAS_NS_TYPES + +#define NS_MAXDNAME 1025 +#define NS_INT16SZ  2 +#define NS_INT32SZ  4 + +#define NS_GET16(s, cp) do { \ +	register const unsigned char *t_cp = (const unsigned char*)(cp); \ +	(s) = ((guint16)t_cp[0] << 8) \ +	    | ((guint16)t_cp[1]) \ +	    ; \ +	(cp) += NS_INT16SZ; \ +} while(0) + +#define NS_GET32(s, cp) do { \ +	register const unsigned char *t_cp = (const unsigned char*)(cp); \ +	(s) = ((guint16)t_cp[0] << 24) \ +	    | ((guint16)t_cp[1] << 16) \ +	    | ((guint16)t_cp[2] << 8) \ +	    | ((guint16)t_cp[3]) \ +	    ; \ +	(cp) += NS_INT32SZ; \ +} while(0) + +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +struct _ns_flagdata { int mask, shift; }; + +typedef struct __ns_rr { +	char name[NS_MAXDNAME]; +	guint16 type; +	guint16 rr_class; +	guint32 ttl; +	guint16 rdlength; +	const unsigned char* rdata; +} ns_rr; + +typedef enum __ns_sect { +	ns_s_qd = 0, +	ns_s_zn = 0, +	ns_s_an = 1, +	ns_s_pr = 1, +	ns_s_ns = 2, +	ns_s_ud = 2, +	ns_s_ar = 3, +	ns_s_max =4 +} ns_sect; + +typedef struct __ns_msg +{ +	const unsigned char* _msg; +	const unsigned char* _eom; +	guint16 _id; +	guint16 _flags; +	guint16 _counts[ns_s_max]; +	const unsigned char* _sections[ns_s_max]; +	ns_sect _sect; +	int _rrnum; +	const unsigned char* _msg_ptr; +} ns_msg; + +typedef enum __ns_class { +	ns_c_invalid = 0, +	ns_c_in = 1, +	ns_c_2 = 2, +	ns_c_chaos = 3, +	ns_c_hs = 4, +	ns_c_none = 254, +	ns_c_any = 255, +	ns_c_max = 65536 +} ns_class; + + +/* TODO : fill out the rest */ +typedef enum __ns_type { +	ns_t_srv = 33 +} ns_type; + +#endif /* NAMESER_HAS_NS_INITPARSE */ +  G_MODULE_EXPORT void strip_linefeed( gchar *text );  G_MODULE_EXPORT char *add_cr( char *text );  G_MODULE_EXPORT char *strip_newlines(char *source); diff --git a/lib/ns_parse.c b/lib/ns_parse.c new file mode 100644 index 00000000..ba45d513 --- /dev/null +++ b/lib/ns_parse.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bitlbee.h" + +#ifndef lint +static const char rcsid[] = "$Id: ns_parse.c,v 1.10 2009/01/23 19:59:16 each Exp $"; +#endif + +#ifdef HAVE_RESOLV_A +#ifndef HAVE_RESOLV_A_WITH_NS +/* Import. */ + + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + + +/* Forward. */ + +static void	setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#if !defined(SOLARIS2) || defined(__COVERITY__) +#define RETERR(err) do { errno = (err); return (-1); } while (0) +#else +#define RETERR(err) \ +	do { errno = (err); if (errno == errno) return (-1); } while (0) +#endif + +#define PARSE_FMT_PRESO 0	/* Parse using presentation-format names */ +#define PARSE_FMT_WIRE 1	/* Parse using network-format names */ + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { +	{ 0x8000, 15 },		/*%< qr. */ +	{ 0x7800, 11 },		/*%< opcode. */ +	{ 0x0400, 10 },		/*%< aa. */ +	{ 0x0200, 9 },		/*%< tc. */ +	{ 0x0100, 8 },		/*%< rd. */ +	{ 0x0080, 7 },		/*%< ra. */ +	{ 0x0040, 6 },		/*%< z. */ +	{ 0x0020, 5 },		/*%< ad. */ +	{ 0x0010, 4 },		/*%< cd. */ +	{ 0x000f, 0 },		/*%< rcode. */ +	{ 0x0000, 0 },		/*%< expansion (1/6). */ +	{ 0x0000, 0 },		/*%< expansion (2/6). */ +	{ 0x0000, 0 },		/*%< expansion (3/6). */ +	{ 0x0000, 0 },		/*%< expansion (4/6). */ +	{ 0x0000, 0 },		/*%< expansion (5/6). */ +	{ 0x0000, 0 },		/*%< expansion (6/6). */ +}; + +int ns_msg_getflag(ns_msg handle, int flag) { +	return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { +	const u_char *optr = ptr; + +	for ((void)NULL; count > 0; count--) { +		int b, rdlength; + +		b = dn_skipname(ptr, eom); +		if (b < 0) +			RETERR(EMSGSIZE); +		ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; +		if (section != ns_s_qd) { +			if (ptr + NS_INT32SZ + NS_INT16SZ > eom) +				RETERR(EMSGSIZE); +			ptr += NS_INT32SZ/*TTL*/; +			NS_GET16(rdlength, ptr); +			ptr += rdlength/*RData*/; +		} +	} +	if (ptr > eom) +		RETERR(EMSGSIZE); +	return (ptr - optr); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { +	const u_char *eom = msg + msglen; +	int i; + +	handle->_msg = msg; +	handle->_eom = eom; +	if (msg + NS_INT16SZ > eom) +		RETERR(EMSGSIZE); +	NS_GET16(handle->_id, msg); +	if (msg + NS_INT16SZ > eom) +		RETERR(EMSGSIZE); +	NS_GET16(handle->_flags, msg); +	for (i = 0; i < ns_s_max; i++) { +		if (msg + NS_INT16SZ > eom) +			RETERR(EMSGSIZE); +		NS_GET16(handle->_counts[i], msg); +	} +	for (i = 0; i < ns_s_max; i++) +		if (handle->_counts[i] == 0) +			handle->_sections[i] = NULL; +		else { +			int b = ns_skiprr(msg, eom, (ns_sect)i, +					  handle->_counts[i]); + +			if (b < 0) +				return (-1); +			handle->_sections[i] = msg; +			msg += b; +		} +	if (msg != eom) +		RETERR(EMSGSIZE); +	setsection(handle, ns_s_max); +	return (0); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { +	int b; +	int tmp; + +	/* Make section right. */ +	tmp = section; +	if (tmp < 0 || section >= ns_s_max) +		RETERR(ENODEV); +	if (section != handle->_sect) +		setsection(handle, section); + +	/* Make rrnum right. */ +	if (rrnum == -1) +		rrnum = handle->_rrnum; +	if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) +		RETERR(ENODEV); +	if (rrnum < handle->_rrnum) +		setsection(handle, section); +	if (rrnum > handle->_rrnum) { +		b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, +			      rrnum - handle->_rrnum); + +		if (b < 0) +			return (-1); +		handle->_msg_ptr += b; +		handle->_rrnum = rrnum; +	} + +	/* Do the parse. */ +	b = dn_expand(handle->_msg, handle->_eom, +		      handle->_msg_ptr, rr->name, NS_MAXDNAME); +	if (b < 0) +		return (-1); +	handle->_msg_ptr += b; +	if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) +		RETERR(EMSGSIZE); +	NS_GET16(rr->type, handle->_msg_ptr); +	NS_GET16(rr->rr_class, handle->_msg_ptr); +	if (section == ns_s_qd) { +		rr->ttl = 0; +		rr->rdlength = 0; +		rr->rdata = NULL; +	} else { +		if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) +			RETERR(EMSGSIZE); +		NS_GET32(rr->ttl, handle->_msg_ptr); +		NS_GET16(rr->rdlength, handle->_msg_ptr); +		if (handle->_msg_ptr + rr->rdlength > handle->_eom) +			RETERR(EMSGSIZE); +		rr->rdata = handle->_msg_ptr; +		handle->_msg_ptr += rr->rdlength; +	} +	if (++handle->_rrnum > handle->_counts[(int)section]) +		setsection(handle, (ns_sect)((int)section + 1)); + +	/* All done. */ +	return (0); +} + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { +	msg->_sect = sect; +	if (sect == ns_s_max) { +		msg->_rrnum = -1; +		msg->_msg_ptr = NULL; +	} else { +		msg->_rrnum = 0; +		msg->_msg_ptr = msg->_sections[(int)sect]; +	} +} + +/*! \file */ +#endif +#endif | 
