diff options
-rw-r--r-- | include/arpa/nameser.h | 7 | ||||
-rw-r--r-- | libc/inet/Makefile.in | 2 | ||||
-rw-r--r-- | libc/inet/ns_parse.c | 8 | ||||
-rw-r--r-- | libc/inet/resolv.c | 195 |
4 files changed, 206 insertions, 6 deletions
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h index cdc3df555..153424954 100644 --- a/include/arpa/nameser.h +++ b/include/arpa/nameser.h @@ -120,13 +120,9 @@ typedef struct __ns_msg { /* Private data structure - do not use from outside library. */ struct _ns_flagdata { int mask, shift; }; -extern struct _ns_flagdata _ns_flagdata[]; +extern const struct _ns_flagdata _ns_flagdata[]; /* Accessor macros - this is part of the public interface. */ -#define ns_msg_getflag(handle, flag) ( \ - ((handle)._flags & _ns_flagdata[flag].mask) \ - >> _ns_flagdata[flag].shift \ - ) #define ns_msg_id(handle) ((handle)._id + 0) #define ns_msg_base(handle) ((handle)._msg + 0) #define ns_msg_end(handle) ((handle)._eom + 0) @@ -499,6 +495,7 @@ typedef enum __ns_cert_types { #define ns_samename __ns_samename __BEGIN_DECLS +int ns_msg_getflag (ns_msg, int) __THROW; u_int ns_get16 (const u_char *) __THROW; u_long ns_get32 (const u_char *) __THROW; void ns_put16 (u_int, u_char *) __THROW; diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in index 6c2c576f8..f2a495aa5 100644 --- a/libc/inet/Makefile.in +++ b/libc/inet/Makefile.in @@ -41,7 +41,7 @@ CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ res_init.c res_query.c res_comp.c ns_name.c \ _res_state.c CSRC-$(findstring y,$(UCLIBC_HAS_RESOLVER_SUPPORT)) += \ - ns_netint.c + ns_netint.c ns_parse.c ## # unused ATM ## CSRC-y += encodep.c decodep.c formquery.c diff --git a/libc/inet/ns_parse.c b/libc/inet/ns_parse.c new file mode 100644 index 000000000..e7aecb421 --- /dev/null +++ b/libc/inet/ns_parse.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ns_parse +#include RESOLVER diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 6bfe52c79..011cd5e56 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -3886,6 +3886,201 @@ void ns_put32(unsigned long src, unsigned char *dst) } #endif /* L_ns_netint */ +#ifdef L_ns_parse +/* These need to be in the same order as the nres.h:ns_flag enum. */ +const 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). */ +}; + +static void setsection(ns_msg *msg, ns_sect sect) +{ + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_ptr = msg->_sections[(int)sect]; + } +} + +int ns_skiprr(const unsigned char *ptr, + const unsigned char *eom, + ns_sect section, int count) +{ + const u_char *optr = ptr; + + for (; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) { + errno = EMSGSIZE; + return -1; + } + + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + + if (ptr > eom) { + errno = EMSGSIZE; + return -1; + } + + return ptr - optr; +} + +int +ns_initparse(const unsigned 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) { + errno = EMSGSIZE; + return -1; + } + + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) { + errno = EMSGSIZE; + return -1; + } + + 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) { + errno = EMSGSIZE; + return -1; + } + + 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) { + errno = ENODEV; + return -1; + } + + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) { + errno = ENODEV; + return -1; + } + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_ptr += b; + if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + NS_GET16(rr->type, handle->_ptr); + NS_GET16(rr->rr_class, handle->_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + NS_GET32(rr->ttl, handle->_ptr); + NS_GET16(rr->rdlength, handle->_ptr); + if (handle->_ptr + rr->rdlength > handle->_eom) { + errno = EMSGSIZE; + return -1; + } + rr->rdata = handle->_ptr; + handle->_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + return 0; +} + +int ns_msg_getflag(ns_msg handle, int flag) { + return ((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift; +} +#endif /* L_ns_parse */ + /* Unimplemented: */ /* res_mkquery */ /* res_send */ |