Beispiel #1
0
static int
print_axfr(FILE *file, const u_char *msg, size_t msglen) {
	ns_msg handle;

	if (ns_initparse(msg, msglen, &handle) < 0) {
		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
		return (ns_r_formerr);
	}
	if (ns_msg_getflag(handle, ns_f_rcode) != ns_r_noerror)
		return (ns_msg_getflag(handle, ns_f_rcode));

	/*
	 * We are looking for info from answer resource records.
	 * If there aren't any, return with an error. We assume
	 * there aren't any question records.
	 */
	if (ns_msg_count(handle, ns_s_an) == 0)
		return (NO_INFO);

#ifdef PROTOCOLDEBUG
	printf(";;; (message of %d octets has %d answers)\n",
	       msglen, ns_msg_count(handle, ns_s_an));
#endif
	for (;;) {
		static char origin[NS_MAXDNAME], name_ctx[NS_MAXDNAME];
		const char *name;
		char buf[2048];		/* XXX need to malloc/realloc. */
		ns_rr rr;

		if (ns_parserr(&handle, ns_s_an, -1, &rr)) {
			if (errno != ENODEV) {
				fprintf(file, ";; ns_parserr: %s\n",
					strerror(errno));
				return (FORMERR);
			}
			break;
		}
		name = ns_rr_name(rr);
		if (origin[0] == '\0' && name[0] != '\0') {
			if (strcmp(name, ".") != 0)
				strcpy(origin, name);
			fprintf(file, "$ORIGIN %s.\n", origin);
			if (strcmp(name, ".") == 0)
				strcpy(origin, name);
			if (res.pfcode & RES_PRF_TRUNC)
				strcpy(name_ctx, "@");
		}
		if (ns_sprintrr(&handle, &rr,
				(res.pfcode & RES_PRF_TRUNC) ? name_ctx : NULL,
				(res.pfcode & RES_PRF_TRUNC) ? origin : NULL,
				buf, sizeof buf) < 0) {
			fprintf(file, ";; ns_sprintrr: %s\n", strerror(errno));
			return (FORMERR);
		}
		strcpy(name_ctx, name);
		fputs(buf, file);
		fputc('\n', file);
	}
	return (SUCCESS);
}
Beispiel #2
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);
			}
		}
	}
}
Beispiel #3
0
const char *
hostname_from_question(ns_msg msg) {
    static char hostname[256] = {0};
    ns_rr rr;
    int rrnum, rrmax;
    const char *result;
    int result_len;
    rrmax = ns_msg_count(msg, ns_s_qd);
    if (rrmax == 0)
        return NULL;
    for (rrnum = 0; rrnum < rrmax; rrnum++) {
        if (local_ns_parserr(&msg, ns_s_qd, rrnum, &rr)) {
            logger_log(LOG_ERR, "local_ns_parserr");
            return NULL;
        }
        result = ns_rr_name(rr);
        result_len = strlen(result) + 1;
        if (result_len > sizeof(hostname)) {
            logger_log(LOG_ERR, "hostname too long: %s", result);
        }
        memset(hostname, 0, sizeof(hostname));
        memcpy(hostname, result, result_len);
        return hostname;
    }
    return NULL;
}
Beispiel #4
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);
}
Beispiel #5
0
KDCENTRY* krb_locate_kdc(rdpSettings* settings)
{
#ifdef WITH_RESOLV
	char *qname;
	int reslen, i;
	unsigned char response[4096];
	char kdc_host[4096];
	unsigned char* temp;
	KDCENTRY* head;
	KDCENTRY* kdcentry;
	KDCENTRY* srvans;
	ns_msg handle;
	ns_rr rr;
	head = kdcentry =  NULL;
	if (get_krb_realm(settings))
		return NULL;
	if (settings->kerberos_kdc)
	{
		srvans = xnew(KDCENTRY);
		srvans->kdchost = xstrdup(settings->kerberos_kdc);
		srvans->port = 88;
		return srvans;
	}
	qname = get_dns_queryname(settings->kerberos_realm, "_tcp.");

	if ((reslen = res_query(qname, ns_c_in, ns_t_srv, response, sizeof(response))) < 0)
		return NULL;

	ns_initparse(response, reslen, &handle);

	for (i = 0;i < ns_msg_count(handle, ns_s_an);i++)
	{
		ns_parserr(&handle, ns_s_an, i, &rr);
		srvans = xnew(KDCENTRY);
		temp = (unsigned char*)ns_rr_rdata(rr);
		GETUINT16(temp, &(srvans->priority));
		GETUINT16(temp, &(srvans->weight));
		GETUINT16(temp, &(srvans->port));
		if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), temp, (char*)kdc_host, sizeof(kdc_host)) < 0)
			srvans->kdchost = xstrdup((const char*)temp);
		else
			srvans->kdchost = xstrdup(kdc_host);
		if (head == NULL || head->priority > srvans->priority)
		{
			srvans->next = head;
			head = srvans;
		}
		else
		{
			for (kdcentry = head;kdcentry->next != NULL && kdcentry->next->priority < srvans->priority;kdcentry = kdcentry->next);
			srvans->next = kdcentry->next;
			kdcentry->next = srvans;
		}
	}

	return head;
#else
	return NULL;
