Esempio n. 1
0
DNS_STATUS DnsQuery_A(const char * service,
                              unsigned short requestType,
                             unsigned long options,
                            void *,
                     DNS_RECORD * results,
                            void *)
{
  if (results == 0)
    return -1;

  *results = 0;

  struct __res_state statbuf;
  res_ninit(&statbuf);

  union {
    HEADER hdr;
    unsigned char buf[PACKETSZ];
  } reply;

  int replyLen = res_nsearch(&statbuf, service, C_IN, requestType, (unsigned char *)&reply, sizeof(reply));

  if (replyLen < 1)
    return -1;

  unsigned char * replyStart = reply.buf;
  unsigned char * replyEnd   = reply.buf + replyLen;
  unsigned char * cp         = reply.buf + sizeof(HEADER);

  // ignore questions in response
  uint16_t i;
  for (i = 0; i < ntohs(reply.hdr.qdcount); i++) {
    char qName[MAXDNAME];
    if (!GetDN(replyStart, replyEnd, cp, qName))
      return -1;
    cp += QFIXEDSZ;
  }

  if (!ProcessDNSRecords(
       replyStart,
       replyEnd,
       cp,
       ntohs(reply.hdr.ancount),
       ntohs(reply.hdr.nscount),
       ntohs(reply.hdr.arcount),
       results)) {
    DnsRecordListFree(*results, 0);
    res_nclose(&statbuf);
    return -1;
  }

  res_nclose(&statbuf);
  return 0;
}
Esempio n. 2
0
bool HHVM_FUNCTION(checkdnsrr, const String& host,
                   const String& type /* = null_string */) {
    int ntype;
    if (!validate_dns_arguments(host, type, ntype)) {
        return false;
    }

    unsigned char ans[MAXPACKET];
    struct __res_state *res;
    res = ResolverInit::s_res.get()->getResolver();
    if (res == NULL) {
        return false;
    }

    int i = res_nsearch(res, host.data(), C_IN, ntype, ans, sizeof(ans));
    res_nclose(res);
    php_dns_free_res(res);
    return (i >= 0);
}
Esempio n. 3
0
bool HHVM_FUNCTION(checkdnsrr, const String& host,
                   const String& type /* = null_string */) {
    IOStatusHelper io("dns_check_record", host.data());
    const char *stype;
    if (type.empty()) {
        stype = "MX";
    } else {
        stype = type.data();
    }
    if (host.empty()) {
        throw_invalid_argument("host: [empty]");
    }

    int ntype;
    if (!strcasecmp("A", stype)) ntype = DNS_T_A;
    else if (!strcasecmp("NS",    stype)) ntype = DNS_T_NS;
    else if (!strcasecmp("MX",    stype)) ntype = DNS_T_MX;
    else if (!strcasecmp("PTR",   stype)) ntype = DNS_T_PTR;
    else if (!strcasecmp("ANY",   stype)) ntype = DNS_T_ANY;
    else if (!strcasecmp("SOA",   stype)) ntype = DNS_T_SOA;
    else if (!strcasecmp("TXT",   stype)) ntype = DNS_T_TXT;
    else if (!strcasecmp("CNAME", stype)) ntype = DNS_T_CNAME;
    else if (!strcasecmp("AAAA",  stype)) ntype = DNS_T_AAAA;
    else if (!strcasecmp("SRV",   stype)) ntype = DNS_T_SRV;
    else if (!strcasecmp("NAPTR", stype)) ntype = DNS_T_NAPTR;
    else if (!strcasecmp("A6",    stype)) ntype = DNS_T_A6;
    else {
        throw_invalid_argument("type: %s", stype);
        return false;
    }

    unsigned char ans[MAXPACKET];
    struct __res_state *res;
    res = ResolverInit::s_res.get()->getResolver();
    if (res == NULL) {
        return false;
    }
    int i = res_nsearch(res, host.data(), C_IN, ntype, ans, sizeof(ans));
    res_nclose(res);
    php_dns_free_res(res);
    return (i >= 0);
}
Esempio n. 4
0
bool HHVM_FUNCTION(getmxrr, const String& hostname,
                   VRefParam mxhostsRef,
                   VRefParam weightsRef /* = null */) {
    IOStatusHelper io("dns_get_mx", hostname.data());
    int count, qdc;
    unsigned short type, weight;
    unsigned char ans[MAXPACKET];
    char buf[MAXHOSTNAMELEN];
    unsigned char *cp, *end;

    Array mxhosts;
    Array weights;
    SCOPE_EXIT {
        mxhostsRef = mxhosts;
        weightsRef = weights;
    };

    /* Go! */
    struct __res_state *res;
    res = ResolverInit::s_res.get()->getResolver();
    if (res == NULL) {
        return false;
    }

    int i = res_nsearch(res, hostname.data(), C_IN, DNS_T_MX,
                        (unsigned char*)&ans, sizeof(ans));
    if (i < 0) {
        res_nclose(res);
        php_dns_free_res(res);
        return false;
    }
    if (i > (int)sizeof(ans)) {
        i = sizeof(ans);
    }
    HEADER *hp = (HEADER *)&ans;
    cp = (unsigned char *)&ans + HFIXEDSZ;
    end = (unsigned char *)&ans +i;
    for (qdc = ntohs((unsigned short)hp->qdcount); qdc--; cp += i + QFIXEDSZ) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
    }
    count = ntohs((unsigned short)hp->ancount);
    while (--count >= 0 && cp < end) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        GETSHORT(type, cp);
        cp += INT16SZ + INT32SZ;
        GETSHORT(i, cp);
        if (type != DNS_T_MX) {
            cp += i;
            continue;
        }
        GETSHORT(weight, cp);
        if ((i = dn_expand(ans, end, cp, buf, sizeof(buf)-1)) < 0) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        mxhosts.append(String(buf, CopyString));
        weights.append(weight);
    }
    res_nclose(res);
    php_dns_free_res(res);
    return true;
}
Esempio n. 5
0
Variant HHVM_FUNCTION(dns_get_record, const String& hostname, int type /*= -1*/,
                      VRefParam authnsRef /* = null */,
                      VRefParam addtlRef /* = null */) {
    IOStatusHelper io("dns_get_record", hostname.data(), type);
    if (type < 0) type = PHP_DNS_ALL;
    if (type & ~PHP_DNS_ALL && type != PHP_DNS_ANY) {
        raise_warning("Type '%d' not supported", type);
        return false;
    }

    unsigned char *cp = NULL, *end = NULL;
    int qd, an, ns = 0, ar = 0;
    querybuf answer;

    /* - We emulate an or'ed type mask by querying type by type.
     *   (Steps 0 - NUMTYPES-1 )
     *   If additional info is wanted we check again with DNS_T_ANY
     *   (step NUMTYPES / NUMTYPES+1 )
     *   store_results is used to skip storing the results retrieved in step
     *   NUMTYPES+1 when results were already fetched.
     * - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY.
     *   (step NUMTYPES+1 )
     */
    Array ret;
    bool first_query = true;
    bool store_results = true;
    for (int t = (type == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
            t < PHP_DNS_NUM_TYPES + 2 || first_query; t++) {
        first_query = false;
        int type_to_fetch;
        switch (t) {
        case 0:
            type_to_fetch = type & PHP_DNS_A     ? DNS_T_A     : 0;
            break;
        case 1:
            type_to_fetch = type & PHP_DNS_NS    ? DNS_T_NS    : 0;
            break;
        case 2:
            type_to_fetch = type & PHP_DNS_CNAME ? DNS_T_CNAME : 0;
            break;
        case 3:
            type_to_fetch = type & PHP_DNS_SOA   ? DNS_T_SOA   : 0;
            break;
        case 4:
            type_to_fetch = type & PHP_DNS_PTR   ? DNS_T_PTR   : 0;
            break;
        case 5:
            type_to_fetch = type & PHP_DNS_HINFO ? DNS_T_HINFO : 0;
            break;
        case 6:
            type_to_fetch = type & PHP_DNS_MX    ? DNS_T_MX    : 0;
            break;
        case 7:
            type_to_fetch = type & PHP_DNS_TXT   ? DNS_T_TXT   : 0;
            break;
        case 8:
            type_to_fetch = type & PHP_DNS_AAAA  ? DNS_T_AAAA  : 0;
            break;
        case 9:
            type_to_fetch = type & PHP_DNS_SRV   ? DNS_T_SRV   : 0;
            break;
        case 10:
            type_to_fetch = type & PHP_DNS_NAPTR ? DNS_T_NAPTR : 0;
            break;
        case 11:
            type_to_fetch = type & PHP_DNS_A6    ? DNS_T_A6    : 0;
            break;
        case PHP_DNS_NUM_TYPES:
            store_results = false;
            continue;
        default:
        case (PHP_DNS_NUM_TYPES + 1):
            type_to_fetch = DNS_T_ANY;
            break;
        }
        if (!type_to_fetch) continue;

        struct __res_state *res;
        res = ResolverInit::s_res.get()->getResolver();
        if (res == NULL) {
            return false;
        }

        int n = res_nsearch(res, hostname.data(), C_IN, type_to_fetch,
                            answer.qb2, sizeof answer);
        if (n < 0) {
            res_nclose(res);
            php_dns_free_res(res);
            continue;
        }

        HEADER *hp;
        cp = answer.qb2 + HFIXEDSZ;
        end = answer.qb2 + n;
        hp = (HEADER *)&answer;
        qd = ntohs(hp->qdcount);
        an = ntohs(hp->ancount);
        ns = ntohs(hp->nscount);
        ar = ntohs(hp->arcount);

        /* Skip QD entries, they're only used by dn_expand later on */
        while (qd-- > 0) {
            n = dn_skipname(cp, end);
            if (n < 0) {
                raise_warning("Unable to parse DNS data received");
                res_nclose(res);
                php_dns_free_res(res);
                return false;
            }
            cp += n + QFIXEDSZ;
        }

        /* YAY! Our real answers! */
        while (an-- && cp && cp < end) {
            Array retval;
            cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, retval);
            if (!retval.empty() && store_results) {
                ret.append(retval);
            }
        }
        res_nclose(res);
        php_dns_free_res(res);
    }

    Array authns;
    Array addtl;

    /* List of Authoritative Name Servers */
    while (ns-- > 0 && cp && cp < end) {
        Array retval;
        cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval);
        if (!retval.empty()) {
            authns.append(retval);
        }
    }

    /* Additional records associated with authoritative name servers */
    while (ar-- > 0 && cp && cp < end) {
        Array retval;
        cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval);
        if (!retval.empty()) {
            addtl.append(retval);
        }
    }

    authnsRef = authns;
    addtlRef = addtl;
    return ret;
}
Esempio n. 6
0
/*
 * Simplified version of srv_query() for domain auto-discovery.
 */
