Пример #1
0
static void dns_handle_local() {
    struct sockaddr *src_addr = malloc(sizeof(struct sockaddr));
    socklen_t src_addrlen = sizeof(struct sockaddr);
    uint16_t query_id;
    ssize_t len;
    int i;
    const char *question_hostname;
    ns_msg msg;
    len = recvfrom(local_sock, global_buf, BUF_SIZE, 0, src_addr, &src_addrlen);
    if (len > 0) {
        if (ns_initparse((const u_char *)global_buf, len, &msg) < 0) {
            ERR("ns_initparse");
            free(src_addr);
            return;
        }
        // parse DNS query id
        // TODO generate id for each request to avoid conflicts
        query_id = ns_msg_id(msg);
        question_hostname = hostname_from_question(msg);
        LOG("request %s\n", question_hostname);
        id_addr_t id_addr;
        id_addr.id = query_id;
        id_addr.addr = src_addr;
        id_addr.addrlen = src_addrlen;
        queue_add(id_addr);
        for (i = 0; i < dns_servers_len; i++) {
            if (-1 == sendto(remote_sock, global_buf, len, 0,
                             dns_server_addrs[i].addr, dns_server_addrs[i].addrlen))
                ERR("sendto");
        }
    }
    else
        ERR("recvfrom");
}
Пример #2
0
static void dns_handle_remote() {
  struct sockaddr *src_addr = malloc(sizeof(struct sockaddr));
  socklen_t src_len = sizeof(struct sockaddr);
  uint16_t query_id;
  ssize_t len;
  const char *question_hostname;
  int r;
  ns_msg msg;
  len = recvfrom(remote_sock, global_buf, BUF_SIZE, 0, src_addr, &src_len);
  if (len > 0) {
    if (ns_initparse((const u_char *)global_buf, len, &msg) < 0) {
      ERR("ns_initparse");
      free(src_addr);
      return;
    }
    // parse DNS query id
    query_id = ns_msg_id(msg);
    question_hostname = hostname_from_question(msg);
    if (question_hostname) {
      LOG("response %s from %s:%d - ", question_hostname,
          inet_ntoa(((struct sockaddr_in *)src_addr)->sin_addr),
          htons(((struct sockaddr_in *)src_addr)->sin_port));
    }
    id_addr_t *id_addr = queue_lookup(query_id);
    if (id_addr) {
      id_addr->addr->sa_family = AF_INET;
      uint16_t ns_old_id = htons(id_addr->old_id);
      memcpy(global_buf, &ns_old_id, 2);
      r = should_filter_query(msg, ((struct sockaddr_in *)src_addr)->sin_addr);
      if (r == 0) {
        if (verbose)
          printf("pass\n");
        if (-1 == sendto(local_sock, global_buf, len, 0, id_addr->addr,
                         id_addr->addrlen))
          ERR("sendto");
      } else if (r == -1) {
        schedule_delay(query_id, global_buf, len, id_addr->addr,
                       id_addr->addrlen);
        if (verbose)
          printf("delay\n");
      } else {
        if (verbose)
          printf("filter\n");
      }
    } else {
      if (verbose)
        printf("skip\n");
    }
    free(src_addr);
  }
  else
    ERR("recvfrom");
}
Пример #3
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);
}
Пример #4
0
void
dump_dns(const u_char *payload, size_t paylen,
	  FILE *trace, const char *endline)
{
	u_int opcode, rcode, id;
	const char *sep;
	ns_msg msg;

	fprintf(trace, " %sdns ", endline);
	if (ns_initparse(payload, paylen, &msg) < 0) {
		fputs(strerror(errno), trace);
		return;
	}
	opcode = ns_msg_getflag(msg, ns_f_opcode);
	rcode = ns_msg_getflag(msg, ns_f_rcode);
	id = ns_msg_id(msg);
	fprintf(trace, "%s,%s,%u", p_opcode(opcode), p_rcode(rcode), id);
	sep = ",";
#define FLAG(t,f) if (ns_msg_getflag(msg, f)) { \
			fprintf(trace, "%s%s", sep, t); \
			sep = "|"; \
		  }
	FLAG("qr", ns_f_qr);
	FLAG("aa", ns_f_aa);
	FLAG("tc", ns_f_tc);
	FLAG("rd", ns_f_rd);
	FLAG("ra", ns_f_ra);
	FLAG("z", ns_f_z);
	FLAG("ad", ns_f_ad);
	FLAG("cd", ns_f_cd);
