head 1.1; access; symbols pkgsrc-2026Q1:1.1.0.62 pkgsrc-2026Q1-base:1.1 pkgsrc-2025Q4:1.1.0.60 pkgsrc-2025Q4-base:1.1 pkgsrc-2025Q3:1.1.0.58 pkgsrc-2025Q3-base:1.1 pkgsrc-2025Q2:1.1.0.56 pkgsrc-2025Q2-base:1.1 pkgsrc-2025Q1:1.1.0.54 pkgsrc-2025Q1-base:1.1 pkgsrc-2024Q4:1.1.0.52 pkgsrc-2024Q4-base:1.1 pkgsrc-2024Q3:1.1.0.50 pkgsrc-2024Q3-base:1.1 pkgsrc-2024Q2:1.1.0.48 pkgsrc-2024Q2-base:1.1 pkgsrc-2024Q1:1.1.0.46 pkgsrc-2024Q1-base:1.1 pkgsrc-2023Q4:1.1.0.44 pkgsrc-2023Q4-base:1.1 pkgsrc-2023Q3:1.1.0.42 pkgsrc-2023Q3-base:1.1 pkgsrc-2023Q2:1.1.0.40 pkgsrc-2023Q2-base:1.1 pkgsrc-2023Q1:1.1.0.38 pkgsrc-2023Q1-base:1.1 pkgsrc-2022Q4:1.1.0.36 pkgsrc-2022Q4-base:1.1 pkgsrc-2022Q3:1.1.0.34 pkgsrc-2022Q3-base:1.1 pkgsrc-2022Q2:1.1.0.32 pkgsrc-2022Q2-base:1.1 pkgsrc-2022Q1:1.1.0.30 pkgsrc-2022Q1-base:1.1 pkgsrc-2021Q4:1.1.0.28 pkgsrc-2021Q4-base:1.1 pkgsrc-2021Q3:1.1.0.26 pkgsrc-2021Q3-base:1.1 pkgsrc-2021Q2:1.1.0.24 pkgsrc-2021Q2-base:1.1 pkgsrc-2021Q1:1.1.0.22 pkgsrc-2021Q1-base:1.1 pkgsrc-2020Q4:1.1.0.20 pkgsrc-2020Q4-base:1.1 pkgsrc-2020Q3:1.1.0.18 pkgsrc-2020Q3-base:1.1 pkgsrc-2020Q2:1.1.0.16 pkgsrc-2020Q2-base:1.1 pkgsrc-2020Q1:1.1.0.12 pkgsrc-2020Q1-base:1.1 pkgsrc-2019Q4:1.1.0.14 pkgsrc-2019Q4-base:1.1 pkgsrc-2019Q3:1.1.0.10 pkgsrc-2019Q3-base:1.1 pkgsrc-2019Q2:1.1.0.8 pkgsrc-2019Q2-base:1.1 pkgsrc-2019Q1:1.1.0.6 pkgsrc-2019Q1-base:1.1 pkgsrc-2018Q4:1.1.0.4 pkgsrc-2018Q4-base:1.1 pkgsrc-2018Q3:1.1.0.2 pkgsrc-2018Q3-base:1.1; locks; strict; comment @# @; 1.1 date 2018.09.28.20.36.24; author schmonz; state Exp; branches; next ; commitid R9q4qBimG5IyCUTA; desc @@ 1.1 log @Rename 'djbdns-qmerge2' option to 'djbdns-mergequeries', still enabled by default. Deprecate 'djbdns-qmerge1'. When applying the 'djbdns-mergequeries' patch, also apply a missing bounds check. Patch from Tim Stewart on dns@@list.cr.yp.to. Bump PKGREVISION. @ text @$NetBSD: patch-qmerge2,v 1.2 2015/12/29 04:04:29 dholland Exp $ Address the dnscache poisoning weaknesses described in CVE-2008-4392. From Jeff King in --- clients.h.orig 2009-04-21 23:43:02.000000000 -0400 +++ clients.h @@@@ -0,0 +1,7 @@@@ +#ifndef CLIENTS_H +#define CLIENTS_H + +#define MAXUDP 200 +#define MAXTCP 20 + +#endif /* CLIENTS_H */ --- dns.h.orig 2001-02-11 16:11:45.000000000 -0500 +++ dns.h @@@@ -4,6 +4,7 @@@@ #include "stralloc.h" #include "iopause.h" #include "taia.h" +#include "clients.h" #define DNS_C_IN "\0\1" #define DNS_C_ANY "\0\377" @@@@ -37,8 +38,14 @@@@ struct dns_transmit { const char *servers; char localip[4]; char qtype[2]; + struct dns_transmit *master; + struct dns_transmit *slaves[MAXUDP]; + int nslaves; } ; +extern void dns_enable_merge(void (*logger)(const char *, const char *, + const char *)); + extern void dns_random_init(const char *); extern unsigned int dns_random(unsigned int); --- dns_transmit.c.orig 2001-02-11 16:11:45.000000000 -0500 +++ dns_transmit.c @@@@ -7,6 +7,61 @@@@ #include "byte.h" #include "uint16.h" #include "dns.h" +#include "strerr.h" + +static int merge_enable; +static void (*merge_logger)(const char *, const char *, const char *); +void dns_enable_merge(void (*f)(const char *, const char *, const char *)) +{ + merge_enable = 1; + merge_logger = f; +} + +static int merge_equal(struct dns_transmit *a, struct dns_transmit *b) +{ + const char *ip1 = a->servers + 4 * a->curserver; + const char *ip2 = b->servers + 4 * b->curserver; + return + byte_equal(ip1, 4, ip2) && + byte_equal(a->qtype, 2, b->qtype) && + dns_domain_equal(a->query + 14, b->query + 14); +} + +struct dns_transmit *inprogress[MAXUDP]; + +static int try_merge(struct dns_transmit *d) +{ + int i; + for (i = 0; i < MAXUDP; i++) { + if (!inprogress[i]) continue; + if (!merge_equal(d, inprogress[i])) continue; + d->master = inprogress[i]; + inprogress[i]->slaves[inprogress[i]->nslaves++] = d; + return 1; + } + return 0; +} + +static void register_inprogress(struct dns_transmit *d) +{ + int i; + for (i = 0; i < MAXUDP; i++) { + if (!inprogress[i]) { + inprogress[i] = d; + return; + } + } + strerr_die1x(100, "BUG: out of inprogress slots"); +} + +static void unregister_inprogress(struct dns_transmit *d) +{ + int i; + for (i = 0; i < MAXUDP; i++) { + if (inprogress[i] == d) + inprogress[i] = 0; + } +} static int serverwantstcp(const char *buf,unsigned int len) { @@@@ -59,8 +114,28 @@@@ static void packetfree(struct dns_transm d->packet = 0; } +static void mergefree(struct dns_transmit *d) +{ + int i; + if (merge_enable) + unregister_inprogress(d); + /* unregister us from our master */ + if (d->master) { + for (i = 0; i < d->master->nslaves; i++) + if (d->master->slaves[i] == d) + d->master->slaves[i] = 0; + } + /* and unregister all of our slaves from us */ + for (i = 0; i < d->nslaves; i++) { + if (d->slaves[i]) + d->slaves[i]->master = NULL; + } + d->nslaves = 0; +} + static void queryfree(struct dns_transmit *d) { + mergefree(d); if (!d->query) return; alloc_free(d->query); d->query = 0; @@@@ -99,11 +174,18 @@@@ static int thisudp(struct dns_transmit * const char *ip; socketfree(d); + mergefree(d); while (d->udploop < 4) { for (;d->curserver < 16;++d->curserver) { ip = d->servers + 4 * d->curserver; if (byte_diff(ip,4,"\0\0\0\0")) { + if (merge_enable && try_merge(d)) { + if (merge_logger) + merge_logger(ip, d->qtype, d->query + 14); + return 0; + } + d->query[2] = dns_random(256); d->query[3] = dns_random(256); @@@@ -118,6 +200,8 @@@@ static int thisudp(struct dns_transmit * taia_uint(&d->deadline,timeouts[d->udploop]); taia_add(&d->deadline,&d->deadline,&now); d->tcpstate = 0; + if (merge_enable) + register_inprogress(d); return 0; } @@@@ -226,8 +310,12 @@@@ void dns_transmit_io(struct dns_transmit x->fd = d->s1 - 1; switch(d->tcpstate) { - case 0: case 3: case 4: case 5: - x->events = IOPAUSE_READ; + case 0: + if (d->master) return; + if (d->packet) { taia_now(deadline); return; } + /* otherwise, fall through */ + case 3: case 4: case 5: + x->events = IOPAUSE_READ; break; case 1: case 2: x->events = IOPAUSE_WRITE; @@@@ -244,10 +332,14 @@@@ int dns_transmit_get(struct dns_transmit unsigned char ch; int r; int fd; + int i; errno = error_io; fd = d->s1 - 1; + if (d->tcpstate == 0 && d->master) return 0; + if (d->tcpstate == 0 && d->packet) return 1; + if (!x->revents) { if (taia_less(when,&d->deadline)) return 0; errno = error_timeout; @@@@ -279,6 +371,15 @@@@ have sent query to curserver on UDP sock d->packet = alloc(d->packetlen); if (!d->packet) { dns_transmit_free(d); return -1; } byte_copy(d->packet,d->packetlen,udpbuf); + + for (i = 0; i < d->nslaves; i++) { + if (!d->slaves[i]) continue; + d->slaves[i]->packetlen = d->packetlen; + d->slaves[i]->packet = alloc(d->packetlen); + if (!d->slaves[i]->packet) { dns_transmit_free(d->slaves[i]); continue; } + byte_copy(d->slaves[i]->packet,d->packetlen,udpbuf); + } + queryfree(d); return 1; } --- dnscache.c.orig 2001-02-11 16:11:45.000000000 -0500 +++ dnscache.c @@@@ -54,7 +54,6 @@@@ uint64 numqueries = 0; static int udp53; -#define MAXUDP 200 static struct udpclient { struct query q; struct taia start; @@@@ -131,7 +130,6 @@@@ void u_new(void) static int tcp53; -#define MAXTCP 20 struct tcpclient { struct query q; struct taia start; @@@@ -435,6 +433,8 @@@@ int main() response_hidettl(); if (env_get("FORWARDONLY")) query_forwardonly(); + if (env_get("MERGEQUERIES")) + dns_enable_merge(log_merge); if (!roots_init()) strerr_die2sys(111,FATAL,"unable to read servers: "); --- log.c.orig 2001-02-11 16:11:45.000000000 -0500 +++ log.c @@@@ -150,6 +150,12 @@@@ void log_tx(const char *q,const char qty line(); } +void log_merge(const char *addr, const char qtype[2], const char *q) +{ + string("merge "); ip(addr); space(); logtype(qtype); space(); name(q); + line(); +} + void log_cachedanswer(const char *q,const char type[2]) { string("cached "); logtype(type); space(); --- log.h.orig 2001-02-11 16:11:45.000000000 -0500 +++ log.h @@@@ -18,6 +18,7 @@@@ extern void log_cachednxdomain(const cha extern void log_cachedns(const char *,const char *); extern void log_tx(const char *,const char *,const char *,const char *,unsigned int); +extern void log_merge(const char *, const char *, const char *); extern void log_nxdomain(const char *,const char *,unsigned int); extern void log_nodata(const char *,const char *,const char *,unsigned int); @