diff options
Diffstat (limited to 'sbin/unwind/frontend.c')
-rw-r--r-- | sbin/unwind/frontend.c | 129 |
1 files changed, 71 insertions, 58 deletions
diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c index d4b0fd7ab03..a1542257b62 100644 --- a/sbin/unwind/frontend.c +++ b/sbin/unwind/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.1 2019/01/23 13:11:00 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.2 2019/01/24 15:33:44 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -47,7 +47,15 @@ #include <string.h> #include <unistd.h> -#include "asr_private.h" +#include <assert.h> +#include "libunbound/config.h" +#include "libunbound/libunbound/unbound.h" +#include "libunbound/unbound-event.h" +#include "libunbound/sldns/rrdef.h" +#include "libunbound/sldns/pkthdr.h" +#include "libunbound/sldns/sbuffer.h" +#include "libunbound/sldns/wire2str.h" + #include "uw_log.h" #include "unwind.h" #include "frontend.h" @@ -483,41 +491,62 @@ udp_receive(int fd, short events, void *arg) struct udp_ev *udpev = (struct udp_ev *)arg; struct pending_query *pq; struct query_imsg *query_imsg; - struct asr_unpack p; - struct asr_dns_header h; - struct asr_dns_query q; - ssize_t len; - char *str_from, buf[1024]; - + ssize_t len, rem_len, buf_len; + uint16_t qdcount, ancount, nscount, arcount, t, c; + uint8_t *queryp; + char *str_from, *str, buf[1024], *bufp; if ((len = recvmsg(fd, &udpev->rcvmhdr, 0)) < 0) { log_warn("recvmsg"); return; } - str_from = ip_port((struct sockaddr *)&udpev->from); + bufp = buf; + buf_len = sizeof(buf); - _asr_unpack_init(&p, udpev->query, len); + str_from = ip_port((struct sockaddr *)&udpev->from); - if (_asr_unpack_header(&p, &h) == -1) { - log_warnx("bad query: %s, from: %s", strerror(p.err), str_from); + if (len < LDNS_HEADER_SIZE) { + log_warnx("bad query: too short, from: %s", str_from); return; } - if (h.qdcount != 1 && h.ancount != 0 && h.nscount != 0 && - h.arcount != 0) { + qdcount = LDNS_QDCOUNT(udpev->query); + ancount = LDNS_ANCOUNT(udpev->query); + nscount = LDNS_NSCOUNT(udpev->query); + arcount = LDNS_ARCOUNT(udpev->query); + + if (qdcount != 1 && ancount != 0 && nscount != 0 && arcount != 0) { log_warnx("invalid query from %s, qdcount: %d, ancount: %d " - "nscount: %d, arcount: %d", str_from, h.qdcount, h.ancount, - h.nscount, h.arcount); + "nscount: %d, arcount: %d", str_from, qdcount, ancount, + nscount, arcount); return; } log_debug("query from %s", str_from); - log_debug(";; HEADER %s", print_header(&h, buf, sizeof(buf))); - log_debug(";; QUERY SECTION:"); - if (_asr_unpack_query(&p, &q) == -1) - goto error; - log_debug("%s", print_query(&q, buf, sizeof(buf))); + if ((str = sldns_wire2str_pkt(udpev->query, len)) != NULL) { + log_debug("%s", str); + free(str); + } + + queryp = udpev->query; + rem_len = len; + + queryp += LDNS_HEADER_SIZE; + rem_len -= LDNS_HEADER_SIZE; + + sldns_wire2str_dname_scan(&queryp, &rem_len, &bufp, &buf_len, + udpev->query, len); + + if (rem_len < 4) { + log_warnx("malformed query"); + return; + } + + t = sldns_read_uint16(queryp); + c = sldns_read_uint16(queryp+2); + queryp += 4; + rem_len -= 4; if ((pq = malloc(sizeof(*pq))) == NULL) { log_warn(NULL); @@ -544,11 +573,18 @@ udp_receive(int fd, short events, void *arg) return; } - /* XXX */ - print_dname(q.q_dname, query_imsg->qname, sizeof(query_imsg->qname)); + if (strlcpy(query_imsg->qname, buf, sizeof(query_imsg->qname)) >= + sizeof(buf)) { + log_warnx("qname too long"); + free(query_imsg); + /* XXX SERVFAIL */ + free(pq->query); + free(pq); + return; + } query_imsg->id = pq->imsg_id; - query_imsg->t = q.q_type; - query_imsg->c = q.q_class; + query_imsg->t = t; + query_imsg->c = c; if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, query_imsg, sizeof(*query_imsg)) != -1) { @@ -560,62 +596,39 @@ udp_receive(int fd, short events, void *arg) free(pq); } -error: - if (p.err) - log_debug(";; ERROR AT OFFSET %zu/%zu: %s", p.offset, p.len, - strerror(p.err)); } void send_answer(struct pending_query *pq, uint8_t *answer, ssize_t len) { - struct asr_pack p; - struct asr_unpack query_u, answer_u; - struct asr_dns_header query_h, answer_h; - log_debug("result for %s", ip_port((struct sockaddr*)&pq->from)); - _asr_unpack_init(&query_u, pq->query, pq->len); - _asr_unpack_header(&query_u, &query_h); /* XXX */ - if (answer == NULL) { answer = pq->query; len = pq->len; - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - answer_h.flags = 0; - answer_h.flags |= RA_MASK; - answer_h.flags = (answer_h.flags & ~RCODE_MASK) | SERVFAIL; + LDNS_QR_SET(answer); + LDNS_RA_SET(answer); + LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); } else { - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - if (pq->bogus) { - if(query_h.flags & CD_MASK) { - answer_h.id = query_h.id; - answer_h.flags |= CD_MASK; + if(LDNS_CD_WIRE(pq->query)) { + LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); + LDNS_CD_SET(answer); } else { answer = pq->query; len = pq->len; - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - - answer_h.flags = 0; - answer_h.flags |= RA_MASK; - answer_h.flags = (answer_h.flags & ~RCODE_MASK) - | SERVFAIL; + LDNS_QR_SET(answer); + LDNS_RA_SET(answer); + LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); } } else { - answer_h.id = query_h.id; + LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); } } - _asr_pack_init(&p, answer, len); - _asr_pack_header(&p, &answer_h); - if(sendto(pq->fd, answer, len, 0, (struct sockaddr *) &pq->from, pq->from.ss_len) == -1) log_warn("sendto"); |