23 #define TTL_POSITIVE 86400
24 #define TTL_NEGATIVE 2560
26 #define FATAL "tinydns-data: fatal: "
28 void die_datatmp(void)
30 strerr_die2sys(111,FATAL
,"unable to create data.tmp: ");
34 strerr_die1sys(111,FATAL
);
37 void ttdparse(stralloc
*sa
,char ttd
[8])
43 for (i
= 0;(i
< 16) && (i
< sa
->len
);++i
) {
45 if ((ch
>= '0') && (ch
<= '9'))
47 else if ((ch
>= 'a') && (ch
<= 'f'))
51 if (!(i
& 1)) ch
<<= 4;
56 void locparse(stralloc
*sa
,char loc
[2])
58 loc
[0] = (sa
->len
> 0) ? sa
->s
[0] : 0;
59 loc
[1] = (sa
->len
> 1) ? sa
->s
[1] : 0;
62 void ipprefix_cat(stralloc
*out
,char *s
)
76 if (!stralloc_catb(out
,&ch
,1)) nomem();
80 void txtparse(stralloc
*sa
)
91 if (i
>= sa
->len
) break;
93 if ((ch
>= '0') && (ch
<= '7')) {
95 if ((i
< sa
->len
) && (sa
->s
[i
] >= '0') && (sa
->s
[i
] <= '7')) {
97 ch
+= sa
->s
[i
++] - '0';
98 if ((i
< sa
->len
) && (sa
->s
[i
] >= '0') && (sa
->s
[i
] <= '7')) {
100 ch
+= sa
->s
[i
++] - '0';
112 void defaultsoa_init(int fd
)
115 if (fstat(fd
,&st
) == -1)
116 strerr_die2sys(111,FATAL
,"unable to stat data: ");
117 uint32_pack_big(defaultsoa
,st
.st_mtime
);
118 if (byte_equal(defaultsoa
,4,"\0\0\0\0"))
120 byte_copy(defaultsoa
+ 4,16,"\0\0\100\000\0\0\010\000\0\020\000\000\0\0\012\000");
126 static stralloc result
;
128 void rr_add(const char *buf
,unsigned int len
)
130 if (!stralloc_catb(&result
,buf
,len
)) nomem();
132 void rr_addname(const char *d
)
134 rr_add(d
,dns_domain_length(d
));
136 void rr_start(const char type
[2],unsigned long ttl
,const char ttd
[8],const char loc
[2])
139 if (!stralloc_copyb(&result
,type
,2)) nomem();
140 if (byte_equal(loc
,2,"\0\0"))
146 uint32_pack_big(buf
,ttl
);
150 void rr_finish(const char *owner
)
152 if (byte_equal(owner
,2,"\1*")) {
156 if (!stralloc_copyb(&key
,owner
,dns_domain_length(owner
))) nomem();
157 case_lowerb(key
.s
,key
.len
);
158 if (cdb_make_add(&cdb
,key
.s
,key
.len
,result
.s
,result
.len
) == -1)
165 static stralloc line
;
167 unsigned long linenum
= 0;
170 static stralloc f
[NUMFIELDS
];
174 char dptr
[DNS_NAME4_DOMAIN
];
176 char strnum
[FMT_ULONG
];
178 void syntaxerror(const char *why
)
180 strnum
[fmt_ulong(strnum
,linenum
)] = 0;
181 strerr_die4x(111,FATAL
,"unable to parse data line ",strnum
,why
);
202 fddata
= open_read("data");
204 strerr_die2sys(111,FATAL
,"unable to open data: ");
205 defaultsoa_init(fddata
);
207 buffer_init(&b
,buffer_unixread
,fddata
,bspace
,sizeof bspace
);
209 fdcdb
= open_trunc("data.tmp");
210 if (fdcdb
== -1) die_datatmp();
211 if (cdb_make_start(&cdb
,fdcdb
) == -1) die_datatmp();
215 if (getln(&b
,&line
,&match
,'\n') == -1)
216 strerr_die2sys(111,FATAL
,"unable to read line: ");
219 ch
= line
.s
[line
.len
- 1];
220 if ((ch
!= ' ') && (ch
!= '\t') && (ch
!= '\n')) break;
223 if (!line
.len
) continue;
224 if (line
.s
[0] == '#') continue;
225 if (line
.s
[0] == '-') continue;
228 for (i
= 0;i
< NUMFIELDS
;++i
) {
230 if (!stralloc_copys(&f
[i
],"")) nomem();
233 k
= byte_chr(line
.s
+ j
,line
.len
- j
,':');
234 if (!stralloc_copyb(&f
[i
],line
.s
+ j
,k
)) nomem();
243 if (!stralloc_copyb(&key
,"\0%",2)) nomem();
244 if (!stralloc_0(&f
[1])) nomem();
245 ipprefix_cat(&key
,f
[1].s
);
246 if (cdb_make_add(&cdb
,key
.s
,key
.len
,loc
,2) == -1)
251 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
253 if (!stralloc_0(&f
[3])) nomem();
254 if (!scan_ulong(f
[3].s
,&u
)) uint32_unpack_big(defaultsoa
,&u
);
255 uint32_pack_big(soa
,u
);
256 if (!stralloc_0(&f
[4])) nomem();
257 if (!scan_ulong(f
[4].s
,&u
)) uint32_unpack_big(defaultsoa
+ 4,&u
);
258 uint32_pack_big(soa
+ 4,u
);
259 if (!stralloc_0(&f
[5])) nomem();
260 if (!scan_ulong(f
[5].s
,&u
)) uint32_unpack_big(defaultsoa
+ 8,&u
);
261 uint32_pack_big(soa
+ 8,u
);
262 if (!stralloc_0(&f
[6])) nomem();
263 if (!scan_ulong(f
[6].s
,&u
)) uint32_unpack_big(defaultsoa
+ 12,&u
);
264 uint32_pack_big(soa
+ 12,u
);
265 if (!stralloc_0(&f
[7])) nomem();
266 if (!scan_ulong(f
[7].s
,&u
)) uint32_unpack_big(defaultsoa
+ 16,&u
);
267 uint32_pack_big(soa
+ 16,u
);
269 if (!stralloc_0(&f
[8])) nomem();
270 if (!scan_ulong(f
[8].s
,&ttl
)) ttl
= TTL_NEGATIVE
;
272 locparse(&f
[10],loc
);
274 rr_start(DNS_T_SOA
,ttl
,ttd
,loc
);
275 if (!dns_domain_fromdot(&d2
,f
[1].s
,f
[1].len
)) nomem();
277 if (!dns_domain_fromdot(&d2
,f
[2].s
,f
[2].len
)) nomem();
284 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
285 if (!stralloc_0(&f
[3])) nomem();
286 if (!scan_ulong(f
[3].s
,&ttl
)) ttl
= TTL_NS
;
290 if (!stralloc_0(&f
[1])) nomem();
292 if (byte_chr(f
[2].s
,f
[2].len
,'.') >= f
[2].len
) {
293 if (!stralloc_cats(&f
[2],".ns.")) nomem();
294 if (!stralloc_catb(&f
[2],f
[0].s
,f
[0].len
)) nomem();
296 if (!dns_domain_fromdot(&d2
,f
[2].s
,f
[2].len
)) nomem();
298 if (line
.s
[0] == '.') {
299 rr_start(DNS_T_SOA
,ttl
? TTL_NEGATIVE
: 0,ttd
,loc
);
301 rr_add("\12hostmaster",11);
303 rr_add(defaultsoa
,20);
307 rr_start(DNS_T_NS
,ttl
,ttd
,loc
);
311 if (ip4_scan(f
[1].s
,ip
)) {
312 rr_start(DNS_T_A
,ttl
,ttd
,loc
);
320 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
321 if (!stralloc_0(&f
[2])) nomem();
322 if (!scan_ulong(f
[2].s
,&ttl
)) ttl
= TTL_POSITIVE
;
326 if (!stralloc_0(&f
[1])) nomem();
328 if (ip4_scan(f
[1].s
,ip
)) {
329 rr_start(DNS_T_A
,ttl
,ttd
,loc
);
333 if (line
.s
[0] == '=') {
334 dns_name4_domain(dptr
,ip
);
335 rr_start(DNS_T_PTR
,ttl
,ttd
,loc
);
343 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
344 if (!stralloc_0(&f
[4])) nomem();
345 if (!scan_ulong(f
[4].s
,&ttl
)) ttl
= TTL_POSITIVE
;
349 if (!stralloc_0(&f
[1])) nomem();
351 if (byte_chr(f
[2].s
,f
[2].len
,'.') >= f
[2].len
) {
352 if (!stralloc_cats(&f
[2],".mx.")) nomem();
353 if (!stralloc_catb(&f
[2],f
[0].s
,f
[0].len
)) nomem();
355 if (!dns_domain_fromdot(&d2
,f
[2].s
,f
[2].len
)) nomem();
357 if (!stralloc_0(&f
[3])) nomem();
358 if (!scan_ulong(f
[3].s
,&u
)) u
= 0;
360 rr_start(DNS_T_MX
,ttl
,ttd
,loc
);
361 uint16_pack_big(buf
,u
);
366 if (ip4_scan(f
[1].s
,ip
)) {
367 rr_start(DNS_T_A
,ttl
,ttd
,loc
);
374 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
375 if (!dns_domain_fromdot(&d2
,f
[1].s
,f
[1].len
)) nomem();
376 if (!stralloc_0(&f
[2])) nomem();
377 if (!scan_ulong(f
[2].s
,&ttl
)) ttl
= TTL_POSITIVE
;
381 if (line
.s
[0] == 'C')
382 rr_start(DNS_T_CNAME
,ttl
,ttd
,loc
);
384 rr_start(DNS_T_PTR
,ttl
,ttd
,loc
);
390 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
391 if (!stralloc_0(&f
[2])) nomem();
392 if (!scan_ulong(f
[2].s
,&ttl
)) ttl
= TTL_POSITIVE
;
396 rr_start(DNS_T_TXT
,ttl
,ttd
,loc
);
400 while (i
< f
[1].len
) {
402 if (k
> 127) k
= 127;
405 rr_add(f
[1].s
+ i
,k
);
413 if (!dns_domain_fromdot(&d1
,f
[0].s
,f
[0].len
)) nomem();
414 if (!stralloc_0(&f
[3])) nomem();
415 if (!scan_ulong(f
[3].s
,&ttl
)) ttl
= TTL_POSITIVE
;
419 if (!stralloc_0(&f
[1])) nomem();
420 scan_ulong(f
[1].s
,&u
);
421 uint16_pack_big(type
,u
);
422 if (byte_equal(type
,2,DNS_T_AXFR
))
423 syntaxerror(": type AXFR prohibited");
424 if (byte_equal(type
,2,"\0\0"))
425 syntaxerror(": type 0 prohibited");
426 if (byte_equal(type
,2,DNS_T_SOA
))
427 syntaxerror(": type SOA prohibited");
428 if (byte_equal(type
,2,DNS_T_NS
))
429 syntaxerror(": type NS prohibited");
430 if (byte_equal(type
,2,DNS_T_CNAME
))
431 syntaxerror(": type CNAME prohibited");
432 if (byte_equal(type
,2,DNS_T_PTR
))
433 syntaxerror(": type PTR prohibited");
434 if (byte_equal(type
,2,DNS_T_MX
))
435 syntaxerror(": type MX prohibited");
439 rr_start(type
,ttl
,ttd
,loc
);
440 rr_add(f
[2].s
,f
[2].len
);
445 syntaxerror(": unrecognized leading character");
449 if (cdb_make_finish(&cdb
) == -1) die_datatmp();
450 if (fsync(fdcdb
) == -1) die_datatmp();
451 if (close(fdcdb
) == -1) die_datatmp(); /* NFS stupidity */
452 if (rename("data.tmp","data.cdb") == -1)
453 strerr_die2sys(111,FATAL
,"unable to move data.tmp to data.cdb: ");