Esempio n. 1
0
/*
 * クエリを投げる.
 * @return
 */
static int
DnsResolver_query(DnsResolver *self, const char *domain, int rrtype)
{
    self->resolver.res_h_errno = 0;
    self->resolv_errno = 0;
    self->resolv_h_errno = NETDB_SUCCESS;
    self->msglen = res_nquery(&self->resolver, domain, ns_c_in, rrtype, self->msgbuf, NS_MAXMSG);
    if (0 > self->msglen) {
        goto queryfail;
    }   // end if
    if (0 > ns_initparse(self->msgbuf, self->msglen, &self->msghanlde)) {
        self->resolver.res_h_errno = NO_RECOVERY;
        goto queryfail;
    }   // end if

    int rcode_flag = ns_msg_getflag(self->msghanlde, ns_f_rcode);
    if (rcode_flag != ns_r_noerror) {
        self->resolver.res_h_errno = DnsResolver_rcode2statcode(rcode_flag);
        goto queryfail;
    }   // end if

    return NETDB_SUCCESS;

  queryfail:
    return DnsResolver_setError(self, self->resolver.res_h_errno);
}   // end function : DnsResolver_query
Esempio n. 2
0
static void test_res_fake_aaaa_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    char addr[INET6_ADDRSTRLEN];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "cwrap6.org", ns_c_in, ns_t_aaaa,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);
    /* The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type AAAA and have the address that our
     * fake hosts file contains
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_aaaa);
    assert_non_null(inet_ntop(AF_INET6, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "2a00:1450:4013:c01::63");
}
Esempio n. 3
0
static void test_res_fake_a_query_case_insensitive(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    char addr[INET_ADDRSTRLEN];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "CWRAP.ORG", ns_c_in, ns_t_a,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);
    /* The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type A and have the address that our
     * fake hosts file contains. Case does not matter.
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.21");

    res_nclose(&dnsstate);
}
Esempio n. 4
0
static JSBool Dns_query(JSContext *cx, unsigned argc, jsval *vp)
{
	char *domain;
	int32_t type;
	struct __res_state rs;
	unsigned char rsp[NS_PACKETSZ];
	int rlen;
	ns_msg hdl;
	JSObject *robj, *sobj;
	int i;

	if (argc < 2)
		return JS_RetErrno(cx, EINVAL);

	if (res_ninit(&rs))
		return JS_RetError(cx, "res_ninit: %s", hstrerror(h_errno));

	if (!JS_ValueToInt32(cx, JS_ARGV(cx, vp)[1], &type))
		return JS_RetErrno(cx, EINVAL);

	if (!(domain = JS_EncodeStringValue(cx, JS_ARGV(cx, vp)[0])))
		return JS_RetErrno(cx, EINVAL);

	rlen = res_nquery(&rs, domain, ns_c_in, type, rsp, sizeof(rsp));
	JS_free(cx, domain);
	if (rlen < 0) {
		JS_SET_RVAL(cx, vp, INT_TO_JSVAL(h_errno));
		return JS_TRUE;
	}

	if (ns_initparse(rsp, rlen, &hdl))
		return JS_RetError(cx, "ns_initparse: %s", strerror(errno));

	robj = JS_NewObject(cx, NULL, NULL, NULL);
	if (!robj)
		return JS_RetErrno(cx, ENOMEM);

	JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(robj));
	for (i = 0; i < ARRAY_SIZE(smap); i++) {
		sobj = JS_NewArrayObject(cx, 0, NULL);
		if (!sobj) {
			JS_SET_RVAL(cx, vp, JSVAL_NULL);
			return JS_RetErrno(cx, ENOMEM);
		}

		if (!JS_DefineProperty(cx, robj, smap[i].prop, OBJECT_TO_JSVAL(sobj), NULL, NULL, JSPROP_ENUMERATE)) {
			JS_SET_RVAL(cx, vp, JSVAL_NULL);
			return JS_RetErrno(cx, ENOMEM);
		}

		if (!parse_section(cx, sobj, &hdl, smap[i].sect)) {
			JS_SET_RVAL(cx, vp, JSVAL_NULL);
			return JS_FALSE;
		}
	}

	return JS_TRUE;
}
Esempio n. 5
0
static int worker(int qfd, int afd)
{
	{
		int r = res_ninit(statp);

		if (r != 0) {
			syslog(LOG_ERR, "cannot initialize resolver");
			return HES_RES_INIT;
		}
#ifndef OLD_RESOLVER
		statp->options |= RES_ROTATE;
#endif
		statp->options |= RES_DEBUG;
	}

	for (;; ) {
		struct adns_query q;
		struct adns_answer a;

		enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q,
						      sizeof(q), sizeof(q));

		if (r != HES_CONTINUE)
			return r; /* some kind of exit */

		if (q.qmagic != ADNS_Q_MAGIC) {
			syslog(LOG_ERR,
			       "error in input from master: bad magic");
			return HES_BAD_MAGIC;
		}

		a.amagic = ADNS_A_MAGIC;
		a.serial = q.serial;

		a.result = res_nquery(statp, q.name_buf, ns_c_in, q.type,
				      a.ans, sizeof(a.ans));
		a.h_errno_val = h_errno;

		a.len =
			offsetof(struct adns_answer,
				 ans) + (a.result < 0 ? 0 : a.result);

		if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type ==
		     ns_t_key) ||
		    ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type ==
		     ns_t_txt))
			sleep(30); /* delay the answer */

		/* write answer, possibly a bit at a time */
		r = write_pipe(afd, (const unsigned char *)&a);

		if (r != HES_CONTINUE)
			return r; /* some kind of exit */
	}
}
Esempio n. 6
0
static void test_res_fake_srv_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    int prio;
    int weight;
    int port;
    char hostname[MAXDNAME];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "_ldap._tcp.cwrap.org", ns_c_in, ns_t_srv,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SRV and have the priority, weight,
     * port and hostname as in the fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_srv);

    rrdata = ns_rr_rdata(rr);
    NS_GET16(prio, rrdata);
    NS_GET16(weight, rrdata);
    NS_GET16(port, rrdata);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            hostname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_int_equal(prio, 1);
    assert_int_equal(weight, 5);
    assert_int_equal(port, 389);
    assert_string_equal(hostname, "ldap.cwrap.org");
}
Esempio n. 7
0
static void test_res_fake_aaaa_query_notfound(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "nosuchentry.org", ns_c_in, ns_t_aaaa,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);
    /* The query must finish w/o an error and have no answer */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 0);
}
Esempio n. 8
0
// Perform a DNS query and parse the results.  Follows CNAME records.
void SipSrvLookup::res_query_and_parse(const char* in_name,
                                       int type,
                                       res_response* in_response,
                                       const char*& out_name,
                                       res_response*& out_response
   )
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSrvLookup::res_query_and_parse in_name = '%s', "
                 "type = %d (%s)",
                 in_name,type,
                 type == T_CNAME ? "CNAME" :
                 type == T_SRV ? "SRV" :
                 type == T_A ? "A" :
                 type == T_NAPTR ? "NAPTR" :
                 "unknown");

   // The number of CNAMEs we have followed.
   int cname_count = 0;
   // The response currently being examined.
   res_response* response = in_response;
   // The name currently being examined.
   const char* name = in_name;
   // TRUE if 'response' was a lookup for 'name' and 'type'.
   UtlBoolean response_for_this_name = FALSE;
   // Buffer into which to read DNS replies.
   char answer[DNS_RESPONSE_SIZE];
   union u_rdata* p;

   // Loop until we find a reason to exit.  Each turn around the loop does
   // another DNS lookup.
   while (1)
   {
      // While response != NULL and there is a CNAME record for name
      // in response.
      while (response != NULL &&
             (p = look_for(response, name, T_CNAME)) != NULL)
      {
         cname_count++;
         if (cname_count > SipSrvLookup::getOption(SipSrvLookup::OptionCodeCNAMELimit))
         {
            break;
         }
         // If necessary, free the current 'name'.
         if (name != in_name)
         {
            free((void*) name);
         }
         // Copy the canonical name from the CNAME record into 'name', so
         // we can still use it after freeing 'response'.
         name = strdup(p->string);
         // Remember that we are now looking for a name that was not the one
         // that we searched for to produce this response.  Hence, if we don't
         // find any RRs for it, that is not authoritative and we have to do
         // another DNS query.
         response_for_this_name = FALSE;
         // Go back and check whether the result name of the CNAME is listed
         // in this response.
      }
      // This response does not contain a CNAME for 'name'.  So it is either
      // a final response that gives us the RRs we are looking for, or
      // we need to do a lookup on 'name'.

      // Check whether the response was for this name, or contains records
      // of the type we are looking for.  If either, then any records we
      // are looking for are in this response, so we can return.
      if (response_for_this_name ||
          (response != NULL && look_for(response, name, type) != NULL))
      {
         break;
      }

      // We must do another lookup.
      // Start by freeing 'response' if we need to.
      if (response != in_response)
      {
         res_free(response);
      }
      response = NULL;
      // Now, 'response' will be from a query for 'name'.
      response_for_this_name = TRUE;
      // Debugging print.
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodePrintAnswers))
      {
         printf("res_nquery(\"%s\", class = %d, type = %d)\n",
                name, C_IN, type);
      }

      // Initialize the res state struct and set the timeout to
      // 3 secs and retries to 2
      struct __res_state res;
      res_ninit(&res);
      res.retrans = mTimeout;
      res.retry = mRetries;

      if (!mNameserverIP.isNull())
      {
          res.nscount = 1;
          inet_aton(mNameserverIP.data(), &res.nsaddr_list[0].sin_addr);

          if (mNameserverPort > 1)
          {
             res.nsaddr_list[0].sin_port = htons(mNameserverPort);
          }
      }

      // Use res_nquery, not res_search or res_query, so defaulting rules are not
      // applied to the domain, and so that the query is thread-safe.
      int r = res_nquery(&res, name, C_IN, type,
                         (unsigned char*) answer, sizeof (answer));
      // Done with res state struct, so cleanup.
      // Must close once and only once per res_ninit, after res_nquery.
      res_nclose(&res);

      if (r == -1)
      {
         // res_query failed, return.
         OsSysLog::add(FAC_SIP, PRI_WARNING,
                       "DNS query for name '%s', "
                       "type = %d (%s): returned error",
                       name, type,
                       type == T_CNAME ? "CNAME" :
                       type == T_SRV ? "SRV" :
                       type == T_A ? "A" :
                       type == T_NAPTR ? "NAPTR" :
                       "unknown");
         break;
      }

      response = res_parse((char*) &answer);
      if (response == NULL)
      {
         // res_parse failed, return.
         OsSysLog::add(FAC_SIP, PRI_WARNING,
                       "DNS query for name '%s', "
                       "type = %d (%s): response could not be parsed",
                       name, type,
                       type == T_CNAME ? "CNAME" :
                       type == T_SRV ? "SRV" :
                       type == T_A ? "A" :
                       type == T_NAPTR ? "NAPTR" :
                       "unknown");
         break;
      }
      // If requested for testing purposes, sort the query and print it.
      // Sort first, so we see how sorting came out.
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodeSortAnswers))
      {
         sort_answers(response);
      }
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodePrintAnswers))
      {
         res_print(response);
      }
      // Now that we have a fresh DNS query to analyze, go back and check it
      // for a CNAME for 'name' and then for records of the requested type.
   }

   // Final processing:  Copy the working name and response to the output
   // variables.
   out_name = name;
   out_response = response;
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSrvLookup::res_query_and_parse out_name = '%s', out_response = %p",
                 out_name, out_response);

}
Esempio n. 9
0
int getrrs(const char *label, int rrtype, void gotrec(unsigned int num, int type, const char *record))
{
#ifdef _LINUX
	struct __res_state	res;
#endif
	unsigned char		answer[8192];
	HEADER			*header = (HEADER *)answer;
	char			buf[2048];
	int			ret, count;
	unsigned int		i,j,k,rrnum = 0;
	unsigned char		*startptr, *endptr, *ptr;
	uint16_t		type = 0, class = 0;
	uint32_t		ttl = 0;

#ifdef _LINUX
	memset(&res, 0, sizeof(res));
	res.options = RES_DEBUG;
	res_ninit(&res);
#else
	res_init();
#endif

	memset(answer, 0, sizeof(answer));
#ifdef _LINUX
	ret = res_nquery(&res, label, C_IN, rrtype, answer, sizeof(answer));
#else
	ret = res_query(label, C_IN, rrtype, answer, sizeof(answer));
#endif
	if (ret < 0) return -1;

	/* Our start and end */
	startptr = &answer[0];
	endptr = &answer[ret];

	/* Skip the header */
	ptr = startptr + HFIXEDSZ;

	/* Skip Query part */
	for (count = ntohs(header->qdcount); count--; ptr += ret + QFIXEDSZ)
	{
		if ((ret = dn_skipname(ptr, endptr)) < 0) return -1;
	}

	/* Only look at the Answer section */
	count = ntohs(header->ancount);

	/* Go through all the Answer records */
	while (ptr < endptr && count > 0)
	{
		rrnum++;

		memset(buf, 0, sizeof(buf));
		ret = dn_expand (startptr, endptr, ptr, buf, sizeof(buf));
		if (ret < 0) break;
		ptr += ret;

		if (ptr + INT16SZ + INT16SZ + INT32SZ >= endptr) break;

		/* Get the type */
		NS_GET16(type, ptr);

		/* Get the class */
		NS_GET16(class, ptr);

		/* Get the TTL */
		NS_GET32(ttl, ptr);

		/* Get the RDLength */
		NS_GET16(ret, ptr);

		memset(buf, 0, sizeof(buf));

		switch (type)
		{
		case T_TXT:
			for (k = ret, j = 0; j < k && &ptr[j] < endptr; j += (i+1))
			{
				i = ptr[j];
				memcpy(buf, &ptr[j+1], i > sizeof(buf) ? sizeof(buf) : i);
				buf[i > sizeof(buf) ? sizeof(buf) : i] = '\0';
				if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
			}
			break;

		case T_A:
			inet_ntop(AF_INET, ptr, buf, sizeof(buf));
			if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
			break;

		case T_AAAA:
			inet_ntop(AF_INET6, ptr, buf, sizeof(buf));
			if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
			break;

		case T_MX:
			/* Get the MX preference */
			NS_GET16(ttl, ptr);
			ret = dn_expand(startptr, endptr, ptr, buf, sizeof(buf));
			if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
			break;

		case T_NS:
			ret = dn_expand(startptr, endptr, ptr, buf, sizeof(buf));
			if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
			break;

		default:
			/* Unhandled */
			break;
		}

		ptr += ret;
		count--;
	}
	return 0;
}
Esempio n. 10
0
static void test_res_fake_a_via_cname(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char cname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    /* Query for A record, but the key is a CNAME. The expected result is
     * that the whole chain of CNAMEs will be included in the answer section
     * along with the resulting A
     */
    rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_a,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have three answers and the answers
     * must be a parseable RR of type CNAME and have the cname as in the
     * fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 3);

    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "web.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_an, 1, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "www.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_an, 2, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "www.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.22");
}
Esempio n. 11
0
static void test_res_fake_cname_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char cname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "rwrap.org", ns_c_in, ns_t_cname,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, 256, &handle);
    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type CNAME and have the cname as in the
     * fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "web.cwrap.org");

    /* The CNAME points to an A record that's present in the additional
     * section
     */
    assert_int_equal(ns_msg_count(handle, ns_s_ar), 2);

    assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_cname);
    assert_string_equal(ns_rr_name(rr), "web.cwrap.org");
    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            cname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_string_equal(cname, "www.cwrap.org");

    assert_int_equal(ns_parserr(&handle, ns_s_ar, 1, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "www.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.22");
}
Esempio n. 12
0
static void test_res_fake_soa_query(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    char nameser[MAXDNAME];
    char admin[MAXDNAME];
    int serial;
    int refresh;
    int retry;
    int expire;
    int minimum;

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_soa,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 100);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SOA and have the data as in the fake
     * hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_soa);

    rrdata = ns_rr_rdata(rr);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            nameser, MAXDNAME);
    assert_int_not_equal(rv, -1);
    rrdata += rv;

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            admin, MAXDNAME);
    assert_int_not_equal(rv, -1);
    rrdata += rv;

    NS_GET32(serial, rrdata);
    NS_GET32(refresh, rrdata);
    NS_GET32(retry, rrdata);
    NS_GET32(expire, rrdata);
    NS_GET32(minimum, rrdata);

    assert_string_equal(nameser, "ns1.cwrap.org");
    assert_string_equal(admin, "admin.cwrap.org");
    assert_int_equal(serial, 2014100457);
    assert_int_equal(refresh, 3600);
    assert_int_equal(retry, 300);
    assert_int_equal(expire, 1814400);
    assert_int_equal(minimum, 600);
}
Esempio n. 13
0
/*
 * Test the case of a SRV record query where the
 * fake hosts file entry is minimal in the sense
 * that it omits the priority and weight entries.
 * The server then fills in some default values.
 */
