1
1
Files
zyxel-vmg8825_b50b-cfw/toolchain/uClibc/patches-0.9.32/uClibc-0.9.32-libresolve.patch
T
2026-04-17 18:33:03 +02:00

1568 lines
38 KiB
Diff

diff -rupN uClibc-0.9.32-ori/extra/Configs/Config.in uClibc-0.9.32/extra/Configs/Config.in
--- uClibc-0.9.32-ori/extra/Configs/Config.in 2011-06-08 12:35:20.000000000 -0700
+++ uClibc-0.9.32/extra/Configs/Config.in 2012-11-14 00:13:00.485546754 -0800
@@ -1268,6 +1268,16 @@ config UCLIBC_HAS_EXTRA_COMPAT_RES_STATE
Answer Y if selecting UCLIBC_HAS_COMPAT_RES_STATE is not enough.
As far as I can say, this should never be needed.
+config UCLIBC_HAS_RESOLVER_SUPPORT
+ bool "DNS resolver functions"
+ select UCLIBC_HAS_COMPAT_RES_STATE
+ help
+ Provide implementations for DNS resolver functions.
+ In particular, the following functions will be added to the
+ library:
+
+ ns_get16, ns_get32, ns_put16, ns_put32
+
config UCLIBC_HAS_LIBRESOLV_STUB
bool "Provide libresolv stub"
default n
diff -rupN uClibc-0.9.32-ori/include/arpa/nameser.h uClibc-0.9.32/include/arpa/nameser.h
--- uClibc-0.9.32-ori/include/arpa/nameser.h 2011-06-08 12:35:20.000000000 -0700
+++ uClibc-0.9.32/include/arpa/nameser.h 2012-11-14 00:13:23.481545598 -0800
@@ -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;
@@ -521,6 +518,7 @@ int ns_name_ntol (const u_char *, u_cha
int ns_name_ntop (const u_char *, char *, size_t) __THROW;
libc_hidden_proto(ns_name_ntop)
int ns_name_pton (const char *, u_char *, size_t) __THROW;
+libc_hidden_proto(ns_name_pton)
int ns_name_unpack (const u_char *, const u_char *,
const u_char *, u_char *, size_t) __THROW;
libc_hidden_proto(ns_name_unpack)
diff -rupN uClibc-0.9.32-ori/include/resolv.h uClibc-0.9.32/include/resolv.h
--- uClibc-0.9.32-ori/include/resolv.h 2011-06-08 12:35:20.000000000 -0700
+++ uClibc-0.9.32/include/resolv.h 2012-11-14 00:13:36.605544938 -0800
@@ -138,7 +138,6 @@ struct __res_state {
} sort_list[MAXRESOLVSORT];
#endif
-#ifdef __UCLIBC_HAS_IPV6__
/* I assume that the intention is to store all
* DNS servers' addresses here, and duplicate in nsaddr_list[]
* those which have IPv4 address. In the case of IPv4 address
@@ -152,7 +151,9 @@ struct __res_state {
*/
union {
struct {
+#ifdef __UCLIBC_HAS_IPV6__
struct sockaddr_in6 *nsaddrs[MAXNS];
+#endif
u_int8_t nscount; /* (was: u_int16_t) */
#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
/* rather obscure, and differs in BSD and glibc */
@@ -166,7 +167,6 @@ struct __res_state {
#endif
} _ext;
} _u;
-#endif
#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__
/* Truly obscure stuff.
@@ -292,8 +292,8 @@ __END_DECLS
#define res_init __res_init
#if 0
#define res_isourserver __res_isourserver
-#define res_mkquery __res_mkquery
#endif
+#define res_mkquery __res_mkquery
#define res_query __res_query
#define res_querydomain __res_querydomain
#define res_search __res_search
@@ -315,9 +315,9 @@ int res_init (void) __THROW;
libc_hidden_proto(res_init)
#if 0
int res_isourserver (const struct sockaddr_in *) __THROW;
+#endif
int res_mkquery (int, const char *, int, int, const u_char *,
int, const u_char *, u_char *, int) __THROW;
-#endif
int res_query (const char *, int, int, u_char *, int) __THROW;
libc_hidden_proto(res_query)
int res_querydomain (const char *, const char *, int, int,
@@ -332,12 +332,14 @@ __END_DECLS
#if 0
#define b64_ntop __b64_ntop
#define b64_pton __b64_pton
-#define dn_comp __dn_comp
#define dn_count_labels __dn_count_labels
#endif
+#define dn_comp __dn_comp
#define dn_expand __dn_expand
-#if 0
#define dn_skipname __dn_skipname
+#define res_ninit __res_ninit
+#define res_nclose __res_nclose
+#if 0
#define fp_resstat __fp_resstat
#define loc_aton __loc_aton
#define loc_ntoa __loc_ntoa
@@ -359,8 +361,6 @@ __END_DECLS
#define res_hostalias __res_hostalias
#define res_mailok __res_mailok
#define res_nameinquery __res_nameinquery
-#define res_nclose __res_nclose
-#define res_ninit __res_ninit
#define res_nmkquery __res_nmkquery
#define res_npquery __res_npquery
#define res_nquery __res_nquery
@@ -388,7 +388,6 @@ int b64_ntop (u_char const *, size_t, c
int b64_pton (char const *, u_char *, size_t) __THROW;
int loc_aton (const char *ascii, u_char *binary) __THROW;
const char * loc_ntoa (const u_char *binary, char *ascii) __THROW;
-int dn_skipname (const u_char *, const u_char *) __THROW;
void putlong (u_int32_t, u_char *) __THROW;
void putshort (u_int16_t, u_char *) __THROW;
const char * p_class (int) __THROW;
@@ -404,11 +403,14 @@ const u_char * p_fqname (const u_char *,
const char * p_option (u_long option) __THROW;
char * p_secstodate (u_long) __THROW;
int dn_count_labels (const char *) __THROW;
+#endif
+int dn_skipname (const u_char *, const u_char *) __THROW;
int dn_comp (const char *, u_char *, int, u_char **, u_char **)
__THROW;
-#endif
int dn_expand (const u_char *, const u_char *, const u_char *,
char *, int) __THROW;
+int res_ninit (res_state) __THROW;
+void res_nclose (res_state) __THROW;
#if 0
u_int res_randomid (void) __THROW;
int res_nameinquery (const char *, int, int,
@@ -417,7 +419,6 @@ int res_queriesmatch (const u_char *, c
const u_char *, const u_char *) __THROW;
const char * p_section (int section, int opcode) __THROW;
/* Things involving a resolver context. */
-int res_ninit (res_state) __THROW;
int res_nisourserver (const res_state,
const struct sockaddr_in *) __THROW;
void fp_resstat (const res_state, FILE *) __THROW;
@@ -436,7 +437,6 @@ int res_nmkquery (res_state, int, const
int) __THROW;
int res_nsend (res_state, const u_char *, int, u_char *, int)
__THROW;
-void res_nclose (res_state) __THROW;
#endif
__END_DECLS
diff -rupN uClibc-0.9.32-ori/libc/inet/Makefile.in uClibc-0.9.32/libc/inet/Makefile.in
--- uClibc-0.9.32-ori/libc/inet/Makefile.in 2011-06-08 12:35:20.000000000 -0700
+++ uClibc-0.9.32/libc/inet/Makefile.in 2012-11-14 00:13:40.317544752 -0800
@@ -37,7 +37,8 @@ CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(
get_hosts_byaddr_r.c get_hosts_byname_r.c \
gethostbyaddr_r.c gethostbyname_r.c gethostbyname2_r.c \
gethostbyaddr.c gethostbyname.c gethostbyname2.c
-CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \
+CSRC-$(findstring y,$(UCLIBC_HAS_RESOLVER_SUPPORT)) += \
+ ns_netint.c ns_parse.c res_data.c \
res_init.c res_query.c res_comp.c ns_name.c \
_res_state.c
## # unused ATM
diff -rupN uClibc-0.9.32-ori/libc/inet/ns_netint.c uClibc-0.9.32/libc/inet/ns_netint.c
--- uClibc-0.9.32-ori/libc/inet/ns_netint.c 1969-12-31 16:00:00.000000000 -0800
+++ uClibc-0.9.32/libc/inet/ns_netint.c 2012-11-14 00:13:00.485546754 -0800
@@ -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_netint
+#include RESOLVER
diff -rupN uClibc-0.9.32-ori/libc/inet/ns_parse.c uClibc-0.9.32/libc/inet/ns_parse.c
--- uClibc-0.9.32-ori/libc/inet/ns_parse.c 1969-12-31 16:00:00.000000000 -0800
+++ uClibc-0.9.32/libc/inet/ns_parse.c 2012-11-14 00:13:23.485545598 -0800
@@ -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 -rupN uClibc-0.9.32-ori/libc/inet/res_data.c uClibc-0.9.32/libc/inet/res_data.c
--- uClibc-0.9.32-ori/libc/inet/res_data.c 1969-12-31 16:00:00.000000000 -0800
+++ uClibc-0.9.32/libc/inet/res_data.c 2012-11-14 00:13:27.849545379 -0800
@@ -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_res_data
+#include RESOLVER
diff -rupN uClibc-0.9.32-ori/libc/inet/resolv.c uClibc-0.9.32/libc/inet/resolv.c
--- uClibc-0.9.32-ori/libc/inet/resolv.c 2011-06-08 12:35:20.000000000 -0700
+++ uClibc-0.9.32/libc/inet/resolv.c 2012-11-14 00:13:32.697545135 -0800
@@ -297,6 +297,7 @@ Domain name in a message can be represen
#include <features.h>
#include <string.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <signal.h>
#include <errno.h>
#include <sys/poll.h>
@@ -339,6 +340,9 @@ Domain name in a message can be represen
#define BUFSZ (80) /* one line */
#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
+#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
+#define DNS_LABELTYPE_BITSTRING 0x41
+
#undef DEBUG
/* #define DEBUG */
@@ -590,7 +594,7 @@ int attribute_hidden __encode_header(str
return HFIXEDSZ;
}
-#endif
+#endif /* L_encodeh */
#ifdef L_decodeh
@@ -611,7 +615,7 @@ void attribute_hidden __decode_header(un
h->nscount = (data[8] << 8) | data[9];
h->arcount = (data[10] << 8) | data[11];
}
-#endif
+#endif /* L_decodeh */
#ifdef L_encoded
@@ -650,7 +654,7 @@ int attribute_hidden __encode_dotted(con
return used;
}
-#endif
+#endif /* L_encoded */
#ifdef L_decoded
@@ -717,7 +721,7 @@ int attribute_hidden __decode_dotted(con
return total;
}
-#endif
+#endif /* L_decoded */
#ifdef L_encodeq
@@ -745,7 +749,7 @@ int attribute_hidden __encode_question(c
return i + 4;
}
-#endif
+#endif /* L_encodeq */
#ifdef L_encodea
@@ -778,7 +782,7 @@ int attribute_hidden __encode_answer(str
return i + RRFIXEDSZ + a->rdlength;
}
-#endif
+#endif /* L_encodea */
#ifdef CURRENTLY_UNUSED
@@ -844,7 +848,7 @@ int __encode_packet(struct resolv_header
return total;
}
-#endif
+#endif /* L_encodep */
#ifdef L_decodep
@@ -855,7 +859,7 @@ int __decode_packet(unsigned char *data,
__decode_header(data, h);
return HFIXEDSZ;
}
-#endif
+#endif /* L_decodep */
#ifdef L_formquery
@@ -893,7 +897,7 @@ int __form_query(int id,
return i + j;
}
-#endif
+#endif /* L_formquery */
#endif /* CURRENTLY_UNUSED */
@@ -1116,7 +1120,7 @@ void attribute_hidden __open_nameservers
if (__res_sync)
__res_sync();
}
-#endif
+#endif /* L_opennameservers */
#ifdef L_closenameservers
@@ -1134,7 +1138,7 @@ void attribute_hidden __close_nameserver
__searchdomain = NULL;
/*__searchdomains = 0; - already is */
}
-#endif
+#endif /* L_closenameservers */
#ifdef L_dnslookup
@@ -1400,7 +1404,7 @@ int attribute_hidden __dns_lookup(const
goto try_next_server;
}
reply_timeout--;
-#else
+#else /* !USE_SELECT */
reply_timeout = __resolv_timeout * 1000;
wait_again:
fds.fd = fd;
@@ -1413,7 +1417,7 @@ int attribute_hidden __dns_lookup(const
}
/*TODO: better timeout accounting?*/
reply_timeout -= 1000;
-#endif
+#endif /* USE_SELECT */
/* vda: a bogus response seen in real world (caused SEGV in uclibc):
* "ping www.google.com" sending AAAA query and getting
@@ -1571,7 +1575,7 @@ int attribute_hidden __dns_lookup(const
free(packet);
return -1;
}
-#endif
+#endif /* L_dnslookup */
#ifdef L_read_etc_hosts_r
@@ -1700,7 +1704,7 @@ found:
return ret;
#undef in6
}
-#endif
+#endif /* L_read_etc_hosts_r */
#ifdef L_get_hosts_byname_r
@@ -1716,7 +1720,7 @@ int attribute_hidden __get_hosts_byname_
return __read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME,
result_buf, buf, buflen, result, h_errnop);
}
-#endif
+#endif /* L_get_hosts_byname_r */
#ifdef L_get_hosts_byaddr_r
@@ -1758,7 +1762,7 @@ int attribute_hidden __get_hosts_byaddr_
return __read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR,
result_buf, buf, buflen, result, h_errnop);
}
-#endif
+#endif /* L_get_hosts_byaddr_r */
#ifdef L_getnameinfo
@@ -1961,7 +1965,7 @@ DONE:
return 0;
}
libc_hidden_def(getnameinfo)
-#endif
+#endif /* L_getnameinfo */
#ifdef L_gethostbyname_r
@@ -2175,7 +2179,7 @@ int gethostbyname_r(const char *name,
}
libc_hidden_def(gethostbyname_r)
link_warning(gethostbyname_r, "gethostbyname_r is obsolescent, use getnameinfo() instead.");
-#endif
+#endif /* L_gethostbyname_r */
#ifdef L_gethostbyname2_r
@@ -2332,7 +2336,7 @@ int gethostbyname2_r(const char *name,
#endif /* __UCLIBC_HAS_IPV6__ */
}
libc_hidden_def(gethostbyname2_r)
-#endif
+#endif /* L_gethostbyname2_r */
#ifdef L_gethostbyaddr_r
@@ -2493,7 +2497,7 @@ int gethostbyaddr_r(const void *addr, so
}
libc_hidden_def(gethostbyaddr_r)
link_warning(gethostbyaddr_r, "gethostbyaddr_r is obsolescent, use getaddrinfo() instead.");
-#endif
+#endif /* L_gethostbyaddr_r */
#ifdef L_gethostent_r
@@ -2550,7 +2554,7 @@ DONE:
return ret;
}
libc_hidden_def(gethostent_r)
-#endif
+#endif /* L_gethostent_r */
#ifdef L_gethostent
@@ -2570,7 +2574,7 @@ struct hostent *gethostent(void)
gethostent_r(&hoste, buf, sizeof(buf), &host, &h_errno);
return host;
}
-#endif
+#endif /* L_gethostent */
#ifdef L_gethostbyname2
@@ -2591,7 +2595,7 @@ struct hostent *gethostbyname2(const cha
#endif
}
libc_hidden_def(gethostbyname2)
-#endif
+#endif /* L_gethostbyname2 */
#ifdef L_gethostbyname
@@ -2613,7 +2617,7 @@ struct hostent *gethostbyname(const char
}
libc_hidden_def(gethostbyname)
link_warning(gethostbyname, "gethostbyname is obsolescent, use getnameinfo() instead.");
-#endif
+#endif /* L_gethostbyname */
#ifdef L_gethostbyaddr
@@ -2635,7 +2639,7 @@ struct hostent *gethostbyaddr(const void
}
libc_hidden_def(gethostbyaddr)
link_warning(gethostbyaddr, "gethostbyaddr is obsolescent, use getaddrinfo() instead.");
-#endif
+#endif /* L_gethostbyaddr */
#ifdef L_res_comp
@@ -2656,6 +2660,20 @@ int dn_expand(const u_char *msg, const u
dst[0] = '\0';
return n;
}
+
+/*
+ * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ */
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ return ns_name_compress(src, dst, (size_t) dstsiz,
+ (const u_char **) dnptrs,
+ (const u_char **) lastdnptr);
+}
#endif /* L_res_comp */
@@ -2792,6 +2810,259 @@ int ns_name_ntop(const u_char *src, char
}
libc_hidden_def(ns_name_ntop)
+static const char digits[] = "0123456789";
+
+static const char digitvalue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
+static int encode_bitstring(const char **bp, const char *end,
+ unsigned char **labelp,
+ unsigned char ** dst,
+ unsigned const char *eom)
+{
+ int afterslash = 0;
+ const char *cp = *bp;
+ unsigned char *tp;
+ char c;
+ const char *beg_blen;
+ char *end_blen = NULL;
+ int value = 0, count = 0, tbcount = 0, blen = 0;
+
+ beg_blen = end_blen = NULL;
+
+ /* a bitstring must contain at least 2 characters */
+ if (end - cp < 2)
+ return (EINVAL);
+
+ /* XXX: currently, only hex strings are supported */
+ if (*cp++ != 'x')
+ return (EINVAL);
+ if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
+ return (EINVAL);
+
+ for (tp = *dst + 1; cp < end && tp < eom; cp++) {
+ switch((c = *cp)) {
+ case ']': /*%< end of the bitstring */
+ if (afterslash) {
+ if (beg_blen == NULL)
+ return (EINVAL);
+ blen = (int)strtol(beg_blen, &end_blen, 10);
+ if (*end_blen != ']')
+ return (EINVAL);
+ }
+ if (count)
+ *tp++ = ((value << 4) & 0xff);
+ cp++; /*%< skip ']' */
+ goto done;
+ case '/':
+ afterslash = 1;
+ break;
+ default:
+ if (afterslash) {
+ if (!isdigit(c&0xff))
+ return (EINVAL);
+ if (beg_blen == NULL) {
+
+ if (c == '0') {
+ /* blen never begings with 0 */
+ return (EINVAL);
+ }
+ beg_blen = cp;
+ }
+ } else {
+ if (!isxdigit(c&0xff))
+ return (EINVAL);
+ value <<= 4;
+ value += digitvalue[(int)c];
+ count += 4;
+ tbcount += 4;
+ if (tbcount > 256)
+ return (EINVAL);
+ if (count == 8) {
+ *tp++ = value;
+ count = 0;
+ }
+ }
+ break;
+ }
+ }
+ done:
+ if (cp >= end || tp >= eom)
+ return (EMSGSIZE);
+
+ /*
+ * bit length validation:
+ * If a <length> is present, the number of digits in the <bit-data>
+ * MUST be just sufficient to contain the number of bits specified
+ * by the <length>. If there are insignificant bits in a final
+ * hexadecimal or octal digit, they MUST be zero.
+ * RFC2673, Section 3.2.
+ */
+ if (blen > 0) {
+ int traillen;
+
+ if (((blen + 3) & ~3) != tbcount)
+ return (EINVAL);
+ traillen = tbcount - blen; /*%< between 0 and 3 */
+ if (((value << (8 - traillen)) & 0xff) != 0)
+ return (EINVAL);
+ }
+ else
+ blen = tbcount;
+ if (blen == 256)
+ blen = 0;
+
+ /* encode the type and the significant bit fields */
+ **labelp = DNS_LABELTYPE_BITSTRING;
+ **dst = blen;
+
+ *bp = cp;
+ *dst = tp;
+
+ return (0);
+}
+
+int ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+{
+ u_char *label, *bp, *eom;
+ int c, n, escaped, e = 0;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if (c == '[') { /*%< start a bit string label */
+ if ((cp = strchr(src, ']')) == NULL) {
+ errno = EINVAL; /*%< ??? */
+ return (-1);
+ }
+ if ((e = encode_bitstring(&src, cp + 2,
+ &label, &bp, eom))
+ != 0) {
+ errno = e;
+ return (-1);
+ }
+ escaped = 0;
+ label = bp++;
+ if ((c = *src++) == 0)
+ goto done;
+ else if (c != '.') {
+ errno = EINVAL;
+ return (-1);
+ }
+ continue;
+ }
+ else if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+
+ return (1);
+ }
+ if (c == 0 || *src == '.') {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ done:
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /*%< src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+
+ return (0);
+}
+libc_hidden_def(ns_name_pton)
+
/*
* ns_name_unpack(msg, eom, src, dst, dstsiz)
* Unpack a domain name from a message, source may be compressed.
@@ -2866,6 +3137,270 @@ int ns_name_unpack(const u_char *msg, co
return len;
}
libc_hidden_def(ns_name_unpack)
+
+static int labellen(const unsigned char *lp)
+{
+ int bitlen;
+ unsigned char l = *lp;
+
+ if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* should be avoided by the caller */
+ return -1;
+ }
+
+ if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ if (l == DNS_LABELTYPE_BITSTRING) {
+ if ((bitlen = *(lp + 1)) == 0)
+ bitlen = 256;
+ return ((bitlen + 7 ) / 8 + 1);
+ }
+
+ return -1; /*%< unknwon ELT */
+ }
+
+ return l;
+}
+
+static int mklower(int ch)
+{
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+
+ return (ch);
+}
+
+static int dn_find(const unsigned char *domain,
+ const unsigned char *msg,
+ const unsigned char * const *dnptrs,
+ const unsigned char * const *lastdnptr)
+{
+ const unsigned char *dn, *cp, *sp;
+ const unsigned char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ sp = *cpp;
+ /*
+ * terminate search on:
+ * root label
+ * compression pointer
+ * unusable offset
+ */
+ while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
+ (sp - msg) < 0x4000) {
+ dn = domain;
+ cp = sp;
+
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ n = labellen(cp - 1); /*%< XXX */
+ if (n != *dn++)
+ goto next;
+
+ for (; n > 0; n--)
+ if (mklower(*dn++) !=
+ mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return -1;
+ }
+ }
+next:
+ sp += *sp + 1;
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+int ns_name_pack(const unsigned char *src,
+ unsigned char *dst, int dstsiz,
+ const unsigned char **dnptrs,
+ const unsigned char **lastdnptr)
+{
+ unsigned char *dstp;
+ const unsigned char **cpp, **lpp, *eob, *msg;
+ const unsigned char *srcp;
+ int n, l, first = 1;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ continue;
+
+ lpp = cpp; /*%< end of list to search */
+ }
+ } else {
+ msg = NULL;
+ }
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ int l0;
+
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ if ((l0 = labellen(srcp)) < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ l += l0 + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ srcp += l0 + 1;
+ } while (n != 0);
+
+ /* from here on we need to reset compression pointer array on error */
+ srcp = src;
+
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const unsigned char * const *) dnptrs,
+ (const unsigned char * const *) lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ goto cleanup;
+ }
+
+ *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000 && first) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ first = 0;
+ }
+ }
+
+ /* copy label to buffer */
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Should not happen. */
+ goto cleanup;
+ }
+
+ n = labellen(srcp);
+ if (dstp + 1 + n >= eob) {
+ goto cleanup;
+ }
+
+ memcpy(dstp, srcp, (size_t)(n + 1));
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+cleanup:
+ if (msg != NULL)
+ *lpp = NULL;
+
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return dstp - dst;
+}
+
+int ns_name_compress(const char *src,
+ unsigned char *dst, size_t dstsiz,
+ const unsigned char **dnptrs,
+ const unsigned char **lastdnptr)
+{
+ unsigned char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof(tmp)) == -1)
+ return -1;
+
+ return ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr);
+}
+
+int ns_name_skip(const unsigned char **ptrptr,
+ const unsigned char *eom)
+{
+ const unsigned char *cp;
+ u_int n;
+ int l;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ cp += n;
+ continue;
+ case NS_TYPE_ELT: /*%< EDNS0 extended label */
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /*%< XXX */
+ return -1;
+ }
+ cp += l;
+ continue;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp++;
+ break;
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ break;
+ }
+
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ *ptrptr = cp;
+
+ return 0;
+}
+
+int dn_skipname(const unsigned char *ptr, const unsigned char *eom)
+{
+ const unsigned char *saveptr = ptr;
+
+ if (ns_name_skip(&ptr, eom) == -1)
+ return -1;
+
+ return ptr - saveptr;
+}
#endif /* L_ns_name */
@@ -2906,12 +3441,10 @@ static void res_sync_func(void)
*/
}
-/* Our res_init never fails (always returns 0) */
-int res_init(void)
+static int
+__res_vinit(res_state rp, int preinit)
{
- struct __res_state *rp = &(_res);
- int i;
- int n;
+ int i, n, options, retrans, retry, ndots;
#ifdef __UCLIBC_HAS_IPV6__
int m = 0;
#endif
@@ -2920,13 +3453,27 @@ int res_init(void)
__close_nameservers();
__open_nameservers();
- __res_sync = res_sync_func;
+ if (preinit) {
+ options = rp->options;
+ retrans = rp->retrans;
+ retry = rp->retry;
+ ndots = rp->ndots;
+ }
memset(rp, 0, sizeof(*rp));
- rp->options = RES_INIT;
- rp->retrans = RES_TIMEOUT;
- rp->retry = RES_DFLRETRY;
- rp->ndots = 1;
+
+ if (!preinit) {
+ rp->options = RES_DEFAULT;
+ rp->retrans = RES_TIMEOUT;
+ rp->retry = RES_DFLRETRY;
+ rp->ndots = 1;
+ } else {
+ rp->options = options;
+ rp->retrans = retrans;
+ rp->retry = retry;
+ rp->ndots = ndots;
+ }
+
#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
/* Was: "rp->id = random();" but:
* - random() pulls in largish static buffers
@@ -2992,13 +3539,14 @@ int res_init(void)
rp->_u._ext.nscount = m;
#endif
+ rp->options |= RES_INIT;
+
__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
return 0;
}
-libc_hidden_def(res_init)
-#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__
-void res_close(void)
+static void
+__res_iclose(res_state statp, int free_addr)
{
__UCLIBC_MUTEX_LOCK(__resolv_lock);
__close_nameservers();
@@ -3018,7 +3566,27 @@ void res_close(void)
memset(&_res, 0, sizeof(_res));
__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
}
-#endif
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+
+void
+res_nclose(res_state statp)
+{
+ __res_iclose(statp, 1);
+}
+
+#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__
+void res_close(void)
+{
+ __res_iclose(&_res, 0);
+}
+#endif /* __UCLIBC_HAS_BSD_RES_CLOSE__ */
/* This needs to be after the use of _res in res_init, above. */
#undef _res
@@ -3047,7 +3615,88 @@ extern __thread struct __res_state *__li
# undef __resp
struct __res_state *__resp = &_res;
# endif
-#endif
+#endif /* !__UCLIBC_HAS_THREADS__ */
+
+static unsigned int
+res_randomid(void) {
+ return 0xffff & getpid();
+}
+
+/* Our res_init never fails (always returns 0) */
+int
+res_init(void)
+{
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+
+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+ __res_sync = res_sync_func;
+
+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+
+ __res_vinit(&_res, 1);
+
+ return 0;
+}
+libc_hidden_def(res_init)
+
+/*
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_ninit(res_state statp)
+{
+ return __res_vinit(statp, 0);
+}
#endif /* L_res_init */
@@ -3071,7 +3720,7 @@ __res_state (void)
}
# endif
-#endif
+#endif /* L_res_state */
#ifdef L_res_query
@@ -3324,9 +3973,343 @@ int res_querydomain(const char *name, co
return res_query(longname, class, type, answer, anslen);
}
libc_hidden_def(res_querydomain)
+#endif /* L_res_query */
+
+#ifdef L_ns_netint
+unsigned int ns_get16(const unsigned char *src)
+{
+ unsigned int dst;
+ NS_GET16(dst, src);
+ return dst;
+}
+
+unsigned long ns_get32(const unsigned char *src)
+{
+ unsigned long dst;
+ NS_GET32(dst, src);
+ return dst;
+}
+
+void ns_put16(unsigned int src, unsigned char *dst)
+{
+ NS_PUT16(src, dst);
+}
+
+void ns_put32(unsigned long src, unsigned char *dst)
+{
+ NS_PUT32(src, 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 */
+
+#ifdef L_res_data
+int res_mkquery(int op, const char *dname, int class, int type,
+ const unsigned char *data, int datalen,
+ const unsigned char *newrr_in,
+ unsigned char *buf, int buflen)
+{
+ HEADER *hp;
+ unsigned char *cp, *ep;
+ unsigned char *dnptrs[20], **dpp, **lastdnptr;
+ uint32_t _res_options;
+ int n;
+
+ if (!buf || buflen < HFIXEDSZ) {
+ h_errno = NETDB_INTERNAL;
+ return -1;
+ }
+
+ again:
+ __UCLIBC_MUTEX_LOCK(__resolv_lock);
+ _res_options = _res.options;
+ __UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+ if (!(_res_options & RES_INIT)) {
+ res_init(); /* our res_init never fails */
+ goto again;
+ }
+
+#ifdef DEBUG
+ if (_res_options & RES_DEBUG)
+ printf(";; res_mkquery(%d, %s, %s, %d, %d)\n",
+ name, (op, dname ? dname : "<Nil>"), class, type);
#endif
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = getpid() & 0xffff;
+ hp->opcode = op;
+ hp->rd = (_res.options & RES_RECURSE) != 0U;
+ hp->rcode = NOERROR;
+
+ cp = buf + HFIXEDSZ;
+ ep = buf + buflen;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY:
+ case NS_NOTIFY_OP:
+ if (ep - cp < QFIXEDSZ)
+ return -1;
+
+ if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr)) < 0)
+ return -1;
+
+ cp += n;
+ NS_PUT16(type, cp);
+ NS_PUT16(class, cp);
+ hp->qdcount = htons(1);
+
+ if (op == QUERY || data == NULL)
+ break;
+
+ /*
+ * Make an additional record for completion domain.
+ */
+ if ((ep - cp) < RRFIXEDSZ)
+ return -1;
+
+ n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return -1;
+
+ cp += n;
+ NS_PUT16(T_NULL, cp);
+ NS_PUT16(class, cp);
+ NS_PUT32(0, cp);
+ NS_PUT16(0, cp);
+ hp->arcount = htons(1);
+
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (ep - cp < 1 + RRFIXEDSZ + datalen)
+ return -1;
+
+ *cp++ = '\0'; /*%< no domain name */
+ NS_PUT16(type, cp);
+ NS_PUT16(class, cp);
+ NS_PUT32(0, cp);
+ NS_PUT16(datalen, cp);
+
+ if (datalen) {
+ memcpy(cp, data, (size_t)datalen);
+ cp += datalen;
+ }
+
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return cp - buf;
+}
+#endif /* L_res_data */
+
/* Unimplemented: */
-/* res_mkquery */
/* res_send */
-/* dn_comp */