#endif
}
Beispiel #6
0
static int should_filter_query(ns_msg msg, struct in_addr dns_addr) {
    ns_rr rr;
    int rrnum, rrmax;
    void *r;
    // TODO cache result for each dns server
    int dns_is_chn = chnroute_file && (dns_servers_len > 1) &&
                     test_ip_in_list(dns_addr, &chnroute_list);
    rrmax = ns_msg_count(msg, ns_s_an);
    if (rrmax == 0)
        return -1;
    for (rrnum = 0; rrnum < rrmax; rrnum++) {
        if (ns_parserr(&msg, ns_s_an, rrnum, &rr)) {
            ERR("ns_parserr");
            return 0;
        }
        u_int type;
        const u_char *rd;
        type = ns_rr_type(rr);
        rd = ns_rr_rdata(rr);
        if (type == ns_t_a) {
            if (verbose)
                printf("%s, ", inet_ntoa(*(struct in_addr *)rd));
            r = bsearch(rd, ip_list.ips, ip_list.entries, sizeof(struct in_addr),
                        cmp_in_addr);
            if (r)
                return 1;
            if (chnroute_file && dns_is_chn) {
                // filter DNS result from chn dns if result is outside chn
                if (!test_ip_in_list(*(struct in_addr *)rd, &chnroute_list))
                    return 1;
            }
        }
    }
    return 0;
}
Beispiel #7
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");
}
Beispiel #8
0
/**
 * @return 成功した場合は NETDB_SUCCESS.
 */
static int
DnsResolver_lookupTxtData(DnsResolver *self, int rrtype, const char *domain, DnsTxtResponse **resp)
{
    int query_stat = DnsResolver_query(self, domain, rrtype);
    if (NETDB_SUCCESS != query_stat) {
        return query_stat;
    }   // end if
    size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an);
    DnsTxtResponse *respobj =
        (DnsTxtResponse *) malloc(sizeof(DnsTxtResponse) + msg_count * sizeof(char *));
    if (NULL == respobj) {
        return DnsResolver_setError(self, NETDB_INTERNAL);
    }   // end if
    memset(respobj, 0, sizeof(DnsTxtResponse) + msg_count * sizeof(char *));
    respobj->num = 0;
    for (size_t n = 0; n < msg_count; ++n) {
        ns_rr rr;
        int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr);
        if (0 != parse_stat) {
            goto formerr;
        }   // end if
        if (ns_t_txt != ns_rr_type(rr)) {
            continue;
        }   // end if
        respobj->data[respobj->num] = (char *) malloc(ns_rr_rdlen(rr)); // RDLEN を越えることはない.
        if (NULL == respobj->data[respobj->num]) {
            goto noresource;
        }   // end if
        const unsigned char *rdata = ns_rr_rdata(rr);
        const unsigned char *rdata_tail = ns_rr_rdata(rr) + ns_rr_rdlen(rr);
        char *bufp = respobj->data[respobj->num];
        while (rdata < rdata_tail) {
            // 長さフィールドが RDLEN の中に収まっているか確認する
            if (rdata_tail < rdata + (*rdata) + 1) {
                free(respobj->data[respobj->num]);
                goto formerr;
            }   // end if
            memcpy(bufp, rdata + 1, *rdata);
            bufp += (size_t) *rdata;
            rdata += (size_t) *rdata + 1;
        }   // end while
        *bufp = '\0';   // 扱いやすいように NULL 終端させる
        ++(respobj->num);
    }   // end for
    if (0 == respobj->num) {
        goto formerr;
    }   // end if
    *resp = respobj;
    return NETDB_SUCCESS;

  formerr:
    DnsTxtResponse_free(respobj);
    return DnsResolver_setError(self, NO_RECOVERY);

  noresource:
    DnsTxtResponse_free(respobj);
    return DnsResolver_setError(self, NETDB_INTERNAL);
}   // end function : DnsResolver_lookupTxtData
Beispiel #9
0
static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options,
                                PDNS_RECORDA *result )
{
    DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;

    unsigned int i, num;
    unsigned char answer[NS_PACKETSZ];
    ns_sect sections[] = { ns_s_an, ns_s_ar };
    ns_msg msg;

    DNS_RECORDA *record = NULL;
    DNS_RRSET rrset;
    int len;

    DNS_RRSET_INIT( rrset );

    len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
    if (len < 0)
    {
        ret = dns_map_h_errno( h_errno );
        goto exit;
    }

    if (dns_ns_initparse( answer, len, &msg ) < 0)
    {
        ret = DNS_ERROR_BAD_PACKET;
        goto exit;
    }

#define RCODE_MASK 0x0f
    if ((msg._flags & RCODE_MASK) != ns_r_noerror)
    {
        ret = dns_map_error( msg._flags & RCODE_MASK );
        goto exit;
    }

    for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++)
    {
        for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
        {
            ret = dns_copy_record( msg, sections[i], num, &record );
            if (ret != ERROR_SUCCESS) goto exit;

            DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
        }
    }

