/**
 * 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);
}
Example #2
0
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*/
}