--- embedaddon/dnsmasq/src/rrfilter.c 2016/11/02 09:57:01 1.1 +++ embedaddon/dnsmasq/src/rrfilter.c 2023/09/27 11:02:07 1.1.1.3 @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ along with this program. If not, see . */ -/* Code to safely remove RRs from an DNS answer */ +/* Code to safely remove RRs from a DNS answer */ #include "dnsmasq.h" @@ -156,10 +156,10 @@ static int check_rrs(unsigned char *p, struct dns_head } -/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */ +/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */ size_t rrfilter(struct dns_header *header, size_t plen, int mode) { - static unsigned char **rrs; + static unsigned char **rrs = NULL; static int rr_sz = 0; unsigned char *p = (unsigned char *)(header+1); @@ -173,7 +173,7 @@ size_t rrfilter(struct dns_header *header, size_t plen GETSHORT(qclass, p); /* First pass, find pointers to start and end of all the records we wish to elide: - records added for DNSSEC, unless explicity queried for */ + records added for DNSSEC, unless explicitly queried for */ for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++) @@ -192,21 +192,38 @@ size_t rrfilter(struct dns_header *header, size_t plen if (!ADD_RDLEN(header, p, plen, rdlen)) return plen; - /* Don't remove the answer. */ - if (i < ntohs(header->ancount) && type == qtype && class == qclass) - continue; - - if (mode == 0) /* EDNS */ + if (mode == RRFILTER_EDNS0) /* EDNS */ { /* EDNS mode, remove T_OPT from additional section only */ if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT) continue; } - else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG) - /* DNSSEC mode, remove SIGs and NSECs from all three sections. */ - continue; + else if (mode == RRFILTER_DNSSEC) + { + if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG) + /* DNSSEC mode, remove SIGs and NSECs from all three sections. */ + continue; + + /* Don't remove the answer. */ + if (i < ntohs(header->ancount) && type == qtype && class == qclass) + continue; + } + else + { + /* Only looking at answer section now. */ + if (i >= ntohs(header->ancount)) + break; + + if (class != C_IN) + continue; + + if (mode == RRFILTER_A && type != T_A) + continue; + + if (mode == RRFILTER_AAAA && type != T_AAAA) + continue; + } - if (!expand_workspace(&rrs, &rr_sz, rr_found + 1)) return plen; @@ -239,7 +256,15 @@ size_t rrfilter(struct dns_header *header, size_t plen if (!check_rrs(p, header, plen, 0, rrs, rr_found)) return plen; - /* Third pass, elide records */ + /* Third pass, actually fix up pointers in the records */ + p = (unsigned char *)(header+1); + + check_name(&p, header, plen, 1, rrs, rr_found); + p += 4; /* qclass, qtype */ + + check_rrs(p, header, plen, 1, rrs, rr_found); + + /* Fourth pass, elide records */ for (p = rrs[0], i = 1; i < rr_found; i += 2) { unsigned char *start = rrs[i]; @@ -254,14 +279,6 @@ size_t rrfilter(struct dns_header *header, size_t plen header->nscount = htons(ntohs(header->nscount) - chop_ns); header->arcount = htons(ntohs(header->arcount) - chop_ar); - /* Fourth pass, fix up pointers in the remaining records */ - p = (unsigned char *)(header+1); - - check_name(&p, header, plen, 1, rrs, rr_found); - p += 4; /* qclass, qtype */ - - check_rrs(p, header, plen, 1, rrs, rr_found); - return plen; } @@ -270,7 +287,7 @@ u16 *rrfilter_desc(int type) { /* List of RRtypes which include domains in the data. 0 -> domain - integer -> no of plain bytes + integer -> no. of plain bytes -1 -> end zero is not a valid RRtype, so the final entry is returned for @@ -322,15 +339,11 @@ int expand_workspace(unsigned char ***wkspc, int *szp, return 0; new += 5; - - if (!(p = whine_malloc(new * sizeof(unsigned char *)))) - return 0; - - if (old != 0 && *wkspc) - { - memcpy(p, *wkspc, old * sizeof(unsigned char *)); - free(*wkspc); - } + + if (!(p = whine_realloc(*wkspc, new * sizeof(unsigned char *)))) + return 0; + + memset(p+old, 0, new-old); *wkspc = p; *szp = new;