exit:
    DNS_RRSET_TERMINATE( rrset );

    if (ret != ERROR_SUCCESS)
        DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
    else
        *result = (DNS_RECORDA *)rrset.pFirstRR;

    return ret;
}
Beispiel #10
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");
}
int count_mx (const char *host)
{
    u_char nsbuf[4096];
    ns_msg amsg;
    int l;

    l = res_query (host, ns_c_any, ns_t_mx, nsbuf, sizeof (nsbuf));
    if (l < 0) 
    {
        return 0;
    } 
    else 
    {
        ns_initparse (nsbuf, l, &amsg);
        l = ns_msg_count (amsg, ns_s_an);
    }
    
    return l;
}
Beispiel #12
0
int
DnsResolver_lookupAaaa(DnsResolver *self, const char *domain, DnsAaaaResponse **resp)
{
    int query_stat = DnsResolver_query(self, domain, ns_t_aaaa);
    if (NETDB_SUCCESS != query_stat) {
        return query_stat;
    }   // end if
    size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an);
    DnsAaaaResponse *respobj =
        (DnsAaaaResponse *) malloc(sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr));
    if (NULL == respobj) {
        return DnsResolver_setError(self, NETDB_INTERNAL);
    }   // end if
    memset(respobj, 0, sizeof(DnsAaaaResponse) + msg_count * sizeof(struct in6_addr));
    respobj->num = 0;
    for (size_t n = 0; n < msg_count; ++n) {
        ns_rr rr;
        int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr);
        if (0 != parse_stat) {
            goto formerr;
        }   // end if
        if (ns_t_aaaa != ns_rr_type(rr)) {
            continue;
        }   // end if
        if (NS_IN6ADDRSZ != ns_rr_rdlen(rr)) {
            goto formerr;
        }   // end if
        memcpy(&(respobj->addr[respobj->num]), ns_rr_rdata(rr), NS_IN6ADDRSZ);
        ++(respobj->num);
    }   // end for
    if (0 == respobj->num) {
        goto formerr;
    }   // end if
    *resp = respobj;
    return NETDB_SUCCESS;

  formerr:
    DnsAaaaResponse_free(respobj);
    return DnsResolver_setError(self, NO_RECOVERY);
}   // end function : DnsResolver_lookupAaaa
Beispiel #13
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);
}
Beispiel #14
0
static void
dump_dns_sect(ns_msg *msg, ns_sect sect, FILE *trace, const char *endline) {
	int rrnum, rrmax;
	const char *sep;
	ns_rr rr;

	rrmax = ns_msg_count(*msg, sect);
	if (rrmax == 0) {
		fputs(" 0", trace);
		return;
	}
	fprintf(trace, " %s%d", endline, rrmax);
	sep = "";
	for (rrnum = 0; rrnum < rrmax; rrnum++) {
		if (ns_parserr(msg, sect, rrnum, &rr)) {
			fputs(strerror(errno), trace);
			return;
		}
		fprintf(trace, " %s", sep);
		dump_dns_rr(msg, &rr, sect, trace);
		sep = endline;
	}
}
Beispiel #15
0
/*
 * krb5int_dns_nextans - get next matching answer record
 *
 * Sets pp to NULL if no more records.  Returns -1 on error, 0 on
 * success.
 */
int
krb5int_dns_nextans(struct krb5int_dns_state *ds,
                    const unsigned char **pp, int *lenp)
{
    int len;
    ns_rr rr;

    *pp = NULL;
    *lenp = 0;
    while (ds->cur_ans < ns_msg_count(ds->msg, ns_s_an)) {
        len = ns_parserr(&ds->msg, ns_s_an, ds->cur_ans, &rr);
        if (len < 0)
            return -1;
        ds->cur_ans++;
        if (ds->nclass == (int)ns_rr_class(rr)
            && ds->ntype == (int)ns_rr_type(rr)) {
            *pp = ns_rr_rdata(rr);
            *lenp = ns_rr_rdlen(rr);
            return 0;
        }
    }
    return 0;
}
Beispiel #16
0
/* Initialize a "newmsg" object by copying an existing parsed message.
 */