static void test_res_fake_srv_query_minimal(void **state)
{
    int rv;
    struct __res_state dnsstate;
    unsigned char answer[ANSIZE];
    ns_msg handle;
    ns_rr rr;   /* expanded resource record */
    const uint8_t *rrdata;
    int prio;
    int weight;
    int port;
    char hostname[MAXDNAME];
    char addr[INET_ADDRSTRLEN];

    (void) state; /* unused */

    memset(&dnsstate, 0, sizeof(struct __res_state));
    rv = res_ninit(&dnsstate);
    assert_int_equal(rv, 0);

    rv = res_nquery(&dnsstate, "_krb5._tcp.cwrap.org", ns_c_in, ns_t_srv,
                    answer, sizeof(answer));
    assert_in_range(rv, 1, 256);

    ns_initparse(answer, sizeof(answer), &handle);

    /*
     * The query must finish w/o an error, have one answer and the answer
     * must be a parseable RR of type SRV and have the priority, weight,
     * port and hostname as in the fake hosts file
     */
    assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
    assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_srv);

    rrdata = ns_rr_rdata(rr);
    NS_GET16(prio, rrdata);
    NS_GET16(weight, rrdata);
    NS_GET16(port, rrdata);

    rv = ns_name_uncompress(ns_msg_base(handle),
                            ns_msg_end(handle),
                            rrdata,
                            hostname, MAXDNAME);
    assert_int_not_equal(rv, -1);

    assert_int_equal(prio, 1);
    assert_int_equal(weight, 100);
    assert_int_equal(port, 88);
    assert_string_equal(hostname, "krb5.cwrap.org");

    /* The additional section contains the A record of krb5.cwrap.org */
    assert_int_equal(ns_msg_count(handle, ns_s_ar), 1);
    assert_int_equal(ns_parserr(&handle, ns_s_ar, 0, &rr), 0);
    assert_int_equal(ns_rr_type(rr), ns_t_a);
    assert_string_equal(ns_rr_name(rr), "krb5.cwrap.org");
    assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
                              addr, sizeof(addr)));
    assert_string_equal(addr, "127.0.0.23");
}
Esempio n. 14
0
DWORD
LWNetDnsQueryWithBuffer(
    IN PCSTR pszQuestion,
    IN BOOLEAN bReInit,
    IN BOOLEAN bUseTcp,
    OUT PVOID pBuffer,
    IN DWORD dwBufferSize,
    OUT PDWORD pdwResponseSize
    )
{
    DWORD dwError = 0;
    PDNS_RESPONSE_HEADER pHeader = (PDNS_RESPONSE_HEADER)pBuffer;
    int responseSize =  0;
    BOOLEAN bInLock = FALSE;
#if HAVE_DECL_RES_NINIT
    union
    {
        struct __res_state res;
#ifdef __LWI_AIX__
        // struct __res_state was enlarged from 720 in AIX 5.2 to 824 in AIX
        // 5.3. This means calling res_ninit on AIX 5.3 on a structure compiled
        // on AIX 5.2 will result in a buffer overflow. Furthermore, even on
        // AIX 5.3, res_ninit seems to expect 1596 bytes in the structure (1491
        // on AIX 5.2). As a workaround, this padding will ensure enough space
        // is allocated on the stack.
        char buffer[2048];
#endif
    } resLocal = { {0} };
    res_state res = &resLocal.res;
#else
    struct __res_state *res = &_res;
#endif

    LWNET_LOCK_RESOLVER_API(bInLock);

#if HAVE_DECL_RES_NINIT
    if (res_ninit(res) != 0)
#else
    if (res_init() != 0)
#endif
    {
        dwError = ERROR_NOT_FOUND;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    
    if (dwBufferSize < CT_MIN(sizeof(DNS_RESPONSE_HEADER), MAX_DNS_UDP_BUFFER))
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    // TODO: Add lock on calling resolver due to global options, which may or
    // may not be safe depending on the system.
    if (bUseTcp)
    {
        res->options |= RES_USEVC;
    }
    else
    {
        res->options &= ~(RES_USEVC);
    }

    /* Assertion: pResolverContext != NULL && pResolverContext->bLocked == TRUE */
#if HAVE_DECL_RES_NINIT
    responseSize = res_nquery(res, pszQuestion, ns_c_in, ns_t_srv, (PBYTE) pBuffer, dwBufferSize);
#else
    responseSize = res_query(pszQuestion, ns_c_in, ns_t_srv, (PBYTE) pBuffer, dwBufferSize);
#endif
    if (responseSize < 0)
    {
        LWNET_LOG_VERBOSE("DNS lookup for '%s' failed with errno %d, h_errno = %d", pszQuestion, errno, h_errno);
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    if (responseSize < CT_FIELD_OFFSET(DNS_RESPONSE_HEADER, data))
    {
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    if (responseSize > dwBufferSize)
    {
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    LWNetDnsFixHeaderForEndianness(pHeader);

    if (!LWNetDnsIsValidResponse(pHeader))
    {
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }

error:

#if HAVE_DECL_RES_NINIT
    res_nclose(res);
#else
    /* Indicate that we are done with the resolver, except on HPUX which
       does not implement the res_close function. */
#ifndef __LWI_HP_UX__
    res_close();
#endif
#endif

    LWNET_UNLOCK_RESOLVER_API(bInLock);

    if (dwError)
    {
        responseSize = 0;
    }
    *pdwResponseSize = responseSize;
    return dwError;
}