parse_packet() is used by unbound(8) to parse response packets, not
queries. There is no need to do all this work just to get access to
the query id and flags. This is what unbound(8) is doing.

OK?

diff --git frontend.c frontend.c
index 6316231f4bf..ac53fc01ef1 100644
--- frontend.c
+++ frontend.c
@@ -100,12 +100,13 @@ struct pending_query {
        struct sldns_buffer             *abuf;
        struct regional                 *region;
        struct query_info                qinfo;
-       struct msg_parse                *qmsg;
        struct edns_data                 edns;
        struct event                     ev;            /* for tcp */
        struct event                     resp_ev;       /* for tcp */
        struct event                     tmo_ev;        /* for tcp */
        uint64_t                         imsg_id;
+       uint16_t                         id;
+       uint16_t                         flags;
        int                              fd;
        int                              tcp;
        int                              dns64_synthesize;
@@ -536,8 +537,7 @@ frontend_dispatch_resolver(int fd, short event, void *bula)
                                break;
                        }
 
-                       if (answer_header->bogus && !(pq->qmsg->flags &
-                           BIT_CD)) {
+                       if (answer_header->bogus && !(pq->flags & BIT_CD)) {
                                error_answer(pq, LDNS_RCODE_SERVFAIL);
                                send_answer(pq);
                                break;
@@ -716,15 +716,13 @@ udp_receive(int fd, short events, void *arg)
        pq->qbuf = sldns_buffer_new(len);
        pq->abuf = sldns_buffer_new(len); /* make sure we can send errors */
        pq->region = regional_create();
-       pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
 
-       if (!pq->qbuf || !pq->abuf || !pq->region || !pq->qmsg) {
+       if (!pq->qbuf || !pq->abuf || !pq->region) {
                log_warnx("out of memory");
                free_pending_query(pq);
                return;
        }
 
-       memset(pq->qmsg, 0, sizeof(*pq->qmsg));
        sldns_buffer_write(pq->qbuf, udpev->query, len);
        sldns_buffer_flip(pq->qbuf);
        handle_query(pq);
@@ -734,7 +732,6 @@ void
 handle_query(struct pending_query *pq)
 {
        struct query_imsg        query_imsg;
-       struct query_info        skip;
        struct bl_node           find;
        int                      rcode;
        char                    *str;
@@ -750,16 +747,16 @@ handle_query(struct pending_query *pq)
                free(str);
        }
 
-       if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
-               log_warnx("query_info_parse failed");
+       if (sldns_buffer_remaining(pq->qbuf) < LDNS_HEADER_SIZE) {
+               log_warnx("bad query: too short, dropped");
                goto drop;
        }
 
-       sldns_buffer_rewind(pq->qbuf);
+       pq->id = sldns_buffer_read_u16_at(pq->qbuf, 0);
+       pq->flags = sldns_buffer_read_u16_at(pq->qbuf, 2);
 
-       if (parse_packet(pq->qbuf, pq->qmsg, pq->region) !=
-           LDNS_RCODE_NOERROR) {
-               log_warnx("parse_packet failed");
+       if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
+               log_warnx("query_info_parse failed");
                goto drop;
        }
 
@@ -774,11 +771,6 @@ handle_query(struct pending_query *pq)
                goto send_answer;
        }
 
-       sldns_buffer_rewind(pq->qbuf);
-       if (!query_info_parse(&skip, pq->qbuf)) {
-               error_answer(pq, LDNS_RCODE_SERVFAIL);
-               goto send_answer;
-       }
        rcode = parse_edns_from_query_pkt(pq->qbuf, &pq->edns, NULL, NULL,
            pq->region);
        if (rcode != LDNS_RCODE_NOERROR) {
@@ -891,7 +883,7 @@ noerror_answer(struct pending_query *pq)
        }
 
        sldns_buffer_clear(pq->abuf);
-       if (reply_info_encode(&pq->qinfo, rinfo, pq->qmsg->id, rinfo->flags,
+       if (reply_info_encode(&pq->qinfo, rinfo, htons(pq->id), rinfo->flags,
            pq->abuf, 0, pq->region, pq->tcp ? UINT16_MAX : pq->edns.udp_size,
            pq->edns.bits & EDNS_DO, MINIMIZE_ANSWER) == 0)
                goto srvfail;
@@ -986,7 +978,7 @@ synthesize_dns64_answer(struct pending_query *pq)
 
        sldns_buffer_clear(pq->abuf);
 
-       if (reply_info_encode(&pq->qinfo, synth_rinfo, pq->qmsg->id,
+       if (reply_info_encode(&pq->qinfo, synth_rinfo, htons(pq->id),
            synth_rinfo->flags, pq->abuf, 0, pq->region,
            pq->tcp ? UINT16_MAX : pq->edns.udp_size,
            pq->edns.bits & EDNS_DO, MINIMIZE_ANSWER) == 0)
@@ -1006,7 +998,6 @@ void
 resend_dns64_query(struct pending_query *opq) {
        struct pending_query    *pq;
        struct query_imsg        query_imsg;
-       struct query_info        skip;
        int                      rcode;
        char                     dname[LDNS_MAX_DOMAINLEN + 1];
 
@@ -1028,9 +1019,8 @@ resend_dns64_query(struct pending_query *opq) {
        pq->qbuf = sldns_buffer_new(sldns_buffer_capacity(opq->qbuf));
        pq->abuf = sldns_buffer_new(sldns_buffer_capacity(opq->abuf));
        pq->region = regional_create();
-       pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
 
-       if (!pq->qbuf || !pq->abuf || !pq->region || !pq->qmsg) {
+       if (!pq->qbuf || !pq->abuf || !pq->region) {
                log_warnx("out of memory");
                free_pending_query(pq);
                free_pending_query(opq);
@@ -1041,7 +1031,6 @@ resend_dns64_query(struct pending_query *opq) {
        sldns_buffer_write(pq->qbuf, sldns_buffer_current(opq->qbuf),
            sldns_buffer_remaining(opq->qbuf));
        sldns_buffer_flip(pq->qbuf);
-       memset(pq->qmsg, 0, sizeof(*pq->qmsg));
 
        if (pq->tcp) {
                struct timeval   timeout = {TCP_TIMEOUT, 0};
@@ -1054,24 +1043,19 @@ resend_dns64_query(struct pending_query *opq) {
                evtimer_add(&pq->tmo_ev, &timeout);
        }
 
-       if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
-               log_warnx("query_info_parse failed");
+       if (sldns_buffer_remaining(pq->qbuf) < LDNS_HEADER_SIZE) {
+               log_warnx("bad query: too short, dropped");
                goto drop;
        }
 
-       sldns_buffer_rewind(pq->qbuf);
+       pq->id = sldns_buffer_read_u16_at(pq->qbuf, 0);
+       pq->flags = sldns_buffer_read_u16_at(pq->qbuf, 2);
 
-       if (parse_packet(pq->qbuf, pq->qmsg, pq->region) !=
-           LDNS_RCODE_NOERROR) {
-               log_warnx("parse_packet failed");
+       if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
+               log_warnx("query_info_parse failed");
                goto drop;
        }
 
-       sldns_buffer_rewind(pq->qbuf);
-       if (!query_info_parse(&skip, pq->qbuf)) {
-               error_answer(pq, LDNS_RCODE_SERVFAIL);
-               goto send_answer;
-       }
        rcode = parse_edns_from_query_pkt(pq->qbuf, &pq->edns, NULL, NULL,
            pq->region);
        if (rcode != LDNS_RCODE_NOERROR) {
@@ -1154,8 +1138,8 @@ void
 error_answer(struct pending_query *pq, int rcode)
 {
        sldns_buffer_clear(pq->abuf);
-       error_encode(pq->abuf, rcode, &pq->qinfo, pq->qmsg->id,
-           pq->qmsg->flags, pq->edns.edns_present ? &pq->edns : NULL);
+       error_encode(pq->abuf, rcode, &pq->qinfo, htons(pq->id), pq->flags,
+           pq->edns.edns_present ? &pq->edns : NULL);
 }
 
 int
@@ -1669,15 +1653,12 @@ tcp_accept(int fd, short events, void *arg)
        pq->tcp = 1;
        pq->qbuf = sldns_buffer_new(DEFAULT_TCP_SIZE);
        pq->region = regional_create();
-       pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
 
-       if (!pq->qbuf || !pq->region || !pq->qmsg) {
+       if (!pq->qbuf || !pq->region) {
                free_pending_query(pq);
                return;
        }
 
-       memset(pq->qmsg, 0, sizeof(*pq->qmsg));
-
        event_set(&pq->ev, s, EV_READ | EV_PERSIST, tcp_request, pq);
        event_add(&pq->ev, NULL);
        event_set(&pq->resp_ev, s, EV_WRITE | EV_PERSIST, tcp_response, pq);

-- 
I'm not entirely sure you are real.

Reply via email to