1 /* DNS packet handling routines for rbldnsd
2  */
3 
4 #include <string.h>
5 #include <time.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <netdb.h>
12 #include <syslog.h>
13 #include "rbldnsd.h"
14 
15 #ifndef NO_IPv6
16 # ifndef NI_MAXHOST
17 #  define IPSIZE 1025
18 # else
19 #  define IPSIZE NI_MAXHOST
20 # endif
21 #else
22 # define IPSIZE 16
23 #endif
24 
25 #define MAX_GLUE (MAX_NS*2)
26 
27 static int addrr_soa(struct dnspacket *pkt, const struct zone *zone, int auth);
28 static int addrr_ns(struct dnspacket *pkt, const struct zone *zone, int auth);
29 static int version_req(struct dnspacket *pkt, const struct dnsquery *qry);
30 
31 /* DNS packet:
32  * bytes comment */
33 /* 0:1   identifier (client supplied) */
34 #define p_id1 0
35 #define p_id2 1
36 /* 2     flags1 */
37 #define p_f1 2
38 #define pf1_qr     0x80	/* query response flag */
39 #define pf1_opcode 0x78	/* opcode, 0 = query */
40 #define pf1_aa     0x04	/* auth answer */
41 #define pf1_tc     0x02	/* truncation flag */
42 #define pf1_rd     0x01	/* recursion desired (may be set in query) */
43 /* 3     flags2 */
44 #define p_f2 3
45 #define pf2_ra     0x80	/* recursion available */
46 #define pf2_z      0x70	/* reserved */
47 #define pf2_rcode  0x0f	/* response code */
48   /* 0 ok, 1 format error, 2 servfail, 3 nxdomain, 4 notimpl, 5 refused */
49 /* 4:5   qdcount (numqueries) */
50 #define p_qdcnt1 4
51 #define p_qdcnt2 5
52 /* 6:7   ancount (numanswers) */
53 #define p_ancnt1 6
54 #define p_ancnt2 7
55 /* 8:9   nscount (numauthority) */
56 #define p_nscnt1 8
57 #define p_nscnt2 9
58 /* 10:11 arcount (numadditional) */
59 #define p_arcnt1 10
60 #define p_arcnt2 11
61 #define p_hdrsize 12	/* size of packet header */
62 /* next is a DN name, a series of labels with first byte is label's length,
63  *  terminated by zero-length label (i.e. at least one zero byte is here)
64  * next two bytes are query type (A, SOA etc)
65  * next two bytes are query class (IN, HESIOD etc)
66  */
67 
68 static int
parsequery(struct dnspacket * pkt,unsigned qlen,struct dnsquery * qry)69 parsequery(struct dnspacket *pkt, unsigned qlen,
70            struct dnsquery *qry) {
71 
72   /* parsing incoming query.  Untrusted data read directly from the network.
73    * pkt->p_buf is a buffer - data that was read (DNS_EDNS0_MAXPACKET max).
74    * qlen is number of bytes actually read (packet length)
75    * first p_hdrsize bytes is header, next is query DN,
76    * next are QTYPE and QCLASS (2x2 bytes).
77    * If NSCNT==0 && ARCNT==1, and an OPT record comes after the query,
78    * EDNS0 packet size gets extracted from the OPT record.
79    * Rest of data is ignored.
80    * Returns true on success, 0 on failure.
81    * Upon successeful return, pkt->p_sans = pkt->p_cur points to the end of
82    * the query section (where our answers will be placed), and
83    * pkt->p_endp is initialized to point to the real end of answers.
84    * Real end of answers is:
85    * for non-EDNS0-aware clients it's pkt->p_buf+DNS_MAXPACKET, and
86    * if a vaild EDNS0 UDPsize is given, it will be pkt->p_buf+UDPsize-11,
87    * with the 11 bytes needed for a minimal OPT record.
88    * In replypacket() we check whenever all our answers fits in standard
89    * UDP buffer size (DNS_MAXPACKET), and if not (which means we're replying
90    * to EDNS0-aware client due to the above rules), we just add proper OPT
91    * record at the end.
92    */
93 
94   register unsigned const char *q = pkt->p_buf;
95   register unsigned const char *x, *e;
96   register unsigned char *d;
97   unsigned qlab;			/* number of labels in qDN */
98 
99   x = q + qlen - 5;	/* last possible qDN zero terminator position */
100   /* qlen isn't needed anymore, it'll be used as length of qDN below */
101 
102   if (q + p_hdrsize > x)	/* short packet (header isn't here) */
103     return 0;
104   else if (q + p_hdrsize + DNS_MAXDN <= x)
105     x = q + p_hdrsize + DNS_MAXDN - 1; /* constrain query DN to DNS_MAXDN */
106 
107   if (q[p_f1] & pf1_qr)			/* response packet?! */
108     return 0;
109   if (q[p_qdcnt1] || q[p_qdcnt2] != 1)	/* qdcount should be == 1 */
110     return 0;
111 
112   /* parse and lowercase query DN, count and init labels */
113   qlab = 0;			/* number of labels so far */
114   q += p_hdrsize;		/* start of qDN */
115   d = qry->q_dn;		/* destination lowercased DN */
116   while((*d = *q) != 0) {	/* loop by DN lables */
117     qry->q_lptr[qlab++] = d++;	/* another label */
118     e = q + *q + 1;		/* end of this label */
119     if (*q > DNS_MAXLABEL	/* too long label? */
120         || e > x)		/* or it ends past packet? */
121       return 0;
122     /* lowercase it */
123     ++q;			/* length */
124     do *d++ = dns_dnlc(*q);	/* lowercase each char */
125     while(++q < e);		/* until end of label */
126   }
127   /* d points to qDN terminator now */
128   qry->q_dnlen = d - qry->q_dn + 1;
129   qry->q_dnlab = qlab;
130 
131   /* q is end of qDN. decode qtype and qclass, and prepare for an answer */
132   ++q;
133   qry->q_type = ((unsigned)(q[0]) << 8) | q[1];
134   qry->q_class = ((unsigned)(q[2]) << 8) | q[3];
135 
136   q += 4;
137   pkt->p_sans = (unsigned char *)q; /* answers will start here */
138   pkt->p_cur = (unsigned char *)q;  /* and current answer pointer is here */
139   d = pkt->p_buf;
140   if (q < x &&
141       d[p_nscnt1] == 0 && d[p_nscnt2] == 0 &&
142       d[p_arcnt1] == 0 && d[p_arcnt2] == 1 &&
143       q[0] == 0 /* empty DN */ &&
144       q[1] == (DNS_T_OPT>>8) && q[2] == (DNS_T_OPT&255)) {
145     qlen = (((unsigned)q[3]) << 8) | q[4];
146     /* 11 bytes are needed to encode minimal EDNS0 OPT record */
147     if (qlen < DNS_MAXPACKET + 11)
148       qlen = DNS_MAXPACKET;
149     else if (qlen > sizeof(pkt->p_buf) - 11)
150       qlen = sizeof(pkt->p_buf) - 11;
151     else
152       qlen -= 11;
153     pkt->p_endp = d + qlen;
154   }
155   else
156     pkt->p_endp = d + DNS_MAXPACKET;
157 
158   return 1;
159 }
160 
161 #define digit(c) ((c) >= '0' && (c) <= '9')
162 #define d2n(c) ((unsigned)((c) - '0'))
163 
dntoip4addr(const unsigned char * q,ip4addr_t * ap)164 static int dntoip4addr(const unsigned char *q, ip4addr_t *ap) {
165   unsigned o, a = 0;
166 #define oct(q,o)					\
167     switch(*q) {					\
168     case 1:						\
169       if (!digit(q[1]))					\
170         return 0;					\
171       o = d2n(q[1]);					\
172       break;						\
173     case 2:						\
174       if (!digit(q[1]) || !digit(q[2]))			\
175         return 0;					\
176       o = d2n(q[1]) * 10 + d2n(q[2]);			\
177       break;						\
178     case 3:						\
179       if (!digit(q[1]) || !digit(q[2]) || !digit(q[3]))	\
180         return 0;					\
181       o = d2n(q[1]) * 100 + d2n(q[2]) * 10 + d2n(q[3]);	\
182       if (o > 255) return 0;				\
183       break;						\
184     default: return 0;					\
185     }
186   oct(q,o); a |= o;  q += *q + 1;
187   oct(q,o); a |= o << 8;  q += *q + 1;
188   oct(q,o); a |= o << 16;  q += *q + 1;
189   oct(q,o); a |= o << 24;
190   *ap = a;
191   return 1;
192 #undef oct
193 }
194 
dntoip6addr(const unsigned char * q,ip6oct_t ap[IP6ADDR_FULL])195 static int dntoip6addr(const unsigned char *q, ip6oct_t ap[IP6ADDR_FULL]) {
196   unsigned o1, o2, c;
197   for(c = IP6ADDR_FULL; c; ) {
198     if (*q++ != 1)
199       return 0;
200     if (digit(*q)) o2 = d2n(*q++);
201     else if (*q >= 'a' && *q <= 'f') o2 = *q++ - 'a' + 10;
202     else return 0;
203     if (*q++ != 1)
204       return 0;
205     if (digit(*q)) o1 = d2n(*q++);
206     else if (*q >= 'a' && *q <= 'f') o1 = *q++ - 'a' + 10;
207     else return 0;
208     ap[--c] = (o1 << 4) | o2;
209   }
210   return 1;
211 }
212 
213 static const ip6oct_t ip6mapped_pfx[12] =
214   "\0\0\0\0\0\0\0\0"
215   "\0\0\377\377";
216 
217 /* parse DN (as in 4.3.2.1.in-addr.arpa) to ip4addr_t (4 octets 0..255).
218  * parse DN (as in 0.1.2.3.4.5...f.base.dn) to ip6 address (32 nibbles 0..f)
219  */
dntoip(struct dnsqinfo * qi,int flags)220 static void dntoip(struct dnsqinfo *qi, int flags) {
221 
222   const unsigned char *q = qi->qi_dn;
223   unsigned qlab = qi->qi_dnlab;
224 
225   qi->qi_ip4valid = qlab == 4 && dntoip4addr(q, &qi->qi_ip4);
226   if (qi->qi_ip4valid)
227     qi->qi_ip6valid = 0;
228   else {
229     qi->qi_ip6valid =
230       qlab == 32 && qi->qi_dnlen0 == 64 && dntoip6addr(q, qi->qi_ip6);
231     if (qi->qi_ip6valid && (flags & DSTF_IP4REV)) {
232       if (qi->qi_ip6[0] == 0x20 && qi->qi_ip6[1] == 0x02) {
233         /* construct IP4 from 2002:V4ADDR::/48 6to4 address, RFC3056 */
234         qi->qi_ip4 = unpack32(qi->qi_ip6 + 2);
235         qi->qi_ip4valid = 1;
236       }
237       else if (memcmp(qi->qi_ip6, ip6mapped_pfx, sizeof(ip6mapped_pfx)) == 0) {
238         /* construct IP4 from IP4MAPPED, ::ffff:V4ADDR */
239         qi->qi_ip4 = unpack32(qi->qi_ip6 + 12);
240         qi->qi_ip4valid = 1;
241         qi->qi_ip6valid = 0; /* don't bother looking v6 */
242       }
243     }
244   }
245 }
246 
247 const struct zone *
findqzone(const struct zone * zone,unsigned dnlen,unsigned dnlab,unsigned char * const * const dnlptr,struct dnsqinfo * qi)248 findqzone(const struct zone *zone,
249           unsigned dnlen, unsigned dnlab, unsigned char *const *const dnlptr,
250           struct dnsqinfo *qi) {
251   const unsigned char *q;
252 
253   for(;; zone = zone->z_next) {
254     if (!zone) return NULL;
255     if (zone->z_dnlab > dnlab) continue;
256     q = dnlptr[dnlab - zone->z_dnlab];
257     if (memcmp(zone->z_dn, q, zone->z_dnlen - 1)) continue;
258     break;
259   }
260   qi->qi_dn = dnlptr[0];
261   qi->qi_dnlptr = dnlptr;
262   qi->qi_dnlab = dnlab - zone->z_dnlab;
263   qi->qi_dnlen0 = dnlen - zone->z_dnlen;
264 
265   if (zone->z_dstflags & (DSTF_IP4REV|DSTF_IP6REV)) /* IP address */
266     dntoip(qi, zone->z_dstflags);
267 
268   return zone;
269 }
270 
271 #ifdef NO_STATS
272 # define do_stats(x)
273 #else
274 # define do_stats(x) x
275 #endif
276 
277 /* construct reply to a query. */
replypacket(struct dnspacket * pkt,unsigned qlen,struct zone * zone)278 int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
279 
280   struct dnsquery qry;			/* query structure */
281   struct dnsqinfo qi;			/* query info structure */
282   unsigned char *h = pkt->p_buf;	/* packet's header */
283   const struct dslist *dsl;
284   int found;
285   extern int lazy; /*XXX hack*/
286 
287   pkt->p_substrr = 0;
288   /* check global ACL */
289   if (g_dsacl && g_dsacl->ds_stamp) {
290     found = ds_acl_query(g_dsacl, pkt);
291     if (found & NSQUERY_IGNORE) {
292       do_stats(gstats.q_err += 1; gstats.b_in += qlen);
293       return 0;
294     }
295   }
296   else
297     found = 0;
298 
299   if (!parsequery(pkt, qlen, &qry)) {
300     do_stats(gstats.q_err += 1; gstats.b_in += qlen);
301     return 0;
302   }
303 
304   /* from now on, we see (almost?) valid dns query, should reply */
305 
306 #define setnonauth(h) (h[p_f1] &= ~pf1_aa)
307 #define _refuse(code,lab) \
308     do { setnonauth(h); h[p_f2] = (code); goto lab; } while(0)
309 #define refuse(code) _refuse(code, err_nz)
310 #define rlen() pkt->p_cur - h
311 
312   /* construct reply packet */
313 
314   /* identifier already in place */
315   /* flags will be set up later */
316   /* qdcount already set up in query */
317   /* all counts (qd,an,ns,ar) are <= 255 due to size limit */
318   h[p_ancnt1] = h[p_ancnt2] = 0;
319   h[p_nscnt1] = h[p_nscnt2] = 0;
320   h[p_arcnt1] = h[p_arcnt2] = 0;
321 
322   if (h[p_f1] & (pf1_opcode | pf1_aa | pf1_tc | pf1_qr)) {
323     h[p_f1] = pf1_qr;
324     refuse(DNS_R_NOTIMPL);
325   }
326   h[p_f1] |= pf1_qr;
327   if (qry.q_class == DNS_C_IN)
328     h[p_f1] |= pf1_aa;
329   else if (qry.q_class != DNS_C_ANY) {
330     if (version_req(pkt, &qry)) {
331       do_stats(gstats.q_ok += 1; gstats.b_in += qlen; gstats.b_out += rlen());
332       return rlen();
333     }
334     else
335       refuse(DNS_R_REFUSED);
336   }
337   switch(qry.q_type) {
338   case DNS_T_ANY: qi.qi_tflag = NSQUERY_ANY; break;
339   case DNS_T_A:   qi.qi_tflag = NSQUERY_A;   break;
340   case DNS_T_TXT: qi.qi_tflag = NSQUERY_TXT; break;
341   case DNS_T_NS:  qi.qi_tflag = NSQUERY_NS;  break;
342   case DNS_T_SOA: qi.qi_tflag = NSQUERY_SOA; break;
343   case DNS_T_MX:  qi.qi_tflag = NSQUERY_MX;  break;
344   default:
345     if (qry.q_type >= DNS_T_TSIG)
346       refuse(DNS_R_NOTIMPL);
347     qi.qi_tflag = NSQUERY_OTHER;
348   }
349   qi.qi_tflag |= found;
350   h[p_f2] = DNS_R_NOERROR;
351 
352   /* find matching zone */
353   zone = (struct zone*)
354       findqzone(zone, qry.q_dnlen, qry.q_dnlab, qry.q_lptr, &qi);
355   if (!zone) /* not authoritative */
356     refuse(DNS_R_REFUSED);
357 
358   /* found matching zone */
359 #undef refuse
360 #define refuse(code)  _refuse(code, err_z)
361   do_stats(zone->z_stats.b_in += qlen);
362 
363   if (zone->z_dsacl && zone->z_dsacl->ds_stamp) {
364     qi.qi_tflag |= ds_acl_query(zone->z_dsacl, pkt);
365     if (qi.qi_tflag & NSQUERY_IGNORE) {
366       do_stats(gstats.q_err += 1);
367       return 0;
368     }
369   }
370 
371   if (!zone->z_stamp)	/* do not answer if not loaded */
372     refuse(DNS_R_SERVFAIL);
373 
374   if (qi.qi_tflag & NSQUERY_REFUSE)
375     refuse(DNS_R_REFUSED);
376 
377   if ((found = call_hook(query_access, (pkt->p_peer, zone, &qi)))) {
378     if (found < 0) return 0;
379     refuse(DNS_R_REFUSED);
380   }
381 
382   if (qi.qi_dnlab == 0) {	/* query to base zone: SOA and NS */
383 
384     found = NSQUERY_FOUND;
385 
386     /* NS and SOA with auth=0 will only touch answer section */
387     if ((qi.qi_tflag & NSQUERY_SOA) && !addrr_soa(pkt, zone, 0))
388       found = 0;
389     else
390     if ((qi.qi_tflag & NSQUERY_NS) && !addrr_ns(pkt, zone, 0))
391       found = 0;
392     if (!found) {
393       pkt->p_cur = pkt->p_sans;
394       h[p_ancnt2] = h[p_nscnt2] = 0;
395       refuse(DNS_R_REFUSED);
396     }
397 
398   }
399   else /* not to zone base DN */
400     found = 0;
401 
402   /* search the datasets */
403   for(dsl = zone->z_dsl; dsl; dsl = dsl->dsl_next)
404     found |= dsl->dsl_queryfn(dsl->dsl_ds, &qi, pkt);
405 
406   if (found & NSQUERY_ADDPEER) {
407 #ifdef NO_IPv6
408     addrr_a_txt(pkt, qi.qi_tflag, pkt->p_substrr,
409                 inet_ntoa(((struct sockaddr_in*)pkt->p_peer)->sin_addr),
410                 pkt->p_substds);
411 #else
412     char subst[IPSIZE];
413     if (getnameinfo(pkt->p_peer, pkt->p_peerlen,
414                     subst, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0)
415       subst[0] = '\0';
416     addrr_a_txt(pkt, qi.qi_tflag, pkt->p_substrr, subst, pkt->p_substds);
417 #endif
418   }
419 
420   /* now complete the reply: add AUTH etc sections */
421   /* addrr_ns(auth=1) should be called last as it fills in
422    * both AUTH and ADDITIONAL sections */
423   if (!found) {			/* negative result */
424     addrr_soa(pkt, zone, 1);	/* add SOA if any to AUTHORITY */
425     h[p_f2] = DNS_R_NXDOMAIN;
426     do_stats(zone->z_stats.q_nxd += 1);
427   }
428   else {
429     if (!h[p_ancnt2]) {	/* positive reply, no answers */
430       addrr_soa(pkt, zone, 1);	/* add SOA if any to AUTHORITY */
431     }
432     else if (zone->z_nns &&
433              /* (!(qi.qi_tflag & NSQUERY_NS) || qi.qi_dnlab) && */
434              !lazy)
435       addrr_ns(pkt, zone, 1); /* add nameserver records to positive reply */
436     do_stats(zone->z_stats.q_ok += 1);
437   }
438   (void)call_hook(query_result, (pkt->p_peer, zone, &qi, found));
439   if (rlen() > DNS_MAXPACKET) {	/* add OPT record for long replies */
440     /* as per parsequery(), we always have 11 bytes for minimal OPT record at
441      * the end of our reply packet, OR rlen() does not exceed DNS_MAXPACKET */
442     h[p_arcnt2] += 1;		/* arcnt is limited to 254 records */
443     h = pkt->p_cur;
444     *h++ = 0;			/* empty (root) DN */
445     PACK16S(h, DNS_T_OPT);
446     PACK16S(h, DNS_EDNS0_MAXPACKET);
447     *h++ = 0; *h++ = 0;		/* RCODE and version */
448     *h++ = 0; *h++ = 0;		/* rest of the TTL field */
449     *h++ = 0; *h++ = 0;		/* RDLEN */
450     pkt->p_cur = h;
451     h = pkt->p_buf;		/* restore for rlen() to work */
452   }
453   do_stats(zone->z_stats.b_out += rlen());
454   return rlen();
455 
456 err_nz:
457   do_stats(gstats.q_err += 1; gstats.b_in += qlen; gstats.b_out += rlen());
458   return rlen();
459 
460 err_z:
461   do_stats(zone->z_stats.q_err += 1; zone->z_stats.b_out += rlen());
462   return rlen();
463 }
464 
465 #define fit(pkt, c, bytes) ((c) + (bytes) <= (pkt)->p_endp)
466 
467 
468 /* DN compression pointers/structures */
469 
470 /* We store pre-computed RRs for NS and SOA records in special
471  * cache buffers referenced to by zone structure.
472  *
473  * The precomputed RRs consists of ready-to-be-sent data (with
474  * all record types/classes, TTLs, and data in place), modulo
475  * compressed DN backreferences.  When this cached data will be
476  * copied into answer packet, we'll need to adjust "jumps" in
477  * DN name compressions to reflect actual position of the data
478  * in answer packet.
479  *
480  * Cache data is calculated as if it where inside some packet,
481  * where it's start is exactly at the beginning of cached/precomputed
482  * record, and with zone's base DN (with class and type) being in
483  * question section immediately BEFORE the data (i.e. before our
484  * "virtual packet").  So some DN compression offsets (pointers)
485  * will be negative (referring to the query section of actual answer,
486  * as zone base DN will be present in answer anyway), and some will
487  * be positive (referring to this very record in actual answer).
488  */
489 
490 struct dnjump {	/* one DN "jump": */
491   unsigned char *pos;	/* position in precomputed packet where the jump is */
492   int off;		/* jump offset relative to beginning of the RRs */
493 };
494 
495 struct dnptr {	/* domain pointer for DN compression */
496   const unsigned char *dn;	/* actual (complete) domain name */
497   int off;			/* jump offset relative to start of RRs */
498 };
499 
500 struct dncompr {	/* DN compression structure */
501   struct dnptr ptr[256];	/* array of all known domain names */
502   struct dnptr *lptr;		/* last unused slot in ptr[] */
503   unsigned char *buf;		/* buffer for the cached RRs */
504   unsigned char *bend;		/* pointer to past the end of buf */
505   struct dnjump *jump;		/* current jump ptr (array of jumps) */
506 };
507 
508 #define CACHEBUF_SIZE (DNS_MAXPACKET-p_hdrsize-4)
509 /* maxpacket minus header minus (class+type) */
510 
511 /* initialize compression/cache structures */
512 static unsigned char *
dnc_init(struct dncompr * compr,unsigned char * buf,unsigned bufsize,struct dnjump * jump,const unsigned char * dn)513 dnc_init(struct dncompr *compr,
514          unsigned char *buf, unsigned bufsize, struct dnjump *jump,
515          const unsigned char *dn) {
516   struct dnptr *ptr;
517   unsigned char *cpos;
518 
519   compr->buf = buf; compr->bend = buf + bufsize;
520   compr->jump = jump;
521 
522   cpos = buf - dns_dnlen(dn) - 4; /* current position: qDN BEFORE the RRs */
523   ptr = compr->ptr;
524 
525   while(*dn) {
526     ptr->dn = dn;
527     ptr->off = cpos - buf;
528     ++ptr;
529     cpos += *dn + 1;
530     dn += *dn + 1;
531   }
532   compr->lptr = ptr;
533   return cpos + 5;
534 }
535 
536 /* add one DN into cache, adjust compression pointers and current pointer */
537 static unsigned char *
dnc_add(struct dncompr * compr,unsigned char * cpos,const unsigned char * dn)538 dnc_add(struct dncompr *compr, unsigned char *cpos, const unsigned char *dn) {
539   struct dnptr *ptr;
540 
541   while(*dn) {
542     /* lookup DN in already stored names */
543     for(ptr = compr->ptr; ptr < compr->lptr; ++ptr) {
544       if (!dns_dnequ(ptr->dn, dn))
545         continue;
546       /* found one, make a jump to it */
547       if (cpos + 2 >= compr->bend) return NULL;
548       compr->jump->pos = cpos;
549       compr->jump->off = ptr->off;
550       ++compr->jump;
551       return cpos + 2;
552     }
553     /* not found, add it to the list of known DNs... */
554     if (cpos + *dn + 1 >= compr->bend)
555       return NULL;	/* does not fit */
556     if (ptr < compr->ptr + sizeof(compr->ptr) / sizeof(compr->ptr[0])) {
557       ptr->dn = dn;
558       ptr->off = cpos - compr->buf;
559       ++compr->lptr;
560     }
561     /* ...and add one label into the "packet" */
562     memcpy(cpos, dn, *dn + 1);
563     cpos += *dn + 1;
564     dn += *dn + 1;
565   }
566   if (cpos + 1 >= compr->bend)
567     return NULL;
568   *cpos++ = '\0';
569   return cpos;
570 }
571 
572 /* finalize RRs: remember it's size and number of jumps */
dnc_finish(struct dncompr * compr,unsigned char * cptr,unsigned * sizep,struct dnjump ** jendp)573 static void dnc_finish(struct dncompr *compr, unsigned char *cptr,
574                        unsigned *sizep, struct dnjump **jendp) {
575    *sizep = cptr - compr->buf;
576    *jendp = compr->jump;
577 }
578 
579 /* place pre-cached RRs into the packet, adjusting jumps */
580 static int
dnc_final(struct dnspacket * pkt,const unsigned char * data,unsigned dsize,const struct dnjump * jump,const struct dnjump * jend)581 dnc_final(struct dnspacket *pkt,
582           const unsigned char *data, unsigned dsize,
583           const struct dnjump *jump,
584           const struct dnjump *jend) {
585   const unsigned qoff = (pkt->p_sans - pkt->p_buf) + 0xc000;
586   const unsigned coff = (pkt->p_cur - pkt->p_buf) + 0xc000;
587   unsigned pos;
588   if (!fit(pkt, pkt->p_cur, dsize))
589     return 0;
590   /* first, adjust offsets - in cached data anyway */
591   while(jump < jend) {
592     /* jump to either query section or this very RRs */
593     pos = jump->off + (jump->off < 0 ? qoff : coff);
594     PACK16(jump->pos, pos);
595     ++jump;
596   }
597   /* and finally, copy the RRs into answer packet */
598   memcpy(pkt->p_cur, data, dsize);
599   pkt->p_cur += dsize;
600   return 1;
601 }
602 
603 
604 struct zonesoa {	/* cached SOA RR */
605   unsigned size;		/* size of the RR */
606   unsigned ttloff;		/* offset of the TTL field */
607   const unsigned char *minttl;	/* pointer to minttl in data */
608   struct dnjump jump[3];	/* jumps to fix: 3 max (qdn, odn, pdn) */
609   struct dnjump *jend;		/* last jump */
610   unsigned char data[CACHEBUF_SIZE];
611 };
612 
613 struct zonens {		/* cached NS RRs */
614   unsigned nssize;			/* size of all NS RRs */
615   unsigned tsize;			/* size of NS+glue recs */
616   struct dnjump jump[MAX_NS*2+MAX_GLUE];/* jumps: for qDNs and for NSes */
617   struct dnjump *nsjend;		/* last NS jump */
618   struct dnjump *tjend;			/* last glue jump */
619   unsigned char data[CACHEBUF_SIZE];
620 };
621 
init_zones_caches(struct zone * zonelist)622 void init_zones_caches(struct zone *zonelist) {
623   while(zonelist) {
624     if (!zonelist->z_dsl) {
625       char name[DNS_MAXDOMAIN];
626       dns_dntop(zonelist->z_dn, name, sizeof(name));
627       error(0, "missing data for zone `%s'", name);
628     }
629     zonelist->z_zsoa = tmalloc(struct zonesoa);
630     /* for NS RRs, we allocate MAX_NS caches:
631      * each stores one variant of NS rotation */
632     zonelist->z_zns = (struct zonens *)emalloc(sizeof(struct zonens) * MAX_NS);
633     zonelist = zonelist->z_next;
634   }
635 }
636 
637 /* update SOA RR cache */
638 
update_zone_soa(struct zone * zone,const struct dssoa * dssoa)639 int update_zone_soa(struct zone *zone, const struct dssoa *dssoa) {
640    struct zonesoa *zsoa;
641    unsigned char *cpos;
642    struct dncompr compr;
643    unsigned t;
644    unsigned char *sizep;
645 
646    zsoa = zone->z_zsoa;
647    zsoa->size = 0;
648    if (!(zone->z_dssoa = dssoa)) return 1;
649 
650    cpos = dnc_init(&compr, zsoa->data, sizeof(zsoa->data),
651                    zsoa->jump, zone->z_dn);
652 
653    cpos = dnc_add(&compr, cpos, zone->z_dn);
654    PACK16S(cpos, DNS_T_SOA);
655    PACK16S(cpos, DNS_C_IN);
656    zsoa->ttloff = cpos - compr.buf;
657    PACK32S(cpos, dssoa->dssoa_ttl);
658    sizep = cpos;
659    cpos += 2;
660    cpos = dnc_add(&compr, cpos, dssoa->dssoa_odn);
661    if (!cpos) return 0;
662    cpos = dnc_add(&compr, cpos, dssoa->dssoa_pdn);
663    if (!cpos) return 0;
664    t = dssoa->dssoa_serial ? dssoa->dssoa_serial : zone->z_stamp;
665    PACK32S(cpos, t);
666    memcpy(cpos, dssoa->dssoa_n, 16); cpos += 16;
667    zsoa->minttl = cpos - 4;
668    t = cpos - sizep - 2;
669    PACK16(sizep, t);
670    dnc_finish(&compr, cpos, &zsoa->size, &zsoa->jend);
671 
672    return 1;
673 }
674 
addrr_soa(struct dnspacket * pkt,const struct zone * zone,int auth)675 static int addrr_soa(struct dnspacket *pkt, const struct zone *zone, int auth) {
676   const struct zonesoa *zsoa = zone->z_zsoa;
677   unsigned char *c = pkt->p_cur;
678   if (!zone->z_dssoa || !zsoa->size) {
679     if (!auth)
680       setnonauth(pkt->p_buf);
681     return 0;
682   }
683   if (!dnc_final(pkt, zsoa->data, zsoa->size, zsoa->jump, zsoa->jend)) {
684     if (!auth)
685       setnonauth(pkt->p_buf); /* non-auth answer as we can't fit the record */
686     return 0;
687   }
688   /* for AUTHORITY section for NXDOMAIN etc replies, use minttl as TTL */
689   if (auth) memcpy(c + zsoa->ttloff, zsoa->minttl, 4);
690   pkt->p_buf[auth ? p_nscnt2 : p_ancnt2]++;
691   return 1;
692 }
693 
694 static unsigned char *
find_glue(struct zone * zone,const unsigned char * nsdn,struct dnspacket * pkt,const struct zone * zonelist)695 find_glue(struct zone *zone, const unsigned char *nsdn,
696           struct dnspacket *pkt, const struct zone *zonelist) {
697   struct dnsqinfo qi;
698   unsigned lab;
699   unsigned char dnbuf[DNS_MAXDN], *dp;
700   unsigned char *dnlptr[DNS_MAXLABELS];
701   const struct dslist *dsl;
702   const struct zone *qzone;
703 
704   /* lowercase the nsdn and find label pointers */
705   lab = 0; dp = dnbuf;
706   while((*dp = *nsdn)) {
707     const unsigned char *e = nsdn + *nsdn + 1;
708     dnlptr[lab++] = dp++;
709     while(++nsdn < e)
710       *dp++ = dns_dnlc(*nsdn);
711   }
712 
713   qzone = findqzone(zonelist, dp - dnbuf + 1, lab, dnlptr, &qi);
714   if (!qzone)
715     return NULL;
716 
717   /* pefrorm fake query */
718   qi.qi_tflag = NSQUERY_A/*|NSQUERY_AAAA*/;
719   dp = pkt->p_cur;
720   for(dsl = qzone->z_dsl; dsl; dsl = dsl->dsl_next)
721     dsl->dsl_queryfn(dsl->dsl_ds, &qi, pkt);
722 
723   if (dp == pkt->p_cur) {
724     char name[DNS_MAXDOMAIN];
725     dns_dntop(qi.qi_dn, name, sizeof(name));
726     zlog(LOG_WARNING, zone, "no glue record(s) for %.60s NS found", name);
727     return NULL;
728   }
729 
730   return dp;
731 }
732 
update_zone_ns(struct zone * zone,const struct dsns * dsns,unsigned ttl,const struct zone * zonelist)733 int update_zone_ns(struct zone *zone, const struct dsns *dsns, unsigned ttl,
734                    const struct zone *zonelist) {
735   struct zonens *zns;
736   unsigned char *cpos, *sizep;
737   struct dncompr compr;
738   unsigned size, i, ns, nns;
739   const unsigned char *nsdna[MAX_NS];
740   const unsigned char *dn;
741   unsigned char *nsrrs[MAX_NS], *nsrre[MAX_NS];
742   unsigned nglue;
743   struct dnspacket pkt;
744 
745   memset(&pkt, 0, sizeof(pkt));
746   pkt.p_sans = pkt.p_cur = pkt.p_buf + p_hdrsize;
747   pkt.p_endp = pkt.p_buf + CACHEBUF_SIZE + p_hdrsize;
748 
749   for(nns = 0; dsns; dsns = dsns->dsns_next) {
750     i = 0;
751     while(i < nns && !dns_dnequ(nsdna[i], dsns->dsns_dn))
752       ++i;
753     if (i < nns)
754       continue;
755     if (nns >= MAX_NS) {
756       zlog(LOG_WARNING, zone,
757            "too many NS records specified, only first %d will be used", MAX_NS);
758       break;
759     }
760     nsdna[nns] = dsns->dsns_dn;
761     if ((nsrrs[nns] = find_glue(zone, dsns->dsns_dn, &pkt, zonelist)))
762       nsrre[nns] = pkt.p_cur;
763     ++nns;
764   }
765   /* number of additional records must not exceed 254: (room for EDNS0 OPT) */
766   nglue = pkt.p_buf[p_ancnt2];
767   if (pkt.p_buf[p_ancnt1] || nglue > 254)	/* too many glue recs */
768     return 0;
769   /* check if we have enouth dnjump slots */
770   if (nns * 2 + nglue > sizeof(zns->jump)/sizeof(zns->jump[0]))
771     return 0;
772 
773   memcpy(zone->z_nsdna, nsdna, nns * sizeof(nsdna[0]));
774   memset(nsdna + nns, 0, (MAX_NS - nns) * sizeof(nsdna[0]));
775   zone->z_nns = 0;	/* for now, in case of error return */
776   zone->z_nsttl = ttl;
777 
778   /* fill up nns variants of NS RRs ordering:
779    * zns is actually an array, not single structure */
780   ns = 0;
781   zns = zone->z_zns;
782   for(;;) {
783     cpos = dnc_init(&compr, zns->data, sizeof(zns->data),
784                     zns->jump, zone->z_dn);
785 
786     for(i = 0; i < nns; ++i) {
787       cpos = dnc_add(&compr, cpos, zone->z_dn);
788       if (!cpos || cpos + 10 > compr.bend) return 0;
789       PACK16S(cpos, DNS_T_NS);
790       PACK16S(cpos, DNS_C_IN);
791       PACK32S(cpos, ttl);
792       sizep = cpos; cpos += 2;
793       cpos = dnc_add(&compr, cpos, nsdna[i]);
794       if (!cpos) return 0;
795       size = cpos - sizep - 2;
796       PACK16(sizep, size);
797     }
798     dnc_finish(&compr, cpos, &zns->nssize, &zns->nsjend);
799 
800     if (nglue)
801       for(i = 0; i < nns; ++i)
802         for(dn = nsrrs[i]; dn && dn < nsrre[i]; ) {
803           /* pack the glue record. dnjump, type+class, ttl, size (= 4 or 16) */
804           dn += 2;
805           size = 10 + dn[2+2+4+1];
806           cpos = dnc_add(&compr, cpos, zone->z_nsdna[i]);
807           if (!cpos || cpos + size > compr.bend) return 0;
808           memcpy(cpos, dn, size);
809           dn += size; cpos += size;
810         }
811     dnc_finish(&compr, cpos, &zns->tsize, &zns->tjend);
812 
813     if (++ns >= nns) break;
814 
815     /* rotate list of NSes */
816     dn = nsdna[0];
817     memmove(nsdna, nsdna + 1, (nns - 1) * sizeof(nsdna[0]));
818     nsdna[nns - 1] = dn;
819     ++zns;
820 
821   }
822   zone->z_nns = nns;
823   zone->z_nglue = nglue;
824 
825   return 1;
826 }
827 
addrr_ns(struct dnspacket * pkt,const struct zone * zone,int auth)828 static int addrr_ns(struct dnspacket *pkt, const struct zone *zone, int auth) {
829   unsigned cns = zone->z_cns;
830   const struct zonens *zns = zone->z_zns + cns;
831   if (!zone->z_nns)
832     return 0;
833   /* if auth=1, we're adding last records (except maybe EDNS0 OPT),
834    * so it's ok to fill in both AUTH and ADDITIONAL sections. */
835   /* If we can't fit both NS and glue recs, try NS only, omitting glue.
836    * For auth=0, don't add glue records at all.  */
837   if (auth && dnc_final(pkt, zns->data, zns->tsize, zns->jump, zns->tjend)) {
838     pkt->p_buf[p_nscnt2] += zone->z_nns;
839     pkt->p_buf[p_arcnt2] += zone->z_nglue;
840   }
841   else if (!dnc_final(pkt, zns->data, zns->nssize, zns->jump, zns->nsjend))
842     return 0;
843   else
844     /* we can't overflow p_ancnt2 (255 max) because addrr_ns(auth=0)
845      * is called before all other answers will be collected,
846      * and MAX_NS (zone->z_nns) is definitely less than 255 */
847     pkt->p_buf[auth ? p_nscnt2 : p_ancnt2] += zone->z_nns;
848   /* pick up next variation of NS ordering */
849   ++cns;
850   if (cns >= zone->z_nns)
851     cns = 0;
852   ((struct zone *)zone)->z_cns = cns;
853   return 1;
854 }
855 
856 static unsigned
checkrr_present(register unsigned char * c,register unsigned char * e,unsigned dtp,const void * data,unsigned dsz,unsigned ttl)857 checkrr_present(register unsigned char *c, register unsigned char *e,
858                 unsigned dtp, const void *data, unsigned dsz, unsigned ttl) {
859   /* check whenever we already have this (type of) RR in reply,
860    * ensure that all RRs of the same type has the same TTL */
861 
862   const unsigned char dtp1 = dtp >> 8, dtp2 = dtp & 255;
863   unsigned t;
864 
865 #define nextRR(c) ((c) + 12 + (c)[11])
866 #define hasRR(c,e) ((c) < (e))
867 #define sameRRT(c,dtp1,dtp2) ((c)[2] == (dtp1) && (c)[3] == (dtp2))
868 #define sameDATA(c,dsz,data) \
869    ((c)[11] == (dsz) && memcmp((c)+12, (data), (dsz)) == 0)
870 #define rrTTL(c) ((c)+6)
871 
872   for(;;) {
873     if (!hasRR(c,e))
874       return ttl;
875     if (sameRRT(c,dtp1,dtp2))
876       break;
877     c = nextRR(c);
878   }
879 
880   /* found at least one RR with the same type as new */
881 
882   if (ttl >= (t = unpack32(rrTTL(c)))) {
883     /* new ttl is either larger or the same as ttl of one of existing RRs */
884     /* if we already have the same record, do nothing */
885     if (sameDATA(c,dsz,data))
886       return 0;
887     /* check other records too */
888     for(c = nextRR(c); hasRR(c,e); c = nextRR(c))
889       if (sameRRT(c,dtp1,dtp2) && sameDATA(c,dsz,data))
890         /* already has exactly the same data */
891         return 0;
892     return t; /* use existing, smaller TTL for new RR */
893   }
894   else { /* change TTLs of existing RRs to new, smaller one */
895     int same = sameDATA(c,dsz,data);
896     unsigned char *ttlnb = rrTTL(c);
897     PACK32(ttlnb, ttl);
898     for(c = nextRR(c); hasRR(c,e); c = nextRR(c))
899       if (sameRRT(c,dtp1,dtp2)) {
900         memcpy(rrTTL(c), ttlnb, 4);
901         if (sameDATA(c,dsz,data))
902           same = 1;
903       }
904     return same ? 0 : ttl;
905   }
906 #undef nextRR
907 #undef hasRR
908 #undef sameRRT
909 #undef sameDATA
910 #undef rrTTL
911 }
912 
913 /* add a new record into answer, check for dups.
914  * We just ignore any data that exceeds packet size */
addrr_any(struct dnspacket * pkt,unsigned dtp,const void * data,unsigned dsz,unsigned ttl)915 void addrr_any(struct dnspacket *pkt, unsigned dtp,
916                const void *data, unsigned dsz,
917                unsigned ttl) {
918   register unsigned char *c = pkt->p_cur;
919   ttl = checkrr_present(pkt->p_sans, c, dtp, data, dsz, ttl);
920   if (!ttl) return; /* if RR is already present, do nothing */
921 
922   if (!fit(pkt, c, 12 + dsz) || pkt->p_buf[p_ancnt2] == 255) {
923     setnonauth(pkt->p_buf); /* non-auth answer as we can't fit the record */
924     return;
925   }
926   *c++ = 192; *c++ = p_hdrsize;	/* jump after header: query DN */
927   PACK16S(c, dtp);
928   PACK16S(c, DNS_C_IN);
929   PACK32S(c, ttl);
930   PACK16S(c, dsz);
931   memcpy(c, data, dsz);
932   pkt->p_cur = c + dsz;
933   pkt->p_buf[p_ancnt2] += 1; /* increment numanswers */
934 }
935 
936 void
addrr_a_txt(struct dnspacket * pkt,unsigned qtflag,const char * rr,const char * subst,const struct dataset * ds)937 addrr_a_txt(struct dnspacket *pkt, unsigned qtflag,
938             const char *rr, const char *subst,
939             const struct dataset *ds) {
940   if (qtflag & NSQUERY_A)
941     addrr_any(pkt, DNS_T_A, rr, 4, ds->ds_ttl);
942   if (qtflag & NSQUERY_TXT) {
943     char sb[TXTBUFSIZ+1];
944     unsigned sl = txtsubst(sb + 1, rr + 4, subst, ds);
945     if (sl) {
946       sb[0] = sl;
947       addrr_any(pkt, DNS_T_TXT, sb, sl + 1, ds->ds_ttl);
948     }
949   }
950 }
951 
version_req(struct dnspacket * pkt,const struct dnsquery * qry)952 static int version_req(struct dnspacket *pkt, const struct dnsquery *qry) {
953   register unsigned char *c;
954   unsigned dsz;
955 
956   if (!show_version)
957     return 0;
958   if (qry->q_class != DNS_C_CH || qry->q_type != DNS_T_TXT)
959     return 0;
960   if ((qry->q_dnlen != 16 || memcmp(qry->q_dn, "\7version\6server", 16)) &&
961       (qry->q_dnlen != 14 || memcmp(qry->q_dn, "\7version\4bind", 14)))
962     return 0;
963 
964   c = pkt->p_cur;
965   *c++ = 192; *c++ = p_hdrsize; /* jump after header: query DN */
966   *c++ = DNS_T_TXT>>8; *c++ = DNS_T_TXT;
967   *c++ = DNS_C_CH>>8; *c++ = DNS_C_CH;
968   *c++ = 0; *c++ = 0; *c++ = 0; *c++ = 0; /* ttl */
969   dsz = strlen(show_version) + 1;
970   PACK16(c, dsz); c += 2;       /* dsize */
971   *c++ = --dsz;
972   memcpy(c, show_version, dsz);
973   pkt->p_cur = c + dsz;
974   pkt->p_buf[p_ancnt2] += 1; /* increment numanswers */
975   return 1;
976 }
977 
logreply(const struct dnspacket * pkt,FILE * flog,int flushlog)978 void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog) {
979   char cbuf[DNS_MAXDOMAIN + IPSIZE + 50];
980   char *cp = cbuf;
981   const unsigned char *const q = pkt->p_sans - 4;
982 
983   cp += sprintf(cp, "%lu ", (unsigned long)time(NULL));
984 #ifndef NO_IPv6
985   if (getnameinfo(pkt->p_peer, pkt->p_peerlen,
986                   cp, NI_MAXHOST, NULL, 0,
987                   NI_NUMERICHOST) == 0)
988     cp += strlen(cp);
989   else
990     *cp++ = '?';
991 #else
992   strcpy(cp, inet_ntoa(((struct sockaddr_in*)pkt->p_peer)->sin_addr));
993   cp += strlen(cp);
994 #endif
995   *cp++ = ' ';
996   cp += dns_dntop(pkt->p_buf + p_hdrsize, cp, DNS_MAXDOMAIN);
997   cp += sprintf(cp, " %s %s: %s/%u/%d\n",
998       dns_typename(((unsigned)q[0]<<8)|q[1]),
999       dns_classname(((unsigned)q[2]<<8)|q[3]),
1000       dns_rcodename(pkt->p_buf[p_f2] & pf2_rcode),
1001       pkt->p_buf[p_ancnt2], (int)(pkt->p_cur - pkt->p_buf));
1002   if (flushlog)
1003     write(fileno(flog), cbuf, cp - cbuf);
1004   else
1005     fwrite(cbuf, cp - cbuf, 1, flog);
1006 }
1007