1 /* common rbldnsd #include header
2  */
3 
4 #include <stdarg.h>
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include "config.h"
8 #include "ip4addr.h"
9 #include "ip6addr.h"
10 #include "dns.h"
11 #include "mempool.h"
12 
13 #if !defined(__GNUC__) && !defined(__attribute__)
14 # define __attribute__(x)
15 #endif
16 #ifndef PRINTFLIKE
17 # define PRINTFLIKE(fmtp, ap) __attribute__((format(printf,fmtp,ap)))
18 #endif
19 #ifndef UNUSED
20 # define UNUSED __attribute__((unused))
21 #endif
22 #ifndef NORETURN
23 # define NORETURN __attribute__((noreturn))
24 #endif
25 
26 extern char *progname; /* limited to 32 chars */
27 extern int logto;
28 #define LOGTO_STDOUT 0x01
29 #define LOGTO_STDERR 0x02
30 #define LOGTO_SYSLOG 0x04
31 void PRINTFLIKE(2,3) NORETURN error(int errnum, const char *fmt, ...);
32 
33 struct zone;
34 struct dataset;
35 struct dsdata;
36 struct dsctx;
37 struct sockaddr;
38 
39 struct dnspacket {		/* private structure */
40   unsigned char p_buf[DNS_EDNS0_MAXPACKET]; /* packet buffer */
41   unsigned char *p_endp;	/* end of packet buffer */
42   unsigned char *p_cur;		/* current pointer */
43   unsigned char *p_sans;	/* start of answers */
44   const char *p_substrr;	/* for always-listed queries */
45   const struct dataset *p_substds;
46   const struct sockaddr *p_peer;/* address of the requesting client */
47   unsigned p_peerlen;
48 };
49 
50 struct dnsquery {	/* q */
51   unsigned q_type;			/* query RR type */
52   unsigned q_class;			/* query class */
53   unsigned char q_dn[DNS_MAXDN];	/* original query DN, lowercased */
54   unsigned q_dnlen;			/* length of q_dn */
55   unsigned q_dnlab;			/* number of labels in q_dn */
56   unsigned char *q_lptr[DNS_MAXLABELS];	/* pointers to labels */
57 };
58 
59 struct dnsqinfo {	/* qi */
60   unsigned char *const *qi_dnlptr;
61   const unsigned char *qi_dn;		/* cached query DN */
62   unsigned qi_tflag;			/* query RR type flag (NSQUERY_XX) */
63   unsigned qi_dnlen0;			/* length of qi_dn - 1 */
64   unsigned qi_dnlab;			/* number of labels in q_dn */
65   int qi_ip4valid;			/* true if qi_ip4 is valid */
66   int qi_ip6valid;			/* true if qi_ip6 is valid */
67   ip4addr_t qi_ip4;			/* parsed IP4 address */
68   ip6oct_t qi_ip6[IP6ADDR_FULL];	/* parsed IP6 address */
69 };
70 
71 #define PACK32(b,n) ((b)[0]=(n)>>24,(b)[1]=(n)>>16,(b)[2]=(n)>>8,(b)[3]=(n))
72 #define PACK32S(b,n) (*b++=(n)>>24,*b++=(n)>>16,*b++=(n)>>8,*b++=n)
73 #define PACK16(b,n) ((b)[0]=(n)>>8,(b)[1]=(unsigned char)(n))
74 #define PACK16S(b,n) (*b++=(n)>>8,*b++=(unsigned char)(n))
75 
76 unsigned unpack32(const unsigned char nb[4]);
77 
78 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
79 #define ISCOMMENT(c) ((c) == '#' || (c) == ';')
80 #define SKIPSPACE(s) while(ISSPACE(*s)) ++s
81 
82 char *parse_uint32(char *s, unsigned *np);
83 char *parse_uint32_nb(char *s, unsigned char nb[4]);
84 char *parse_time(char *s, unsigned *tp);
85 char *parse_time_nb(char *s, unsigned char nb[4]);
86 char *parse_ttl(char *s, unsigned *ttlp, unsigned defttl);
87 char *parse_timestamp(char *s, time_t *tsp);
88 char *parse_dn(char *s, unsigned char *dn, unsigned *dnlenp);
89 /* parse line in form :ip:text into rr
90  * where first 4 bytes is ip in network byte order.
91  * Note this routine uses 4 bytes BEFORE str (it's safe to call it after
92  * readdslines() */
93 int parse_a_txt(char *str, const char **rrp, const char *def_rr,
94                 struct dsctx *dsc);
95 char *firstword_lc(char *line, const char *word_lc);
96 
97 typedef void ds_startfn_t(struct dataset *ds);
98 typedef int ds_linefn_t(struct dataset *ds, char *line, struct dsctx *dsc);
99 typedef void ds_finishfn_t(struct dataset *ds, struct dsctx *dsc);
100 typedef void ds_resetfn_t(struct dsdata *dsd, int freeall);
101 typedef int
102 ds_queryfn_t(const struct dataset *ds, const struct dnsqinfo *qi,
103              struct dnspacket *pkt);
104 #ifdef NO_MASTER_DUMP
105 typedef void ds_dumpfn_t(void);
106 #define _master_dump_body(n) static void n(void) {}
107 #else
108 typedef void
109 ds_dumpfn_t(const struct dataset *ds, const unsigned char *odn, FILE *f);
110 #define _master_dump_body(n)
111 #endif
112 
113 #define NSQUERY_OTHER	0
114 #define NSQUERY_SOA	(1u<<0)
115 #define NSQUERY_NS	(1u<<1)
116 #define NSQUERY_A	(1u<<2)
117 #define NSQUERY_MX	(1u<<3)
118 #define NSQUERY_TXT	(1u<<4)
119 #define NSQUERY_ANY	0xffffu
120 
121 /* special cases for ACLs */
122 #define NSQUERY_IGNORE	0x010000u
123 #define NSQUERY_REFUSE	0x020000u
124 #define NSQUERY_EMPTY	0x040000u
125 #define NSQUERY_ALWAYS	0x080000u
126 
127 /* result flags from dataset queryfn */
128 #define NSQUERY_FOUND	0x01
129 #define NSQUERY_ADDPEER	0x02
130 
131 struct dstype {	/* dst */
132   const char *dst_name;		/* name of the type */
133   unsigned dst_flags;		/* how to pass arguments to queryfn */
134   unsigned dst_size;		/* size of struct dataset */
135   ds_resetfn_t *dst_resetfn;	/* routine to release ds internal data */
136   ds_startfn_t *dst_startfn;	/* routine called at start of every file */
137   ds_linefn_t *dst_linefn;	/* routine to parse input line */
138   ds_finishfn_t *dst_finishfn;	/* finish loading */
139   ds_queryfn_t *dst_queryfn;	/* routine to perform query */
140   ds_dumpfn_t *dst_dumpfn;	/* dump zone in BIND format */
141   const char *dst_descr;    	/* short description of a ds type */
142 };
143 
144 /* dst_flags */
145 #define DSTF_IP4REV	0x01	/* ip4 set */
146 #define DSTF_IP6REV	0x02	/* ip6 set */
147 #define DSTF_SPECIAL	0x08	/* special ds: non-recursive */
148 
149 #define declaredstype(t) extern const struct dstype dataset_##t##_type
150 #define definedstype(t, flags, descr) \
151  static ds_resetfn_t ds_##t##_reset; \
152  static ds_startfn_t ds_##t##_start; \
153  static ds_linefn_t ds_##t##_line; \
154  static ds_finishfn_t ds_##t##_finish; \
155  static ds_queryfn_t ds_##t##_query; \
156  static ds_dumpfn_t ds_##t##_dump; \
157  _master_dump_body(ds_##t##_dump) \
158  const struct dstype dataset_##t##_type = { \
159    #t /* name */, flags, sizeof(struct dsdata), \
160    ds_##t##_reset, ds_##t##_start, ds_##t##_line, ds_##t##_finish, \
161    ds_##t##_query, ds_##t##_dump, \
162    descr }
163 
164 declaredstype(ip4set);
165 declaredstype(ip4tset);
166 declaredstype(ip4trie);
167 declaredstype(ip6tset);
168 declaredstype(ip6trie);
169 declaredstype(dnset);
170 declaredstype(dnhash);
171 declaredstype(generic);
172 declaredstype(combined);
173 declaredstype(acl);
174 
175 #define dstype(type) (&dataset_##type##_type)
176 #define isdstype(dst, type)	((dst) == dstype(type))
177 
178 extern const struct dstype *ds_types[];
179 
180 /*
181  * Each zone is composed of a set of datasets.
182  * There is a global list of datasets, each
183  * with a timestamp etc.
184  * Each zonedata is composed of a list of files.
185  */
186 
187 struct dsfile {	/* dsf */
188   time_t dsf_stamp;		/* last timestamp of this file */
189   off_t  dsf_size;		/* last size of this file */
190   struct dsfile *dsf_next;	/* next file in list */
191   const char *dsf_name;		/* name of this file */
192 };
193 
194 struct dssoa { /* dssoa */
195   unsigned dssoa_ttl;			/* TTL value */
196   const unsigned char *dssoa_odn;	/* origin DN */
197   const unsigned char *dssoa_pdn;	/* person DN */
198   unsigned dssoa_serial;		/* SOA serial # */
199   unsigned char dssoa_n[16];		/* refresh, retry, expire, minttl */
200 };
201 
202 struct dsns { /* dsns, nameserver */
203   struct dsns *dsns_next;		/* next nameserver in list */
204   unsigned char dsns_dn[1];		/* nameserver DN, varlen */
205 };
206 
207 struct dataset {	/* ds */
208   const struct dstype *ds_type;	/* type of this data */
209   struct dsdata *ds_dsd;		/* type-specific data */
210   time_t ds_stamp;			/* timestamp */
211   time_t ds_expires;			/* when the dataset expires if any */
212   const char *ds_spec;			/* original specification */
213   struct dsfile *ds_dsf;		/* list of files for this data */
214   struct dssoa *ds_dssoa;		/* SOA record */
215   struct dsns *ds_dsns;			/* list of nameservers */
216   unsigned ds_nsttl;			/* TTL for NS records */
217 #ifndef INCOMPAT_0_99
218   int ds_nsflags;
219 #define DSF_NEWNS  0x01			/* new-style NS on one line */
220 #define DSF_NSWARN 0x02			/* warned about new-style NS */
221 #endif
222   unsigned ds_ttl;			/* default ttl for a dataset */
223   char *ds_subst[11];			/* substitution variables */
224 #define SUBST_BASE_TEMPLATE	10
225   struct mempool *ds_mp;		/* memory pool for data */
226   struct dataset *ds_next;		/* next in global list */
227 };
228 
229 struct dslist {	/* dsl */
230   struct dataset *dsl_ds;
231   ds_queryfn_t *dsl_queryfn;	/* cached dsl_ds->ds_type->dst_queryfn */
232   struct dslist *dsl_next;
233 };
234 
235 struct zonesoa;
236 struct zonens;
237 
238 #ifndef NO_STATS
239 #if !defined(NO_STDINT_H)
240 typedef uint64_t dnscnt_t;
241 #define PRI_DNSCNT PRIu64
242 #elif SIZEOF_LONG < 8 && defined(SIZEOF_LONG_LONG)
243 typedef unsigned long long dnscnt_t;
244 #define PRI_DNSCNT "llu"
245 #else
246 typedef unsigned long dnscnt_t;
247 #define PRI_DNSCNT "lu"
248 #endif
249 struct dnsstats {
250   dnscnt_t b_in, b_out;		/* number of bytes: in, out */
251   dnscnt_t q_ok, q_nxd, q_err;	/* number of requests: OK, NXDOMAIN, ERROR */
252 };
253 extern struct dnsstats gstats;	/* global statistics counters */
254 #endif /* NO_STATS */
255 
256 #define MAX_NS 32
257 
258 struct zone {	/* zone, list of zones */
259   unsigned z_stamp;			/* timestamp, 0 if not loaded */
260   time_t z_expires;			/* when the zone expires if any */
261   unsigned char z_dn[DNS_MAXDN+1];	/* zone domain name */
262   unsigned z_dnlen;			/* length of z_dn */
263   unsigned z_dnlab;			/* number of dn labels */
264   unsigned z_dstflags;			/* flags of all datasets */
265   struct dslist *z_dsl;			/* list of datasets */
266   struct dslist **z_dslp;		/* last z_dsl in list */
267   struct dataset *z_dsacl;		/* zone ACL */
268   /* SOA record */
269   const struct dssoa *z_dssoa;		/* original SOA from a dataset */
270   struct zonesoa *z_zsoa;		/* pre-packed SOA record */
271   const unsigned char *z_nsdna[MAX_NS];	/* array of nameserver DNs */
272   unsigned z_nns;			/* number of NSes in z_dsnsa[] */
273   unsigned z_nsttl;			/* ttl for NS records */
274   unsigned z_cns;			/* current NS in rotation */
275   unsigned z_nglue;			/* number of glue records */
276   struct zonens *z_zns;			/* pre-packed NS records */
277 #ifndef NO_STATS
278   struct dnsstats z_stats;		/* statistic counters */
279   struct dnsstats z_pstats;		/* for stats monitoring: prev values */
280 #endif
281 #ifndef NO_DSO
282   void *z_hookdata;			/* data ptr for hooks */
283 #endif
284   struct zone *z_next;			/* next in list */
285 };
286 
287 void init_zones_caches(struct zone *zonelist);
288 int update_zone_soa(struct zone *zone, const struct dssoa *dssoa);
289 int update_zone_ns(struct zone *zone, const struct dsns *dsns, unsigned ttl,
290                    const struct zone *zonelist);
291 
292 /* parse query and construct a reply to it, return len of answer or 0 */
293 int replypacket(struct dnspacket *p, unsigned qlen, struct zone *zone);
294 const struct zone *
295 findqzone(const struct zone *zonelist,
296           unsigned dnlen, unsigned dnlab, unsigned char *const *const dnlptr,
297           struct dnsqinfo *qi);
298 
299 /* log a reply */
300 void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog);
301 
302 /* details of DNS packet structure are in rbldnsd_packet.c */
303 
304 /* add a record into answer section */
305 void addrr_a_txt(struct dnspacket *pkt, unsigned qtflag,
306                  const char *rr, const char *subst,
307                  const struct dataset *ds);
308 void addrr_any(struct dnspacket *pkt, unsigned dtp,
309                const void *data, unsigned dsz, unsigned ttl);
310 
311 #define check_query_overwrites(qi) \
312   if ((qi)->qi_tflag & NSQUERY_EMPTY)  return 0; \
313   if ((qi)->qi_tflag & NSQUERY_ALWAYS) return NSQUERY_ADDPEER
314 
315 int ds_acl_query(const struct dataset *ds, struct dnspacket *pkt);
316 
317 #ifndef NO_MASTER_DUMP
318 void dump_a_txt(const char *name, const char *rr,
319                 const char *subst, const struct dataset *ds, FILE *f);
320 void dump_ip4range(ip4addr_t a, ip4addr_t b, const char *rr,
321 		   const struct dataset *ds, FILE *f);
322 void dump_ip4(ip4addr_t a, const char *rr, const struct dataset *ds, FILE *f);
323 void dumpzone(const struct zone *z, FILE *f);
324 void dump_ip6(const ip6oct_t *addr, unsigned wild_nibbles, const char *rr,
325               const struct dataset *ds, FILE *f);
326 void dump_ip6range(const ip6oct_t *beg, const ip6oct_t *end, const char *rr,
327                    const struct dataset *ds, FILE *f);
328 #endif
329 #define TXTBUFSIZ 260
330 int txtsubst(char txtbuf[TXTBUFSIZ], const char *template,
331 	     const char *sub0, const struct dataset *ds);
332 
333 struct zone *addzone(struct zone *zonelist, const char *spec);
334 void connectdataset(struct zone *zone,
335                     struct dataset *ds,
336                     struct dslist *dsl);
337 struct zone *newzone(struct zone **zonelist,
338                      unsigned char *dn, unsigned dnlen,
339                      struct mempool *mp);
340 struct dataset *nextdataset2reload(struct dataset *ds);
341 int loaddataset(struct dataset *ds);
342 
343 struct dsctx {
344   struct dataset *dsc_ds;	/* currently loading dataset */
345   struct dataset *dsc_subset;	/* currently loading subset (combined) */
346   const char *dsc_fname;	/* currently loading file name */
347   int dsc_lineno;		/* current line number */
348   int dsc_warns;		/* number of warnings so far */
349   unsigned dsc_ip4maxrange;	/* max IP4 range allowed */
350 };
351 
352 void PRINTFLIKE(3,4) dslog(int level, struct dsctx *dsc, const char *fmt, ...);
353 void PRINTFLIKE(2,3) dswarn(struct dsctx *dsc, const char *fmt, ...);
354 void PRINTFLIKE(2,3) dsloaded(struct dsctx *dsc, const char *fmt, ...);
355 void PRINTFLIKE(3,4)
356 zlog(int level, const struct zone *zone, const char *fmt, ...);
357 
358 /* from rbldnsd_combined.c, special routine used inside ds_special() */
359 int ds_combined_newset(struct dataset *ds, char *line, struct dsctx *dsc);
360 
361 extern unsigned def_ttl, min_ttl, max_ttl;
362 extern const char def_rr[5];
363 extern int accept_in_cidr;
364 extern int nouncompress;
365 extern struct dataset *g_dsacl;	/* global acl */
366 
367 extern const char *show_version; /* version.bind CH TXT */
368 
369 void oom(void);
370 char *emalloc(unsigned size);
371 char *ezalloc(unsigned size); /* zero-fill */
372 char *erealloc(void *ptr, unsigned size);
373 char *estrdup(const char *str);
374 char *ememdup(const void *buf, unsigned size);
375 
376 #define tmalloc(type) ((type*)emalloc(sizeof(type)))
377 #define tzalloc(type) ((type*)ezalloc(sizeof(type)))
378 #define trealloc(type,ptr,n) ((type*)erealloc((ptr),(n)*(sizeof(type))))
379 
380 int vssprintf(char *buf, int bufsz, const char *fmt, va_list ap);
381 int PRINTFLIKE(3, 4) ssprintf(char *buf, int bufsz, const char *fmt, ...);
382 
383 /* a helper to shrink an array */
384 /* some malloc implementations may return NULL on realloc()
385  * even if newsize is smaller than current size, so deal with
386  * this here.  Note that if realloc() fails, we're under memory
387  * pressure here, so next reload will probably hit ENOMEM anyway...
388  */
389 #define SHRINK_ARRAY(type, arr, needed, allocated)	\
390   if ((allocated) > (needed)) {				\
391      type *_temp = trealloc(type, (arr), (needed));	\
392      if (_temp) {					\
393        (arr) = _temp; (allocated) = (needed);		\
394      }							\
395   }
396 
397 /* a helper macro to remove dups from a sorted array */
398 
399 #define REMOVE_DUPS(type, arr, num, eq)	\
400 { register type *_p, *_e, *_t;		\
401   _p = arr; _t = _p + num - 1;		\
402   while(_p < _t)			\
403     if (!(eq((_p[0]), (_p[1])))) ++_p;	\
404     else {				\
405       ++_t; _e = _p + 1;		\
406       do				\
407         if (eq((*_p), (*_e))) ++_e;	\
408         else *++_p = *_e++;		\
409       while (_e < _t);			\
410       num = _p + 1 - arr;		\
411       break;				\
412     }					\
413 }
414 
415 /* helper macro to test whenever two given RRs (A and TXT) are equal,
416  * provided that arr is zero, this is an exclusion entry.
417  *  if arr is zero, we're treating them equal.
418  *   else compare pointers
419  *   else memcmp first 4 (A) bytes and strcmp rest (TXT)
420  */
421 #define rrs_equal(a, b) \
422   (!(a).rr \
423    || (a).rr == (b).rr \
424    || (memcmp((a).rr, (b).rr, 4) == 0 \
425        && strcmp((a).rr + 4, (b).rr + 4) == 0 \
426       ) \
427   )
428 
429 /* hooks from a DSO extensions */
430 #ifndef NO_DSO
431 
432 /* prototype for init routine */
433 int rbldnsd_extension_init(char *arg, struct zone *zonelist);
434 
435 /* return true/false depending whenever hook needs to be reloaded */
436 extern int (*hook_reload_check)(const struct zone *zonelist);
437 
438 /* perform actual reload, after all zones has been reloaded. */
439 extern int (*hook_reload)(struct zone *zonelist);
440 
441 /* check whenever this query is allowed for this client:
442  *  * 0 = ok, <0 = drop the packet, >0 = refuse */
443 extern int (*hook_query_access)
444   (const struct sockaddr *requestor,
445    const struct zone *zone,
446    const struct dnsqinfo *qinfo);
447 
448 /* notice result of the OK query */
449 extern int (*hook_query_result)
450   (const struct sockaddr *requestor,
451    const struct zone *zone,
452    const struct dnsqinfo *qinfo,
453    int positive);
454 
455 #define call_hook(name, args)	\
456 	(hook_##name ? hook_##name args : 0)
457 
458 #else	/* dummy "functions" */
459 
460 #define call_hook(name, args) 0
461 
462 #endif
463