1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
Description: Use root.hints from dns-root-data
This patch enables loading DNS root server hints as offered by
package dns-root-data (or using equivalent paths under /usr/local) if
they are available. Otherwise the compiled-in defaults are used.
.
Setting BELLE_SIP_NO_SYS_ROOT_HINTS in the environment disables this
feature. Setting BELLE_SIP_LOG_ROOT_HINTS in the environment logs
the loaded root server definitions to stderr which can be used to
reveal discrepancies.
.
The code is short and easy to understand, though not very efficient,
but since it runs only once at start-up that should not matter much.
Bug-Debian: https://bugs.debian.org/760467
Author: Dennis Filder <d.filder@web.de>
Last-Update: 2021-12-03
Forwarded: not-needed
--- a/src/dns/dns.c
+++ b/src/dns/dns.c
@@ -5856,11 +5856,120 @@
return 0;
} /* dns_hints_local() */
+struct rootserver {
+ int af;
+ char addr[INET6_ADDRSTRLEN];
+};
+
+static int learn_system_root_servers(struct rootserver **servers_pp, size_t *nentries) {
+ static const char *Hint_paths[] = {
+ "/usr/local/share/dns/root.hints",
+ "/usr/share/dns/root.hints",
+ NULL
+ };
+
+ FILE *fp;
+ char *hintfile;
+ int addrfam = AF_INET, linecount=0, stillgood = 1;
+ struct rootserver *servers = NULL;
+ size_t nservers = 0;
+
+ for (hintfile = (char*) Hint_paths[0]; hintfile; hintfile++) {
+ if ((fp = fopen(hintfile, "r")) != NULL)
+ break;
+ }
+
+ if (fp == NULL) {
+ fprintf(stderr, "Error: parse-root-hints: could not open any root.hints file. Aborting.\n");
+ return -1;
+ }
+
+ do {
+ size_t linelen=0;
+ char *line = NULL;
+ errno = 0;
+ ssize_t res = getline(&line, &linelen, fp);
+
+ if (res == -1) {
+ if (errno != 0) /* something irrecoverable happened */
+ stillgood = 0;
+ break;
+ }
+ linecount++;
+
+ if (line) {
+ if ( ( line[0] >= 'A' && line[0] <= 'Z' )
+ && linelen >= strlen("*.ROOT-SERVERS.NET.")
+ && memcmp(line+1, ".ROOT-SERVERS.NET.", strlen(".ROOT-SERVERS.NET.")) == 0) {
+ char *rr = NULL, *ipaddr = NULL;
+ int ret = sscanf(line, " %*s %*s %ms %ms ", &rr, &ipaddr);
+
+ if (ret == 2) {
+ if (rr && strlen(rr) == strlen("AAAA") && strcmp(rr, "AAAA") == 0) {
+ addrfam = AF_INET6;
+ } else if (rr && strlen(rr) == strlen("A") && strcmp(rr, "A") == 0) {
+ addrfam = AF_INET;
+ } else {
+ fprintf(stderr, "Warning: bogus resource record %s in %s, line %d. Skipping.\n", rr, hintfile, linecount);
+ goto free_fields;
+ }
+
+ if (ipaddr && strlen(ipaddr) >= 1) {
+ /* we got a new server definition, add it! */
+ nservers++;
+
+ struct rootserver *p = realloc(servers, sizeof(struct rootserver) * nservers);
+ if (p == NULL) {
+ if (servers)
+ free(servers);
+ nservers = 0;
+ servers = NULL;
+ fprintf(stderr, "Error: out of memory. Aborting.\n");
+ stillgood = 0;
+ goto free_fields;
+ }
+ servers = p;
+
+ memset(&servers[nservers-1], 0, sizeof(struct rootserver));
+ servers[nservers-1].af = addrfam;
+ strncpy(servers[nservers-1].addr, ipaddr, INET6_ADDRSTRLEN);
+ servers[nservers-1].addr[INET6_ADDRSTRLEN-1] = '\0';
+ }
+
+ }
+ free_fields:
+ if (rr)
+ free(rr);
+ if (ipaddr)
+ free(ipaddr);
+ }
+
+ free(line);
+ line = NULL;
+ linelen = 0;
+ res = 0;
+ if (stillgood)
+ continue;
+ } else {
+ break;
+ }
+
+ } while (1);
+
+ if (fp)
+ fclose(fp);
+
+ if (stillgood && nservers >= 1) {
+ *servers_pp = servers;
+ *nentries = nservers;
+ return 0;
+ }
+ return -1;
+} /* learn_system_root_servers() */
+
struct dns_hints *dns_hints_root(struct dns_resolv_conf *resconf, int *error_) {
- static const struct {
- int af;
- char addr[INET6_ADDRSTRLEN];
- } root_hints[] = {
+ static const struct rootserver
+ fallback_root_hints[] = {
{AF_INET, "198.41.0.4"}, /* A.ROOT-SERVERS.NET. */
{AF_INET6, "2001:503:ba3e::2:30"}, /* A.ROOT-SERVERS.NET. */
{AF_INET, "192.228.79.201"}, /* B.ROOT-SERVERS.NET. */
@@ -5887,6 +5996,16 @@
{AF_INET, "202.12.27.33"}, /* M.ROOT-SERVERS.NET. */
{AF_INET6, "2001:DC3::35"}, /* M.ROOT-SERVERS.NET. */
};
+ struct rootserver *sys_root_hints, *root_hints;
+ size_t nsys_root_hints, nroot_hints, nfallback_root_hints = lengthof(fallback_root_hints);
+ int ret = learn_system_root_servers(&sys_root_hints, &nsys_root_hints);
+ if (ret == -1 || getenv("BELLE_SIP_NO_SYS_ROOT_HINTS")) {
+ root_hints = (struct rootserver *)&fallback_root_hints[0];
+ nroot_hints = nfallback_root_hints;
+ } else {
+ root_hints = sys_root_hints;
+ nroot_hints = nsys_root_hints;
+ }
struct dns_hints *hints = 0;
struct sockaddr_storage ss;
unsigned i;
@@ -5895,9 +6014,12 @@
if (!(hints = dns_hints_open(resconf, &error))) goto error;
- for (i = 0; i < lengthof(root_hints); i++) {
+ for (i = 0; i < nroot_hints; i++) {
af = root_hints[i].af;
if ((error = dns_pton(af, root_hints[i].addr, dns_sa_addr(af, &ss, NULL)))) goto error;
+ if (getenv("BELLE_SIP_LOG_ROOT_HINTS")) {
+ fprintf(stderr, "src/dns/dns.c:dns_hints_root():addr=%s, af=%d\n",root_hints[i].addr,af);
+ }
*dns_sa_port(af, &ss) = htons(53);
ss.ss_family = af;
|