diff options
| -rw-r--r-- | include/arpa/nameser.h | 58 | ||||
| -rw-r--r-- | src/network/ns_parse.c | 171 | 
2 files changed, 194 insertions, 35 deletions
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h index b9ee6659..581925a4 100644 --- a/include/arpa/nameser.h +++ b/include/arpa/nameser.h @@ -1,6 +1,11 @@  #ifndef _ARPA_NAMESER_H  #define _ARPA_NAMESER_H +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h>  #include <stdint.h>  #define __NAMESER	19991006 @@ -48,6 +53,8 @@ extern const struct _ns_flagdata _ns_flagdata[];  #define ns_msg_end(handle) ((handle)._eom + 0)  #define ns_msg_size(handle) ((handle)._eom - (handle)._msg)  #define ns_msg_count(handle, section) ((handle)._counts[section] + 0) +#define ns_msg_getflag(handle, flag) \ +	(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)  typedef	struct __ns_rr {  	char		name[NS_MAXDNAME]; @@ -296,43 +303,20 @@ typedef enum __ns_cert_types {  #define NS_OPT_DNSSEC_OK        0x8000U  #define NS_OPT_NSID		3 -#define NS_GET16(s, cp) do { \ -	register const unsigned char *t_cp = (const unsigned char *)(cp); \ -	(s) = ((uint16_t)t_cp[0] << 8) \ -	    | ((uint16_t)t_cp[1]) \ -	    ; \ -	(cp) += NS_INT16SZ; \ -} while (0) - -#define NS_GET32(l, cp) do { \ -	register const unsigned char *t_cp = (const unsigned char *)(cp); \ -	(l) = ((uint32_t)t_cp[0] << 24) \ -	    | ((uint32_t)t_cp[1] << 16) \ -	    | ((uint32_t)t_cp[2] << 8) \ -	    | ((uint32_t)t_cp[3]) \ -	    ; \ -	(cp) += NS_INT32SZ; \ -} while (0) - -#define NS_PUT16(s, cp) do { \ -	register uint16_t t_s = (uint16_t)(s); \ -	register unsigned char *t_cp = (unsigned char *)(cp); \ -	*t_cp++ = t_s >> 8; \ -	*t_cp   = t_s; \ -	(cp) += NS_INT16SZ; \ -} while (0) - -#define NS_PUT32(l, cp) do { \ -	register uint32_t t_l = (uint32_t)(l); \ -	register unsigned char *t_cp = (unsigned char *)(cp); \ -	*t_cp++ = t_l >> 24; \ -	*t_cp++ = t_l >> 16; \ -	*t_cp++ = t_l >> 8; \ -	*t_cp   = t_l; \ -	(cp) += NS_INT32SZ; \ -} while (0) +#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2)) +#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4)) +#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2) +#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4) +unsigned ns_get16(const unsigned char *); +unsigned long ns_get32(const unsigned char *); +void ns_put16(unsigned, unsigned char *); +void ns_put32(unsigned long, unsigned char *); +int ns_initparse(const unsigned char *, int, ns_msg *); +int ns_parserr(ns_msg *, ns_sect, int, ns_rr *); +int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int); +int ns_name_uncompress(const unsigned char *, const unsigned char *, const unsigned char *, char *, size_t);  #define	__BIND		19950621 @@ -464,4 +448,8 @@ typedef struct {  #define	PUTSHORT		NS_PUT16  #define	PUTLONG			NS_PUT32 +#ifdef __cplusplus +} +#endif +  #endif diff --git a/src/network/ns_parse.c b/src/network/ns_parse.c new file mode 100644 index 00000000..3ff33a87 --- /dev/null +++ b/src/network/ns_parse.c @@ -0,0 +1,171 @@ +#define _BSD_SOURCE +#include <errno.h> +#include <stddef.h> +#include <resolv.h> +#include <arpa/nameser.h> + +const struct _ns_flagdata _ns_flagdata[16] = { +	{ 0x8000, 15 }, +	{ 0x7800, 11 }, +	{ 0x0400, 10 }, +	{ 0x0200, 9 }, +	{ 0x0100, 8 }, +	{ 0x0080, 7 }, +	{ 0x0040, 6 }, +	{ 0x0020, 5 }, +	{ 0x0010, 4 }, +	{ 0x000f, 0 }, +	{ 0x0000, 0 }, +	{ 0x0000, 0 }, +	{ 0x0000, 0 }, +	{ 0x0000, 0 }, +	{ 0x0000, 0 }, +	{ 0x0000, 0 }, +}; + +unsigned ns_get16(const unsigned char *cp) +{ +	return cp[0]<<8 | cp[1]; +} + +unsigned long ns_get32(const unsigned char *cp) +{ +	return (unsigned)cp[0]<<24 | cp[1]<<16 | cp[2]<<8 | cp[3]; +} + +void ns_put16(unsigned s, unsigned char *cp) +{ +	*cp++ = s>>8; +	*cp++ = s; +} + +void ns_put32(unsigned long l, unsigned char *cp) +{ +	*cp++ = l>>24; +	*cp++ = l>>16; +	*cp++ = l>>8; +	*cp++ = l; +} + +int ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle) +{ +	int i, r; + +	handle->_msg = msg; +	handle->_eom = msg + msglen; +	if (msglen < (2 + ns_s_max) * NS_INT16SZ) goto bad; +	NS_GET16(handle->_id, msg); +	NS_GET16(handle->_flags, msg); +	for (i = 0; i < ns_s_max; i++) NS_GET16(handle->_counts[i], msg); +	for (i = 0; i < ns_s_max; i++) { +		if (handle->_counts[i]) { +			handle->_sections[i] = msg; +			r = ns_skiprr(msg, handle->_eom, i, handle->_counts[i]); +			if (r < 0) return -1; +			msg += r; +		} else { +			handle->_sections[i] = NULL; +		} +	} +	if (msg != handle->_eom) goto bad; +	handle->_sect = ns_s_max; +	handle->_rrnum = -1; +	handle->_msg_ptr = NULL; +	return 0; +bad: +	errno = EMSGSIZE; +	return -1; +} + +int ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count) +{ +	const unsigned char *p = ptr; +	int r; + +	while (count--) { +		r = dn_skipname(p, eom); +		if (r < 0) goto bad; +		if (r + 2 * NS_INT16SZ > eom - p) goto bad; +		p += r + 2 * NS_INT16SZ; +		if (section != ns_s_qd) { +			if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad; +			p += NS_INT32SZ; +			NS_GET16(r, p); +			if (r > eom - p) goto bad; +			p += r; +		} +	} +	return ptr - p; +bad: +	errno = EMSGSIZE; +	return -1; +} + +int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) +{ +	int r; + +	if (section < 0 || section >= ns_s_max) goto bad; +	if (section != handle->_sect) { +		handle->_sect = section; +		handle->_rrnum = 0; +		handle->_msg_ptr = handle->_sections[section]; +	} +	if (rrnum == -1) rrnum = handle->_rrnum; +	if (rrnum < 0 || rrnum >= handle->_counts[section]) goto bad; +	if (rrnum < handle->_rrnum) { +		handle->_rrnum = 0; +		handle->_msg_ptr = handle->_sections[section]; +	} +	if (rrnum > handle->_rrnum) { +		r = ns_skiprr(handle->_msg_ptr, handle->_eom, section, rrnum - handle->_rrnum); +		if (r < 0) return -1; +		handle->_msg_ptr += r; +		handle->_rrnum = rrnum; +	} +	r = ns_name_uncompress(handle->_msg, handle->_eom, handle->_msg_ptr, rr->name, NS_MAXDNAME); +	if (r < 0) return -1; +	handle->_msg_ptr += r; +	if (2 * NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size; +	NS_GET16(rr->type, handle->_msg_ptr); +	NS_GET16(rr->rr_class, handle->_msg_ptr); +	if (section != ns_s_qd) { +		if (NS_INT32SZ + NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size; +		NS_GET32(rr->ttl, handle->_msg_ptr); +		NS_GET16(rr->rdlength, handle->_msg_ptr); +		if (rr->rdlength > handle->_eom - handle->_msg_ptr) goto size; +		rr->rdata = handle->_msg_ptr; +		handle->_msg_ptr += rr->rdlength; +	} else { +		rr->ttl = 0; +		rr->rdlength = 0; +		rr->rdata = NULL; +	} +	handle->_rrnum++; +	if (handle->_rrnum > handle->_counts[section]) { +		handle->_sect = section + 1; +		if (handle->_sect == ns_s_max) { +			handle->_rrnum = -1; +			handle->_msg_ptr = NULL; +		} else { +			handle->_rrnum = 0; +		} +	} +	return 0; +bad: +	errno = ENODEV; +	return -1; +size: +	errno = EMSGSIZE; +	return -1; +} + +int ns_name_uncompress(const unsigned char *msg, const unsigned char *eom, +                       const unsigned char *src, char *dst, size_t dstsiz) +{ +	int r; +	r = dn_expand(msg, eom, src, dst, dstsiz); +	if (r < 0) errno = EMSGSIZE; +	return r; +} +  | 
