/** * QUERY. * */ static query_state query_process_query(query_type* q, ldns_rr_type qtype, engine_type* engine) { dnsout_type* dnsout = NULL; if (!q || !q->zone) { return QUERY_DISCARDED; } ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming query qtype=%s for zone %s", query_str, rrset_type2str(qtype), q->zone->name); /* sanity checks */ if (buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_tc(q->buffer)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } if (buffer_pkt_ancount(q->buffer) != 0 || (qtype != LDNS_RR_TYPE_IXFR && buffer_pkt_nscount(q->buffer) != 0)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } /* acl */ if (!q->zone->adoutbound || q->zone->adoutbound->type != ADAPTER_DNS) { ods_log_error("[%s] zone %s is not configured to have output dns " "adapter", query_str, q->zone->name); return query_refused(q); } ods_log_assert(q->zone->adoutbound->config); dnsout = (dnsout_type*) q->zone->adoutbound->config; /* acl also in use for soa and other queries */ if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) { return query_refused(q); } /* ixfr? */ if (qtype == LDNS_RR_TYPE_IXFR) { if (query_process_ixfr(q) != QUERY_PROCESSED) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } query_prepare(q); ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s", query_str, q->serial, q->zone->name); return ixfr(q, engine); } query_prepare(q); /* axfr? */ if (qtype == LDNS_RR_TYPE_AXFR) { ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming axfr request for zone %s", query_str, q->zone->name); return axfr(q, engine); } /* (soa) query */ return query_response(q, qtype); }
void axfr_fork(TASK *t) { int pfd[2] = { -1, -1 }; /* Parent/child pipe descriptors */ pid_t pid = -1, parent = -1; #if DEBUG_ENABLED && DEBUG_AXFR DebugX("axfr", 1,_("%s: axfr_fork called on fd %d"), desctask(t), t->fd); #endif if (pipe(pfd)) Err(_("pipe")); parent = getpid(); if ((pid = fork()) < 0) { close(pfd[0]); close(pfd[1]); Warn(_("%s: fork"), clientaddr(t)); return; } if (!pid) { /* Child: reset all signal handlers to default before we dive off elsewhere */ struct sigaction act; memset(&act, 0, sizeof(act)); sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = SIG_DFL; sigaction(SIGHUP, &act, NULL); sigaction(SIGUSR1, &act, NULL); sigaction(SIGUSR2, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGCHLD, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGABRT, &act, NULL); sigaction(SIGTERM, &act, NULL); #if DEBUG_ENABLED && DEBUG_AXFR DebugX("axfr", 1,_("%s: axfr_fork is in the child"), desctask(t)); #endif /* Let parent know I have started */ close(pfd[0]); if (write(pfd[1], "OK", 2) != 2) Warn(_("error writing startup notification")); close(pfd[1]); #if DEBUG_ENABLED && DEBUG_AXFR DebugX("axfr", 1,_("%s: axfr_fork child has told parent I am running"), desctask(t)); #endif /* Clean up parents resources */ free_other_tasks(t, 1); #if DEBUG_ENABLED && DEBUG_AXFR DebugX("axfr", 1,_("%s: AXFR child built"), desctask(t)); #endif /* Do AXFR */ axfr(t); } else { /* Parent */ char buf[5] = "\0\0\0\0\0"; int errct = 0; close(pfd[1]); for (errct = 0; errct < 5; errct++) { if (read(pfd[0], &buf, 4) != 2) Warn(_("%s (%d of 5)"), _("error reading startup notification"), errct+1); else break; } close(pfd[0]); #if DEBUG_ENABLED && DEBUG_AXFR DebugX("axfr", 1,_("AXFR: process started on pid %d for TCP fd %d, task ID %u"), pid, t->fd, t->internal_id); #endif } /* NOTREACHED*/ }