From 0ccbdf8087bd6137b1a8b99adade34417d94e2e3 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 7 Feb 2025 22:13:31 +0000 Subject: [PATCH] Make extract_name() easier to call operating on first name in message. --- src/forward.c | 26 +++++++++----------------- src/rfc1035.c | 20 +++++++++++++------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/forward.c b/src/forward.c index 00e4284..030f9b6 100644 --- a/src/forward.c +++ b/src/forward.c @@ -329,8 +329,6 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr, /* new query */ if (!forward) { - unsigned char *p; - if (OPCODE(header) != QUERY) { flags = F_RCODE; @@ -393,8 +391,7 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr, forward->frec_src.encode_bitmap = (!option_bool(OPT_NO_0x20) && option_bool(OPT_DO_0x20)) ? rand32() : 0; forward->frec_src.encode_bigmap = NULL; - p = (unsigned char *)(header+1); - if (!extract_name(header, plen, &p, (char *)&forward->frec_src.encode_bitmap, EXTR_NAME_FLIP, 1)) + if (!extract_name(header, plen, NULL, (char *)&forward->frec_src.encode_bitmap, EXTR_NAME_FLIP, 1)) goto reply; /* Keep copy of query for retries and move to TCP */ @@ -1270,8 +1267,7 @@ void reply_query(int fd, time_t now) server->query_latency = server->mma_latency/128; /* Flip the bits back in the query name. */ - p = (unsigned char *)(header+1); - if (!extract_name(header, n, &p, (char *)&forward->frec_src.encode_bitmap, EXTR_NAME_FLIP, 1)) + if (!extract_name(header, n, NULL, (char *)&forward->frec_src.encode_bitmap, EXTR_NAME_FLIP, 1)) return; #ifdef HAVE_DNSSEC @@ -1304,8 +1300,7 @@ static void xor_array(unsigned int *arg1, unsigned int *arg2, unsigned int len) /* Call extract_name() to flip case of query in packet according to the XOR of the bit maps help in arg1 and arg2 */ static void flip_queryname(struct dns_header *header, ssize_t len, struct frec_src *arg1, struct frec_src *arg2) { - unsigned char *p = (unsigned char *)(header+1); - unsigned int *arg1p, *arg2p, arg1len, arg2len, *swapp, swap; + unsigned int *arg1p, *arg2p, arg1len, arg2len; /* Two cases: bitmap is single 32 bit int, or it's arbitrary-length array of 32bit ints. The two args may be different and of different lengths. @@ -1324,17 +1319,14 @@ static void flip_queryname(struct dns_header *header, ssize_t len, struct frec_s /* make arg1 the longer, if they differ. */ if (arg2len > arg1len) { - swap = arg1len; - swapp = arg1p; - arg1len = arg2len; - arg1p = arg2p; - arg2len = swap; - arg2p = swapp; + unsigned int swapl = arg1len, *swapp = arg1p; + arg1len = arg2len, arg1p = arg2p; + arg2len = swapl, arg2p = swapp; } /* XOR on shorter length, flip on longer, operate on longer */ xor_array(arg1p, arg2p, arg2len); - extract_name(header, len, &p, (char *)arg1p, EXTR_NAME_FLIP, arg1len); + extract_name(header, len, NULL, (char *)arg1p, EXTR_NAME_FLIP, arg1len); xor_array(arg1p, arg2p, arg2len); /* restore */ } @@ -2129,7 +2121,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, /* We us the _ONCE veriant of read_write() here because we've set a timeout on the tcp socket and wish to abort if the whole data is not read/written within the timeout. */ - if ((!data_sent && !read_write(serv->tcpfd, (unsigned char *)packet, qsize + sizeof(u16), RW_WRITE_ONCE)) || + if ((!data_sent && !read_write(serv->tcpfd, (unsigned char *)packet, qsize + sizeof(u16), RW_WRITE_ONCE)) || !read_write(serv->tcpfd, (unsigned char *)length, sizeof (*length), RW_READ_ONCE) || !read_write(serv->tcpfd, payload, (rsize = ntohs(*length)), RW_READ_ONCE)) { @@ -2145,7 +2137,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, else goto failed; } - + /* If the question section of the reply doesn't match the question we sent, then someone might be attempting to insert bogus values into the cache by sending replies containing questions and bogus answers. diff --git a/src/rfc1035.c b/src/rfc1035.c index d37cca9..f7afe1b 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -29,16 +29,19 @@ return = 1 -> extract OK, compare OK, flip OK return = 2 -> extract OK, compare failed. return = 3 -> extract OK, compare failed but only on case. + + If pp == NULL, operate on the query name in the packet. */ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, char *name, int func, unsigned int parm) { - unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL; + unsigned char *cp = (unsigned char *)name, *p1 = NULL; unsigned int j, l, namelen = 0, hops = 0; unsigned int bigmap_counter = 0, bigmap_posn = 0, bigmap_size = parm, bitmap = 0; int retvalue = 1, case_insens = 1, isExtract = 0, flip = 0, extrabytes = (int)parm; unsigned int *bigmap = (unsigned int *)name; - + unsigned char *p = pp ? *pp : (unsigned char *)(header+1); + if (func == EXTR_NAME_EXTRACT) isExtract = 1, *cp = 0; else if (func == EXTR_NAME_NOCASE) @@ -71,11 +74,14 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, } else if (!flip && *cp != 0) retvalue = 2; - - if (p1) /* we jumped via compression */ - *pp = p1; - else - *pp = p; + + if (pp) + { + if (p1) /* we jumped via compression */ + *pp = p1; + else + *pp = p; + } return retvalue; }