aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-01-14 14:49:25 +0200
committerTimo Teräs <timo.teras@iki.fi>2013-01-14 14:49:25 +0200
commit7a030c45b097b136f520d36c567f76010bf96d04 (patch)
treec282196773d537d48b7891cc882cbbbe859da4ff
parent977010472670883c12788e8a3ddb490884939c67 (diff)
downloadalpine_aports-7a030c45b097b136f520d36c567f76010bf96d04.tar.bz2
alpine_aports-7a030c45b097b136f520d36c567f76010bf96d04.tar.xz
alpine_aports-7a030c45b097b136f520d36c567f76010bf96d04.zip
main/gdnsd: upgrade to 1.6.9 and fixes
cherry-picked commits: 1952e27 upgrade to 1.6.5 and update init.d 939241b upgrade to 1.6.7 0425fea cherry pick some improvements from bug tracker b7a63d5 add preliminary support for djbdns config files 1c5eeb6 build fix (regenerate autotools) 6705665 add a fix for startup race 5932040 upgrade to 1.6.8 db3867d refresh autodc patch 75e96f2 build fix for automake-1.13 aa04d0a upgrade to 1.6.9
-rw-r--r--main/gdnsd/0001-preliminary-djbdns-support.patch576
-rw-r--r--main/gdnsd/APKBUILD32
-rwxr-xr-xmain/gdnsd/gdnsd.initd38
-rw-r--r--main/gdnsd/geoip-speedup.patch101
4 files changed, 731 insertions, 16 deletions
diff --git a/main/gdnsd/0001-preliminary-djbdns-support.patch b/main/gdnsd/0001-preliminary-djbdns-support.patch
new file mode 100644
index 0000000000..2384368571
--- /dev/null
+++ b/main/gdnsd/0001-preliminary-djbdns-support.patch
@@ -0,0 +1,576 @@
1From d72aa39cb88178792c1e058b0b757b7cd9466e82 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Tue, 8 May 2012 16:57:06 +0300
4Subject: [PATCH] preliminary djbdns support
5
6---
7 docs/TODO | 2 +-
8 gdnsd/Makefile.am | 2 +-
9 gdnsd/conf.c | 6 +-
10 gdnsd/conf.h | 1 +
11 gdnsd/ltree.c | 10 +-
12 gdnsd/zscan-djb.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++++
13 gdnsd/zscan.h | 3 +
14 7 files changed, 460 insertions(+), 6 deletions(-)
15 create mode 100644 gdnsd/zscan-djb.c
16
17diff --git a/docs/TODO b/docs/TODO
18index 2f84a9f..2a7fd9c 100644
19--- a/docs/TODO
20+++ b/docs/TODO
21@@ -58,7 +58,7 @@ Realistically, AXFR is pretty far down the priority list. I think a higher-prio
22
23 Other zonefile formats:
24 -------------------------
25-Load other zonefile (or zone data in general) formats? The BIND syntax sucks, but I'm keeping it as the default, it's too widespread not to. However, the zonefile scanner is mostly cleanly separated from the rest of the code, and it wouldn't be that hard to add support for more formats (djbdns? a SQL connection? in both cases, they could periodically update using the same switching mechanism as stat() watcher above...).
26+Load other zonefile (or zone data in general) formats? The BIND syntax sucks, but I'm keeping it as the default, it's too widespread not to. However, the zonefile scanner is mostly cleanly separated from the rest of the code, and it wouldn't be that hard to add support for more formats (a SQL connection? in both cases, they could periodically update using the same switching mechanism as stat() watcher above...).
27
28 Stuff from conversations w/ Paul Dekkers: --------
29
30diff --git a/gdnsd/Makefile.am b/gdnsd/Makefile.am
31index feaed57..266b344 100644
32--- a/gdnsd/Makefile.am
33+++ b/gdnsd/Makefile.am
34@@ -12,7 +12,7 @@ AM_CPPFLAGS = -I$(srcdir)/libgdnsd -I$(builddir)/libgdnsd -DVARDIR=\"$(localstat
35
36 # How to build gdnsd
37 sbin_PROGRAMS = gdnsd
38-gdnsd_SOURCES = main.c conf.c $(ZSCAN_C) ltarena.c ltree.c dnspacket.c dnsio_udp.c dnsio_tcp.c statio.c monio.c conf.h dnsio_tcp.h dnsio_udp.h dnspacket.h dnswire.h ltarena.h ltree.h statio.h monio.h zscan.h pkterr.h gdnsd.h
39+gdnsd_SOURCES = main.c conf.c $(ZSCAN_C) ltarena.c ltree.c zscan-djb.c dnspacket.c dnsio_udp.c dnsio_tcp.c statio.c monio.c conf.h dnsio_tcp.h dnsio_udp.h dnspacket.h dnswire.h ltarena.h ltree.h statio.h monio.h zscan.h pkterr.h gdnsd.h
40 gdnsd_LDADD = libgdnsd/libgdnsd.la $(CAPLIBS)
41
42 zscan.c: zscan.rl
43diff --git a/gdnsd/conf.c b/gdnsd/conf.c
44index b79cbb2..a3357d4 100644
45--- a/gdnsd/conf.c
46+++ b/gdnsd/conf.c
47@@ -55,6 +55,7 @@ global_config_t gconfig = {
48 .pidfile = def_pidfile,
49 .username = def_username,
50 .chroot_path = def_chroot_path,
51+ .djbdns_path = NULL,
52 .include_optional_ns = false,
53 .realtime_stats = false,
54 .lock_mem = false,
55@@ -577,7 +578,7 @@ void conf_load(const char* cfg_file) {
56
57 const vscf_data_t* options = vscf_hash_get_data_byconstkey(cfg_root, "options", true);
58
59- const char* zdopt = NULL;
60+ const char* zdopt = NULL, * djbopt = NULL;
61 char* zones_dir = NULL;
62 const vscf_data_t* listen_opt = NULL;
63 const vscf_data_t* http_listen_opt = NULL;
64@@ -628,6 +629,7 @@ void conf_load(const char* cfg_file) {
65 CFG_OPT_STR(options, pidfile);
66 CFG_OPT_STR(options, username);
67 CFG_OPT_STR(options, chroot_path);
68+ CFG_OPT_STR_NOCOPY(options, djbdns_path, djbopt);
69 CFG_OPT_STR_NOCOPY(options, zones_dir, zdopt);
70 listen_opt = vscf_hash_get_data_byconstkey(options, "listen", true);
71 http_listen_opt = vscf_hash_get_data_byconstkey(options, "http_listen", true);
72@@ -637,6 +639,8 @@ void conf_load(const char* cfg_file) {
73
74 // Potentially a subdirectory of cfg_dir
75 zones_dir = make_zones_dir(gdnsd_get_cfdir(), zdopt);
76+ if (djbopt)
77+ gconfig.djbdns_path = make_zones_dir(gdnsd_get_cfdir(), djbopt);
78
79 // Set up the http listener data
80 process_http_listen(http_listen_opt, def_http_port);
81diff --git a/gdnsd/conf.h b/gdnsd/conf.h
82index 07a39d4..4374aa6 100644
83--- a/gdnsd/conf.h
84+++ b/gdnsd/conf.h
85@@ -48,6 +48,7 @@ typedef struct {
86 const char* pidfile;
87 const char* username;
88 const char* chroot_path;
89+ const char* djbdns_path;
90 bool include_optional_ns;
91 bool realtime_stats;
92 bool lock_mem;
93diff --git a/gdnsd/ltree.c b/gdnsd/ltree.c
94index 8d3debf..ef5d46c 100644
95--- a/gdnsd/ltree.c
96+++ b/gdnsd/ltree.c
97@@ -1126,9 +1126,13 @@ void ltree_load_zones(void) {
98 ltree_find_or_add_dname(zone->dname, true);
99 }
100
101- for(unsigned i = 0; i < gconfig.num_zones; i++) {
102- const zoneinfo_t* zone = &gconfig.zones[i];
103- scan_zone(zone);
104+ if (!gconfig.djbdns_path) {
105+ for(unsigned i = 0; i < gconfig.num_zones; i++) {
106+ const zoneinfo_t* zone = &gconfig.zones[i];
107+ scan_zone(zone);
108+ }
109+ } else {
110+ read_djb_directory(gconfig.djbdns_path);
111 }
112
113 // Close the ltarena to further allocations. Mostly
114diff --git a/gdnsd/zscan-djb.c b/gdnsd/zscan-djb.c
115new file mode 100644
116index 0000000..fb18133
117--- /dev/null
118+++ b/gdnsd/zscan-djb.c
119@@ -0,0 +1,442 @@
120+/* Copyright © 2012 Timo Teräs <timo.teras@iki.fi>
121+ *
122+ * This file is part of gdnsd.
123+ *
124+ * gdnsd is free software: you can redistribute it and/or modify
125+ * it under the terms of the GNU General Public License as published by
126+ * the Free Software Foundation, either version 3 of the License, or
127+ * (at your option) any later version.
128+ *
129+ * gdnsd is distributed in the hope that it will be useful,
130+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
131+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132+ * GNU General Public License for more details.
133+ *
134+ * You should have received a copy of the GNU General Public License
135+ * along with gdnsd. If not, see <http://www.gnu.org/licenses/>.
136+ *
137+ */
138+
139+#include "zscan.h"
140+
141+#include <string.h>
142+#include <stdlib.h>
143+#include <unistd.h>
144+#include <sys/stat.h>
145+#include <fcntl.h>
146+#include <dirent.h>
147+
148+#include "conf.h"
149+#include "ltree.h"
150+#include "ltarena.h"
151+#include "gdnsd-misc.h"
152+
153+#define TTL_NS 259200
154+#define TTL_POSITIVE 86400
155+#define TTL_NEGATIVE 2560
156+
157+#define parse_warn(_fmt...) \
158+ log_warn("Zonefile parse error: " _fmt)
159+
160+#define parse_error(_fmt...) \
161+ log_fatal("Zonefile parse error: " _fmt)
162+
163+typedef struct {
164+ char* ptr;
165+ unsigned len;
166+} field_t;
167+
168+typedef struct {
169+ uint8_t ns[256];
170+ uint8_t email[256];
171+ unsigned ttl;
172+ unsigned serial;
173+ unsigned refresh;
174+ unsigned retry;
175+ unsigned expire;
176+ unsigned cache;
177+
178+ unsigned mtime;
179+} soa_info_t;
180+
181+static const uint8_t dname_root[] = {1,0};
182+static const uint8_t dname_ns[] = {4,2,'n','s',255};
183+static const uint8_t dname_mx[] = {4,2,'m','x',255};
184+static const uint8_t dname_srv[] = {5,3,'s','r','v',255};
185+
186+F_NONNULL
187+static uint8_t *parse_dname(uint8_t *dname, field_t *f) {
188+ dname_status_t status = dname_from_string(dname, (const uint8_t*) f->ptr, f->len);
189+
190+ switch(status) {
191+ case DNAME_INVALID:
192+ parse_error("'%.*s' is not a domain name", f->len, f->ptr);
193+ break;
194+ case DNAME_VALID:
195+ break;
196+ case DNAME_PARTIAL:
197+ if(dname_cat(dname, dname_root) == DNAME_INVALID)
198+ parse_error("'%.*s' is not a valid name", f->len, f->ptr);
199+ break;
200+ }
201+ return dname;
202+}
203+
204+F_NONNULL
205+static uint8_t *expand_dname(uint8_t *dname, field_t *f, const uint8_t *subzone, const uint8_t *zone) {
206+ /* fully qualified name in the primary field? */
207+ if (strchr(f->ptr, '.') != NULL)
208+ return parse_dname(dname, f);
209+
210+ /* construct dname of form <fieldname>.<subzone>.<zone>
211+ * e.g. ns1.ns.example.com */
212+ dname_from_string(dname, (const uint8_t*) f->ptr, f->len);
213+ dname_cat(dname, subzone);
214+ switch (dname_cat(dname, zone)) {
215+ case DNAME_VALID:
216+ break;
217+ case DNAME_PARTIAL:
218+ if(dname_cat(dname, dname_root) != DNAME_INVALID)
219+ break;
220+ /* fallthrough */
221+ case DNAME_INVALID:
222+ parse_error("unable to expand '%.*s' as to valid domain name", f->len, f->ptr);
223+ break;
224+ }
225+
226+ return dname;
227+}
228+
229+F_NONNULL
230+static uint32_t parse_ipv4(field_t *f) {
231+ struct in_addr addr;
232+
233+ if(inet_pton(AF_INET, f->ptr, &addr) <= 0)
234+ parse_error("IPv4 address '%s' invalid", f->ptr);
235+
236+ return addr.s_addr;
237+}
238+
239+F_NONNULL
240+static unsigned parse_ttl(field_t *f, unsigned defttl) {
241+ char *end;
242+ if (f->len == 0)
243+ return defttl;
244+ unsigned ttl = strtol(f->ptr, &end, 10);
245+ if (end != f->ptr + f->len)
246+ parse_error("Invalid TTL '%.*s'", f->len, f->ptr);
247+ return ttl;
248+}
249+
250+F_NONNULL
251+static unsigned parse_int(field_t *f) {
252+ char *end;
253+ unsigned ttl = strtol(f->ptr, &end, 10);
254+ if (end != f->ptr + f->len)
255+ parse_error("Invalid integer value '%.*s'", f->len, f->ptr);
256+ return ttl;
257+}
258+
259+F_NONNULL
260+static void parse_txt(field_t *f) {
261+ char ch;
262+ unsigned int i;
263+ unsigned int j;
264+
265+ j = 0;
266+ i = 0;
267+ while (i < f->len) {
268+ ch = f->ptr[i++];
269+ if (ch == '\\') {
270+ if (i >= f->len) break;
271+ ch = f->ptr[i++];
272+ if ((ch >= '0') && (ch <= '7')) {
273+ ch -= '0';
274+ if ((i < f->len) && (f->ptr[i] >= '0') && (f->ptr[i] <= '7')) {
275+ ch <<= 3;
276+ ch += f->ptr[i++] - '0';
277+ if ((i < f->len) && (f->ptr[i] >= '0') && (f->ptr[i] <= '7')) {
278+ ch <<= 3;
279+ ch += f->ptr[i++] - '0';
280+ }
281+ }
282+ }
283+ }
284+ f->ptr[j++] = ch;
285+ }
286+ f->len = j;
287+ f->ptr[j] = 0;
288+}
289+
290+#define TTDCHECK(fno) if (field[fno].len) { skipped++; continue; }
291+#define LOCCHECK(fno) if (field[fno].len) { skipped++; continue; }
292+
293+unsigned read_djb_file(const char *filename, soa_info_t *soas, unsigned mtime) {
294+ field_t field[15];
295+ unsigned skipped = 0;
296+
297+ dmn_assert(filename);
298+
299+ log_debug("Scanning djbzone file '%s'", filename);
300+
301+ FILE *f = fopen(filename, "rt");
302+ if(f == NULL)
303+ log_fatal("Cannot open zone file '%s' for reading: %s", filename, logf_errno());
304+
305+ size_t allocated = 0;
306+ ssize_t len;
307+ char *line = NULL;
308+ uint8_t dname[256], dname2[256], **texts = NULL;
309+ unsigned i, ttl;
310+
311+ while ((len = getline(&line, &allocated, f)) != -1) {
312+ if (len == 0 || line[0] == '#' || line[0] == '-')
313+ continue;
314+ if (line[len-1] == '\n') {
315+ line[len-1] = 0;
316+ len--;
317+ }
318+ if (len == 0)
319+ continue;
320+
321+ /* Skip location records */
322+ if (line[0] == '%')
323+ continue;
324+
325+ char *c;
326+ for (i = 0, c = line + 1; i < sizeof(field)/sizeof(field[0]); i++) {
327+ field[i].ptr = c ?: "";
328+ field[i].len = 0;
329+ if (c) {
330+ char *n = strchr(c, ':');
331+ if (n) {
332+ field[i].len = n - c;
333+ *n = 0;
334+ c = n + 1;
335+ } else {
336+ field[i].len = strlen(c);
337+ c = NULL;
338+ }
339+ }
340+ }
341+
342+ parse_dname(dname, &field[0]);
343+
344+ for (i = 0; i < gconfig.num_zones; i++) {
345+ if (dname_isinzone(gconfig.zones[i].dname, dname))
346+ break;
347+ }
348+ if (i >= gconfig.num_zones)
349+ continue;
350+
351+ if (mtime > soas[i].mtime)
352+ soas[i].mtime = mtime;
353+
354+ switch (line[0]) {
355+ case 'Z': /* SOA */
356+ TTDCHECK(9);
357+ LOCCHECK(10);
358+ if (dname_cmp(gconfig.zones[i].dname, dname) == 0) {
359+ parse_dname(soas[i].ns, &field[1]);
360+ parse_dname(soas[i].email, &field[2]);
361+ soas[i].ttl = parse_ttl(&field[8], TTL_NEGATIVE);
362+ soas[i].serial = parse_int(&field[3]);
363+ soas[i].refresh = parse_int(&field[4]) ?: 16384;
364+ soas[i].retry = parse_int(&field[5]) ?: 2048;
365+ soas[i].expire = parse_int(&field[6]) ?: 1048576;
366+ soas[i].cache = parse_int(&field[7]) ?: 2560;
367+ } else {
368+ uint8_t email[256];
369+ ltree_add_rec_soa(dname,
370+ parse_dname(dname2, &field[1]),
371+ parse_dname(email, &field[2]),
372+ parse_ttl(&field[8], TTL_NEGATIVE),
373+ parse_int(&field[3]) ?: mtime, /* serial */
374+ parse_int(&field[4]) ?: 16384, /* refresh */
375+ parse_int(&field[5]) ?: 2048, /* retry */
376+ parse_int(&field[6]) ?: 1048576, /* expire */
377+ parse_int(&field[7]) ?: 2560 /* cache */);
378+ }
379+ break;
380+ case '.': /* NS + SOA (+ A) */
381+ case '&': /* NS (+ A) */
382+ TTDCHECK(4);
383+ LOCCHECK(5);
384+ expand_dname(dname2, &field[2], dname_ns, dname);
385+ ttl = parse_ttl(&field[3], TTL_NS);
386+ ltree_add_rec_ns(dname, dname2, ttl);
387+ if (field[1].len) {
388+ ltree_add_rec_a(dname2,
389+ parse_ipv4(&field[1]),
390+ ttl, 0, NULL);
391+ }
392+ break;
393+ case '@': /* MX (+ A) */
394+ TTDCHECK(5);
395+ LOCCHECK(6);
396+ expand_dname(dname2, &field[2], dname_mx, dname);
397+ ttl = parse_ttl(&field[4], TTL_POSITIVE);
398+ ltree_add_rec_mx(dname, dname2, ttl, parse_int(&field[3]));
399+ if (field[1].len) {
400+ ltree_add_rec_a(dname2,
401+ parse_ipv4(&field[1]),
402+ ttl, 0, NULL);
403+ }
404+ break;
405+ case '+': /* A */
406+ case '=': /* A + PTR */
407+ TTDCHECK(3);
408+ ttl = parse_ttl(&field[2], TTL_POSITIVE);
409+ if (field[4].len == 2 && memcmp(field[4].ptr, "~~", 2) == 0) {
410+ ltree_add_rec_dynaddr(dname, (const uint8_t *) field[1].ptr,
411+ ttl, 0, 0);
412+ } else {
413+ LOCCHECK(4);
414+ ltree_add_rec_a(dname, parse_ipv4(&field[1]), ttl, 0, NULL);
415+#if 0
416+ /* FIXME: autogen PTR record */
417+ if (line[0] == '=') {
418+ ltree_add_rec_ptr();
419+ }
420+#endif
421+ }
422+ break;
423+ case 'C': /* CNAME */
424+ TTDCHECK(3);
425+ ttl = parse_ttl(&field[2], TTL_POSITIVE);
426+ if (field[4].len == 2 && memcmp(field[4].ptr, "~~", 2) == 0) {
427+ ltree_add_rec_dyncname(dname, (const uint8_t *) field[1].ptr,
428+ dname_root, ttl);
429+ } else {
430+ LOCCHECK(4);
431+ ltree_add_rec_cname(dname, parse_dname(dname2, &field[1]), ttl);
432+ }
433+ break;
434+ case '\'': /* TXT */
435+ TTDCHECK(3);
436+ LOCCHECK(4);
437+
438+ parse_txt(&field[1]);
439+
440+ unsigned bytes = field[1].len;
441+ const char* src = field[1].ptr;
442+ unsigned chunks = (bytes + 254) / 255;
443+
444+ if(bytes > 255 && gconfig.disable_text_autosplit)
445+ parse_error("Text chunk too long (>255 unescaped)");
446+ if(bytes > 65500)
447+ parse_error("Text chunk too long (>65500 unescaped)");
448+
449+ texts = realloc(texts, sizeof(uint8_t *) * (chunks + 1));
450+ for (i = 0; i < chunks; i++) {
451+ int s = (bytes > 255 ? 255 : bytes);
452+ texts[i] = lta_malloc_1(s + 1);
453+ texts[i][0] = s;
454+ memcpy(&texts[i][1], src, s);
455+
456+ bytes -= s;
457+ src += s;
458+ }
459+ texts[i] = NULL;
460+ ltree_add_rec_txt(dname, chunks, texts,
461+ parse_ttl(&field[2], TTL_POSITIVE));
462+ break;
463+ case 'S': /* SRV (+ A) */
464+ TTDCHECK(7);
465+ LOCCHECK(8);
466+ expand_dname(dname2, &field[2], dname_srv, dname);
467+ ttl = parse_ttl(&field[6], TTL_POSITIVE);
468+ ltree_add_rec_srv(dname, dname2,
469+ ttl,
470+ parse_int(&field[4]),
471+ parse_int(&field[5]),
472+ parse_int(&field[3]));
473+ if (field[1].len) {
474+ ltree_add_rec_a(dname2,
475+ parse_ipv4(&field[1]),
476+ ttl, 0, NULL);
477+ }
478+ break;
479+ case 'N': /* NAPTR */
480+ TTDCHECK(8);
481+ LOCCHECK(9);
482+ parse_txt(&field[3]);
483+ parse_txt(&field[4]);
484+ parse_txt(&field[5]);
485+ if (field[3].len > 255 || field[4].len > 255 || field[5].len > 255)
486+ parse_error("NAPTR label cannot exceed 255 chars");
487+
488+ texts = realloc(texts, sizeof(uint8_t *) * (3 + 1));
489+ for (i = 0; i < 3; i++) {
490+ texts[i] = lta_malloc_1(field[3+i].len + 1);
491+ texts[i][0] = field[3+i].len;
492+ memcpy(&texts[i][1], field[3+i].ptr, field[3+i].len);
493+ }
494+ texts[i] = NULL;
495+ ltree_add_rec_naptr(dname,
496+ parse_dname(dname2, &field[6]),
497+ parse_ttl(&field[7], TTL_POSITIVE),
498+ parse_int(&field[1]),
499+ parse_int(&field[2]),
500+ 3, texts);
501+ break;
502+#if 0
503+ case '3': /* AAAA */
504+ case '6': /* AAAA + PTR */
505+ case '^': /* PTR */
506+ case ':': /* raw */
507+#endif
508+ default:
509+ log_warn("Unsupported djbdns record type '%c'", line[0]);
510+ }
511+ }
512+ free(texts);
513+ free(line);
514+ fclose(f);
515+
516+ return skipped;
517+}
518+
519+void read_djb_directory(const char *path) {
520+ struct dirent *e;
521+ DIR *dir;
522+ unsigned i, skipped = 0;
523+ soa_info_t *soas;
524+
525+ soas = calloc(gconfig.num_zones, sizeof(soa_info_t));
526+
527+ dir = opendir(path);
528+ if (dir == NULL)
529+ log_fatal("Cannot open djbzone directory '%s': %s", path, logf_errno());
530+ while ((e = readdir(dir)) != NULL) {
531+ if (e->d_name[0] == '.')
532+ continue;
533+ struct stat st;
534+ char *fn = gdnsd_make_abs_fn(gconfig.djbdns_path, e->d_name);
535+ if (stat(fn, &st))
536+ log_fatal("Cannot stat djbzone file '%s': %s", e->d_name, logf_errno());
537+ if((st.st_mode & S_IFMT) == S_IFREG)
538+ skipped += read_djb_file(fn, soas, st.st_mtime);
539+ free(fn);
540+ }
541+ closedir(dir);
542+
543+ for (i = 0; i < gconfig.num_zones; i++) {
544+ if (soas[i].mtime == 0)
545+ continue;
546+
547+ ltree_add_rec_soa(gconfig.zones[i].dname,
548+ soas[i].ns, soas[i].email,
549+ soas[i].ttl,
550+ soas[i].serial ? : soas[i].mtime,
551+ soas[i].refresh,
552+ soas[i].retry,
553+ soas[i].expire,
554+ soas[i].cache);
555+ }
556+
557+ free(soas);
558+
559+ if (skipped)
560+ log_warn("Skipped: %d records with TTD or location", skipped);
561+}
562diff --git a/gdnsd/zscan.h b/gdnsd/zscan.h
563index faaba1f..d246617 100644
564--- a/gdnsd/zscan.h
565+++ b/gdnsd/zscan.h
566@@ -36,4 +36,7 @@ typedef struct {
567 F_NONNULL
568 void scan_zone(const zoneinfo_t* zone);
569
570+F_NONNULL
571+void read_djb_directory(const char* path);
572+
573 #endif // _GDNSD_ZSCAN_H
574--
5751.7.10.2
576
diff --git a/main/gdnsd/APKBUILD b/main/gdnsd/APKBUILD
index 6da9d6caad..d9fafbf4ce 100644
--- a/main/gdnsd/APKBUILD
+++ b/main/gdnsd/APKBUILD
@@ -1,18 +1,21 @@
1# Contributor: Natanael Copa <ncopa@alpinelinux.org> 1# Contributor: Natanael Copa <ncopa@alpinelinux.org>
2# Maintainer: Natanael Copa <ncopa@alpinelinux.org> 2# Maintainer: Timo Teräs <timo.teras@iki.fi>
3pkgname=gdnsd 3pkgname=gdnsd
4pkgver=1.6.2 4pkgver=1.6.9
5pkgrel=2 5pkgrel=0
6pkgdesc="Geographic Authoritative DNS server" 6pkgdesc="Geographic Authoritative DNS server"
7url="http://code.google.com/p/gdnsd/" 7url="https://github.com/blblack/gdnsd/"
8arch="all" 8arch="all"
9license="GPL-3" 9license="GPL-3"
10depends="" 10depends=""
11depends_dev="" 11depends_dev=""
12makedepends="libev-dev libcap-dev" 12makedepends="libev-dev libcap-dev autoconf automake libtool"
13install="$pkgname.pre-install" 13install="$pkgname.pre-install"
14subpackages="$pkgname-dev $pkgname-doc" 14subpackages="$pkgname-dev $pkgname-doc"
15source="http://gdnsd.googlecode.com/files/gdnsd-$pkgver.tar.xz 15source="https://github.com/downloads/blblack/gdnsd/gdnsd-$pkgver.tar.xz
16 geoip-autodc.patch
17 geoip-speedup.patch
18 0001-preliminary-djbdns-support.patch
16 gdnsd.initd" 19 gdnsd.initd"
17 20
18_builddir="$srcdir"/gdnsd-$pkgver 21_builddir="$srcdir"/gdnsd-$pkgver
@@ -24,6 +27,10 @@ prepare() {
24 *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;; 27 *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
25 esac 28 esac
26 done 29 done
30 libtoolize --force || return 1
31 aclocal -I m4 || return 1
32 autoconf || return 1
33 automake --add-missing || return 1
27} 34}
28 35
29build() { 36build() {
@@ -34,8 +41,8 @@ build() {
34 --enable-fast-install \ 41 --enable-fast-install \
35 || return 1 42 || return 1
36 make || return 1 43 make || return 1
37 install -Dm755 "$srcdir"/gdnsd.initd "$pkgdir"/etc/init.d/gdnsd \ 44 install -Dm755 "$srcdir"/gdnsd.initd \
38 || return 1 45 "$pkgdir"/etc/init.d/gdnsd || return 1
39} 46}
40 47
41package() { 48package() {
@@ -43,7 +50,12 @@ package() {
43 make DESTDIR="$pkgdir" install || return 1 50 make DESTDIR="$pkgdir" install || return 1
44 rm -f "$pkgdir"/usr/lib/*.la \ 51 rm -f "$pkgdir"/usr/lib/*.la \
45 "$pkgdir"/usr/lib/gdnsd/*.la 52 "$pkgdir"/usr/lib/gdnsd/*.la
53 install -Dm755 "$srcdir"/gdnsd.initd \
54 "$pkgdir"/etc/init.d/gdnsd || return 1
46} 55}
47 56
48md5sums="082f874d24cdc7073950ed6294f8d39b gdnsd-1.6.2.tar.xz 57md5sums="c8ea1da00fabc52e3d685528444f1279 gdnsd-1.6.9.tar.xz
49dad20779adfb4b85b57b45c7c903a636 gdnsd.initd" 5802eb668b6cad54552568a35985f44a09 geoip-autodc.patch
597fb697653b8295322e53492f9051e831 geoip-speedup.patch
604c8ff14e377fb8f1854b68b7bf9be282 0001-preliminary-djbdns-support.patch
6100f2838e0908effaaa2f6e6a1699f25b gdnsd.initd"
diff --git a/main/gdnsd/gdnsd.initd b/main/gdnsd/gdnsd.initd
index e11a73d1d6..2dbb568974 100755
--- a/main/gdnsd/gdnsd.initd
+++ b/main/gdnsd/gdnsd.initd
@@ -1,18 +1,44 @@
1#!/sbin/runscript 1#!/sbin/runscript
2 2
3name="gdnsd daemon"
4extra_commands="configtest"
5extra_started_commands="reload"
6description_configtest="Run syntax tests for configuration files only."
7description_reload="Fast reload: check config, load files, kill old server, start new server (in this order)."
8
9if [ -z "${GDNSD_CONFFILE}" ]; then
10 if [ "${SVCNAME}" = "gdnsd" ]; then
11 GDNSD_CONFFILE=/etc/gdnsd/config
12 else
13 GDNSD_CONFFILE=/etc/gdnsd/${SVCNAME}.config
14 fi
15fi
16
3depend() { 17depend() {
4 need net 18 need net
19 use logger
5 after firewall 20 after firewall
21 provide auth-dns
6} 22}
7 23
8start() { 24act() {
9 ebegin "Starting dnsd" 25 ebegin "$1 ${SVCNAME}"
10 start-stop-daemon --start --exec /usr/sbin/dnsd -- -d $DNSD_OPTS 26 /usr/sbin/gdnsd -c ${GDNSD_CONFFILE} ${GDNSD_OPTS} $2
11 eend $? 27 eend $?
12} 28}
13 29
30start() {
31 act "Starting" start
32}
33
14stop () { 34stop () {
15 ebegin "Stopping dnsd" 35 act "Stopping" stop
16 start-stop-daemon --stop --exec /usr/sbin/dnsd 36}
17 eend $? 37
38reload() {
39 act "Reloading" restart
40}
41
42configtest() {
43 act "Checking configuration" checkconf
18} 44}
diff --git a/main/gdnsd/geoip-speedup.patch b/main/gdnsd/geoip-speedup.patch
new file mode 100644
index 0000000000..3816df44ed
--- /dev/null
+++ b/main/gdnsd/geoip-speedup.patch
@@ -0,0 +1,101 @@
1From: Timo TerÃs <timo.teras@iki.fi>
2
3plugin_geoip: speed up cities database loading
4
5Gives over 10x speed-up in loading the large cities database.
6http://code.google.com/p/gdnsd/issues/detail?id=18
7
8diff --git a/plugins/meta/libgdmaps/gdmaps.c b/plugins/meta/libgdmaps/gdmaps.c
9index 9d20351..6bbc410 100644
10--- a/plugins/meta/libgdmaps/gdmaps.c
11+++ b/plugins/meta/libgdmaps/gdmaps.c
12@@ -1215,6 +1215,12 @@ typedef struct {
13 } gdmap_t;
14
15 typedef struct {
16+ unsigned offset;
17+ unsigned dclist;
18+} offset_cache_item_t;
19+#define OFFSET_CACHE_SIZE (1 << 18)
20+
21+typedef struct {
22 char* pathname;
23 uint8_t* data;
24 const fips_t* fips;
25@@ -1223,6 +1229,8 @@ typedef struct {
26 int type;
27 unsigned base;
28 bool ipv6;
29+
30+ offset_cache_item_t *offset_cache[OFFSET_CACHE_SIZE];
31 } geoip_db_t;
32
33 F_NONNULL
34@@ -1230,7 +1238,7 @@ static int geoip_db_close(geoip_db_t* db);
35 F_NONNULLX(1)
36 static geoip_db_t* geoip_db_open(const char* pathname, const fips_t* fips, const char* map_name, const bool city_required);
37 F_NONNULLX(1, 2, 3)
38-static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db, const geoip_db_t* db_v4o);
39+static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db, geoip_db_t* db_v4o);
40
41 F_NONNULL
42 static ntree_t* gdmap_make_tree(const gdmap_t* gdmap, const dclists_t* old_dclists) {
43@@ -1957,10 +1965,18 @@ static unsigned city_lookup_dclist(const geoip_db_t* db, unsigned int offs, cons
44 }
45
46 F_NONNULL
47-static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoip_db_t* db, const unsigned int offset) {
48+static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, geoip_db_t* db, const unsigned int offset) {
49 dmn_assert(gdmap); dmn_assert(db);
50
51 unsigned dclist = 0;
52+ unsigned bucket_size = 0;
53+ unsigned ndx = offset % OFFSET_CACHE_SIZE;
54+
55+ if (db->offset_cache[ndx]) {
56+ for (bucket_size = 0; db->offset_cache[ndx][bucket_size].offset; bucket_size++)
57+ if (db->offset_cache[ndx][bucket_size].offset == offset)
58+ return db->offset_cache[ndx][bucket_size].dclist;
59+ }
60
61 switch(db->type) {
62 case GEOIP_CITY_EDITION_REV1_V6:
63@@ -1983,6 +1999,11 @@ static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoi
64 break;
65 }
66
67+ db->offset_cache[ndx] = realloc(db->offset_cache[ndx], sizeof(offset_cache_item_t) * (bucket_size+2));
68+ db->offset_cache[ndx][bucket_size].offset = offset;
69+ db->offset_cache[ndx][bucket_size].dclist = dclist;
70+ db->offset_cache[ndx][bucket_size+1].offset = 0;
71+
72 return dclist;
73 }
74
75@@ -1991,7 +2012,7 @@ static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoi
76 // C really needs a better macro/template idea :(
77 #define DEFUN_TREE_XLATE(IPVN, IPTYPE, IPZERO, BITDEPTH, V4ROOT_CODE, SKIP_CODE) \
78 F_NONNULL \
79-static int geoip_tree_xlate_ ## IPVN(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db) { \
80+static int geoip_tree_xlate_ ## IPVN(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db) { \
81 dmn_assert(gdmap); dmn_assert(tree); dmn_assert(db); \
82 struct { \
83 int depth; \
84@@ -2107,7 +2128,7 @@ DEFUN_TREE_XLATE(v4, uint32_t, 0, 32, ;, ;)
85
86 DEFUN_TREE_XLATE(v6, struct in6_addr, ip6_zero, 128, V6_V4ROOT_CODE, V6_SKIP_CODE)
87
88-static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db, const geoip_db_t* db_v4o) {
89+static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db, geoip_db_t* db_v4o) {
90 dmn_assert(gdmap); dmn_assert(tree); dmn_assert(db);
91
92 log_info("plugin_geoip: map '%s': Processing GeoIP database '%s'...", gdmap->name, gdmap->geoip_path);
93@@ -2145,6 +2166,8 @@ static int geoip_db_close(geoip_db_t* db) {
94 }
95 }
96
97+ for (unsigned i = 0; i < OFFSET_CACHE_SIZE; i++)
98+ free(db->offset_cache[i]);
99 if(db->pathname)
100 free(db->pathname);
101 free(db);