int
srv_getdom(res_state state, const char *svc_name, char **rrname)
{
	union {
		HEADER hdr;
		uchar_t buf[NS_MAXMSG];
	} msg;
	int len, qdcount, ancount;
	uchar_t *ptr, *eom;
	char namebuf[NS_MAXDNAME];

	/* query necessary resource records */

	*rrname = NULL;
	if (DBG(DNS, 1))  {
		logger(LOG_DEBUG, "Looking for SRV RRs '%s.*'", svc_name);
	}
	len = res_nsearch(state, svc_name, C_IN, T_SRV,
	    msg.buf, sizeof (msg.buf));
	if (len < 0) {
		if (DBG(DNS, 0)) {
			logger(LOG_DEBUG,
			    "DNS search for '%s' failed (%s)",
			    svc_name, hstrerror(state->res_h_errno));
		}
		return (-1);
	}

	if (len > sizeof (msg.buf)) {
		logger(LOG_WARNING,
		    "DNS query %ib message doesn't fit into %ib buffer",
		    len, sizeof (msg.buf));
		len = sizeof (msg.buf);
	}

	/* parse the reply header */

	ptr = msg.buf + sizeof (msg.hdr);
	eom = msg.buf + len;
	qdcount = ntohs(msg.hdr.qdcount);
	ancount = ntohs(msg.hdr.ancount);

	/* skip the question section */

	len = ns_skiprr(ptr, eom, ns_s_qd, qdcount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (-1);
	}
	ptr += len;

	/* parse the answer section */
	if (ancount < 1) {
		logger(LOG_ERR, "DNS query - no answers");
		return (-1);
	}

	len = dn_expand(msg.buf, eom, ptr, namebuf, sizeof (namebuf));
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		return (-1);
	}
	*rrname = strdup(namebuf);
	if (*rrname == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (-1);
	}

	return (0);
}
Esempio n. 7
0
/*
 * Query or search the SRV RRs for a given name.
 *
 * If dname == NULL then search (as in res_nsearch(3RESOLV), honoring any
 * search list/option), else query (as in res_nquery(3RESOLV)).
 *
 * The output TTL will be the one of the SRV RR with the lowest TTL.
 */