int
ns_newmsg_copy(ns_newmsg *handle, ns_msg *msg) {
    ns_flag flag;
    ns_sect sect;

    ns_newmsg_id(handle, ns_msg_id(*msg));
    for (flag = ns_f_qr; flag < ns_f_max; flag++)
        ns_newmsg_flag(handle, flag, ns_msg_getflag(*msg, flag));
    for (sect = ns_s_qd; sect < ns_s_max; sect++) {
        int i, count;

        count = ns_msg_count(*msg, sect);
        for (i = 0; i < count; i++) {
            ns_rr2 rr;
            int x;

            if (ns_parserr2(msg, sect, i, &rr) < 0)
                return (-1);
            if (sect == ns_s_qd)
                x = ns_newmsg_q(handle,
                                ns_rr_nname(rr),
                                ns_rr_type(rr),
                                ns_rr_class(rr));
            else
                x = ns_newmsg_rr(handle, sect,
                                 ns_rr_nname(rr),
                                 ns_rr_type(rr),
                                 ns_rr_class(rr),
                                 ns_rr_ttl(rr),
                                 ns_rr_rdlen(rr),
                                 ns_rr_rdata(rr));
            if (x < 0)
                return (-1);
        }
    }
    return (0);
}
Beispiel #17
0
static const char *hostname_from_question(ns_msg msg) {
    ns_rr rr;
    int rrnum, rrmax;
    const char *result;
    int result_len;
    rrmax = ns_msg_count(msg, ns_s_qd);
    if (rrmax == 0)
        return NULL;
    for (rrnum = 0; rrnum < rrmax; rrnum++) {
        if (ns_parserr(&msg, ns_s_qd, rrnum, &rr)) {
            ERR("ns_parserr");
            return NULL;
        }
        result = ns_rr_name(rr);
        result_len = strlen(result) + 1;
        if (result_len > hostname_buflen) {
            hostname_buflen = result_len << 1;
            hostname_buf = realloc(hostname_buf, hostname_buflen);
        }
        memcpy(hostname_buf, result, result_len);
        return hostname_buf;
    }
    return NULL;
}
Beispiel #18
0
static JSBool parse_section(JSContext *cx, JSObject *sobj, ns_msg *hdl, ns_sect sect)
{
	int rrnum, i;
	ns_rr rr;
	JSObject *robj;
	JSString *name;

	for (rrnum = 0; rrnum < ns_msg_count(*hdl, sect); rrnum++) {
		if (ns_parserr(hdl, sect, rrnum, &rr) < 0)
			return JS_RetError(cx, "ns_parserr: %s", strerror(errno));

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

		if (!JS_DefineElement(cx, sobj, rrnum, OBJECT_TO_JSVAL(robj), NULL, NULL, JSPROP_ENUMERATE))
			return JS_RetErrno(cx, ENOMEM);

		name = JS_NewStringCopyZ(cx, ns_rr_name(rr));
		if (!name || !JS_DefineProperty(cx, robj, "name", STRING_TO_JSVAL(name), NULL, NULL, JSPROP_ENUMERATE))
			return JS_RetErrno(cx, ENOMEM);

		if (!JS_DefineProperty(cx, robj, "type", INT_TO_JSVAL(ns_rr_type(rr)), NULL, NULL, JSPROP_ENUMERATE))
			return JS_RetErrno(cx, ENOMEM);

		for (i = 0; i < ARRAY_SIZE(pmap); i++) {
			if (pmap[i].type != ns_rr_type(rr))
				continue;
			if (!pmap[i].func(cx, robj, hdl, &rr))
				return JS_FALSE;
			break;
		}
	}

	return JS_TRUE;
}
Beispiel #19
0
void dowse_output(const char *descr, iaddr from, iaddr to, uint8_t proto, int isfrag,
              unsigned sport, unsigned dport, my_bpftimeval ts,
              const u_char *pkt_copy, unsigned olen,
              const u_char *dnspkt, unsigned dnslen) {
    /* dnspkt may be NULL if IP packet does not contain a valid DNS message */

    char output[MAX_OUTPUT];

    if (dnspkt) {

        ns_msg msg;
        int qdcount;
        ns_rr rr;

        int *val;
        char *sval;

        char *extracted;
        char *resolved;
        char *from;
        int res;
        char action = 'A';

        char from_color[16];

        ns_initparse(dnspkt, dnslen, &msg);
        if (!ns_msg_getflag(msg, ns_f_qr)) return;

        /*
         * -- flags --
         * 0    1                5    6    7    8           11               15
         * +----+----------------+----+----+----+-----------+----------------+
         * | QR | Operation Code | AA | TC | RA |   Zero    |    Recode      |
         * +----+----------------+----+----+----+-----------+----------------+
         *
         * Question/Response          : ns_f_qr
         * Operation code             : ns_f_opcode
         * Authoritative Answer       : ns_f_aa
         * Truncation occurred        : ns_f_tc
         * Recursion Desired          : ns_f_rd
         * Recursion Available        : ns_f_ra
         * MBZ                        : ns_f_z
         * Authentic Data (DNSSEC)    : ns_f_ad
         * Checking Disabled (DNSSEC) : ns_f_cd
         * Response code              : ns_f_rcode
         */
        // logerr("msg: %p",msg);
        qdcount = ns_msg_count(msg, ns_s_qd);
        if (qdcount > 0 && 0 == ns_parserr(&msg, ns_s_qd, 0, &rr)) {

            // where the query comes from
            from = ia_resolv(to);

            // if its from ourselves omit it
            if(strncmp(from,hostname,MAX_DOMAIN)==0) return;
            if(own_ipv4) if(strncmp(from,own_ipv4,MAX_DOMAIN)==0) return;
            // not reverse resolved means not known by Dowse, code RED
            if(is_ip(from)) strcpy(from_color,"#FF0000");


            resolved = ns_rr_name(rr);
            // what domain is being looked up
            extracted = extract_domain(resolved);

            res = hashmap_get(visited, extracted, (void**)(&val));
            switch(res) {

            case MAP_MISSING : // never visited
                val = malloc(sizeof(int));
                *val = 1; // just a placeholder for now
                res = hashmap_put(visited, strdup(extracted), val);
                break;

            case MAP_OK: // already visited
                action = 'M';
                break;

                // TODO error checks
            case MAP_FULL:
            case MAP_OMEM:
                break;
            }


            // compose the path of the detected query
            // add category if listed
            if(listpath) { // add known domain list information
                res = hashmap_get(domainlist, extracted, (void**)(&sval));
                switch(res) {

                case MAP_OK:
                    /* render with the category in front of domain */
                    snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s/%s",
                             ts.tv_sec, from, action, tld, sval, extracted);
                    break;
                default:
                    /* render only the domain in root category */
                    snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s",
                             ts.tv_sec, from, action, tld, extracted);
                    break;
                }
            } else
                /* render only the domain in root category */
                snprintf(output,MAX_OUTPUT,"%lu|%s|%c|%s/%s",
                         ts.tv_sec, from, action, tld, extracted);



            /* write to file */
            if(fileout) {
                fputs(output, fileout);
                fputc('\n',fileout);
                if(fileout) fflush(fileout);
            }

            /* print fast on console for realtime */
            if(console) {
                puts(output);
                fflush(stdout);
            }

        }


    }

}
Beispiel #20
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);
}
Beispiel #21
0
void txtout_output(const char* descr, iaddr from, iaddr to, uint8_t proto, unsigned flags,
    unsigned sport, unsigned dport, my_bpftimeval ts,
    const u_char* pkt_copy, unsigned olen,
    const u_char* payload, unsigned payloadlen)
{
    /*
     * Short output, only print QTYPE and QNAME for IN records
     */
    if (opt_s) {
        if (flags & DNSCAP_OUTPUT_ISDNS) {
            ns_msg msg;
            int    qdcount, err = 0;
            ns_rr  rr;
            if (ns_initparse(payload, payloadlen, &msg) < 0) {
                if (tcpstate_getcurr && tcpstate_reset)
                    tcpstate_reset(tcpstate_getcurr(), "");
                return;
            }
            qdcount = ns_msg_count(msg, ns_s_qd);

            if (qdcount > 0 && 0 == (err = ns_parserr(&msg, ns_s_qd, 0, &rr)) && ns_rr_class(rr) == 1) {
                fprintf(out, "%s %s\n",
                    p_type(ns_rr_type(rr)),
                    ns_rr_name(rr));
            }
            if (err < 0) {
                if (tcpstate_getcurr && tcpstate_reset)
                    tcpstate_reset(tcpstate_getcurr(), "");
            }
        }
        return;
    }

    /*
     * IP Stuff
     */
    fprintf(out, "%10ld.%06ld", (long)ts.tv_sec, (long)ts.tv_usec);
    fprintf(out, " %s %u", ia_str(from), sport);
    fprintf(out, " %s %u", ia_str(to), dport);
    fprintf(out, " %hhu", proto);

    if (flags & DNSCAP_OUTPUT_ISDNS) {
        ns_msg msg;
        int    qdcount, err = 0;
        ns_rr  rr;
        if (ns_initparse(payload, payloadlen, &msg) < 0) {
            if (tcpstate_getcurr && tcpstate_reset)
                tcpstate_reset(tcpstate_getcurr(), "");
            fprintf(out, "\n");
            return;
        }

        /*
         * DNS Header
         */
        fprintf(out, " %u", ns_msg_id(msg));
        fprintf(out, " %u", ns_msg_getflag(msg, ns_f_opcode));
        fprintf(out, " %u", ns_msg_getflag(msg, ns_f_rcode));
        fprintf(out, " |");
        if (ns_msg_getflag(msg, ns_f_qr))
            fprintf(out, "QR|");
        if (ns_msg_getflag(msg, ns_f_aa))
            fprintf(out, "AA|");
        if (ns_msg_getflag(msg, ns_f_tc))
            fprintf(out, "TC|");
        if (ns_msg_getflag(msg, ns_f_rd))
            fprintf(out, "RD|");
        if (ns_msg_getflag(msg, ns_f_ra))
            fprintf(out, "RA|");
        if (ns_msg_getflag(msg, ns_f_ad))
            fprintf(out, "AD|");
        if (ns_msg_getflag(msg, ns_f_cd))
            fprintf(out, "CD|");

        qdcount = ns_msg_count(msg, ns_s_qd);
        if (qdcount > 0 && 0 == (err = ns_parserr(&msg, ns_s_qd, 0, &rr))) {
            fprintf(out, " %s %s %s",
                p_class(ns_rr_class(rr)),
                p_type(ns_rr_type(rr)),
                ns_rr_name(rr));
        }
        if (err < 0) {
            if (tcpstate_getcurr && tcpstate_reset)
                tcpstate_reset(tcpstate_getcurr(), "");
        }
    }
    /*
     * Done
     */
    fprintf(out, "\n");
}
Beispiel #22
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");
}
Beispiel #23
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");
}
Beispiel #24
0
static void afsdb_hosts_to_addrs(char *vllist[],
				 int *vlsnum,
				 ns_msg handle,
				 ns_sect section,
				 unsigned mask,
				 unsigned long *_ttl)
{
	int rrnum;
	ns_rr rr;
	int subtype, i, ret;
	unsigned int ttl = UINT_MAX, rr_ttl;

	debug("AFSDB RR count is %d", ns_msg_count(handle, section));

	/* Look at all the resource records in this section. */
	for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) {
		/* Expand the resource record number rrnum into rr. */
		if (ns_parserr(&handle, section, rrnum, &rr)) {
			_error("ns_parserr failed : %m");
			continue;
		}

		/* We're only interested in AFSDB records */
		if (ns_rr_type(rr) == ns_t_afsdb) {
			vllist[*vlsnum] = malloc(MAXDNAME);
			if (!vllist[*vlsnum])
				error("Out of memory");

			subtype = ns_get16(ns_rr_rdata(rr));

			/* Expand the name server's domain name */
			if (ns_name_uncompress(ns_msg_base(handle),
					       ns_msg_end(handle),
					       ns_rr_rdata(rr) + 2,
					       vllist[*vlsnum],
					       MAXDNAME) < 0)
				error("ns_name_uncompress failed");

			rr_ttl = ns_rr_ttl(rr);
			if (ttl > rr_ttl)
				ttl = rr_ttl;

			/* Check the domain name we've just unpacked and add it to
			 * the list of VL servers if it is not a duplicate.
			 * If it is a duplicate, just ignore it.
			 */
			for (i = 0; i < *vlsnum; i++)
				if (strcasecmp(vllist[i], vllist[*vlsnum]) == 0)
					goto next_one;

			/* Turn the hostname into IP addresses */
			ret = dns_resolver(vllist[*vlsnum], mask);
			if (ret) {
				debug("AFSDB RR can't resolve."
				      "subtype:%d, server name:%s, netmask:%u",
				      subtype, vllist[*vlsnum], mask);
				goto next_one;
			}

			info("AFSDB RR subtype:%d, server name:%s, ip:%*.*s, ttl:%u",
			     subtype, vllist[*vlsnum],
			     (int)payload[payload_index - 1].iov_len,
			     (int)payload[payload_index - 1].iov_len,
			     (char *)payload[payload_index - 1].iov_base,
			     ttl);

			/* prepare for the next record */
			*vlsnum += 1;
			continue;

		next_one:
			free(vllist[*vlsnum]);
		}
	}

	*_ttl = ttl;
	info("ttl: %u", ttl);
}
Beispiel #25
0
int
DnsResolver_lookupPtr(DnsResolver *self, int af, const void *addr, DnsPtrResponse **resp)
{
    // IPv6 の逆引きエントリ名生成に十分な長さのバッファを確保する.
    char domain[DNS_IP6_REVENT_MAXLEN];
    switch (af) {
    case AF_INET:
        if (!DnsResolver_expandReverseEntry4(addr, domain, sizeof(domain))) {
            abort();
        }   // end if
        break;
    case AF_INET6:
        if (!DnsResolver_expandReverseEntry6(addr, domain, sizeof(domain))) {
            abort();
        }   // end if
        break;
    default:
        errno = EAFNOSUPPORT;
        return NETDB_INTERNAL;
    }   // end if

    int query_stat = DnsResolver_query(self, domain, ns_t_ptr);
    if (NETDB_SUCCESS != query_stat) {
        return query_stat;
    }   // end if
    size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an);
    DnsPtrResponse *respobj =
        (DnsPtrResponse *) malloc(sizeof(DnsPtrResponse) + msg_count * sizeof(char *));
    if (NULL == respobj) {
        return DnsResolver_setError(self, NETDB_INTERNAL);
    }   // end if
    memset(respobj, 0, sizeof(DnsPtrResponse) + msg_count * sizeof(char *));
    respobj->num = 0;
    for (size_t n = 0; n < msg_count; ++n) {
        ns_rr rr;
        int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr);
        if (0 != parse_stat) {
            goto formerr;
        }   // end if
        if (ns_t_ptr != ns_rr_type(rr)) {
            continue;
        }   // end if
        // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか.
        char dnamebuf[NS_MAXDNAME];
        int dnamelen =
            ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, ns_rr_rdata(rr), dnamebuf,
                               sizeof(dnamebuf));
        if (dnamelen != ns_rr_rdlen(rr)) {
            goto formerr;
        }   // end if
        respobj->domain[respobj->num] = strdup(dnamebuf);
        if (NULL == respobj->domain[respobj->num]) {
            goto noresource;
        }   // end if
        ++(respobj->num);
    }   // end for
    if (0 == respobj->num) {
        goto formerr;
    }   // end if
    *resp = respobj;
    return NETDB_SUCCESS;

  formerr:
    DnsPtrResponse_free(respobj);
    return DnsResolver_setError(self, NO_RECOVERY);

  noresource:
    DnsPtrResponse_free(respobj);
    return DnsResolver_setError(self, NETDB_INTERNAL);
}   // end function : DnsResolver_lookupPtr
Beispiel #26
0
/*
 * Print the contents of a query.
 * This is intended to be primarily a debugging routine.
 */
