Example #1
0
static void
parse_answer_section(ns_msg *msg) {
	int rrnum, rrmax;
	ns_rr rr;
	uint16_t prio, weight, port, len;
	const unsigned char *rdata;
	char *tname;

	rrmax = ns_msg_count(*msg, ns_s_an);
	for (rrnum = 0; rrnum < rrmax; rrnum++) {
		if (ns_parserr(msg, ns_s_an, rrnum, &rr)) {
			perror("ns_parserr");
			exit(EXIT_FAILURE);
		}
		if (ns_rr_type(rr) == ns_t_srv) {
			len = ns_rr_rdlen(rr);
			rdata = ns_rr_rdata(rr);
			if (len > 3U * NS_INT16SZ) {
				NS_GET16(prio, rdata);
				NS_GET16(weight, rdata);
				NS_GET16(port, rdata);
				len -= 3U * NS_INT16SZ;
				tname = target_name(rdata);
				insert_tuple(tname, prio, weight, port);
			}
		}
	}
}
Example #2
0
int
ns_initparse(const u_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)
        RETERR(EMSGSIZE);
    NS_GET16(handle->_id, msg);
    if (msg + NS_INT16SZ > eom)
        RETERR(EMSGSIZE);
    NS_GET16(handle->_flags, msg);
    for (i = 0; i < ns_s_max; i++) {
        if (msg + NS_INT16SZ > eom)
            RETERR(EMSGSIZE);
        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)
        RETERR(EMSGSIZE);
    setsection(handle, ns_s_max);
    return (0);
}
Example #3
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)
        RETERR(ENODEV);
    if (section != handle->_sect)
        setsection(handle, section);

    /* Make rrnum right. */
    if (rrnum == -1)
        rrnum = handle->_rrnum;
    if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
        RETERR(ENODEV);
    if (rrnum < handle->_rrnum)
        setsection(handle, section);
    if (rrnum > handle->_rrnum) {
        b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
                      rrnum - handle->_rrnum);

        if (b < 0)
            return (-1);
        handle->_msg_ptr += b;
        handle->_rrnum = rrnum;
    }

    /* Do the parse. */
    b = dn_expand(handle->_msg, handle->_eom,
                  handle->_msg_ptr, rr->name, NS_MAXDNAME);
    if (b < 0)
        return (-1);
    handle->_msg_ptr += b;
    if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
        RETERR(EMSGSIZE);
    NS_GET16(rr->type, handle->_msg_ptr);
    NS_GET16(rr->rr_class, handle->_msg_ptr);
    if (section == ns_s_qd) {
        rr->ttl = 0;
        rr->rdlength = 0;
        rr->rdata = NULL;
    } else {
        if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
            RETERR(EMSGSIZE);
        NS_GET32(rr->ttl, handle->_msg_ptr);
        NS_GET16(rr->rdlength, handle->_msg_ptr);
        if (handle->_msg_ptr + rr->rdlength > handle->_eom)
            RETERR(EMSGSIZE);
        rr->rdata = handle->_msg_ptr;
        handle->_msg_ptr += rr->rdlength;
    }
    if (++handle->_rrnum > handle->_counts[(int)section])
        setsection(handle, (ns_sect)((int)section + 1));

    /* All done. */
    return (0);
}
Example #4
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");
}
Example #5
0
int local_ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle)
{
    const unsigned 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 = local_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;
    }

    local_ns_setsection(handle, ns_s_max);
    return 0;
}
Example #6
0
static int
skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
	const u_char *optr = ptr;

	for ((void)NULL; count > 0; count--) {
		int b, rdlength;

		b = dn_skipname(ptr, eom);
		if (b < 0)
			goto emsgsize;
		ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
		if (section != ns_s_qd) {
			if (ptr + NS_INT32SZ > eom)
				goto emsgsize;
			ptr += NS_INT32SZ/*TTL*/;
			if (ptr + NS_INT16SZ > eom)
				goto emsgsize;
			NS_GET16(rdlength, ptr);
			ptr += rdlength/*RData*/;
		}
	}
	if (ptr > eom)
		goto emsgsize;
	return ((int)(ptr - optr));
 emsgsize:
	errno = EMSGSIZE;
	return (-1);
}
Example #7
0
int
ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count)
{
	const u_char *optr = ptr;

	for ((void) NULL; count > 0; count--) {
		int b, rdlength;

		b = dn_skipname(ptr, eom);
		if (b < 0) {
			RETERR(EMSGSIZE);
		}
		ptr += b /*Name*/ + NS_INT16SZ /*Type*/ + NS_INT16SZ /*Class*/;
		if (section != ns_s_qd) {
			if (ptr + NS_INT32SZ + NS_INT16SZ > eom) {
				RETERR(EMSGSIZE);
			}
			ptr += NS_INT32SZ /*TTL*/;
			NS_GET16(rdlength, ptr);
			ptr += rdlength /*RData*/;
		}
	}
	if (ptr > eom) {
		RETERR(EMSGSIZE);
	}
	return (ptr - optr);
}
Example #8
0
uint16_t
ns_get16(const u_char *src) {
	uint16_t dst;

	NS_GET16(dst, src);
	return (dst);
}
Example #9
0
static int local_ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count)
{
    const unsigned char *optr = ptr;

    for (; count > 0; count--) {
        int b, rdlength;

        b = local_ns_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;
}
Example #10
0
static void get_bn(BIGNUM *bn, u_char **pp)
{
   short i;

   NS_GET16(i, *pp);
   i = ((i + 7) / 8);
   BN_bin2bn(*pp, i, bn);
   *pp += i;
}
Example #11
0
int php_getmxrr(char *hostname, char *mx_list, char *weight_list) {
#ifdef PCC_MINGW
  return 0;
#else

   char *mx_list_ptr = (char *)(mx_list + sprintf(mx_list, ""));
   char *weight_list_ptr = (char *)(weight_list + sprintf(weight_list, ""));
   unsigned char answer[MAXPACKET];
   unsigned char expand_buffer[MAXHOSTNAMELEN];
   int ans_len = res_search(hostname, C_IN, T_MX, answer, sizeof(answer));
   HEADER *header_ptr = (HEADER *)&answer;
   unsigned char *body_ptr = (unsigned char *)&answer + NS_HFIXEDSZ;
   unsigned char *eom_ptr = (unsigned char *)&answer + sizeof(answer);
   int n, ancount, qdcount, type, weight;
   
   for (qdcount = ntohs((unsigned short)header_ptr->qdcount); qdcount--; body_ptr += (n + NS_QFIXEDSZ))
      if ((n = dn_skipname(body_ptr, eom_ptr)) < 0)
         return -1;

   ancount = ntohs((unsigned short)header_ptr->ancount);
   while (--ancount >= 0 && body_ptr < eom_ptr) {
      if ((n = dn_skipname(body_ptr, eom_ptr)) < 0)
	 return -1;
      body_ptr += n;
      NS_GET16(type, body_ptr);
      body_ptr += (NS_INT16SZ + NS_INT32SZ);
      NS_GET16(n, body_ptr);
      if (type != T_MX) {
 	 body_ptr += n;
	 continue;
      }
      NS_GET16(weight, body_ptr);
      if ((n = dn_expand(answer, eom_ptr, body_ptr, expand_buffer, sizeof(expand_buffer) - 1)) < 0)
	 return -1;
      body_ptr += n;
      mx_list_ptr += sprintf(mx_list_ptr - 1, " %s  ", expand_buffer);
      weight_list_ptr += sprintf(weight_list_ptr - 1, " %d ", weight);
   }
   return 0;
#endif /* PCC_MINGW */
}
Example #12
0
int
ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
	const u_char *eom = msg + msglen;
	int i;

	memset(handle, 0x5e, sizeof *handle);
	handle->_msg = msg;
	handle->_eom = eom;
	if (msg + NS_INT16SZ > eom)
		goto emsgsize;
	NS_GET16(handle->_id, msg);
	if (msg + NS_INT16SZ > eom)
		goto emsgsize;
	NS_GET16(handle->_flags, msg);
	for (i = 0; i < ns_s_max; i++) {
		if (msg + NS_INT16SZ > eom)
			goto emsgsize;
		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 = skiprr(msg, eom, (ns_sect)i,
				       handle->_counts[i]);

			if (b < 0)
				return (-1);
			handle->_sections[i] = msg;
			msg += b;
		}
	if (msg != eom)
		goto emsgsize;
	handle->_sect = ns_s_max;
	handle->_rrnum = -1;
	handle->_msg_ptr = NULL;
	return (0);
 emsgsize:
	errno = EMSGSIZE;
	return (-1);
}
Example #13
0
void register_response(struct queries *q, int timeout, char *note)
{
	u_char *p;
	int size;
	int rcode;
	int id;

	id = ntohs(q->send.u.h.id);
	if (note == NULL)
		note = "";
	countqueries++;
	if (timeout >= 0) {
		p = q->recvbuf;
		NS_GET16(size, p);
		response_size_sum += size;
		response_size_sum2 += size * size;
		if (response_size_min == 0 || response_size_min > size)
			response_size_min = size;
		if (response_size_max == 0 || response_size_max < size)
			response_size_max = size;
		rcode = p[3] & 0x0f;
		countrcode[rcode]++;
		countanswers++;
		if (verbose)
			printf("recv response id=%d rcode=%d size=%d rtt=%d\n", id, rcode, size, timeout);
	} else if (timeout == ERRZEROREAD) {
		countzeroread++;
		if (verbose)
			printf("recv response id=%d zeroread\n", id);
	} else if (timeout == TIMEOUTERROR) {
		counttimeout++;
		if (verbose)
			printf("recv timeout id=%d %" PRId64 " usec\n", id, timediff(&current, &q->sent));
	} else {
		counterror++;
		if (verbose) {
			printf("recv error id=%d errno=%d at %s (%s)\n", id, ERROROFFSET - timeout, note, strerror(errno));
		}
	}
#ifdef DEBUG
	printf("%ld.%03ld no=%d fd=%d %d %s\n", q->sent.tv_sec, q->sent.tv_usec/1000, q->no, q->fd, timeout, note);
	fflush(stdout);
#endif
}
Example #14
0
int local_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)
        local_ns_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)
        local_ns_setsection(handle, section);
    if (rrnum > handle->_rrnum) {
        b = local_ns_skiprr(handle->LOCAL_NS_MSG_PTR, handle->_eom, section,
                            rrnum - handle->_rrnum);

        if (b < 0)
            return (-1);
        handle->LOCAL_NS_MSG_PTR += b;
        handle->_rrnum = rrnum;
    }

    /* Do the parse. */
    b = dn_expand(handle->_msg, handle->_eom,
                  handle->LOCAL_NS_MSG_PTR, rr->name, NS_MAXDNAME);
    if (b < 0)
        return (-1);
    handle->LOCAL_NS_MSG_PTR += b;
    if (handle->LOCAL_NS_MSG_PTR + NS_INT16SZ + NS_INT16SZ > handle->_eom) {
        errno = EMSGSIZE;
        return -1;
    }
    NS_GET16(rr->type, handle->LOCAL_NS_MSG_PTR);
    NS_GET16(rr->rr_class, handle->LOCAL_NS_MSG_PTR);
    if (section == ns_s_qd) {
        rr->ttl = 0;
        rr->rdlength = 0;
        rr->rdata = NULL;
    } else {
        if (handle->LOCAL_NS_MSG_PTR + NS_INT32SZ + NS_INT16SZ > handle->_eom) {
            errno = EMSGSIZE;
            return -1;
        }
        NS_GET32(rr->ttl, handle->LOCAL_NS_MSG_PTR);
        NS_GET16(rr->rdlength, handle->LOCAL_NS_MSG_PTR);
        if (handle->LOCAL_NS_MSG_PTR + rr->rdlength > handle->_eom) {
            errno = EMSGSIZE;
            return -1;
        }
        rr->rdata = handle->LOCAL_NS_MSG_PTR;
        handle->LOCAL_NS_MSG_PTR += rr->rdlength;
    }
    if (++handle->_rrnum > handle->_counts[(int)section])
        local_ns_setsection(handle, (ns_sect)((int)section + 1));

    return 0;
}
Example #15
0
int
eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol)
{
	querybuf answer;			/* answer buffer from nameserver */
	int n;
	char zone[1024];
	int ancount, qdcount;		/* answer count and query count */
	HEADER *hp;					/* answer buffer header */
	char hostbuf[256];
	unsigned char *msg, *eom, *cp;	/* answer buffer positions */
	int dlen, type, aclass, pref, weight, port;
	long ttl;
	int answerno;
	char tr[100];

	memset(zone, 0, sizeof(zone));
	memset(record, 0, sizeof(struct osip_srv_record));

	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (eXosip.dns_capabilities <= 0)
		return OSIP_UNKNOWN_HOST;	/* disabled */

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);
	if (eXosip.dns_capabilities >= 2)
		n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1);
	else
		n = -1;					/* avoid NAPTR */
	if (n == OSIP_SUCCESS && zone[0] == '\0') {
		/* protocol is not listed in NAPTR answer: not supported */
		return OSIP_UNKNOWN_HOST;
	}
	if (n != OSIP_SUCCESS) {
		snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain);
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"Using locally generated SRV record %s\n", zone));
	}

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s IN SRV'\n", zone));

	n = res_query(zone, C_IN, T_SRV, (unsigned char *) &answer, sizeof(answer));

	if (n < (int) sizeof(HEADER)) {
		return OSIP_UNKNOWN_HOST;
	}

	/* browse message and search for DNS answers part */
	hp = (HEADER *) & answer;
	qdcount = ntohs(hp->qdcount);
	ancount = ntohs(hp->ancount);

	msg = (unsigned char *) (&answer);
	eom = (unsigned char *) (&answer) + n;
	cp = (unsigned char *) (&answer) + sizeof(HEADER);

	while (qdcount-- > 0 && cp < eom) {
		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid SRV record answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}
		cp += n + QFIXEDSZ;
	}


	/* browse DNS answers */
	answerno = 0;

	/* loop through the answer buffer and extract SRV records */
	while (ancount-- > 0 && cp < eom) {
		struct osip_srv_entry *srventry;

		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid SRV record answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}

		cp += n;