ad_disc_cds_t *
srv_query(res_state state, const char *svc_name, const char *dname,
    ad_disc_ds_t *prefer)
{
	ad_disc_cds_t *cds_res = NULL;
	uchar_t *msg = NULL;
	int len, scnt, maxcnt;

	msg = malloc(NS_MAXMSG);
	if (msg == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (NULL);
	}

	/* query necessary resource records */

	/* Search, querydomain or query */
	if (dname == NULL) {
		dname = "*";
		if (DBG(DNS, 1))  {
			logger(LOG_DEBUG, "Looking for SRV RRs '%s.*'",
			    svc_name);
		}
		len = res_nsearch(state, svc_name, C_IN, T_SRV,
		    msg, NS_MAXMSG);
		if (len < 0) {
			if (DBG(DNS, 0)) {
				logger(LOG_DEBUG,
				    "DNS search for '%s' failed (%s)",
				    svc_name, hstrerror(state->res_h_errno));
			}
			goto errout;
		}
	} else { /* dname != NULL */
		if (DBG(DNS, 1)) {
			logger(LOG_DEBUG, "Looking for SRV RRs '%s.%s' ",
			    svc_name, dname);
		}

		len = res_nquerydomain(state, svc_name, dname, C_IN, T_SRV,
		    msg, NS_MAXMSG);

		if (len < 0) {
			if (DBG(DNS, 0)) {
				logger(LOG_DEBUG, "DNS: %s.%s: %s",
				    svc_name, dname,
				    hstrerror(state->res_h_errno));
			}
			goto errout;
		}
	}

	if (len > NS_MAXMSG) {
		logger(LOG_WARNING,
		    "DNS query %ib message doesn't fit into %ib buffer",
		    len, NS_MAXMSG);
		len = NS_MAXMSG;
	}


	/* parse the reply header */

	cds_res = srv_parse(msg, len, &scnt, &maxcnt);
	if (cds_res == NULL)
		goto errout;

	if (prefer != NULL)
		add_preferred(cds_res, prefer, &scnt, maxcnt);

	get_addresses(cds_res, scnt);

	/* sort list of candidates */
	if (scnt > 1)
		qsort(cds_res, scnt, sizeof (*cds_res),
		    (int (*)(const void *, const void *))srvcmp);

	free(msg);
	return (cds_res);

errout:
	free(msg);
	return (NULL);
}
Esempio n. 8
0
/*
 * krb5int_dns_init()
 *
 * Initialize an opaque handle.  Do name lookup and initial parsing of
 * reply, skipping question section.  Prepare to iterate over answer
 * section.  Returns -1 on error, 0 on success.
 */