void
fp_nquery (const unsigned char *msg, int len, FILE *file)
{
	ns_msg handle;
	int qdcount, ancount, nscount, arcount;
	u_int opcode, rcode, id;

	/* There is no need to initialize _res: If _res is not yet
	   initialized, _res.pfcode is zero.  But initialization will
	   leave it at zero, too.  _res.pfcode is an unsigned long,
	   but the code here assumes that the flags fit into an int,
	   so use that.  */
	int pfcode = _res.pfcode;

	if (ns_initparse(msg, len, &handle) < 0) {
		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
		return;
	}
	opcode = ns_msg_getflag(handle, ns_f_opcode);
	rcode = ns_msg_getflag(handle, ns_f_rcode);
	id = ns_msg_id(handle);
	qdcount = ns_msg_count(handle, ns_s_qd);
	ancount = ns_msg_count(handle, ns_s_an);
	nscount = ns_msg_count(handle, ns_s_ns);
	arcount = ns_msg_count(handle, ns_s_ar);

	/*
	 * Print header fields.
	 */
	if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
		fprintf(file,
			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
			res_opcodes[opcode], p_rcode(rcode), id);
	if ((!pfcode) || (pfcode & RES_PRF_HEADX))
		putc(';', file);
	if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
		fprintf(file, "; flags:");
		if (ns_msg_getflag(handle, ns_f_qr))
			fprintf(file, " qr");
		if (ns_msg_getflag(handle, ns_f_aa))
			fprintf(file, " aa");
		if (ns_msg_getflag(handle, ns_f_tc))
			fprintf(file, " tc");
		if (ns_msg_getflag(handle, ns_f_rd))
			fprintf(file, " rd");
		if (ns_msg_getflag(handle, ns_f_ra))
			fprintf(file, " ra");
		if (ns_msg_getflag(handle, ns_f_z))
			fprintf(file, " ??");
		if (ns_msg_getflag(handle, ns_f_ad))
			fprintf(file, " ad");
		if (ns_msg_getflag(handle, ns_f_cd))
			fprintf(file, " cd");
	}
	if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) {
		fprintf(file, "; %s: %d",
			p_section(ns_s_qd, opcode), qdcount);
		fprintf(file, ", %s: %d",
			p_section(ns_s_an, opcode), ancount);
		fprintf(file, ", %s: %d",
			p_section(ns_s_ns, opcode), nscount);
		fprintf(file, ", %s: %d",
			p_section(ns_s_ar, opcode), arcount);
	}
	if ((!pfcode) || (pfcode &
		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
		putc('\n',file);
	}
	/*
	 * Print the various sections.
	 */
	do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file);
	do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file);
	do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file);
	do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file);
	if (qdcount == 0 && ancount == 0 &&
	    nscount == 0 && arcount == 0)
		putc('\n', file);
}
Beispiel #27
0
int
DnsResolver_lookupMx(DnsResolver *self, const char *domain, DnsMxResponse **resp)
{
    int query_stat = DnsResolver_query(self, domain, ns_t_mx);
    if (NETDB_SUCCESS != query_stat) {
        return query_stat;
    }   // end if
    size_t msg_count = ns_msg_count(self->msghanlde, ns_s_an);
    DnsMxResponse *respobj =
        (DnsMxResponse *) malloc(sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *));
    if (NULL == respobj) {
        return DnsResolver_setError(self, NETDB_INTERNAL);
    }   // end if
    memset(respobj, 0, sizeof(DnsMxResponse) + msg_count * sizeof(struct mxentry *));
    respobj->num = 0;
    for (size_t n = 0; n < msg_count; ++n) {
        ns_rr rr;
        int parse_stat = ns_parserr(&self->msghanlde, ns_s_an, n, &rr);
        if (0 != parse_stat) {
            goto formerr;
        }   // end if
        if (ns_t_mx != ns_rr_type(rr)) {
            continue;
        }   // end if
        const unsigned char *rdata = ns_rr_rdata(rr);
        if (ns_rr_rdlen(rr) < NS_INT16SZ) {
            goto formerr;
        }   // end if

        int preference = ns_get16(rdata);
        rdata += NS_INT16SZ;

        // NOTE: NS_MAXDNAME で十分なのかイマイチ確証が持てないが, bind8 の dig コマンドの実装でもこの値を使っていたのでいいのではないか.
        char dnamebuf[NS_MAXDNAME];
        int dnamelen =
            ns_name_uncompress(self->msgbuf, self->msgbuf + self->msglen, rdata, dnamebuf,
                               sizeof(dnamebuf));
        if (NS_INT16SZ + dnamelen != ns_rr_rdlen(rr)) {
            goto formerr;
        }   // end if
        // TODO: dnamebuf は NULL 終端が保証されているのか?
        size_t domainlen = strlen(dnamebuf);
        respobj->exchange[respobj->num] =
            (struct mxentry *) malloc(sizeof(struct mxentry) + sizeof(char[domainlen + 1]));
        if (NULL == respobj->exchange[respobj->num]) {
            goto noresource;
        }   // end if
        respobj->exchange[respobj->num]->preference = preference;
        if (domainlen + 1 <=
            strlcpy(respobj->exchange[respobj->num]->domain, dnamebuf, domainlen + 1)) {
            abort();
        }   // end if
        ++(respobj->num);
    }   // end for
    if (0 == respobj->num) {
        goto formerr;
    }   // end if
    *resp = respobj;
    return NETDB_SUCCESS;

  formerr:
    DnsMxResponse_free(respobj);
    return DnsResolver_setError(self, NO_RECOVERY);

  noresource:
    DnsMxResponse_free(respobj);
    return DnsResolver_setError(self, NETDB_INTERNAL);
}   // end function : DnsResolver_lookupMx
Beispiel #28
0
/*
 * Print the contents of a query.
 * This is intended to be primarily a debugging routine.
 */