#undef FLAG
	dump_dns_sect(&msg, ns_s_qd, trace, endline);
	dump_dns_sect(&msg, ns_s_an, trace, endline);
	dump_dns_sect(&msg, ns_s_ns, trace, endline);
	dump_dns_sect(&msg, ns_s_ar, trace, endline);
}
Пример #5
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);
        }
    }
}
Пример #6
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");
}
Пример #7
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);
}
Пример #8
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);
}
Пример #9
0
Файл: nb_dns.c Проект: bro/bro
/* Returns 1 with an answer, 0 when reply was old, -1 on fatal errors */
int
nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr)
{
	register int msglen, qtype, atype, n, i;
	register struct nb_dns_entry *ne, *lastne;
	socklen_t fromlen;
	struct sockaddr_storage from;
	u_long msg[MAXPACKET / sizeof(u_long)];
	register char *bp, *ep;
	register char **ap, **hap;
	register u_int16_t id;
	register const u_char *rdata;
	register u_int32_t rttl = 0;	// make compiler happy.
	register struct hostent *he;
	register size_t rdlen;
	ns_msg handle;
	ns_rr rr;

	/* This comes from the second half of do_query() */
	fromlen = sizeof(from);
	msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0,
	                  (struct sockaddr*)&from, &fromlen);
	if (msglen <= 0) {
		snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s",
		    my_strerror(errno));
		return (-1);
	}
	if (msglen < HFIXEDSZ) {
		snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): undersized: %d",
		    msglen);
		return (-1);
	}
	if (ns_initparse((u_char *)msg, msglen, &handle) < 0) {
		snprintf(errstr, NB_DNS_ERRSIZE, "ns_initparse(): %s",
		    my_strerror(errno));
		nr->host_errno = NO_RECOVERY;
		return (-1);
	}

	/* RES_INSECURE1 style check */
	if (_nb_dns_cmpsockaddr((struct sockaddr*)&nd->server,
	                        (struct sockaddr*)&from, errstr) < 0) {
		nr->host_errno = NO_RECOVERY;
		return (-1);
	}

	/* Search for this request */
	lastne = NULL;
	id = ns_msg_id(handle);
	for (ne = nd->list; ne != NULL; ne = ne->next) {
		if (ne->id == id)
			break;
		lastne = ne;
	}

	/* Not an answer to a question we care about anymore */
	if (ne == NULL)
		return (0);

	/* Unlink this entry */
	if (lastne == NULL)
		nd->list = ne->next;
	else
		lastne->next = ne->next;
	ne->next = NULL;

	/* RES_INSECURE2 style check */
	/* XXX not implemented */

	/* Initialize result struct */
	memset(nr, 0, sizeof(*nr));
	nr->cookie = ne->cookie;
	qtype = ne->qtype;

	/* Deal with various errors */
	switch (ns_msg_getflag(handle, ns_f_rcode)) {

	case ns_r_nxdomain:
		nr->host_errno = HOST_NOT_FOUND;
		free(ne);
		return (1);

	case ns_r_servfail:
		nr->host_errno = TRY_AGAIN;
		free(ne);
		return (1);

	case ns_r_noerror:
		break;

	case ns_r_formerr:
	case ns_r_notimpl:
	case ns_r_refused:
	default:
		nr->host_errno = NO_RECOVERY;
		free(ne);
		return (1);
	}

	/* Loop through records in packet */
	memset(&rr, 0, sizeof(rr));
	memset(&nd->dns_hostent, 0, sizeof(nd->dns_hostent));
	he = &nd->dns_hostent.hostent;
	/* XXX no support for aliases */
	he->h_aliases = nd->dns_hostent.host_aliases;
	he->h_addr_list = nd->dns_hostent.h_addr_ptrs;
	he->h_addrtype = ne->atype;
	he->h_length = ne->asize;
	free(ne);

	bp = nd->dns_hostent.hostbuf;
	ep = bp + sizeof(nd->dns_hostent.hostbuf);
	hap = he->h_addr_list;
	ap = he->h_aliases;

	for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) {
		/* Parse next record */
		if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) {
			if (errno != ENODEV) {
				nr->host_errno = NO_RECOVERY;
				return (1);
			}
			/* All done */
			break;
		}

		/* Ignore records that don't answer our query (e.g. CNAMEs) */
		atype = ns_rr_type(rr);
		if (atype != qtype)
			continue;

		rdata = ns_rr_rdata(rr);
		rdlen = ns_rr_rdlen(rr);
		rttl = ns_rr_ttl(rr);
		switch (atype) {

		case T_A:
		case T_AAAA:
			if (rdlen != (unsigned int) he->h_length) {
				snprintf(errstr, NB_DNS_ERRSIZE,
				    "nb_dns_activity(): bad rdlen %d",
				    (int) rdlen);
				nr->host_errno = NO_RECOVERY;
				return (-1);
			}

			if (bp + rdlen >= ep) {
				snprintf(errstr, NB_DNS_ERRSIZE,
				    "nb_dns_activity(): overflow 1");
				nr->host_errno = NO_RECOVERY;
				return (-1);
			}
			if (nd->dns_hostent.numaddrs + 1 >= MAXADDRS) {
				snprintf(errstr, NB_DNS_ERRSIZE,
				    "nb_dns_activity(): overflow 2");
				nr->host_errno = NO_RECOVERY;
				return (-1);
			}

			memcpy(bp, rdata, rdlen);
			*hap++ = bp;
			bp += rdlen;
			++nd->dns_hostent.numaddrs;

			/* Keep looking for more A records */
			break;

		case T_TXT:
			if (bp + rdlen >= ep) {
				snprintf(errstr, NB_DNS_ERRSIZE,
				    "nb_dns_activity(): overflow 1 for txt");
				nr->host_errno = NO_RECOVERY;
				return (-1);
			}

			memcpy(bp, rdata, rdlen);
			he->h_name = bp+1; /* First char is a control character. */
			nr->hostent = he;
			nr->ttl = rttl;
			return (1);

		case T_PTR:
			n = dn_expand((const u_char *)msg,
			    (const u_char *)msg + msglen, rdata, bp, ep - bp);
			if (n < 0) {
				/* XXX return -1 here ??? */
				nr->host_errno = NO_RECOVERY;
				return (1);
			}
			he->h_name = bp;
			/* XXX check for overflow */
			bp += n;		/* returned len includes EOS */

			/* "Find first satisfactory answer" */
			nr->hostent = he;
			nr->ttl = rttl;
			return (1);
		}
	}

	nr->hostent = he;
	nr->ttl = rttl;
	return (1);
}
Пример #10
0
static void dns_handle_local() {
  struct sockaddr *src_addr = malloc(sizeof(struct sockaddr));
  socklen_t src_addrlen = sizeof(struct sockaddr);
  uint16_t query_id;
  ssize_t len;
  int i;
  int sended = 0;
  const char *question_hostname;
  ns_msg msg;
  len = recvfrom(local_sock, global_buf, BUF_SIZE, 0, src_addr, &src_addrlen);
  if (len > 0) {
    if (ns_initparse((const u_char *)global_buf, len, &msg) < 0) {
      ERR("ns_initparse");
      free(src_addr);
      return;
    }
    // parse DNS query id
    // TODO generate id for each request to avoid conflicts
    query_id = ns_msg_id(msg);
    question_hostname = hostname_from_question(msg);
    LOG("request %s\n", question_hostname);

    // assign a new id
    uint16_t new_id;
    do {
      struct timeval tv;
      gettimeofday(&tv, 0);
      int randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
      new_id = randombits & 0xffff;
    } while (queue_lookup(new_id));

    uint16_t ns_new_id = htons(new_id);
    memcpy(global_buf, &ns_new_id, 2);

    id_addr_t id_addr;
    id_addr.id = new_id;
    id_addr.old_id = query_id;

    id_addr.addr = src_addr;
    id_addr.addrlen = src_addrlen;
    queue_add(id_addr);
    if (compression) {
      if (len > 16) {
        size_t off = 12;
        int ended = 0;
        while (off < len - 4) {
          if (global_buf[off] & 0xc0)
            break;
          if (global_buf[off] == 0) {
            ended = 1;
            off ++;
            break;
          }
          off += 1 + global_buf[off];
        }
        if (ended) {
          memcpy(compression_buf, global_buf, off-1);
          memcpy(compression_buf + off + 1, global_buf + off, len - off);
          compression_buf[off-1] = '\xc0';
          compression_buf[off] = '\x04';
          for (i = 0; i < has_chn_dns; i++) {
            if (-1 == sendto(remote_sock, global_buf, len, 0,
                             dns_server_addrs[i].addr,
                             dns_server_addrs[i].addrlen))
              ERR("sendto");
          }
          for (i =  has_chn_dns; i < dns_servers_len; i++) {
            if (-1 == sendto(remote_sock, compression_buf, len + 1, 0,
                             dns_server_addrs[i].addr,
                             dns_server_addrs[i].addrlen))
              ERR("sendto");
            sended = 1;
          }
        }
      }
    }
    if (!sended) {
      for (i = 0; i < dns_servers_len; i++) {
        if (-1 == sendto(remote_sock, global_buf, len, 0,
                         dns_server_addrs[i].addr,
                         dns_server_addrs[i].addrlen))
          ERR("sendto");
      }
    }
  }
  else
    ERR("recvfrom");
}