int
krb5int_dns_init(struct krb5int_dns_state **dsp,
                 char *host, int nclass, int ntype)
{
#if USE_RES_NINIT
    struct __res_state statbuf;
#endif
    struct krb5int_dns_state *ds;
    int len, ret;
    size_t nextincr, maxincr;
    unsigned char *p;

    *dsp = ds = malloc(sizeof(*ds));
    if (ds == NULL)
        return -1;

    ret = -1;
    ds->nclass = nclass;
    ds->ntype = ntype;
    ds->ansp = NULL;
    ds->anslen = 0;
    ds->ansmax = 0;
    nextincr = 2048;
    maxincr = INT_MAX;

#if HAVE_NS_INITPARSE
    ds->cur_ans = 0;
#endif

#if USE_RES_NINIT
    memset(&statbuf, 0, sizeof(statbuf));
    ret = res_ninit(&statbuf);
#else
    ret = res_init();
#endif
    if (ret < 0)
        return -1;

    do {
        p = (ds->ansp == NULL)
            ? malloc(nextincr) : realloc(ds->ansp, nextincr);

        if (p == NULL) {
            ret = -1;
            goto errout;
        }
        ds->ansp = p;
        ds->ansmax = nextincr;

#if USE_RES_NINIT
        len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
                          ds->ansp, ds->ansmax);
#else
        len = res_search(host, ds->nclass, ds->ntype,
                         ds->ansp, ds->ansmax);
#endif
        if ((size_t) len > maxincr) {
            ret = -1;
            goto errout;
        }
        while (nextincr < (size_t) len)
            nextincr *= 2;
        if (len < 0 || nextincr > maxincr) {
            ret = -1;
            goto errout;
        }
    } while (len > ds->ansmax);

    ds->anslen = len;
#if HAVE_NS_INITPARSE
    ret = ns_initparse(ds->ansp, ds->anslen, &ds->msg);
#else
    ret = initparse(ds);
#endif
    if (ret < 0)
        goto errout;

    ret = 0;

errout:
#if USE_RES_NINIT
    res_ndestroy(&statbuf);
#endif
    if (ret < 0) {
        if (ds->ansp != NULL) {
            free(ds->ansp);
            ds->ansp = NULL;
        }
    }

    return ret;
}