void
fp_nquery(const u_char *msg, int len, FILE *file) {
    ns_msg handle;
    int qdcount, ancount, nscount, arcount;
    u_int opcode, rcode, id;

    if ((_res.options & RES_INIT) == 0 && res_init() == -1)
        return;

    if (ns_initparse(msg, len, &handle) < 0) {
        fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
        return;
    }
    opcode = ns_msg_getflag(handle, ns_f_opcode);
    rcode = ns_msg_getflag(handle, ns_f_rcode);
    id = ns_msg_id(handle);
    qdcount = ns_msg_count(handle, ns_s_qd);
    ancount = ns_msg_count(handle, ns_s_an);
    nscount = ns_msg_count(handle, ns_s_ns);
    arcount = ns_msg_count(handle, ns_s_ar);

    /*
     * Print header fields.
     */
    if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode)
        fprintf(file,
            ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
            _res_opcodes[opcode], _res_resultcodes[rcode], (int)id);
    if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
        putc(';', file);
    if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
        fprintf(file, "; flags:");
        if (ns_msg_getflag(handle, ns_f_qr))
            fprintf(file, " qr");
        if (ns_msg_getflag(handle, ns_f_aa))
            fprintf(file, " aa");
        if (ns_msg_getflag(handle, ns_f_tc))
            fprintf(file, " tc");
        if (ns_msg_getflag(handle, ns_f_rd))
            fprintf(file, " rd");
        if (ns_msg_getflag(handle, ns_f_ra))
            fprintf(file, " ra");
        if (ns_msg_getflag(handle, ns_f_z))
            fprintf(file, " ??");
        if (ns_msg_getflag(handle, ns_f_ad))
            fprintf(file, " ad");
        if (ns_msg_getflag(handle, ns_f_cd))
            fprintf(file, " cd");
    }
    if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
        fprintf(file, "; %s: %d",
            p_section(ns_s_qd, (int)opcode), qdcount);
        fprintf(file, ", %s: %d",
            p_section(ns_s_an, (int)opcode), ancount);
        fprintf(file, ", %s: %d",
            p_section(ns_s_ns, (int)opcode), nscount);
        fprintf(file, ", %s: %d",
            p_section(ns_s_ar, (int)opcode), arcount);
    }
    if ((!_res.pfcode) || (_res.pfcode &
        (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
        putc('\n',file);
    }
    /*
     * Print the various sections.
     */
    do_section(&handle, ns_s_qd, RES_PRF_QUES, file);
    do_section(&handle, ns_s_an, RES_PRF_ANS, file);
    do_section(&handle, ns_s_ns, RES_PRF_AUTH, file);
    do_section(&handle, ns_s_ar, RES_PRF_ADD, file);
    if (qdcount == 0 && ancount == 0 &&
        nscount == 0 && arcount == 0)
        putc('\n', file);
}
Beispiel #29
0
void royparse_output(const char* descr, iaddr from, iaddr to, uint8_t proto, unsigned flags,
    unsigned sport, unsigned dport, my_bpftimeval ts,
    const u_char* pkt_copy, unsigned olen,
    const u_char* payload, unsigned payloadlen)
{
    if (flags & DNSCAP_OUTPUT_ISDNS) {
        int    rrmax;
        ns_msg msg;
        ns_rr  rr;
        if (ns_initparse(payload, payloadlen, &msg) < 0) {
            fprintf(r_out, "ERR\n");
            return;
        }
        if (ns_msg_getflag(msg, ns_f_qr) != 0 && sport == 53) {
            fprintf(r_out, "%cD_", ns_msg_getflag(msg, ns_f_rd) ? 'R' : 'N');

            switch (ns_msg_getflag(msg, ns_f_opcode)) {
            case ns_o_query:
                fprintf(r_out, "QUERY");
                break;
            case ns_o_notify:
                fprintf(r_out, "NOTIFY");
                break;
            case ns_o_update:
                fprintf(r_out, "UPDATE");
                break;
            default:
                fprintf(r_out, "ELSE");
            }

            fprintf(r_out, "_%u_%cA_", ns_msg_count(msg, ns_s_an) ? 1 : 0, ns_msg_getflag(msg, ns_f_aa) ? 'A' : 'N');

            switch (ns_msg_getflag(msg, ns_f_rcode)) {
            case ns_r_noerror:
                fprintf(r_out, "NOERROR");
                break;
            case ns_r_formerr:
                fprintf(r_out, "FORMERR");
                break;
            case ns_r_nxdomain:
                fprintf(r_out, "NXDOMAIN");
                break;
            case ns_r_notimpl:
                fprintf(r_out, "NOTIMP");
                break;
            case ns_r_refused:
                fprintf(r_out, "REFUSED");
                break;
            case ns_r_notauth:
                fprintf(r_out, "NOTAUTH");
                break;
            default:
                fprintf(r_out, "ELSE");
            }

            fprintf(r_out, " %s,", royparse_ia_str(to));

            if (ns_msg_count(msg, ns_s_qd) > 0) {
                if (ns_parserr(&msg, ns_s_qd, 0, &rr) == 0) {
                    royparse_normalize(ns_rr_name(rr));
                    fprintf(r_out, "%s%s,%u", ns_rr_name(rr), (ns_rr_name(rr)[0] == '.') ? "" : ".", ns_rr_type(rr));
                } else
                    fprintf(r_out, "ERR,ERR");
            } else
                fprintf(r_out, ",");

            fprintf(r_out, ",%ld,%s%s%s%s", ns_msg_size(msg), ns_msg_id(msg) < 256 ? "-L" : "",
                ns_msg_getflag(msg, ns_f_tc) ? "-TC" : "",
                ns_msg_getflag(msg, ns_f_ad) ? "-AD" : "",
                ns_msg_getflag(msg, ns_f_cd) ? "-CD" : "");
            rrmax = ns_msg_count(msg, ns_s_ar);

            while (rrmax > 0) {
                rrmax--;
                if (ns_parserr(&msg, ns_s_ar, rrmax, &rr) == 0) {
                    if (ns_rr_type(rr) == ns_t_opt) {
                        fprintf(r_out, "-%c", (u_long)ns_rr_ttl(rr) & NS_OPT_DNSSEC_OK ? 'D' : 'E');
                        break;
                    }
                }
            }
            fprintf(r_out, "\n");
        } else if (opt_q != 0 && ns_msg_getflag(msg, ns_f_qr) == 0 && dport == 53) {
            struct pcap_pkthdr h;
            if (flags & DNSCAP_OUTPUT_ISLAYER)
                return;
            memset(&h, 0, sizeof h);
            h.ts  = ts;
            h.len = h.caplen = olen;
            pcap_dump((u_char*)q_out, &h, pkt_copy);
        }
    }
}
Beispiel #30
0
/*
Simple interface to provide DNS MX record resolution.
@param Pointer to the c string hostname you would like resolved to an MX record.
@param Pointer to the struct you would like the results written out to.
@return Return is of type int and is just the mx family type in the variable ohana. Ohana is hawaiian for family.
*/
int resolve_server(char * hostname, struct sockaddr_storage * result)
{
  pthread_mutex_lock(&dns_lock);
  res_init();
  int error = 0;
  int ohana = 0;
  ns_msg msg;
  ns_rr rr;
  struct addrinfo * addr_res;
  int res_length = 0;
  unsigned char dns_answer[4096] = {0};
  char display_buffer[4096] = {0};

  //ldns variables
  ldns_resolver *ldns_resolv;
  ldns_rdf *ldns_domain;
  ldns_pkt *ldns_packet;
  ldns_rr_list *ldns_mx_records;
  ldns_status s;

  //Setup ldns to query for the mx record
  s = ldns_resolver_new_frm_file(&ldns_resolv, NULL);
  ldns_domain = ldns_dname_new_frm_str(hostname);

  //Use ldns to query
  ldns_packet = ldns_resolver_query(ldns_resolv, ldns_domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD);

  //parse ldns query results
  ldns_mx_records = ldns_pkt_rr_list_by_type(ldns_packet, LDNS_RR_TYPE_MX, LDNS_SECTION_ANSWER);

  //Sort and print mx records
  ldns_rr_list_sort(ldns_mx_records);
  ldns_rr_list_print(stdout, ldns_mx_records);
  for (int i = 0; i < ldns_mx_records->_rr_count; i++)
  {
    printf("^_^ i= %d\n", i);
    printf(">_> %s",ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i)));
    printf(">.> %s\n", last_str_split(ldns_rr2str(ldns_rr_list_rr(ldns_mx_records, i)), " "));
  }

  /////////////////Old code below/////////////////////

  res_length = res_query(hostname, C_IN, T_MX, dns_answer, sizeof(dns_answer));
  if (ns_initparse(dns_answer, res_length, &msg)<0)
  {
    printf("hostname = %s\n", hostname);
    printf("res_length = %d\n", res_length);
    perror("DNS has gone wrong!");
    print_to_log("DNS resource query has failed", LOG_ERR);
  }
  else
  {
    res_length = ns_msg_count(msg, ns_s_an);
    for (int i = 0; i < res_length; i++)
    {
      //printf("DNS loop level = %d\n", i);
      ns_parserr(&msg, ns_s_an, i, &rr);
      ns_sprintrr(&msg, &rr, NULL, NULL, display_buffer, sizeof(display_buffer));
      if (ns_rr_type(rr) == ns_t_mx)
      {
        //String parsing solution for rr. Requires creation of display_buffer above
        error = getaddrinfo(last_str_split(display_buffer, " "), NULL, NULL, &addr_res);
        if (error != 0)
        {
          printf("error = %d\n", error);
          printf("display_buffer = %s\n", display_buffer);
          printf("last_str_split = %s\n", last_str_split(display_buffer, " "));
          perror("getaddrinfo");
        }
        if (addr_res->ai_family==AF_INET)
        {
          //printf("IPv4 mode is go\n");
          struct sockaddr_in* temp_addr = (struct sockaddr_in*)addr_res->ai_addr;
          memcpy(result, temp_addr, sizeof(*temp_addr));
          //printf("ai_addr hostname ->  %s\n", inet_ntoa(temp_addr->sin_addr));
          ohana = addr_res->ai_family;
        }
        else if (addr_res->ai_family==AF_INET6)
        {
          //printf("v6 mode engaged\n");
          struct sockaddr_in6 * temp_addr = (struct sockaddr_in6 *) addr_res->ai_addr;
          memcpy(result, temp_addr, sizeof(*temp_addr));
          ohana = addr_res->ai_family;
        }
      }
      freeaddrinfo(addr_res);
    }
  }
  pthread_mutex_unlock(&dns_lock);
  return ohana;
}