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