summaryrefslogtreecommitdiff
path: root/src/pluto/dnskey.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/dnskey.c')
-rw-r--r--src/pluto/dnskey.c2609
1 files changed, 1324 insertions, 1285 deletions
diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c
index 8ba0f7b73..ed901ade5 100644
--- a/src/pluto/dnskey.c
+++ b/src/pluto/dnskey.c
@@ -10,8 +10,6 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
- *
- * RCSID $Id: dnskey.c 3252 2007-10-06 21:24:50Z andreas $
*/
#include <stdlib.h>
@@ -26,32 +24,34 @@
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
-#include <netdb.h> /* ??? for h_errno */
+#include <netdb.h> /* ??? for h_errno */
#include <sys/queue.h>
#include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include <utils/identification.h>
+#include <credentials/keys/public_key.h>
#include "constants.h"
-#include "adns.h" /* needs <resolv.h> */
+#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
#include "log.h"
#include "id.h"
#include "connections.h"
-#include "keys.h" /* needs connections.h */
+#include "keys.h" /* needs connections.h */
#include "dnskey.h"
#include "packet.h"
#include "timer.h"
/* somebody has to decide */
-#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */
+#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */
/* ADNS stuff */
-int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */
- adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
+int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */
+ adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
static pid_t adns_pid = 0;
-const char *pluto_adns_option = NULL; /* path from --pluto_adns */
+const char *pluto_adns_option = NULL; /* path from --pluto_adns */
int adns_restart_count;
#define ADNS_RESTART_MAX 20
@@ -59,152 +59,168 @@ int adns_restart_count;
void
init_adns(void)
{
- const char *adns_path = pluto_adns_option;
+ const char *adns_path = pluto_adns_option;
#ifndef USE_LWRES
- static const char adns_name[] = "_pluto_adns";
- const char *helper_bin_dir = getenv("IPSEC_LIBDIR");
+ static const char adns_name[] = "_pluto_adns";
+ const char *helper_bin_dir = getenv("IPSEC_LIBDIR");
#else /* USE_LWRES */
- static const char adns_name[] = "lwdnsq";
- const char *helper_bin_dir = getenv("IPSEC_EXECDIR");
+ static const char adns_name[] = "lwdnsq";
+ const char *helper_bin_dir = getenv("IPSEC_EXECDIR");
#endif /* USE_LWRES */
- char adns_path_space[4096]; /* plenty long? */
- int qfds[2];
- int afds[2];
-
- /* find a pathname to the ADNS program */
- if (adns_path == NULL)
- {
- /* pathname was not specified as an option: build it.
- * First, figure out the directory to be used.
- */
- ssize_t n;
+ char adns_path_space[4096]; /* plenty long? */
+ int qfds[2];
+ int afds[2];
- if (helper_bin_dir != NULL)
+ /* find a pathname to the ADNS program */
+ if (adns_path == NULL)
{
- n = strlen(helper_bin_dir);
- if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
- {
- strcpy(adns_path_space, helper_bin_dir);
- if (n > 0 && adns_path_space[n -1] != '/')
- adns_path_space[n++] = '/';
- }
- }
- else
- {
- /* The program will be in the same directory as Pluto,
- * so we use the sympolic link /proc/self/exe to
- * tell us of the path prefix.
- */
- n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
-
- if (n < 0)
- exit_log_errno((e
- , "readlink(\"/proc/self/exe\") failed in init_adns()"));
-
- }
-
- if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
- exit_log("path to %s is too long", adns_name);
+ /* pathname was not specified as an option: build it.
+ * First, figure out the directory to be used.
+ */
+ ssize_t n;
- while (n > 0 && adns_path_space[n - 1] != '/')
- n--;
+ if (helper_bin_dir != NULL)
+ {
+ n = strlen(helper_bin_dir);
+ if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
+ {
+ strcpy(adns_path_space, helper_bin_dir);
+ if (n > 0 && adns_path_space[n -1] != '/')
+ {
+ adns_path_space[n++] = '/';
+ }
+ }
+ }
+ else
+ {
+ /* The program will be in the same directory as Pluto,
+ * so we use the sympolic link /proc/self/exe to
+ * tell us of the path prefix.
+ */
+ n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
+
+ if (n < 0)
+ {
+ exit_log_errno((e
+ , "readlink(\"/proc/self/exe\") failed in init_adns()"));
+ }
+ }
- strcpy(adns_path_space + n, adns_name);
- adns_path = adns_path_space;
- }
- if (access(adns_path, X_OK) < 0)
- exit_log_errno((e, "%s missing or not executable", adns_path));
+ if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
+ {
+ exit_log("path to %s is too long", adns_name);
+ }
- if (pipe(qfds) != 0 || pipe(afds) != 0)
- exit_log_errno((e, "pipe(2) failed in init_adns()"));
+ while (n > 0 && adns_path_space[n - 1] != '/')
+ {
+ n--;
+ }
+ strcpy(adns_path_space + n, adns_name);
+ adns_path = adns_path_space;
+ }
+ if (access(adns_path, X_OK) < 0)
+ {
+ exit_log_errno((e, "%s missing or not executable", adns_path));
+ }
- adns_pid = fork();
- switch (adns_pid)
- {
- case -1:
- exit_log_errno((e, "fork() failed in init_adns()"));
+ if (pipe(qfds) != 0 || pipe(afds) != 0)
+ {
+ exit_log_errno((e, "pipe(2) failed in init_adns()"));
+ }
- case 0:
- /* child */
+ adns_pid = fork();
+ switch (adns_pid)
{
- /* Make stdin and stdout our pipes.
- * Take care to handle case where pipes already use these fds.
- */
- if (afds[1] == 0)
- afds[1] = dup(afds[1]); /* avoid being overwritten */
- if (qfds[0] != 0)
- {
- dup2(qfds[0], 0);
+ case -1:
+ exit_log_errno((e, "fork() failed in init_adns()"));
+
+ case 0:
+ /* child */
+ {
+ /* Make stdin and stdout our pipes.
+ * Take care to handle case where pipes already use these fds.
+ */
+ if (afds[1] == 0)
+ {
+ afds[1] = dup(afds[1]); /* avoid being overwritten */
+ }
+ if (qfds[0] != 0)
+ {
+ dup2(qfds[0], 0);
+ close(qfds[0]);
+ }
+ if (afds[1] != 1)
+ {
+ dup2(afds[1], 1);
+ close(qfds[1]);
+ }
+ if (afds[0] > 1)
+ {
+ close(afds[0]);
+ }
+ if (afds[1] > 1)
+ {
+ close(afds[1]);
+ }
+ DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
+
+ execlp(adns_path, adns_name, NULL);
+ exit_log_errno((e, "execlp of %s failed", adns_path));
+ }
+ default:
+ /* parent */
close(qfds[0]);
- }
- if (afds[1] != 1)
- {
- dup2(afds[1], 1);
- close(qfds[1]);
- }
- if (afds[0] > 1)
- close(afds[0]);
- if (afds[1] > 1)
+ adns_qfd = qfds[1];
+ adns_afd = afds[0];
close(afds[1]);
-
- DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL));
-
- execlp(adns_path, adns_name, NULL);
- exit_log_errno((e, "execlp of %s failed", adns_path));
+ fcntl(adns_qfd, F_SETFD, FD_CLOEXEC);
+ fcntl(adns_afd, F_SETFD, FD_CLOEXEC);
+ fcntl(adns_qfd, F_SETFL, O_NONBLOCK);
+ break;
}
-
- default:
- /* parent */
- close(qfds[0]);
- adns_qfd = qfds[1];
- adns_afd = afds[0];
- close(afds[1]);
- fcntl(adns_qfd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_afd, F_SETFD, FD_CLOEXEC);
- fcntl(adns_qfd, F_SETFL, O_NONBLOCK);
- break;
- }
}
void
stop_adns(void)
{
- close_any(adns_qfd);
- adns_qfd = NULL_FD;
- close_any(adns_afd);
- adns_afd = NULL_FD;
-
- if (adns_pid != 0)
- {
- int status;
- pid_t p = waitpid(adns_pid, &status, 0);
+ close_any(adns_qfd);
+ adns_qfd = NULL_FD;
+ close_any(adns_afd);
+ adns_afd = NULL_FD;
- if (p == -1)
- {
- log_errno((e, "waitpid for ADNS process failed"));
- }
- else if (WIFEXITED(status))
+ if (adns_pid != 0)
{
- if (WEXITSTATUS(status) != 0)
- plog("ADNS process exited with status %d"
- , (int) WEXITSTATUS(status));
- }
- else if (WIFSIGNALED(status))
- {
- plog("ADNS process terminated by signal %d", (int)WTERMSIG(status));
- }
- else
- {
- plog("wait for end of ADNS process returned odd status 0x%x\n"
- , status);
+ int status;
+ pid_t p = waitpid(adns_pid, &status, 0);
+
+ if (p == -1)
+ {
+ log_errno((e, "waitpid for ADNS process failed"));
+ }
+ else if (WIFEXITED(status))
+ {
+ if (WEXITSTATUS(status) != 0)
+ {
+ plog("ADNS process exited with status %d"
+ , (int) WEXITSTATUS(status));
+ }
+ }
+ else if (WIFSIGNALED(status))
+ {
+ plog("ADNS process terminated by signal %d", (int)WTERMSIG(status));
+ }
+ else
+ {
+ plog("wait for end of ADNS process returned odd status 0x%x\n"
+ , status);
+ }
}
- }
}
/* tricky macro to pass any hot potato */
-#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
+#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; }
/* Process TXT X-IPsec-Server record, accumulating relevant ones
@@ -225,246 +241,270 @@ static const char our_TXT_attr[] = our_TXT_attr_string;
static err_t
decode_iii(u_char **pp, struct id *gw_id)
{
- u_char *p = *pp + strspn(*pp, " \t");
- u_char *e = p + strcspn(p, " \t");
- u_char under = *e;
-
- if (p == e)
- return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
-
- *e = '\0';
- if (*p == '@')
- {
- /* gateway specification in this record is @FQDN */
- err_t ugh = atoid(p, gw_id, FALSE);
-
- if (ugh != NULL)
- return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
- , ugh);
- }
- else
- {
- /* gateway specification is numeric */
- ip_address ip;
- err_t ugh = tnatoaddr(p, e-p
- , strchr(p, ':') == NULL? AF_INET : AF_INET6
- , &ip);
-
- if (ugh != NULL)
- return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
- , ugh);
-
- if (isanyaddr(&ip))
- return "gateway address must not be 0.0.0.0 or 0::0";
-
- iptoid(&ip, gw_id);
- }
-
- *e = under;
- *pp = e + strspn(e, " \t");
-
- return NULL;
+ u_char *p = *pp + strspn(*pp, " \t");
+ u_char *e = p + strcspn(p, " \t");
+ u_char under = *e;
+
+ if (p == e)
+ {
+ return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+ }
+ *e = '\0';
+ if (*p == '@')
+ {
+ /* gateway specification in this record is @FQDN */
+ err_t ugh = atoid(p, gw_id, FALSE);
+
+ if (ugh != NULL)
+ {
+ return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
+ , ugh);
+ }
+ }
+ else
+ {
+ /* gateway specification is numeric */
+ ip_address ip;
+ err_t ugh = tnatoaddr(p, e-p
+ , strchr(p, ':') == NULL? AF_INET : AF_INET6
+ , &ip);
+
+ if (ugh != NULL)
+ {
+ return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
+ , ugh);
+ }
+ if (isanyaddr(&ip))
+ {
+ return "gateway address must not be 0.0.0.0 or 0::0";
+ }
+ iptoid(&ip, gw_id);
+ }
+
+ *e = under;
+ *pp = e + strspn(e, " \t");
+
+ return NULL;
}
static err_t
process_txt_rr_body(u_char *str
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- const struct id *client_id = &cr->id; /* subject of query */
- u_char *p = str;
- unsigned long pref = 0;
- struct gw_info gi;
+ const struct id *client_id = &cr->id; /* subject of query */
+ u_char *p = str;
+ unsigned long pref = 0;
+ struct gw_info gi;
+
+ p += strspn(p, " \t"); /* ignore leading whitespace */
- p += strspn(p, " \t"); /* ignore leading whitespace */
+ /* is this for us? */
+ if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
+ {
+ return NULL; /* neither interesting nor bad */
+ }
- /* is this for us? */
- if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
- return NULL; /* neither interesting nor bad */
+ p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
+ p += strspn(p, " \t"); /* ignore leading whitespace */
- p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */
- p += strspn(p, " \t"); /* ignore leading whitespace */
+ /* decode '(' nnn ')' */
+ if (*p != '(')
+ {
+ return "X-IPsec-Server missing '('";
+ }
- /* decode '(' nnn ')' */
- if (*p != '(')
- return "X-IPsec-Server missing '('";
+ {
+ char *e;
- {
- char *e;
+ p++;
+ pref = strtoul(p, &e, 0);
+ if ((u_char *)e == p)
+ {
+ return "malformed X-IPsec-Server priority";
+ }
+ p = e + strspn(e, " \t");
- p++;
- pref = strtoul(p, &e, 0);
- if ((u_char *)e == p)
- return "malformed X-IPsec-Server priority";
+ if (*p != ')')
+ {
+ return "X-IPsec-Server priority missing ')'";
+ }
+ p++;
+ p += strspn(p, " \t");
- p = e + strspn(e, " \t");
+ if (pref > 0xFFFF)
+ {
+ return "X-IPsec-Server priority larger than 0xFFFF";
+ }
+ }
- if (*p != ')')
- return "X-IPsec-Server priority missing ')'";
+ /* time for '=' */
+ if (*p != '=')
+ {
+ return "X-IPsec-Server priority missing '='";
+ }
p++;
p += strspn(p, " \t");
- if (pref > 0xFFFF)
- return "X-IPsec-Server priority larger than 0xFFFF";
- }
-
- /* time for '=' */
+ /* Decode iii (Security Gateway ID). */
- if (*p != '=')
- return "X-IPsec-Server priority missing '='";
+ zero(&gi); /* before first use */
- p++;
- p += strspn(p, " \t");
+ TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
- /* Decode iii (Security Gateway ID). */
-
- zero(&gi); /* before first use */
-
- TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
-
- if (!cr->sgw_specified)
- {
- /* we don't know the peer's ID (because we are initiating
- * and we don't know who to initiate with.
- * So we're looking for gateway specs with an IP address
- */
- if (!id_is_ipaddr(&gi.gw_id))
+ if (!cr->sgw_specified)
{
- DBG(DBG_DNS,
+ /* we don't know the peer's ID (because we are initiating
+ * and we don't know who to initiate with.
+ * So we're looking for gateway specs with an IP address
+ */
+ if (!id_is_ipaddr(&gi.gw_id))
{
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored because gateway's IP is unspecified"
- , our_TXT_attr, cidb, gwidb);
- });
- return NULL; /* we cannot use this record, but it isn't wrong */
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ DBG_log("TXT %s record for %s: security gateway %s;"
+ " ignored because gateway's IP is unspecified"
+ , our_TXT_attr, cidb, gwidb);
+ });
+ return NULL; /* we cannot use this record, but it isn't wrong */
+ }
}
- }
- else
- {
- /* We do know the peer's ID (because we are responding)
- * So we're looking for gateway specs specifying this known ID.
- */
- const struct id *peer_id = &cr->sgw_id;
-
- if (!same_id(peer_id, &gi.gw_id))
+ else
{
- DBG(DBG_DNS,
+ /* We do know the peer's ID (because we are responding)
+ * So we're looking for gateway specs specifying this known ID.
+ */
+ const struct id *peer_id = &cr->sgw_id;
+
+ if (!same_id(peer_id, &gi.gw_id))
{
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
- char pidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- idtoa(peer_id, pidb, sizeof(pidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored -- looking to confirm %s as gateway"
- , our_TXT_attr, cidb, gwidb, pidb);
- });
- return NULL; /* we cannot use this record, but it isn't wrong */
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+ char pidb[BUF_LEN];
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ idtoa(peer_id, pidb, sizeof(pidb));
+ DBG_log("TXT %s record for %s: security gateway %s;"
+ " ignored -- looking to confirm %s as gateway"
+ , our_TXT_attr, cidb, gwidb, pidb);
+ });
+ return NULL; /* we cannot use this record, but it isn't wrong */
+ }
}
- }
-
- if (doit)
- {
- /* really accept gateway */
- struct gw_info **gwip; /* gateway insertion point */
- gi.client_id = *client_id; /* will need to unshare_id_content */
-
- /* decode optional kkk: base 64 encoding of key */
-
- gi.gw_key_present = *p != '\0';
- if (gi.gw_key_present)
+ if (doit)
{
- /* Decode base 64 encoding of key.
- * Similar code is in process_lwdnsq_key.
- */
- u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- chunk_t kbc;
- struct RSA_public_key r;
-
- err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len
- , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
-
- if (ugh != NULL)
- return builddiag("malformed key data: %s", ugh);
-
- if (kbc.len > sizeof(kb))
- return builddiag("key data larger than %lu bytes"
- , (unsigned long) sizeof(kb));
-
- kbc.ptr = kb;
- ugh = unpack_RSA_public_key(&r, &kbc);
- if (ugh != NULL)
- return builddiag("invalid key data: %s", ugh);
-
- /* now find a key entry to put it in */
- gi.key = public_key_from_rsa(&r);
-
- free_RSA_public_content(&r);
+ /* really accept gateway */
+ struct gw_info **gwip; /* gateway insertion point */
- unreference_key(&cr->last_info);
- cr->last_info = reference_key(gi.key);
- }
-
- /* we're home free! Allocate everything and add to gateways list. */
- gi.refcnt = 1;
- gi.pref = pref;
- gi.key->dns_auth_level = dns_auth_level;
- gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME;
-
- /* find insertion point */
- for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
- ;
+ gi.client_id = *client_id; /* will need to unshare_id_content */
- DBG(DBG_DNS,
- {
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
+ /* decode optional kkk: base 64 encoding of key */
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ gi.gw_key_present = *p != '\0';
if (gi.gw_key_present)
{
- DBG_log("gateway for %s is %s with key %s"
- , cidb, gwidb, gi.key->u.rsa.keyid);
+ /* Decode base 64 encoding of key.
+ * Similar code is in process_lwdnsq_key.
+ */
+ u_char buf[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
+ size_t sz;
+ err_t ugh;
+ chunk_t rfc3110_chunk;
+ public_key_t *key;
+
+ ugh = ttodatav(p, 0, 64, buf, sizeof(buf), &sz,
+ diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);
+ if (ugh)
+ {
+ return builddiag("malformed key data: %s", ugh);
+ }
+ if (sz > sizeof(buf))
+ {
+ return builddiag("key data larger than %lu bytes",
+ (unsigned long) sizeof(buf));
+ }
+ rfc3110_chunk = chunk_create(buf, sz);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_RFC_3110, rfc3110_chunk,
+ BUILD_END);
+ if (key == NULL)
+ {
+ return builddiag("invalid key data");
+ }
+
+ /* now find a key entry to put it in */
+ gi.key = public_key_from_rsa(key);
+
+ unreference_key(&cr->last_info);
+ cr->last_info = reference_key(gi.key);
}
- else
- {
- DBG_log("gateway for %s is %s; no key specified"
- , cidb, gwidb);
- }
- });
- gi.next = *gwip;
- *gwip = clone_thing(gi, "gateway info");
- unshare_id_content(&(*gwip)->gw_id);
- unshare_id_content(&(*gwip)->client_id);
- }
+ /* we're home free! Allocate everything and add to gateways list. */
+ gi.refcnt = 1;
+ gi.pref = pref;
+ gi.key->dns_auth_level = dns_auth_level;
+ gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME;
+
+ /* find insertion point */
+ for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
+ ;
+
+ DBG(DBG_DNS,
+ {
+ char cidb[BUF_LEN];
+ char gwidb[BUF_LEN];
+ identification_t *keyid;
+ public_key_t *pub_key;
+
+ idtoa(client_id, cidb, sizeof(cidb));
+ idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
+ pub_key = gi.key->public_key;
+ keyid = pub_key->get_id(pub_key, ID_PUBKEY_SHA1);
+
+ if (gi.gw_key_present)
+ {
+ DBG_log("gateway for %s is %s with key %Y"
+ , cidb, gwidb, keyid);
+ }
+ else
+ {
+ DBG_log("gateway for %s is %s; no key specified"
+ , cidb, gwidb);
+ }
+ });
+
+ gi.next = *gwip;
+ *gwip = clone_thing(gi);
+ unshare_id_content(&(*gwip)->gw_id);
+ unshare_id_content(&(*gwip)->client_id);
+ }
- return NULL;
+ return NULL;
}
static const char *
rr_typename(int type)
{
- switch (type)
- {
- case T_TXT:
- return "TXT";
- case T_KEY:
- return "KEY";
- default:
- return "???";
- }
+ switch (type)
+ {
+ case T_TXT:
+ return "TXT";
+ case T_KEY:
+ return "KEY";
+ default:
+ return "???";
+ }
}
@@ -476,72 +516,72 @@ process_lwdnsq_key(u_char *str
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */
- unsigned long flags /* 16 bits */
- , protocol /* 8 bits */
- , algorithm; /* 8 bits */
-
- char *rest = str
- , *p
- , *endofnumber;
-
- /* flags */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing flags";
-
- flags = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed flags";
-
- /* protocol */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing protocol";
-
- protocol = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed protocol";
-
- /* algorithm */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq KEY: missing algorithm";
-
- algorithm = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq KEY: malformed algorithm";
-
- /* is this key interesting? */
- if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
- && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
- && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */
- && (flags & 0x2CF0ul) == 0) /* must be zero */
- {
- /* Decode base 64 encoding of key.
- * Similar code is in process_txt_rr_body.
- */
- u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
- chunk_t kbc;
- err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len
- , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE);
-
- if (ugh != NULL)
- return builddiag("malformed key data: %s", ugh);
-
- if (kbc.len > sizeof(kb))
- return builddiag("key data larger than %lu bytes"
- , (unsigned long) sizeof(kb));
-
- kbc.ptr = kb;
- TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc
- , &cr->keys_from_dns));
-
- /* keep a reference to last one */
- unreference_key(&cr->last_info);
- cr->last_info = reference_key(cr->keys_from_dns->key);
- }
- return NULL;
+ /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */
+ unsigned long flags /* 16 bits */
+ , protocol /* 8 bits */
+ , algorithm; /* 8 bits */
+
+ char *rest = str
+ , *p
+ , *endofnumber;
+
+ /* flags */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing flags";
+
+ flags = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed flags";
+
+ /* protocol */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing protocol";
+
+ protocol = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed protocol";
+
+ /* algorithm */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq KEY: missing algorithm";
+
+ algorithm = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq KEY: malformed algorithm";
+
+ /* is this key interesting? */
+ if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
+ && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
+ && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */
+ && (flags & 0x2CF0ul) == 0) /* must be zero */
+ {
+ /* Decode base 64 encoding of key.
+ * Similar code is in process_txt_rr_body.
+ */
+ u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */
+ chunk_t kbc;
+ err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len
+ , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE);
+
+ if (ugh != NULL)
+ return builddiag("malformed key data: %s", ugh);
+
+ if (kbc.len > sizeof(kb))
+ return builddiag("key data larger than %lu bytes"
+ , (unsigned long) sizeof(kb));
+
+ kbc.ptr = kb;
+ TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc
+ , &cr->keys_from_dns));
+
+ /* keep a reference to last one */
+ unreference_key(&cr->last_info);
+ cr->last_info = reference_key(cr->keys_from_dns->key);
+ }
+ return NULL;
}
# endif /* USE_KEYRR */
@@ -580,158 +620,158 @@ process_lwdnsq_key(u_char *str
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
struct qr_header {
- u_int16_t id; /* 16-bit identifier to match query */
+ u_int16_t id; /* 16-bit identifier to match query */
- u_int16_t stuff; /* packed crud: */
+ u_int16_t stuff; /* packed crud: */
-#define QRS_QR 0x8000 /* QR: on if this is a response */
+#define QRS_QR 0x8000 /* QR: on if this is a response */
-#define QRS_OPCODE_SHIFT 11 /* OPCODE field */
-#define QRS_OPCODE_MASK 0xF
-#define QRSO_QUERY 0 /* standard query */
-#define QRSO_IQUERY 1 /* inverse query */
-#define QRSO_STATUS 2 /* server status request query */
+#define QRS_OPCODE_SHIFT 11 /* OPCODE field */
+#define QRS_OPCODE_MASK 0xF
+#define QRSO_QUERY 0 /* standard query */
+#define QRSO_IQUERY 1 /* inverse query */
+#define QRSO_STATUS 2 /* server status request query */
-#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
-#define QRS_TC 0x0200 /* TC: on if truncation happened */
-#define QRS_RD 0x0100 /* RD: on if recursion desired */
-#define QRS_RA 0x0080 /* RA: on if recursion available */
-#define QRS_Z 0x0040 /* Z: reserved; must be zero */
-#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
-#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
+#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */
+#define QRS_TC 0x0200 /* TC: on if truncation happened */
+#define QRS_RD 0x0100 /* RD: on if recursion desired */
+#define QRS_RA 0x0080 /* RA: on if recursion available */
+#define QRS_Z 0x0040 /* Z: reserved; must be zero */
+#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */
+#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */
-#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
-#define QRS_RCODE_MASK 0xF
-#define QRSR_OK 0
+#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
+#define QRS_RCODE_MASK 0xF
+#define QRSR_OK 0
- u_int16_t qdcount; /* number of entries in question section */
- u_int16_t ancount; /* number of resource records in answer section */
- u_int16_t nscount; /* number of name server resource records in authority section */
- u_int16_t arcount; /* number of resource records in additional records section */
+ u_int16_t qdcount; /* number of entries in question section */
+ u_int16_t ancount; /* number of resource records in answer section */
+ u_int16_t nscount; /* number of name server resource records in authority section */
+ u_int16_t arcount; /* number of resource records in additional records section */
};
static field_desc qr_header_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc qr_header_desc = {
- "Query Response Header",
- qr_header_fields,
- sizeof(struct qr_header)
+ "Query Response Header",
+ qr_header_fields,
+ sizeof(struct qr_header)
};
/* Messages for codes in RCODE (see RFC 1035 4.1.1) */
static const err_t rcode_text[QRS_RCODE_MASK + 1] = {
- NULL, /* not an error */
- "Format error - The name server was unable to interpret the query",
- "Server failure - The name server was unable to process this query"
- " due to a problem with the name server",
- "Name Error - Meaningful only for responses from an authoritative name"
- " server, this code signifies that the domain name referenced in"
- " the query does not exist",
- "Not Implemented - The name server does not support the requested"
- " kind of query",
- "Refused - The name server refuses to perform the specified operation"
- " for policy reasons",
- /* the rest are reserved for future use */
- };
+ NULL, /* not an error */
+ "Format error - The name server was unable to interpret the query",
+ "Server failure - The name server was unable to process this query"
+ " due to a problem with the name server",
+ "Name Error - Meaningful only for responses from an authoritative name"
+ " server, this code signifies that the domain name referenced in"
+ " the query does not exist",
+ "Not Implemented - The name server does not support the requested"
+ " kind of query",
+ "Refused - The name server refuses to perform the specified operation"
+ " for policy reasons",
+ /* the rest are reserved for future use */
+ };
/* throw away a possibly compressed domain name */
static err_t
eat_name(pb_stream *pbs)
{
- u_char name_buf[NS_MAXDNAME + 2];
- u_char *ip = pbs->cur;
- unsigned oi = 0;
- unsigned jump_count = 0;
-
- for (;;)
- {
- u_int8_t b;
+ u_char name_buf[NS_MAXDNAME + 2];
+ u_char *ip = pbs->cur;
+ unsigned oi = 0;
+ unsigned jump_count = 0;
- if (ip >= pbs->roof)
- return "ran out of message while skipping domain name";
-
- b = *ip++;
- if (jump_count == 0)
- pbs->cur = ip;
-
- if (b == 0)
- break;
-
- switch (b & 0xC0)
+ for (;;)
{
- case 0x00:
- /* we grab the next b characters */
- if (oi + b > NS_MAXDNAME)
- return "domain name too long";
+ u_int8_t b;
- if (pbs->roof - ip <= b)
- return "domain name falls off end of message";
+ if (ip >= pbs->roof)
+ return "ran out of message while skipping domain name";
- if (oi != 0)
- name_buf[oi++] = '.';
-
- memcpy(name_buf + oi, ip, b);
- oi += b;
- ip += b;
+ b = *ip++;
if (jump_count == 0)
- pbs->cur = ip;
- break;
-
- case 0xC0:
- {
- unsigned ix;
-
- if (ip >= pbs->roof)
- return "ran out of message in middle of compressed domain name";
-
- ix = ((b & ~0xC0u) << 8) | *ip++;
- if (jump_count == 0)
pbs->cur = ip;
- if (ix >= pbs_room(pbs))
- return "impossible compressed domain name";
+ if (b == 0)
+ break;
- /* Avoid infinite loop.
- * There can be no more jumps than there are bytes
- * in the packet. Not a tight limit, but good enough.
- */
- jump_count++;
- if (jump_count > pbs_room(pbs))
- return "loop in compressed domain name";
-
- ip = pbs->start + ix;
+ switch (b & 0xC0)
+ {
+ case 0x00:
+ /* we grab the next b characters */
+ if (oi + b > NS_MAXDNAME)
+ return "domain name too long";
+
+ if (pbs->roof - ip <= b)
+ return "domain name falls off end of message";
+
+ if (oi != 0)
+ name_buf[oi++] = '.';
+
+ memcpy(name_buf + oi, ip, b);
+ oi += b;
+ ip += b;
+ if (jump_count == 0)
+ pbs->cur = ip;
+ break;
+
+ case 0xC0:
+ {
+ unsigned ix;
+
+ if (ip >= pbs->roof)
+ return "ran out of message in middle of compressed domain name";
+
+ ix = ((b & ~0xC0u) << 8) | *ip++;
+ if (jump_count == 0)
+ pbs->cur = ip;
+
+ if (ix >= pbs_room(pbs))
+ return "impossible compressed domain name";
+
+ /* Avoid infinite loop.
+ * There can be no more jumps than there are bytes
+ * in the packet. Not a tight limit, but good enough.
+ */
+ jump_count++;
+ if (jump_count > pbs_room(pbs))
+ return "loop in compressed domain name";
+
+ ip = pbs->start + ix;
+ }
+ break;
+
+ default:
+ return "invalid code in label";
}
- break;
-
- default:
- return "invalid code in label";
}
- }
- name_buf[oi++] = '\0';
+ name_buf[oi++] = '\0';
- DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
+ DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
- return NULL;
+ return NULL;
}
static err_t
eat_name_helpfully(pb_stream *pbs, const char *context)
{
- err_t ugh = eat_name(pbs);
+ err_t ugh = eat_name(pbs);
- return ugh == NULL? ugh
- : builddiag("malformed name within DNS record of %s: %s", context, ugh);
+ return ugh == NULL? ugh
+ : builddiag("malformed name within DNS record of %s: %s", context, ugh);
}
/* non-variable part of 4.1.2 Question Section entry:
@@ -749,20 +789,20 @@ eat_name_helpfully(pb_stream *pbs, const char *context)
*/
struct qs_fixed {
- u_int16_t qtype;
- u_int16_t qclass;
+ u_int16_t qtype;
+ u_int16_t qclass;
};
static field_desc qs_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
- { ft_end, 0, NULL, NULL }
+ { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
+ { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc qs_fixed_desc = {
- "Question Section entry fixed part",
- qs_fixed_fields,
- sizeof(struct qs_fixed)
+ "Question Section entry fixed part",
+ qs_fixed_fields,
+ sizeof(struct qs_fixed)
};
/* 4.1.3. Resource record format:
@@ -789,26 +829,26 @@ static struct_desc qs_fixed_desc = {
*/
struct rr_fixed {
- u_int16_t type;
- u_int16_t class;
- u_int32_t ttl; /* actually signed */
- u_int16_t rdlength;
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl; /* actually signed */
+ u_int16_t rdlength;
};
static field_desc rr_fixed_fields[] = {
- { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
- { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
- { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
- { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
+ { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
+ { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
+ { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc rr_fixed_desc = {
- "Resource Record fixed part",
- rr_fixed_fields,
- /* note: following is tricky: avoids padding problems */
- offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
+ "Resource Record fixed part",
+ rr_fixed_fields,
+ /* note: following is tricky: avoids padding problems */
+ offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
};
/* RFC 1035 3.3.14: TXT RRs have text in the RDATA field.
@@ -830,22 +870,22 @@ static struct_desc rr_fixed_desc = {
*/
struct key_rdata {
- u_int16_t flags;
- u_int8_t protocol;
- u_int8_t algorithm;
+ u_int16_t flags;
+ u_int8_t protocol;
+ u_int8_t algorithm;
};
static field_desc key_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
+ { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
+ { ft_end, 0, NULL, NULL }
};
static struct_desc key_rdata_desc = {
- "KEY RR RData fixed part",
- key_rdata_fields,
- sizeof(struct key_rdata)
+ "KEY RR RData fixed part",
+ key_rdata_fields,
+ sizeof(struct key_rdata)
};
/* RFC 2535 4.1 SIG RDATA format:
@@ -872,30 +912,30 @@ static struct_desc key_rdata_desc = {
*/
struct sig_rdata {
- u_int16_t type_covered;
- u_int8_t algorithm;
- u_int8_t labels;
- u_int32_t original_ttl;
- u_int32_t sig_expiration;
- u_int32_t sig_inception;
- u_int16_t key_tag;
+ u_int16_t type_covered;
+ u_int8_t algorithm;
+ u_int8_t labels;
+ u_int32_t original_ttl;
+ u_int32_t sig_expiration;
+ u_int32_t sig_inception;
+ u_int16_t key_tag;
};
static field_desc sig_rdata_fields[] = {
- { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
- { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
- { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
- { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
- { ft_end, 0, NULL, NULL }
+ { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
+ { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
+ { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
+ { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
+ { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
+ { ft_end, 0, NULL, NULL }
};
static struct_desc sig_rdata_desc = {
- "SIG RR RData fixed part",
- sig_rdata_fields,
- sizeof(struct sig_rdata)
+ "SIG RR RData fixed part",
+ sig_rdata_fields,
+ sizeof(struct sig_rdata)
};
/* handle a KEY Resource Record. */
@@ -903,38 +943,37 @@ static struct_desc sig_rdata_desc = {
#ifdef USE_KEYRR
static err_t
process_key_rr(u_char *ptr, size_t len
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- pb_stream pbs;
- struct key_rdata kr;
-
- if (len < sizeof(struct key_rdata))
- return "KEY Resource Record's RD Length is too small";
+ pb_stream pbs;
+ struct key_rdata kr;
- init_pbs(&pbs, ptr, len, "KEY RR");
+ if (len < sizeof(struct key_rdata))
+ return "KEY Resource Record's RD Length is too small";
- if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
- return "failed to get fixed part of KEY Resource Record RDATA";
+ init_pbs(&pbs, ptr, len, "KEY RR");
- if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
- && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
- && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
- && (kr.flags & 0x2CF0) == 0) /* must be zero */
- {
- /* we have what seems to be a tasty key */
+ if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
+ return "failed to get fixed part of KEY Resource Record RDATA";
- if (doit)
+ if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */
+ && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */
+ && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
+ && (kr.flags & 0x2CF0) == 0) /* must be zero */
{
- chunk_t k;
+ /* we have what seems to be a tasty key */
+
+ if (doit)
+ {
+ chunk_t k = { pbs.cur, pbs_left(&pbs) };
- setchunk(k, pbs.cur, pbs_left(&pbs));
- TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k
- , &cr->keys_from_dns));
+ TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k
+ , &cr->keys_from_dns));
+ }
}
- }
- return NULL;
+ return NULL;
}
#endif /* USE_KEYRR */
@@ -946,130 +985,130 @@ process_key_rr(u_char *ptr, size_t len
static err_t
unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen)
{
- size_t i = 0
- , o = 0;
+ size_t i = 0
+ , o = 0;
- while (i < slen)
- {
- size_t cl = s[i++];
+ while (i < slen)
+ {
+ size_t cl = s[i++];
- if (i + cl > slen)
- return "TXT rr RDATA representation malformed";
+ if (i + cl > slen)
+ return "TXT rr RDATA representation malformed";
- if (o + cl >= dlen)
- return "TXT rr RDATA too large";
+ if (o + cl >= dlen)
+ return "TXT rr RDATA too large";
- memcpy(d + o, s + i, cl);
- i += cl;
- o += cl;
- }
- d[o] = '\0';
- if (strlen(d) != o)
- return "TXT rr RDATA contains a NUL";
+ memcpy(d + o, s + i, cl);
+ i += cl;
+ o += cl;
+ }
+ d[o] = '\0';
+ if (strlen(d) != o)
+ return "TXT rr RDATA contains a NUL";
- return NULL;
+ return NULL;
}
static err_t
process_txt_rr(u_char *rdata, size_t rdlen
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
{
- u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */
+ u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */
- TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
- return process_txt_rr_body(str, doit, dns_auth_level, cr);
+ TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
+ return process_txt_rr_body(str, doit, dns_auth_level, cr);
}
static err_t
process_answer_section(pb_stream *pbs
-, bool doit /* should we capture information? */
+, bool doit /* should we capture information? */
, enum dns_auth_level *dns_auth_level
-, u_int16_t ancount /* number of RRs in the answer section */
+, u_int16_t ancount /* number of RRs in the answer section */
, struct adns_continuation *const cr)
{
- const int type = cr->query.type; /* type of RR of interest */
- unsigned c;
+ const int type = cr->query.type; /* type of RR of interest */
+ unsigned c;
- DBG(DBG_DNS, DBG_log("*Answer Section:"));
+ DBG(DBG_DNS, DBG_log("*Answer Section:"));
- for (c = 0; c != ancount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != ancount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- /* ??? do we need to match the name? */
+ /* ??? do we need to match the name? */
- TRY(eat_name_helpfully(pbs, "Answer Section"));
+ TRY(eat_name_helpfully(pbs, "Answer Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
- return "failed to get fixed part of Answer Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
+ return "failed to get fixed part of Answer Section Resource Record";
- if (rrf.rdlength > pbs_left(pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- if (rrf.type == type && rrf.class == C_IN)
- {
- err_t ugh = NULL;
+ if (rrf.type == type && rrf.class == C_IN)
+ {
+ err_t ugh = NULL;
- switch (type)
- {
+ switch (type)
+ {
#ifdef USE_KEYRR
- case T_KEY:
- ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
+ case T_KEY:
+ ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
+ break;
#endif /* USE_KEYRR */
- case T_TXT:
- ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
- break;
- case T_SIG:
- /* Check if SIG RR authenticates what we are learning.
- * The RRset covered by a SIG must have the same owner,
- * class, and type.
- * For us, the class is always C_IN, so that matches.
- * We decode the SIG RR's fixed part to check
- * that the type_covered field matches our query type
- * (this may be redundant).
- * We don't check the owner (apparently this is the
- * name on the record) -- we assume that it matches
- * or we would not have been given this SIG in the
- * Answer Section.
- *
- * We only look on first pass, and only if we've something
- * to learn. This cuts down on useless decoding.
- */
- if (!doit && *dns_auth_level == DAL_UNSIGNED)
- {
- struct sig_rdata sr;
-
- if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
- ugh = "failed to get fixed part of SIG Resource Record RDATA";
- else if (sr.type_covered == type)
- *dns_auth_level = DAL_SIGNED;
+ case T_TXT:
+ ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr);
+ break;
+ case T_SIG:
+ /* Check if SIG RR authenticates what we are learning.
+ * The RRset covered by a SIG must have the same owner,
+ * class, and type.
+ * For us, the class is always C_IN, so that matches.
+ * We decode the SIG RR's fixed part to check
+ * that the type_covered field matches our query type
+ * (this may be redundant).
+ * We don't check the owner (apparently this is the
+ * name on the record) -- we assume that it matches
+ * or we would not have been given this SIG in the
+ * Answer Section.
+ *
+ * We only look on first pass, and only if we've something
+ * to learn. This cuts down on useless decoding.
+ */
+ if (!doit && *dns_auth_level == DAL_UNSIGNED)
+ {
+ struct sig_rdata sr;
+
+ if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
+ ugh = "failed to get fixed part of SIG Resource Record RDATA";
+ else if (sr.type_covered == type)
+ *dns_auth_level = DAL_SIGNED;
+ }
+ break;
+ default:
+ ugh = builddiag("unexpected RR type %d", type);
+ break;
+ }
+ if (ugh != NULL)
+ return ugh;
}
- break;
- default:
- ugh = builddiag("unexpected RR type %d", type);
- break;
- }
- if (ugh != NULL)
- return ugh;
+ in_raw(NULL, tail, pbs, "RR RDATA");
}
- in_raw(NULL, tail, pbs, "RR RDATA");
- }
- return doit
- && cr->gateways_from_dns == NULL
+ return doit
+ && cr->gateways_from_dns == NULL
#ifdef USE_KEYRR
- && cr->keys_from_dns == NULL
+ && cr->keys_from_dns == NULL
#endif /* USE_KEYRR */
- ? builddiag("no suitable %s record found in DNS", rr_typename(type))
- : NULL;
+ ? builddiag("no suitable %s record found in DNS", rr_typename(type))
+ : NULL;
}
/* process DNS answer -- TXT or KEY query */
@@ -1078,153 +1117,153 @@ static err_t
process_dns_answer(struct adns_continuation *const cr
, u_char ans[], int anslen)
{
- const int type = cr->query.type; /* type of record being sought */
- int r; /* all-purpose return value holder */
- u_int16_t c; /* number of current RR in current answer section */
- pb_stream pbs;
- u_int8_t *ans_start; /* saved position of answer section */
- struct qr_header qr_header;
- enum dns_auth_level dns_auth_level;
+ const int type = cr->query.type; /* type of record being sought */
+ int r; /* all-purpose return value holder */
+ u_int16_t c; /* number of current RR in current answer section */
+ pb_stream pbs;
+ u_int8_t *ans_start; /* saved position of answer section */
+ struct qr_header qr_header;
+ enum dns_auth_level dns_auth_level;
- init_pbs(&pbs, ans, anslen, "Query Response Message");
+ init_pbs(&pbs, ans, anslen, "Query Response Message");
- /* decode and check header */
+ /* decode and check header */
- if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
- return "malformed header";
+ if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
+ return "malformed header";
- /* ID: nothing to do with us */
+ /* ID: nothing to do with us */
- /* stuff -- lots of things */
- if ((qr_header.stuff & QRS_QR) == 0)
- return "not a response?!?";
+ /* stuff -- lots of things */
+ if ((qr_header.stuff & QRS_QR) == 0)
+ return "not a response?!?";
- if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
- return "unexpected opcode";
+ if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
+ return "unexpected opcode";
- /* I don't think we care about AA */
+ /* I don't think we care about AA */
- if (qr_header.stuff & QRS_TC)
- return "response truncated";
+ if (qr_header.stuff & QRS_TC)
+ return "response truncated";
- /* I don't think we care about RD, RA, or CD */
+ /* I don't think we care about RD, RA, or CD */
- /* AD means "authentic data" */
- dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
+ /* AD means "authentic data" */
+ dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
- if (qr_header.stuff & QRS_Z)
- return "Z bit is not zero";
+ if (qr_header.stuff & QRS_Z)
+ return "Z bit is not zero";
- r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
- if (r != 0)
- return r < (int)elemsof(rcode_text)? rcode_text[r] : "unknown rcode";
+ r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
+ if (r != 0)
+ return r < (int)countof(rcode_text)? rcode_text[r] : "unknown rcode";
- if (qr_header.ancount == 0)
- return builddiag("no %s RR found by DNS", rr_typename(type));
+ if (qr_header.ancount == 0)
+ return builddiag("no %s RR found by DNS", rr_typename(type));
- /* end of header checking */
+ /* end of header checking */
- /* Question Section processing */
+ /* Question Section processing */
- /* 4.1.2. Question section format:
- * 1 1 1 1 1 1
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | |
- * / QNAME /
- * / /
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QTYPE |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | QCLASS |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- */
+ /* 4.1.2. Question section format:
+ * 1 1 1 1 1 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | |
+ * / QNAME /
+ * / /
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | QTYPE |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | QCLASS |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
- DBG(DBG_DNS, DBG_log("*Question Section:"));
+ DBG(DBG_DNS, DBG_log("*Question Section:"));
- for (c = 0; c != qr_header.qdcount; c++)
- {
- struct qs_fixed qsf;
+ for (c = 0; c != qr_header.qdcount; c++)
+ {
+ struct qs_fixed qsf;
- TRY(eat_name_helpfully(&pbs, "Question Section"));
+ TRY(eat_name_helpfully(&pbs, "Question Section"));
- if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Question Section";
+ if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Question Section";
- if (qsf.qtype != type)
- return "unexpected QTYPE in Question Section";
+ if (qsf.qtype != type)
+ return "unexpected QTYPE in Question Section";
- if (qsf.qclass != C_IN)
- return "unexpected QCLASS in Question Section";
- }
+ if (qsf.qclass != C_IN)
+ return "unexpected QCLASS in Question Section";
+ }
- /* rest of sections are made up of Resource Records */
+ /* rest of sections are made up of Resource Records */
- /* Answer Section processing -- error checking, noting T_SIG */
+ /* Answer Section processing -- error checking, noting T_SIG */
- ans_start = pbs.cur; /* remember start of answer section */
+ ans_start = pbs.cur; /* remember start of answer section */
- TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
- , qr_header.ancount, cr));
+ TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
+ , qr_header.ancount, cr));
- /* Authority Section processing (just sanity checking) */
+ /* Authority Section processing (just sanity checking) */
- DBG(DBG_DNS, DBG_log("*Authority Section:"));
+ DBG(DBG_DNS, DBG_log("*Authority Section:"));
- for (c = 0; c != qr_header.nscount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != qr_header.nscount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- TRY(eat_name_helpfully(&pbs, "Authority Section"));
+ TRY(eat_name_helpfully(&pbs, "Authority Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Authority Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Authority Section Resource Record";
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(&pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
+ in_raw(NULL, tail, &pbs, "RR RDATA");
+ }
- /* Additional Section processing (just sanity checking) */
+ /* Additional Section processing (just sanity checking) */
- DBG(DBG_DNS, DBG_log("*Additional Section:"));
+ DBG(DBG_DNS, DBG_log("*Additional Section:"));
- for (c = 0; c != qr_header.arcount; c++)
- {
- struct rr_fixed rrf;
- size_t tail;
+ for (c = 0; c != qr_header.arcount; c++)
+ {
+ struct rr_fixed rrf;
+ size_t tail;
- TRY(eat_name_helpfully(&pbs, "Additional Section"));
+ TRY(eat_name_helpfully(&pbs, "Additional Section"));
- if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
- return "failed to get fixed part of Additional Section Resource Record";
+ if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
+ return "failed to get fixed part of Additional Section Resource Record";
- if (rrf.rdlength > pbs_left(&pbs))
- return "RD Length extends beyond end of message";
+ if (rrf.rdlength > pbs_left(&pbs))
+ return "RD Length extends beyond end of message";
- /* ??? should we care about ttl? */
+ /* ??? should we care about ttl? */
- tail = rrf.rdlength;
+ tail = rrf.rdlength;
- in_raw(NULL, tail, &pbs, "RR RDATA");
- }
+ in_raw(NULL, tail, &pbs, "RR RDATA");
+ }
- /* done all sections */
+ /* done all sections */
- /* ??? is padding legal, or can we complain if more left in record? */
+ /* ??? is padding legal, or can we complain if more left in record? */
- /* process Answer Section again -- accept contents */
+ /* process Answer Section again -- accept contents */
- pbs.cur = ans_start; /* go back to start of answer section */
+ pbs.cur = ans_start; /* go back to start of answer section */
- return process_answer_section(&pbs, TRUE, &dns_auth_level
- , qr_header.ancount, cr);
+ return process_answer_section(&pbs, TRUE, &dns_auth_level
+ , qr_header.ancount, cr);
}
#endif /* ! USE_LWRES */
@@ -1239,101 +1278,101 @@ build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
, const char *typename USED_BY_DEBUG
, const char *gwname USED_BY_DEBUG)
{
- /* note: all end in "." to suppress relative searches */
- id = resolve_myid(id);
- switch (id->kind)
- {
- case ID_IPV4_ADDR:
- {
- /* XXX: this is really ugly and only temporary until addrtot can
- * generate the correct format
- */
- const unsigned char *b;
- size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
-
- passert(bl == 4);
- snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
- , b[3], b[2], b[1], b[0]);
- break;
- }
-
- case ID_IPV6_ADDR:
- {
- /* ??? is this correct? */
- const unsigned char *b;
- size_t bl;
- u_char *op = name_buf;
- static const char suffix[] = "IP6.INT.";
-
- for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
+ /* note: all end in "." to suppress relative searches */
+ id = resolve_myid(id);
+ switch (id->kind)
+ {
+ case ID_IPV4_ADDR:
{
- if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
- return "IPv6 reverse name too long";
- op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
+ /* XXX: this is really ugly and only temporary until addrtot can
+ * generate the correct format
+ */
+ const unsigned char *b;
+ size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
+
+ passert(bl == 4);
+ snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
+ , b[3], b[2], b[1], b[0]);
+ break;
}
- strcpy(op, suffix);
- break;
- }
- case ID_FQDN:
- /* strip trailing "." characters, then add one */
+ case ID_IPV6_ADDR:
{
- size_t il = id->name.len;
-
- while (il > 0 && id->name.ptr[il - 1] == '.')
- il--;
- if (il > NS_MAXDNAME)
- return "FQDN too long for domain name";
+ /* ??? is this correct? */
+ const unsigned char *b;
+ size_t bl;
+ u_char *op = name_buf;
+ static const char suffix[] = "IP6.INT.";
- memcpy(name_buf, id->name.ptr, il);
- strcpy(name_buf + il, ".");
+ for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
+ {
+ if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
+ return "IPv6 reverse name too long";
+ op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
+ }
+ strcpy(op, suffix);
+ break;
}
- break;
- default:
- return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
- }
+ case ID_FQDN:
+ /* strip trailing "." characters, then add one */
+ {
+ size_t il = id->name.len;
+
+ while (il > 0 && id->name.ptr[il - 1] == '.')
+ il--;
+ if (il > NS_MAXDNAME)
+ return "FQDN too long for domain name";
- DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)"
- , serial, typename, name_buf, gwname));
- return NULL;
+ memcpy(name_buf, id->name.ptr, il);
+ strcpy(name_buf + il, ".");
+ }
+ break;
+
+ default:
+ return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
+ }
+
+ DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)"
+ , serial, typename, name_buf, gwname));
+ return NULL;
}
void
gw_addref(struct gw_info *gw)
{
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt))
- gw->refcnt++;
- }
+ if (gw != NULL)
+ {
+ DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt))
+ gw->refcnt++;
+ }
}
void
gw_delref(struct gw_info **gwp)
{
- struct gw_info *gw = *gwp;
-
- if (gw != NULL)
- {
- DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt));
+ struct gw_info *gw = *gwp;
- passert(gw->refcnt != 0);
- gw->refcnt--;
- if (gw->refcnt == 0)
+ if (gw != NULL)
{
- free_id_content(&gw->client_id);
- free_id_content(&gw->gw_id);
- if (gw->gw_key_present)
- unreference_key(&gw->key);
- gw_delref(&gw->next);
- pfree(gw); /* trickery could make this a tail-call */
+ DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt));
+
+ passert(gw->refcnt != 0);
+ gw->refcnt--;
+ if (gw->refcnt == 0)
+ {
+ free_id_content(&gw->client_id);
+ free_id_content(&gw->gw_id);
+ if (gw->gw_key_present)
+ unreference_key(&gw->key);
+ gw_delref(&gw->next);
+ free(gw); /* trickery could make this a tail-call */
+ }
+ *gwp = NULL;
}
- *gwp = NULL;
- }
}
-static int adns_in_flight = 0; /* queries outstanding */
+static int adns_in_flight = 0; /* queries outstanding */
/* Start an asynchronous DNS query.
*
@@ -1372,123 +1411,123 @@ static int adns_in_flight = 0; /* queries outstanding */
* disestablishing any logging context (whack_log_fd, cur_*).
*/
-static struct adns_continuation *continuations = NULL; /* newest of queue */
-static struct adns_continuation *next_query = NULL; /* oldest not sent */
+static struct adns_continuation *continuations = NULL; /* newest of queue */
+static struct adns_continuation *next_query = NULL; /* oldest not sent */
static struct adns_continuation *
continuation_for_qtid(unsigned long qtid)
{
- struct adns_continuation *cr = NULL;
+ struct adns_continuation *cr = NULL;
- if (qtid != 0)
- for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
- ;
- return cr;
+ if (qtid != 0)
+ for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
+ ;
+ return cr;
}
static void
release_adns_continuation(struct adns_continuation *cr)
{
- passert(cr != next_query);
- gw_delref(&cr->gateways_from_dns);
+ passert(cr != next_query);
+ gw_delref(&cr->gateways_from_dns);
#ifdef USE_KEYRR
- free_public_keys(&cr->keys_from_dns);
+ free_public_keys(&cr->keys_from_dns);
#endif /* USE_KEYRR */
- unshare_id_content(&cr->id);
- unshare_id_content(&cr->sgw_id);
-
- /* unlink from doubly-linked list */
- if (cr->next == NULL)
- {
- passert(continuations == cr);
- continuations = cr->previous;
- }
- else
- {
- passert(cr->next->previous == cr);
- cr->next->previous = cr->previous;
- }
-
- if (cr->previous != NULL)
- {
- passert(cr->previous->next == cr);
- cr->previous->next = cr->next;
- }
-
- pfree(cr);
+ unshare_id_content(&cr->id);
+ unshare_id_content(&cr->sgw_id);
+
+ /* unlink from doubly-linked list */
+ if (cr->next == NULL)
+ {
+ passert(continuations == cr);
+ continuations = cr->previous;
+ }
+ else
+ {
+ passert(cr->next->previous == cr);
+ cr->next->previous = cr->previous;
+ }
+
+ if (cr->previous != NULL)
+ {
+ passert(cr->previous->next == cr);
+ cr->previous->next = cr->next;
+ }
+
+ free(cr);
}
err_t
-start_adns_query(const struct id *id /* domain to query */
-, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
-, int type /* T_TXT or T_KEY, selecting rr type of interest */
+start_adns_query(const struct id *id /* domain to query */
+, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
+, int type /* T_TXT or T_KEY, selecting rr type of interest */
, cont_fn_t cont_fn
, struct adns_continuation *cr)
{
- static unsigned long qtid = 1; /* query transaction id; NOTE: static */
- const char *typename = rr_typename(type);
- char gwidb[BUF_LEN];
-
- if(adns_pid == 0
- && adns_restart_count < ADNS_RESTART_MAX)
- {
- plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
- init_adns();
- }
-
-
- /* Splice this in at head of doubly-linked list of continuations.
- * Note: this must be done before any release_adns_continuation().
- */
- cr->next = NULL;
- cr->previous = continuations;
- if (continuations != NULL)
- {
- passert(continuations->next == NULL);
- continuations->next = cr;
- }
- continuations = cr;
-
- cr->qtid = qtid++;
- cr->type = type;
- cr->cont_fn = cont_fn;
- cr->id = *id;
- unshare_id_content(&cr->id);
- cr->sgw_specified = sgw_id != NULL;
- cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
- unshare_id_content(&cr->sgw_id);
- cr->gateways_from_dns = NULL;
+ static unsigned long qtid = 1; /* query transaction id; NOTE: static */
+ const char *typename = rr_typename(type);
+ char gwidb[BUF_LEN];
+
+ if(adns_pid == 0
+ && adns_restart_count < ADNS_RESTART_MAX)
+ {
+ plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
+ init_adns();
+ }
+
+
+ /* Splice this in at head of doubly-linked list of continuations.
+ * Note: this must be done before any release_adns_continuation().
+ */
+ cr->next = NULL;
+ cr->previous = continuations;
+ if (continuations != NULL)
+ {
+ passert(continuations->next == NULL);
+ continuations->next = cr;
+ }
+ continuations = cr;
+
+ cr->qtid = qtid++;
+ cr->type = type;
+ cr->cont_fn = cont_fn;
+ cr->id = *id;
+ unshare_id_content(&cr->id);
+ cr->sgw_specified = sgw_id != NULL;
+ cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
+ unshare_id_content(&cr->sgw_id);
+ cr->gateways_from_dns = NULL;
#ifdef USE_KEYRR
- cr->keys_from_dns = NULL;
+ cr->keys_from_dns = NULL;
#endif /* USE_KEYRR */
#ifdef DEBUG
- cr->debugging = cur_debugging;
+ cr->debugging = cur_debugging;
#else
- cr->debugging = LEMPTY;
+ cr->debugging = LEMPTY;
#endif
- idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
+ idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
- zero(&cr->query);
+ zero(&cr->query);
- {
- err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
- , id, typename, gwidb);
-
- if (ugh != NULL)
{
- release_adns_continuation(cr);
- return ugh;
+ err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
+ , id, typename, gwidb);
+
+ if (ugh != NULL)
+ {
+ release_adns_continuation(cr);
+ return ugh;
+ }
}
- }
- if (next_query == NULL)
- next_query = cr;
+ if (next_query == NULL)
+ next_query = cr;
- unsent_ADNS_queries = TRUE;
+ unsent_ADNS_queries = TRUE;
- return NULL;
+ return NULL;
}
/* send remaining ADNS queries (until pipe full or none left)
@@ -1501,79 +1540,79 @@ bool unsent_ADNS_queries = FALSE;
void
send_unsent_ADNS_queries(void)
{
- static const unsigned char *buf_end = NULL; /* NOTE STATIC */
- static const unsigned char *buf_cur = NULL; /* NOTE STATIC */
+ static const unsigned char *buf_end = NULL; /* NOTE STATIC */
+ static const unsigned char *buf_cur = NULL; /* NOTE STATIC */
- if (adns_qfd == NULL_FD)
- return; /* nothing useful to do */
+ if (adns_qfd == NULL_FD)
+ return; /* nothing useful to do */
- for (;;)
- {
- if (buf_cur != buf_end)
+ for (;;)
{
- static int try = 0; /* NOTE STATIC */
- size_t n = buf_end - buf_cur;
- ssize_t r = write(adns_qfd, buf_cur, n);
-
- if (r == -1)
- {
- switch (errno)
+ if (buf_cur != buf_end)
{
- case EINTR:
- continue; /* try again now */
- case EAGAIN:
- DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS"));
- break; /* try again later */
- default:
- try++;
- log_errno((e, "error %d writing DNS query", try));
- break; /* try again later */
+ static int try = 0; /* NOTE STATIC */
+ size_t n = buf_end - buf_cur;
+ ssize_t r = write(adns_qfd, buf_cur, n);
+
+ if (r == -1)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ continue; /* try again now */
+ case EAGAIN:
+ DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS"));
+ break; /* try again later */
+ default:
+ try++;
+ log_errno((e, "error %d writing DNS query", try));
+ break; /* try again later */
+ }
+ unsent_ADNS_queries = TRUE;
+ break; /* done! */
+ }
+ else
+ {
+ passert(r >= 0);
+ try = 0;
+ buf_cur += r;
+ }
}
- unsent_ADNS_queries = TRUE;
- break; /* done! */
- }
- else
- {
- passert(r >= 0);
- try = 0;
- buf_cur += r;
- }
- }
- else
- {
- if (next_query == NULL)
- {
- unsent_ADNS_queries = FALSE;
- break; /* done! */
- }
+ else
+ {
+ if (next_query == NULL)
+ {
+ unsent_ADNS_queries = FALSE;
+ break; /* done! */
+ }
#ifdef USE_LWRES
- next_query->used = FALSE;
- {
- /* NOTE STATIC: */
- static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */
-
- snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n"
- , rr_typename(next_query->type)
- , next_query->qtid
- , next_query->query.name_buf);
- DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf));
- buf_cur = qbuf;
- buf_end = qbuf + strlen(qbuf);
- }
+ next_query->used = FALSE;
+ {
+ /* NOTE STATIC: */
+ static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */
+
+ snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n"
+ , rr_typename(next_query->type)
+ , next_query->qtid
+ , next_query->query.name_buf);
+ DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf));
+ buf_cur = qbuf;
+ buf_end = qbuf + strlen(qbuf);
+ }
#else /* !USE_LWRES */
- next_query->query.debugging = next_query->debugging;
- next_query->query.serial = next_query->qtid;
- next_query->query.len = sizeof(next_query->query);
- next_query->query.qmagic = ADNS_Q_MAGIC;
- next_query->query.type = next_query->type;
- buf_cur = (const void *)&next_query->query;
- buf_end = buf_cur + sizeof(next_query->query);
+ next_query->query.debugging = next_query->debugging;
+ next_query->query.serial = next_query->qtid;
+ next_query->query.len = sizeof(next_query->query);
+ next_query->query.qmagic = ADNS_Q_MAGIC;
+ next_query->query.type = next_query->type;
+ buf_cur = (const void *)&next_query->query;
+ buf_end = buf_cur + sizeof(next_query->query);
#endif /* !USE_LWRES */
- next_query = next_query->next;
- adns_in_flight++;
+ next_query = next_query->next;
+ adns_in_flight++;
+ }
}
- }
}
#ifdef USE_LWRES
@@ -1584,379 +1623,379 @@ send_unsent_ADNS_queries(void)
static err_t
process_lwdnsq_answer(char *ts)
{
- err_t ugh = NULL;
- char *rest;
- char *p;
- char *endofnumber;
- struct adns_continuation *cr = NULL;
- unsigned long qtid;
- time_t anstime; /* time of answer */
- char *atype; /* type of answer */
- long ttl; /* ttl of answer; int, but long for conversion */
- bool AuthenticatedData = FALSE;
- static char scratch_null_str[] = ""; /* cannot be const, but isn't written */
-
- /* query transaction id */
- rest = ts;
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: answer missing query transaction ID";
-
- qtid = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed query transaction ID";
-
- cr = continuation_for_qtid(qtid);
- if (qtid != 0 && cr == NULL)
- return "lwdnsq: unrecognized qtid"; /* can't happen! */
-
- /* time */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: missing time";
-
- anstime = strtoul(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed time";
-
- /* TTL */
- p = strsep(&rest, " \t");
- if (p == NULL)
- return "lwdnsq: missing TTL";
-
- ttl = strtol(p, &endofnumber, 10);
- if (*endofnumber != '\0')
- return "lwdnsq: malformed TTL";
-
- /* type */
- atype = strsep(&rest, " \t");
- if (atype == NULL)
- return "lwdnsq: missing type";
-
- /* if rest is NULL, make it "", otherwise eat whitespace after type */
- rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t");
-
- if (strncasecmp(atype, "AD-", 3) == 0)
- {
- AuthenticatedData = TRUE;
- atype += 3;
- }
-
- /* deal with each type */
-
- if (cr == NULL)
- {
- /* we don't actually know which this applies to */
- return builddiag("lwdnsq: 0 qtid invalid with %s", atype);
- }
- else if (strcaseeq(atype, "START"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "DONE"))
- {
- if (!cr->used)
+ err_t ugh = NULL;
+ char *rest;
+ char *p;
+ char *endofnumber;
+ struct adns_continuation *cr = NULL;
+ unsigned long qtid;
+ time_t anstime; /* time of answer */
+ char *atype; /* type of answer */
+ long ttl; /* ttl of answer; int, but long for conversion */
+ bool AuthenticatedData = FALSE;
+ static char scratch_null_str[] = ""; /* cannot be const, but isn't written */
+
+ /* query transaction id */
+ rest = ts;
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: answer missing query transaction ID";
+
+ qtid = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed query transaction ID";
+
+ cr = continuation_for_qtid(qtid);
+ if (qtid != 0 && cr == NULL)
+ return "lwdnsq: unrecognized qtid"; /* can't happen! */
+
+ /* time */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: missing time";
+
+ anstime = strtoul(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed time";
+
+ /* TTL */
+ p = strsep(&rest, " \t");
+ if (p == NULL)
+ return "lwdnsq: missing TTL";
+
+ ttl = strtol(p, &endofnumber, 10);
+ if (*endofnumber != '\0')
+ return "lwdnsq: malformed TTL";
+
+ /* type */
+ atype = strsep(&rest, " \t");
+ if (atype == NULL)
+ return "lwdnsq: missing type";
+
+ /* if rest is NULL, make it "", otherwise eat whitespace after type */
+ rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t");
+
+ if (strncasecmp(atype, "AD-", 3) == 0)
{
- /* "no results returned by lwdnsq" should not happen */
- cr->cont_fn(cr
- , cr->gateways_from_dns == NULL
+ AuthenticatedData = TRUE;
+ atype += 3;
+ }
+
+ /* deal with each type */
+
+ if (cr == NULL)
+ {
+ /* we don't actually know which this applies to */
+ return builddiag("lwdnsq: 0 qtid invalid with %s", atype);
+ }
+ else if (strcaseeq(atype, "START"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "DONE"))
+ {
+ if (!cr->used)
+ {
+ /* "no results returned by lwdnsq" should not happen */
+ cr->cont_fn(cr
+ , cr->gateways_from_dns == NULL
#ifdef USE_KEYRR
- && cr->keys_from_dns == NULL
+ && cr->keys_from_dns == NULL
#endif /* USE_KEYRR */
- ? "no results returned by lwdnsq" : NULL);
- cr->used = TRUE;
+ ? "no results returned by lwdnsq" : NULL);
+ cr->used = TRUE;
+ }
+ reset_globals();
+ release_adns_continuation(cr);
+ adns_in_flight--;
+ }
+ else if (strcaseeq(atype, "RETRY"))
+ {
+ if (!cr->used)
+ {
+ cr->cont_fn(cr, rest);
+ cr->used = TRUE;
+ }
}
- reset_globals();
- release_adns_continuation(cr);
- adns_in_flight--;
- }
- else if (strcaseeq(atype, "RETRY"))
- {
- if (!cr->used)
+ else if (strcaseeq(atype, "FATAL"))
{
- cr->cont_fn(cr, rest);
- cr->used = TRUE;
+ if (!cr->used)
+ {
+ cr->cont_fn(cr, rest);
+ cr->used = TRUE;
+ }
}
- }
- else if (strcaseeq(atype, "FATAL"))
- {
- if (!cr->used)
+ else if (strcaseeq(atype, "DNSSEC"))
{
- cr->cont_fn(cr, rest);
- cr->used = TRUE;
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "DNSSEC"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "NAME"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "TXT"))
- {
- char *end = rest + strlen(rest);
- err_t txt_ugh;
-
- if (*rest == '"' && end[-1] == '"')
+ else if (strcaseeq(atype, "NAME"))
{
- /* strip those pesky quotes */
- rest++;
- *--end = '\0';
+ /* ignore */
}
+ else if (strcaseeq(atype, "TXT"))
+ {
+ char *end = rest + strlen(rest);
+ err_t txt_ugh;
+
+ if (*rest == '"' && end[-1] == '"')
+ {
+ /* strip those pesky quotes */
+ rest++;
+ *--end = '\0';
+ }
- txt_ugh = process_txt_rr_body(rest
- , TRUE
- , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
- , cr);
+ txt_ugh = process_txt_rr_body(rest
+ , TRUE
+ , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
+ , cr);
- if (txt_ugh != NULL)
+ if (txt_ugh != NULL)
+ {
+ DBG(DBG_DNS,
+ DBG_log("error processing TXT resource record (%s) while processing: %s"
+ , txt_ugh, rest));
+ cr->cont_fn(cr, txt_ugh);
+ cr->used = TRUE;
+ }
+ }
+ else if (strcaseeq(atype, "SIG"))
+ {
+ /* record the SIG records for posterity */
+ if (cr->last_info != NULL)
+ {
+ free(cr->last_info->dns_sig);
+ cr->last_info->dns_sig = clone_str(rest);
+ }
+ }
+ else if (strcaseeq(atype, "A"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "AAAA"))
{
- DBG(DBG_DNS,
- DBG_log("error processing TXT resource record (%s) while processing: %s"
- , txt_ugh, rest));
- cr->cont_fn(cr, txt_ugh);
- cr->used = TRUE;
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "SIG"))
- {
- /* record the SIG records for posterity */
- if (cr->last_info != NULL)
+ else if (strcaseeq(atype, "CNAME"))
{
- pfreeany(cr->last_info->dns_sig);
- cr->last_info->dns_sig = clone_str(rest, "sigrecord");
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "CNAMEFROM"))
+ {
+ /* ignore */
+ }
+ else if (strcaseeq(atype, "PTR"))
+ {
+ /* ignore */
}
- }
- else if (strcaseeq(atype, "A"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "AAAA"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "CNAME"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "CNAMEFROM"))
- {
- /* ignore */
- }
- else if (strcaseeq(atype, "PTR"))
- {
- /* ignore */
- }
#ifdef USE_KEYRR
- else if (strcaseeq(atype, "KEY"))
- {
- err_t key_ugh = process_lwdnsq_key(rest
- , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
- , cr);
-
- if (key_ugh != NULL)
+ else if (strcaseeq(atype, "KEY"))
{
- DBG(DBG_DNS,
- DBG_log("error processing KEY resource record (%s) while processing: %s"
- , key_ugh, rest));
- cr->cont_fn(cr, key_ugh);
- cr->used = TRUE;
+ err_t key_ugh = process_lwdnsq_key(rest
+ , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC
+ , cr);
+
+ if (key_ugh != NULL)
+ {
+ DBG(DBG_DNS,
+ DBG_log("error processing KEY resource record (%s) while processing: %s"
+ , key_ugh, rest));
+ cr->cont_fn(cr, key_ugh);
+ cr->used = TRUE;
+ }
}
- }
#endif /* USE_KEYRR */
- else
- {
- ugh = "lwdnsq: unrecognized type";
- }
- return ugh;
+ else
+ {
+ ugh = "lwdnsq: unrecognized type";
+ }
+ return ugh;
}
#endif /* USE_LWRES */
static void
recover_adns_die(void)
{
- struct adns_continuation *cr = NULL;
-
- adns_pid = 0;
- if(adns_restart_count < ADNS_RESTART_MAX) {
- adns_restart_count++;
+ struct adns_continuation *cr = NULL;
+
+ adns_pid = 0;
+ if(adns_restart_count < ADNS_RESTART_MAX) {
+ adns_restart_count++;
- /* next DNS query will restart it */
+ /* next DNS query will restart it */
- /* we have to walk the list of the outstanding requests,
- * and redo them!
- */
+ /* we have to walk the list of the outstanding requests,
+ * and redo them!
+ */
- cr = continuations;
+ cr = continuations;
- /* find the head of the list */
- if(continuations != NULL) {
- for (; cr->previous != NULL; cr = cr->previous);
- }
-
- next_query = cr;
+ /* find the head of the list */
+ if(continuations != NULL) {
+ for (; cr->previous != NULL; cr = cr->previous);
+ }
+
+ next_query = cr;
- if(next_query != NULL) {
- unsent_ADNS_queries = TRUE;
+ if(next_query != NULL) {
+ unsent_ADNS_queries = TRUE;
+ }
}
- }
}
void reset_adns_restart_count(void)
{
- adns_restart_count=0;
+ adns_restart_count=0;
}
void
handle_adns_answer(void)
{
/* These are retained across calls to handle_adns_answer. */
- static size_t buflen = 0; /* bytes in answer buffer */
+ static size_t buflen = 0; /* bytes in answer buffer */
#ifndef USE_LWRES
- static struct adns_answer buf;
+ static struct adns_answer buf;
#else /* USE_LWRES */
- static char buf[LWDNSQ_RESULT_LEN_MAX];
- static char buf_copy[LWDNSQ_RESULT_LEN_MAX];
+ static char buf[LWDNSQ_RESULT_LEN_MAX];
+ static char buf_copy[LWDNSQ_RESULT_LEN_MAX];
#endif /* USE_LWRES */
- ssize_t n;
+ ssize_t n;
- passert(buflen < sizeof(buf));
- n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen);
+ passert(buflen < sizeof(buf));
+ n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen);
- if (n < 0)
- {
- if (errno != EINTR)
+ if (n < 0)
{
- log_errno((e, "error reading answer from adns"));
- /* ??? how can we recover? */
+ if (errno != EINTR)
+ {
+ log_errno((e, "error reading answer from adns"));
+ /* ??? how can we recover? */
+ }
+ n = 0; /* now n reflects amount read */
}
- n = 0; /* now n reflects amount read */
- }
- else if (n == 0)
- {
- /* EOF */
- if (adns_in_flight != 0)
+ else if (n == 0)
{
- plog("EOF from ADNS with %d queries outstanding (restarts %d)"
- , adns_in_flight, adns_restart_count);
- recover_adns_die();
+ /* EOF */
+ if (adns_in_flight != 0)
+ {
+ plog("EOF from ADNS with %d queries outstanding (restarts %d)"
+ , adns_in_flight, adns_restart_count);
+ recover_adns_die();
+ }
+ if (buflen != 0)
+ {
+ plog("EOF from ADNS with %lu bytes of a partial answer outstanding"
+ "(restarts %d)"
+ , (unsigned long)buflen
+ , adns_restart_count);
+ recover_adns_die();
+ }
+ stop_adns();
+ return;
}
- if (buflen != 0)
+ else
{
- plog("EOF from ADNS with %lu bytes of a partial answer outstanding"
- "(restarts %d)"
- , (unsigned long)buflen
- , adns_restart_count);
- recover_adns_die();
+ passert(adns_in_flight > 0);
}
- stop_adns();
- return;
- }
- else
- {
- passert(adns_in_flight > 0);
- }
-
- buflen += n;
+
+ buflen += n;
#ifndef USE_LWRES
- while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len)
- {
- /* we've got a tasty answer -- process it */
- err_t ugh;
- struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */
- const char *typename = rr_typename(cr->query.type);
- const char *name_buf = cr->query.name_buf;
+ while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len)
+ {
+ /* we've got a tasty answer -- process it */
+ err_t ugh;
+ struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */
+ const char *typename = rr_typename(cr->query.type);
+ const char *name_buf = cr->query.name_buf;
#ifdef USE_KEYRR
- passert(cr->keys_from_dns == NULL);
+ passert(cr->keys_from_dns == NULL);
#endif /* USE_KEYRR */
- passert(cr->gateways_from_dns == NULL);
- adns_in_flight--;
- if (buf.result == -1)
- {
- /* newer resolvers support statp->res_h_errno as well as h_errno.
- * That might be better, but older resolvers don't.
- * See resolver(3), if you have it.
- * The undocumented(!) h_errno values are defined in
- * /usr/include/netdb.h.
- */
- switch (buf.h_errno_val)
- {
- case NO_DATA:
- ugh = builddiag("no %s record for %s", typename, name_buf);
- break;
- case HOST_NOT_FOUND:
- ugh = builddiag("no host %s for %s record", name_buf, typename);
- break;
- default:
- ugh = builddiag("failure querying DNS for %s of %s: %s"
- , typename, name_buf, hstrerror(buf.h_errno_val));
- break;
- }
- }
- else if (buf.result > (int) sizeof(buf.ans))
- {
- ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
- , (long)buf.result);
- }
- else
- {
- ugh = process_dns_answer(cr, buf.ans, buf.result);
- if (ugh != NULL)
- ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
- , typename, name_buf, ugh);
+ passert(cr->gateways_from_dns == NULL);
+ adns_in_flight--;
+ if (buf.result == -1)
+ {
+ /* newer resolvers support statp->res_h_errno as well as h_errno.
+ * That might be better, but older resolvers don't.
+ * See resolver(3), if you have it.
+ * The undocumented(!) h_errno values are defined in
+ * /usr/include/netdb.h.
+ */
+ switch (buf.h_errno_val)
+ {
+ case NO_DATA:
+ ugh = builddiag("no %s record for %s", typename, name_buf);
+ break;
+ case HOST_NOT_FOUND:
+ ugh = builddiag("no host %s for %s record", name_buf, typename);
+ break;
+ default:
+ ugh = builddiag("failure querying DNS for %s of %s: %s"
+ , typename, name_buf, hstrerror(buf.h_errno_val));
+ break;
+ }
+ }
+ else if (buf.result > (int) sizeof(buf.ans))
+ {
+ ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
+ , (long)buf.result);
+ }
+ else
+ {
+ ugh = process_dns_answer(cr, buf.ans, buf.result);
+ if (ugh != NULL)
+ ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
+ , typename, name_buf, ugh);
+ }
+ DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
+ DBG_log(BLANK_FORMAT);
+ if (ugh == NULL)
+ DBG_log("asynch DNS answer %lu for %s of %s"
+ , cr->query.serial, typename, name_buf);
+ else
+ DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh);
+ );
+
+ passert(GLOBALS_ARE_RESET());
+ cr->cont_fn(cr, ugh);
+ reset_globals();
+ release_adns_continuation(cr);
+
+ /* shift out answer that we've consumed */
+ buflen -= buf.len;
+ memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen);
}
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
- DBG_log(BLANK_FORMAT);
- if (ugh == NULL)
- DBG_log("asynch DNS answer %lu for %s of %s"
- , cr->query.serial, typename, name_buf);
- else
- DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh);
- );
-
- passert(GLOBALS_ARE_RESET());
- cr->cont_fn(cr, ugh);
- reset_globals();
- release_adns_continuation(cr);
-
- /* shift out answer that we've consumed */
- buflen -= buf.len;
- memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen);
- }
#else /* USE_LWRES */
- for (;;)
- {
- err_t ugh;
- char *nlp = memchr(buf, '\n', buflen);
+ for (;;)
+ {
+ err_t ugh;
+ char *nlp = memchr(buf, '\n', buflen);
- if (nlp == NULL)
- break;
+ if (nlp == NULL)
+ break;
- /* we've got a line */
- *nlp++ = '\0';
+ /* we've got a line */
+ *nlp++ = '\0';
- DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS
- , DBG_log("lwdns: %s", buf));
+ DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS
+ , DBG_log("lwdns: %s", buf));
- /* process lwdnsq_answer may modify buf, so make a copy. */
- buf_copy[0]='\0';
- strncat(buf_copy, buf, sizeof(buf_copy));
+ /* process lwdnsq_answer may modify buf, so make a copy. */
+ buf_copy[0]='\0';
+ strncat(buf_copy, buf, sizeof(buf_copy));
- ugh = process_lwdnsq_answer(buf_copy);
- if (ugh != NULL)
- plog("failure processing lwdnsq output: %s; record: %s"
- , ugh, buf);
+ ugh = process_lwdnsq_answer(buf_copy);
+ if (ugh != NULL)
+ plog("failure processing lwdnsq output: %s; record: %s"
+ , ugh, buf);
- passert(GLOBALS_ARE_RESET());
- reset_globals();
+ passert(GLOBALS_ARE_RESET());
+ reset_globals();
- /* shift out answer that we've consumed */
- buflen -= nlp - buf;
- memmove(buf, nlp, buflen);
- }
+ /* shift out answer that we've consumed */
+ buflen -= nlp - buf;
+ memmove(buf, nlp, buflen);
+ }
#endif /* USE_LWRES */
}