-/* $Id$ */
-/* Copyright 1998 by the Massachusetts Institute of Technology.
+/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* without express or implied warranty.
*/
-#include "setup.h"
-#include <sys/types.h>
+#include "ares_setup.h"
-#if defined(WIN32) && !defined(WATT32)
-#include "nameser.h"
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
#else
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#ifdef HAVE_ARPA_NAMESER_COMPAT_H
-#include <arpa/nameser_compat.h>
+# include "nameser.h"
#endif
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+# include <arpa/nameser_compat.h>
#endif
-#include <stdlib.h>
#include "ares.h"
+#include "ares_nowarn.h"
#include "ares_private.h" /* for the memdebug */
static int name_length(const unsigned char *encoded, const unsigned char *abuf,
int len, indir = 0;
char *q;
const unsigned char *p;
+ union {
+ ssize_t sig;
+ size_t uns;
+ } nlen;
- len = name_length(encoded, abuf, alen);
- if (len == -1)
+ nlen.sig = name_length(encoded, abuf, alen);
+ if (nlen.sig < 0)
return ARES_EBADNAME;
- *s = malloc(len + 1);
+ *s = malloc(nlen.uns + 1);
if (!*s)
return ARES_ENOMEM;
q = *s;
+ if (nlen.uns == 0) {
+ /* RFC2181 says this should be ".": the root of the DNS tree.
+ * Since this function strips trailing dots though, it becomes ""
+ */
+ q[0] = '\0';
+
+ /* indirect root label (like 0xc0 0x0c) is 2 bytes long (stupid, but
+ valid) */
+ if ((*encoded & INDIR_MASK) == INDIR_MASK)
+ *enclen = 2L;
+ else
+ *enclen = 1L; /* the caller should move one byte to get past this */
+
+ return ARES_SUCCESS;
+ }
+
/* No error-checking necessary; it was all done by name_length(). */
p = encoded;
while (*p)
{
if (!indir)
{
- *enclen = p + 2 - encoded;
+ *enclen = aresx_uztosl(p + 2U - encoded);
indir = 1;
}
p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1));
}
}
if (!indir)
- *enclen = p + 1 - encoded;
+ *enclen = aresx_uztosl(p + 1U - encoded);
/* Nuke the trailing period if we wrote one. */
if (q > *s)
int n = 0, offset, indir = 0;
/* Allow the caller to pass us abuf + alen and have us check for it. */
- if (encoded == abuf + alen)
+ if (encoded >= abuf + alen)
return -1;
while (*encoded)
*/
return (n) ? n - 1 : n;
}
+
+/* Like ares_expand_name but returns EBADRESP in case of invalid input. */
+int ares__expand_name_for_response(const unsigned char *encoded,
+ const unsigned char *abuf, int alen,
+ char **s, long *enclen)
+{
+ int status = ares_expand_name(encoded, abuf, alen, s, enclen);
+ if (status == ARES_EBADNAME)
+ status = ARES_EBADRESP;
+ return status;
+}