#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		type = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(type, cp);
#else
		NS_GET16(type, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		aclass = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(aclass, cp);
#else
		NS_GET16(aclass, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		ttl = _get_long(cp);
		cp += sizeof(u_long);
#elif defined(__APPLE_CC__)
		GETLONG(ttl, cp);
#else
		NS_GET32(ttl, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		dlen = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(dlen, cp);
#else
		NS_GET16(dlen, cp);
#endif

		if (type != T_SRV) {
			cp += dlen;
			continue;
		}
#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		pref = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(pref, cp);
#else
		NS_GET16(pref, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		weight = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(weight, cp);
#else
		NS_GET16(weight, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		port = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(port, cp);
#else
		NS_GET16(port, cp);
#endif

		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0)
			break;
		cp += n;

		srventry = &record->srventry[answerno];
		snprintf(srventry->srv, sizeof(srventry->srv), "%s", hostbuf);

		srventry->priority = pref;
		srventry->weight = weight;
		if (weight)
			srventry->rweight = 1 + random() % (10000 * srventry->weight);
		else
			srventry->rweight = 0;
		srventry->port = port;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"SRV record %s IN SRV -> %s:%i/%i/%i/%i\n",
					zone, srventry->srv, srventry->port, srventry->priority,
					srventry->weight, srventry->rweight));

		answerno++;
		if (answerno == 10)
			break;
	}

	if (answerno == 0)
		return OSIP_UNKNOWN_HOST;
	osip_srv_record_sort(record, answerno);
	snprintf(record->name, sizeof(record->name), "%s", domain);
	return OSIP_SUCCESS;
}
Example #16
0
u_int _getshort(const u_char *src)
{
        u_int dst;
        NS_GET16(dst, src);
        return dst;
}
Example #17
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;
}
Example #18
0
int
eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length)
{
	querybuf answer;			/* answer buffer from nameserver */
	int n;
	char zone[1024];
	int ancount, qdcount;		/* answer count and query count */
	HEADER *hp;					/* answer buffer header */
	char hostbuf[256];
	unsigned char *msg, *eom, *cp;	/* answer buffer positions */
	int dlen, type, aclass;
	long ttl;
	int answerno;
	char tr[100];

	memset(srv_record, 0, max_length);
	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);

	snprintf(zone, 1024, "%s", domain);

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s IN NAPTR\n", zone));

	n = res_query(zone, C_IN, T_NAPTR, (unsigned char *) &answer, sizeof(answer));

	if (n < (int) sizeof(HEADER)) {
		return OSIP_UNKNOWN_HOST;
	}

	/* browse message and search for DNS answers part */
	hp = (HEADER *) & answer;
	qdcount = ntohs(hp->qdcount);
	ancount = ntohs(hp->ancount);

	msg = (unsigned char *) (&answer);
	eom = (unsigned char *) (&answer) + n;
	cp = (unsigned char *) (&answer) + sizeof(HEADER);

	while (qdcount-- > 0 && cp < eom) {
		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid SRV record answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}
		cp += n + QFIXEDSZ;
	}


	/* browse DNS answers */
	answerno = 0;

	/* loop through the answer buffer and extract SRV records */
	while (ancount-- > 0 && cp < eom) {
		int len;

		typedef struct {
			unsigned short order;
			unsigned short pref;
			char flag[256];
			char service[1024];
			char regexp[1024];
			char replacement[1024];
		} osip_naptr_t;

		osip_naptr_t anaptr;

		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid NAPTR answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}

		cp += n;

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		type = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(type, cp);
#else
		NS_GET16(type, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		aclass = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(aclass, cp);
#else
		NS_GET16(aclass, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		ttl = _get_long(cp);
		cp += sizeof(u_long);
#elif defined(__APPLE_CC__)
		GETLONG(ttl, cp);
#else
		NS_GET32(ttl, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		dlen = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(dlen, cp);
#else
		NS_GET16(dlen, cp);
#endif

		if (type != T_NAPTR) {
			cp += dlen;
			continue;
		}

		memset(&anaptr, 0, sizeof(osip_naptr_t));

		memcpy((void *) &anaptr.order, cp, 2);
		anaptr.order = ntohs(anaptr.order);	/*((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */
		cp += sizeof(unsigned short);
		memcpy((void *) &anaptr.pref, cp, 2);
		anaptr.pref = ntohs(anaptr.pref);	/* ((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */
		cp += sizeof(unsigned short);

		len = *cp;
		cp++;
		strncpy(anaptr.flag, (char *) cp, len);
		anaptr.flag[len] = '\0';
		cp += len;

		len = *cp;
		cp++;
		strncpy(anaptr.service, (char *) cp, len);
		anaptr.service[len] = '\0';
		cp += len;

		len = *cp;
		cp++;
		strncpy(anaptr.regexp, (char *) cp, len);
		anaptr.regexp[len] = '\0';
		cp += len;

		n = dn_expand(msg, eom, cp, anaptr.replacement, 1024 - 1);

		if (n < 0)
			break;
		cp += n;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"NAPTR %s ->%i/%i/%s/%s/%s/%s\n",
					zone, anaptr.order, anaptr.pref, anaptr.flag,
					anaptr.service, anaptr.regexp, anaptr.replacement));

		if (osip_strncasecmp(tr, "udp", 4) == 0
			&& osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tcp", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "udp-tls", 8) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tls", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "sctp", 5) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		}

		answerno++;
	}

	if (answerno == 0)
		return OSIP_UNKNOWN_HOST;

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"protocol: %s is not supported by domain %s\n", protocol, domain));
	return OSIP_SUCCESS;
}
Example #19
0
int
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
	int b;

	/* Make section right. */
	if ((unsigned int)section >= ns_s_max)
		goto enodev;
	if ((int)section != (int)handle->_sect) {
		handle->_sect = section;
		handle->_rrnum = 0;
		handle->_msg_ptr = handle->_sections[(int)section];
	}

	/* Make rrnum right. */
	if (rrnum == -1)
		rrnum = handle->_rrnum;
	if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
		goto enodev;
	if (rrnum < handle->_rrnum) {
		handle->_rrnum = 0;
		handle->_msg_ptr = handle->_sections[(int)section];
	}

	b = skiprr(handle->_msg, handle->_eom, section,
		   rrnum - handle->_rrnum);
	if (b < 0)
		return (-1);
	handle->_msg_ptr += b;
	handle->_rrnum = rrnum;

	/* Do the parse. */
	b = dn_expand(handle->_msg, handle->_eom,
		      handle->_msg_ptr, rr->name, NS_MAXDNAME);
	if (b < 0)
		return (-1);
	handle->_msg_ptr += b;
	if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
		goto emsgsize;
	NS_GET16(rr->type, handle->_msg_ptr);
	if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
		goto emsgsize;
	NS_GET16(rr->rr_class, handle->_msg_ptr);
	if (section == ns_s_qd) {
		rr->ttl = 0;
		rr->rdlength = 0;
		rr->rdata = NULL;
	} else {
		if (handle->_msg_ptr + NS_INT32SZ > handle->_eom)
			goto emsgsize;
		NS_GET32(rr->ttl, handle->_msg_ptr);
		if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
			goto emsgsize;
		NS_GET16(rr->rdlength, handle->_msg_ptr);
		if (handle->_msg_ptr + rr->rdlength > handle->_eom)
			goto emsgsize;
		rr->rdata = handle->_msg_ptr;
		handle->_msg_ptr += rr->rdlength;
	}
	handle->_rrnum++;

	/* All done. */
	return (0);
 enodev:
	errno = ENODEV;
	return (-1);
 emsgsize:
	errno = EMSGSIZE;
	return (-1);
}
Example #20
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");
}
Example #21
0
CAMLprim value mlresolv_query(value vdname, value vclass, value vtype)
{
  union {
    HEADER hdr;              /* defined in resolv.h */
    u_char buf[PACKETSZ];    /* defined in arpa/nameser.h */
  } response;
  int rc;

  u_char *cp, *tcp;
  u_char *eom;

  char r_name[MAXDNAME+1];
  u_short r_class;
  u_short r_type;
  u_int32_t r_ttl;
  u_short r_len;

  int ancount, qdcount;

  value vres = Val_emptylist;

  if(vtype == caml_hash_variant("PTR")) {
    int a, b, c, d;
    a = b = c = d = 0;
    sscanf(String_val(vdname), "%u.%u.%u.%u", &a, &b, &c, &d);
    sprintf(r_name, "%u.%u.%u.%u.in-addr.arpa", d, c, b, a);
    rc = res_query(r_name,
		   mlvariant_to_c(rr_class, vclass),
		   mlvariant_to_c(rr_type, vtype),
		   (u_char*)&response, sizeof(response));
  } else
    rc = res_query(String_val(vdname),
		   mlvariant_to_c(rr_class, vclass),
		   mlvariant_to_c(rr_type, vtype),
		   (u_char*)&response, sizeof(response));

  if (rc < 0) {
    switch (h_errno) {
    case NETDB_INTERNAL:  
      mlresolv_error(errno);
    case HOST_NOT_FOUND:  /* Authoritative Answer Host not found */
      raise_constant(*mlresolv_host_not_found_exn);
    case TRY_AGAIN:       /* Non-Authoritative Host not found, or SERVERFAIL */
      raise_constant(*mlresolv_try_again_exn);
    case NO_RECOVERY:
      raise_constant(*mlresolv_no_recovery_exn);
    case NO_DATA:         /* Valid name, no data record of requested type */
      raise_constant(*mlresolv_no_data_exn);
    case NETDB_SUCCESS:   /* no problem */
    defaykt:
      failwith("res_query: unknown error");
    }
  }

  cp = (u_char *)&response.buf + sizeof(HEADER);
  eom = (u_char *)&response.buf + rc;

  ancount = ntohs(response.hdr.ancount) + ntohs(response.hdr.nscount);
  qdcount = ntohs(response.hdr.qdcount);
  for (; (qdcount > 0) && (cp < eom); qdcount--) {
    rc = dn_skipname(cp, eom) + QFIXEDSZ;
    if(rc < 0)
      failwith("dn_skipname failed");
    cp += rc;
  }

  for (; (ancount > 0) && (cp < eom); ancount--) {
    value vrdata, vfields = Val_unit;

    rc = dn_expand(response.buf, eom, cp, (void*)r_name, MAXDNAME);
    if(rc < 0)
      failwith("dn_expand1 failed");

    cp += rc;

    NS_GET16(r_type, cp);
    NS_GET16(r_class, cp);
    NS_GET32(r_ttl, cp);
    NS_GET16(r_len, cp);

    if(cp + r_len > eom) /* is this check necessary? */
      r_len = eom - cp;

    tcp = cp;

    switch(r_type) {

    case ns_t_a:
      /* if(r_class == ns_c_in || r_class == ns_c_hs) { */

      if(INADDRSZ > r_len)
	vfields = copy_string("");
      else {
	struct in_addr inaddr;
	char *address;

	bcopy(tcp, (char *)&inaddr, INADDRSZ);
	address = (char *)inet_ntoa(inaddr);
	vfields = copy_string(address);
      }
      break;

    case ns_t_cname:
    case ns_t_ns:
    case ns_t_mb:
    case ns_t_md:
    case ns_t_mf:
    case ns_t_mg:
    case ns_t_mr:
    case ns_t_ptr: 
    case ns_t_nsap_ptr:
      {
	char r_name[MAXDNAME+1];
	rc = dn_expand(response.buf, eom, cp, (void *) r_name, MAXDNAME);
	if(rc < 0)
	  vfields = copy_string("");
	else
	  vfields = copy_string(r_name);
	break;
    }

    case ns_t_null:  /* max up to 65535 */
      vfields = caml_alloc_string(r_len);
      memmove(String_val(vfields), cp, r_len);
      break;

    case ns_t_txt: {
      int txtlen, rdata_len = r_len;
      value newcons, txt;
      vfields = Val_emptylist;

      while(tcp < eom && *tcp <= rdata_len) {
	txtlen = *tcp++;
	txt = caml_alloc_string(txtlen);
	memmove(String_val(txt), tcp, txtlen);
	tcp += txtlen;
	rdata_len -= txtlen+1;

	newcons = alloc_small(2, 0);
	Field(newcons, 0) = txt;
	Field(newcons, 1) = vfields;
	vfields = newcons;
      }
      break;
    }

    case ns_t_srv:
      if(INT16SZ * 3 <= r_len) {
	char r_name[MAXDNAME+1];
	int prio, weight, port;
      
	NS_GET16(prio, tcp);
	NS_GET16(weight, tcp);
	NS_GET16(port, tcp);

	rc = dn_expand(response.buf, eom, tcp, (void *) r_name, MAXDNAME);

	vfields = alloc_small(4, 0);
	Field(vfields, 0) = Val_int(prio);
	Field(vfields, 1) = Val_int(weight);
	Field(vfields, 2) = Val_int(port);
      
	if(rc < 0)
	  Field(vfields, 3) = copy_string("");
	else
	  Field(vfields, 3) = copy_string(r_name);
      }
      break;

    case ns_t_mx:
    case ns_t_rt:
    case ns_t_afsdb:
      if(INT16SZ <= r_len) {
	char r_name[MAXDNAME+1];
	int prio;

	NS_GET16(prio, tcp);

	rc = dn_expand(response.buf, eom, tcp, (void *) r_name, MAXDNAME);

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = Val_int(prio);

	if(rc < 0)
	  Field(vfields, 1) = copy_string("");
	else
	  Field(vfields, 1) = copy_string(r_name);
      }
      break;

    case ns_t_soa: 
      {
	char mname[MAXDNAME+1];
	char rname[MAXDNAME+1];
	u_int serial, minimum;
	int refresh, retry, expire;
	
	if((rc = dn_expand(response.buf, eom, tcp, (void *)mname, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	
	if((rc = dn_expand(response.buf, eom, tcp, (void *)rname, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	
	if (tcp - cp + INT32SZ * 5 > r_len)
	  break;
      
	NS_GET32(serial, tcp);
	NS_GET32(refresh, tcp);
	NS_GET32(retry, tcp);
	NS_GET32(expire, tcp);
	NS_GET32(minimum, tcp);
      
	vfields = alloc_small(7, 0);
	Field(vfields, 0) = copy_string(mname);
	Field(vfields, 1) = copy_string(rname);
	Field(vfields, 2) = Val_int(serial);
	Field(vfields, 3) = Val_int(refresh);
	Field(vfields, 4) = Val_int(retry);
	Field(vfields, 5) = Val_int(expire);
	Field(vfields, 6) = Val_int(minimum);
      }
      break;

    case ns_t_minfo: 
      {
	char rmailbx[MAXDNAME+1];
	char emailbx[MAXDNAME+1];

	if((rc = dn_expand(response.buf, eom, tcp, rmailbx, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	if((rc = dn_expand(response.buf, eom, tcp, emailbx, MAXDNAME)) < 0)
	  break;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rmailbx);
	Field(vfields, 1) = copy_string(emailbx);
      }
      break;

      /* two strings */
    case ns_t_hinfo:
    case ns_t_isdn: /* <ISDN-address> <sa> */
    case ns_t_nsap:
      if(r_len > 0 && *tcp < r_len) {
	value str1;
	value str2;

	rc = *tcp++;
	if(r_type == ns_t_nsap) {
	  int result = 0;
	  for(; rc; rc--, tcp++)
	    result += result * 10 + (*tcp - 0x38);
	  str1 = Val_int(result);
	}
	else {
	  str1 = caml_alloc_string(rc);
	  memmove(String_val(str1), tcp, rc);
	  tcp += rc;
	}      
	if(rc + 1 > r_len && *tcp + rc + 2 >= r_len) {
	  rc = *tcp++;
	  str2 = caml_alloc_string(rc);
	  memmove(String_val(str2), tcp, rc);
	}
	else
	  str2 = copy_string("");

	vfields = caml_alloc_small(2, 0);
	Field(vfields, 0) = str1;
	Field(vfields, 1) = str2;
      }
      break;

    case ns_t_wks:
      
      if(INADDRSZ + 1 <= r_len) {
	struct in_addr inaddr;
	char* address;
	u_short protocol;
	value bitmap;

	bcopy(tcp, (char *) &inaddr, INADDRSZ);
	address = (char*) inet_ntoa(inaddr);
	tcp += INADDRSZ;
      
	protocol = *tcp++;  /* getprotobynumber(*cp) */
      
	/*
	  n = 0;
	  while (cp < eom) {
	  c = *cp++;
	  do {
	  if (c & 0200) {
	  int port;
	  
	  port = htons((u_short)n);
	  if (protocol != NULL)
	  service = getservbyport(port, protocol->p_name);
	  else
	  service = NULL;
	  
	  if (service != NULL)
	  doprintf((" %s", service->s_name));
	  else
	  doprintf((" %s", dtoa(n)));
	}
	c <<= 1;
	} while (++n & 07);
	}
	doprintf((" )"));
	*/
      
	bitmap = caml_alloc_string(r_len - INADDRSZ - 1);
	memmove(String_val(bitmap), tcp, eom - tcp);
      
	vfields = alloc_small(4, 0);
	Field(vfields, 0) = copy_string(address);
	Field(vfields, 1) = Val_int(protocol);
	Field(vfields, 2) = bitmap;
      }
      break;

    case ns_t_rp:  /* <mbox-dname> <txt-dname> */
      {
	char rname1[MAXDNAME+1];
	char rname2[MAXDNAME+1];

	rc = dn_expand(response.buf, eom, tcp, rname1, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;
	
	rc = dn_expand(response.buf, eom, tcp, rname2, MAXDNAME);
	if(rc < 0)
	  break;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rname1);
	Field(vfields, 1) = copy_string(rname2);
      }
      break;

    case ns_t_x25: /* <PSDN-address> */
      if(r_len > 0 && *tcp >= r_len) {
	rc = *tcp++;
	vfields = caml_alloc_string(rc);
	memmove(String_val(vfields), tcp, rc);
      }
      else
	vfields = copy_string("");
      break;
      

    case ns_t_px:
      if(r_len > INT16SZ) {
	int pref;
	char rname1[MAXDNAME];
	char rname2[MAXDNAME];

	NS_GET16(pref, tcp);
	rc = dn_expand(response.buf, eom, tcp, rname1, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;
	rc = dn_expand(response.buf, eom, tcp, rname2, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rname1);
	Field(vfields, 1) = copy_string(rname2);
      }
      break;

    case ns_t_gpos:
      if(r_len > 0 && *tcp <= r_len) {
	float f1, f2, f3;
	char *tmp;
	rc = *tcp++;

	tmp = (char *) malloc(rc + 1);
	bcopy(tcp, tmp, rc);
	tmp[rc] = '\0';
	f1 = atof(tmp);
	tcp += rc;
	
	if(tcp < eom && tcp + *tcp <= eom) {
	  if(*tcp > rc)
	    tmp = realloc(tmp, *tcp);
	  rc = *tcp++;
	  bcopy(tcp, tmp, rc);
	  tmp[rc] = '\0';
	  f2 = atof(tmp);
	  tcp += rc;
	}
	else
	  f2 = 0.0;

	if(tcp < eom && tcp + *tcp <= eom) {
	  if(*tcp > rc)
	    tmp = realloc(tmp, *tcp);
	  rc = *tcp++;
	  bcopy(tcp, tmp, rc);
	  tmp[rc] = '\0';
	  f3 = atof(tmp);
	  tcp += rc;
	}
	else
	  f3 = 0.0;

	free(tmp);

	vfields = alloc_small(3, 0);
	Field(vfields, 0) = copy_double((double)f1);
	Field(vfields, 1) = copy_double((double)f2);
	Field(vfields, 2) = copy_double((double)f3);
      }	
      break;

    case ns_t_loc:
      failwith("LOC not implemented");

      /*
      if(r_len > 0 && *tcp != 0)
	failwith("Invalid version in LOC RDATA");

      if(r_len > 0) {
	rc = INT
      n = INT32SZ + 3*INT32SZ;
      if (check_size(rname, type, cp, msg, eor, n) < 0)
	break;
      c = _getlong(cp);
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\t%s ", pr_spherical(n, "N", "S")));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf((" %s ", pr_spherical(n, "E", "W")));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf((" %sm ", pr_vertical(n, "", "-")));
      cp += INT32SZ;
      
      doprintf((" %sm", pr_precision((c >> 16) & 0xff)));
      doprintf((" %sm", pr_precision((c >>  8) & 0xff)));
      doprintf((" %sm", pr_precision((c >>  0) & 0xff)));
      break;
      */

      /*
    case T_UID:
    case T_GID:
      if(INT32SZ <= r_len)
	NS_GET32(rc, cp);
      
      if (dlen == INT32SZ) {
        n = _getlong(cp);
	doprintf(("\t%s", dtoa(n)));
	cp += INT32SZ;
      }
      break;
      
    case T_UINFO:
      doprintf(("\t\"%s\"", stoa(cp, dlen, TRUE)));
      cp += dlen;
      break;

    case T_UNSPEC:
      cp += dlen;
      break;
      
    case T_AAAA:
      if (dlen == IPNGSIZE) {
	doprintf(("\t%s", ipng_ntoa(cp)));
	cp += IPNGSIZE;
      }
      break;
      
    case T_SIG:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      if (n >= T_FIRST && n <= T_LAST)
	doprintf(("\t%s", pr_type(n)));
      else
	doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      n = 3*INT32SZ + INT16SZ;
      if (check_size(rname, type, cp, msg, eor, n) < 0)
	break;
      doprintf((" ("));
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", dtoa(n)));
      doprintf(("\t\t;original ttl"));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", pr_date(n)));
      doprintf(("\t;signature expiration"));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", pr_date(n)));
      doprintf(("\t;signature inception"));
      cp += INT32SZ;
      
      n = _getshort(cp);
      doprintf(("\n\t\t\t%s", dtoa(n)));
      doprintf(("\t\t;key tag"));
      cp += INT16SZ;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf(("\n\t\t\t%s", pr_name(dname)));
      cp += n;
      
      if (cp < eor) {
	register char *buf;
	register int size;
	  
	n = eor - cp;
	buf = base_ntoa(cp, n);
	size = strlength(buf);
	cp += n;
	  
	while ((n = (size > 64) ? 64 : size) > 0) {
	  doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	  buf += n; size -= n;
	}
      }
      doprintf(("\n\t\t\t)"));
      break;
      
    case T_KEY:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t0x%s", xtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
        doprintf((" %s", dtoa(n)));
	
        if (check_size(rname, type, cp, msg, eor, 1) < 0)
	  break;
        n = *cp++;
        doprintf((" %s", dtoa(n)));
	
        if (cp < eor) {
	  register char *buf;
	  register int size;
	    
	  n = eor - cp;
	  buf = base_ntoa(cp, n);
	  size = strlength(buf);
	  cp += n;
	    
	  doprintf((" ("));
	  while ((n = (size > 64) ? 64 : size) > 0) {
	    doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	    buf += n; size -= n;
	  }
	  doprintf(("\n\t\t\t)"));
	}
        break;
	
    case T_NXT:
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf(("\t%s", pr_name(dname)));
      cp += n;
      
      n = 0;
      while (cp < eor) {
	c = *cp++;
	do {
	  if (c & 0200) {
	    if (n >= T_FIRST && n <= T_LAST)
	      doprintf((" %s", pr_type(n)));
	    else
	      doprintf((" %s", dtoa(n)));
                }
	  c <<= 1;
	} while (++n & 07);
      }
      break;
      
    case T_NAPTR:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf((" %s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf((" %s", pr_name(dname)));
      cp += n;
      break;
      
    case T_KX:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf((" %s", pr_name(dname)));
      cp += n;
      break;
      
    case T_CERT:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf((" %s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      if (cp < eor) {
	register char *buf;
	register int size;
	
	n = eor - cp;
	buf = base_ntoa(cp, n);
	size = strlength(buf);
	cp += n;
	
	doprintf((" ("));
	while ((n = (size > 64) ? 64 : size) > 0) {
	  doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	  buf += n; size -= n;
	}
	doprintf(("\n\t\t\t)"));
      }
      break;

    case T_EID:
      failwith("EID not implemented");
      break;

    case T_NIMLOC:
      failwith("NIMLOC not implemented");
      break;

    case T_ATMA:
      failwith("ATMA not implemented");

      */

    default:
      failwith("unknown RDATA type");
    }

    if(vfields != Val_unit) {
      value vrecord, vrdata, newcons;

      Begin_root(vres);

      vrecord = alloc_small(5, 0);
      Field(vrecord, 0) = copy_string(r_name);
      Field(vrecord, 1) = c_to_mlvariant(rr_type, r_type);
      Field(vrecord, 2) = c_to_mlvariant(rr_class, r_class);
      Field(vrecord, 3) = Val_int(r_ttl);
      vrdata = alloc_small(2, 0);
      Field(vrdata, 0) = c_to_mlvariant(rr_type, r_type);
      Field(vrdata, 1) = vfields;
      Field(vrecord, 4) = vrdata;

      newcons = alloc_small(2, 0);
      Field(newcons, 0) = vrecord;
      Field(newcons, 1) = vres;
      vres = newcons;
      End_roots();
      vrdata = Val_unit;
    }
    cp += r_len;
  }
  return vres;
}
Example #22
0
static ad_disc_cds_t *
srv_parse(uchar_t *msg, int len, int *scnt, int *maxcnt)
{
	ad_disc_cds_t *cds;
	ad_disc_cds_t *cds_res = NULL;
	HEADER *hdr;
	int i, qdcount, ancount, nscount, arcount;
	uchar_t *ptr, *eom;
	uchar_t *end;
	uint16_t type;
	/* LINTED  E_FUNC_SET_NOT_USED */
	uint16_t class __unused;
	uint32_t rttl;
	uint16_t size;
	char namebuf[NS_MAXDNAME];

	eom = msg + len;
	hdr = (void *)msg;
	ptr = msg + sizeof (HEADER);

	qdcount = ntohs(hdr->qdcount);
	ancount = ntohs(hdr->ancount);
	nscount = ntohs(hdr->nscount);
	arcount = ntohs(hdr->arcount);

	/* 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 (NULL);
	}
	ptr += len;

	/*
	 * Walk through the answer section, building the result array.
	 * The array size is +2 because we (possibly) add the preferred
	 * DC if it was not there, and an empty one (null termination).
	 */

	*maxcnt = ancount + 2;
	cds_res = calloc(*maxcnt, sizeof (*cds_res));
	if (cds_res == NULL) {
		logger(LOG_ERR, "Out of memory");
		return (NULL);
	}

	cds = cds_res;
	for (i = 0; i < ancount; i++) {

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}

		if (type != T_SRV) {
			ptr = end;
			continue;
		}

		NS_GET16(cds->cds_ds.priority, ptr);
		NS_GET16(cds->cds_ds.weight, ptr);
		NS_GET16(cds->cds_ds.port, ptr);
		len = dn_expand(msg, eom, ptr, cds->cds_ds.host,
		    sizeof (cds->cds_ds.host));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid SRV record");
			goto err;
		}

		cds->cds_ds.ttl = rttl;

		if (DBG(DNS, 2)) {
			logger(LOG_DEBUG, "    %s", namebuf);
			logger(LOG_DEBUG,
			    "        ttl=%d pri=%d weight=%d %s:%d",
			    rttl, cds->cds_ds.priority, cds->cds_ds.weight,
			    cds->cds_ds.host, cds->cds_ds.port);
		}
		cds++;

		/* move ptr to the end of current record */
		ptr = end;
	}
	*scnt = (cds - cds_res);

	/* skip the nameservers section (if any) */

	len = ns_skiprr(ptr, eom, ns_s_ns, nscount);
	if (len < 0) {
		logger(LOG_ERR, "DNS query invalid message format");
		goto err;
	}
	ptr += len;

	/* walk through the additional records */
	for (i = 0; i < arcount; i++) {
		sa_family_t af;

		len = dn_expand(msg, eom, ptr, namebuf,
		    sizeof (namebuf));
		if (len < 0) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		ptr += len;
		NS_GET16(type, ptr);
		NS_GET16(class, ptr);
		NS_GET32(rttl, ptr);
		NS_GET16(size, ptr);
		if ((end = ptr + size) > eom) {
			logger(LOG_ERR, "DNS query invalid message format");
			goto err;
		}
		switch (type) {
		case ns_t_a:
			af = AF_INET;
			break;
		case ns_t_aaaa:
			af = AF_INET6;
			break;
		default:
			continue;
		}

		if (DBG(DNS, 2)) {
			char abuf[INET6_ADDRSTRLEN];
			const char *ap;

			ap = inet_ntop(af, ptr, abuf, sizeof (abuf));
			logger(LOG_DEBUG, "    %s    %s    %s",
			    (af == AF_INET) ? "A   " : "AAAA",
			    (ap) ? ap : "?", namebuf);
		}

		/* Find the server, add to its address list. */
		for (cds = cds_res; cds->cds_ds.host[0] != '\0'; cds++)
			if (0 == strcmp(namebuf, cds->cds_ds.host))
				save_addr(cds, af, ptr, size);

		/* move ptr to the end of current record */
		ptr = end;
	}

	return (cds_res);

err:
	free(cds_res);
	return (NULL);
}