📄 dnskey.c
字号:
idtoa(&cr->sgw_id, gwidb, sizeof(gwidb)); 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; } } if (next_query == NULL) next_query = cr; unsent_ADNS_queries = TRUE; return NULL;}/* send remaining ADNS queries (until pipe full or none left) * * This is a co-routine, so it uses static variables to * preserve state across calls. */bool unsent_ADNS_queries = FALSE;voidsend_unsent_ADNS_queries(void){ 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 */ for (;;) { if (buf_cur != buf_end) { 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; } } 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); }#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);#endif /* !USE_LWRES */ next_query = next_query->next; adns_in_flight++; } }}#ifdef USE_LWRES/* Process a line of lwdnsq answer. * Returns with error message iff lwdnsq result is malformed. * Most errors will be in DNS data and will be handled by cr->cont_fn. */static err_tprocess_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) { /* "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#endif /* USE_KEYRR */ ? "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; } } else if (strcaseeq(atype, "TIMEOUT")) { /* for now, treat as if it was a fatal error, and run failure * shunt. Later, we will consider a valid answer and re-evaluate * life, the universe and everything */ if (!cr->used) { cr->cont_fn(cr, rest); cr->used = TRUE; } } else if (strcaseeq(atype, "FATAL")) { if (!cr->used) { cr->cont_fn(cr, rest); cr->used = TRUE; } } 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] == '"') { /* strip those pesky quotes */ rest++; *--end = '\0'; } txt_ugh = process_txt_rr_body(rest , TRUE , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC , cr); 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) { pfreeany(cr->last_info->dns_sig); cr->last_info->dns_sig = clone_str(rest, "sigrecord"); } } 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) { 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;}#endif /* USE_LWRES */static voidrecover_adns_die(void){ struct adns_continuation *cr = NULL; adns_pid = 0; if(adns_restart_count < ADNS_RESTART_MAX) { adns_restart_count++; /* next DNS query will restart it */ /* we have to walk the list of the outstanding requests, * and redo them! */ cr = continuations; /* 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; } }}void reset_adns_restart_count(void){ adns_restart_count=0;}voidhandle_adns_answer(void){ /* These are retained across calls to handle_adns_answer. */ static size_t buflen = 0; /* bytes in answer buffer */#ifndef USE_LWRES static struct adns_answer buf;#else /* USE_LWRES */ static char buf[LWDNSQ_RESULT_LEN_MAX]; static char buf_copy[LWDNSQ_RESULT_LEN_MAX];#endif /* USE_LWRES */ ssize_t n; passert(buflen < sizeof(buf)); n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen); if (n < 0) { if (errno != EINTR) { log_errno((e, "error reading answer from adns")); /* ??? how can we recover? */ } n = 0; /* now n reflects amount read */ } else if (n == 0) { /* EOF */ if (adns_in_flight != 0) { openswan_log("EOF from ADNS with %d queries outstanding (restarts %d)" , adns_in_flight, adns_restart_count); recover_adns_die(); } if (buflen != 0) { openswan_log("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; } else { passert(adns_in_flight > 0); } 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;#ifdef USE_KEYRR 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); } 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); if (nlp == NULL) break; /* we've got a line */ *nlp++ = '\0'; 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. */ memcpy(buf_copy, buf, nlp-buf); ugh = process_lwdnsq_answer(buf_copy); if (ugh != NULL) openswan_log("failure processing lwdnsq output: %s; record: %s" , ugh, buf); passert(GLOBALS_ARE_RESET()); reset_globals(); /* shift out answer that we've consumed */ buflen -= nlp - buf; memmove(buf, nlp, buflen); }#endif /* USE_LWRES */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -