Exemple #1
0
struct ResolvQuery *
resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *),
             void (*client_free_cb)(void *), void *client_cb_data,
             uint16_t port)
{
    struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;

    /*
     * Wrap udns's call back in our own
     */
    struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery));
    if (cb_data == NULL) {
        LOGE("Failed to allocate memory for DNS query callback data.");
        return NULL;
    }
    memset(cb_data, 0, sizeof(struct ResolvQuery));

    cb_data->client_cb      = client_cb;
    cb_data->client_free_cb = client_free_cb;
    cb_data->client_cb_data = client_cb_data;
    memset(cb_data->queries, 0, sizeof(cb_data->queries));
    cb_data->response_count = 0;
    cb_data->responses      = NULL;
    cb_data->port           = port;

    /* Submit A and AAAA queries */
    if (resolv_mode != MODE_IPV6_ONLY) {
        cb_data->queries[0] = dns_submit_a4(ctx,
                                            hostname, 0,
                                            dns_query_v4_cb, cb_data);
        if (cb_data->queries[0] == NULL) {
            LOGE("Failed to submit DNS query: %s",
                 dns_strerror(dns_status(ctx)));
        }
    }

    if (resolv_mode != MODE_IPV4_ONLY) {
        cb_data->queries[1] = dns_submit_a6(ctx,
                                            hostname, 0,
                                            dns_query_v6_cb, cb_data);
        if (cb_data->queries[1] == NULL) {
            LOGE("Failed to submit DNS query: %s",
                 dns_strerror(dns_status(ctx)));
        }
    }

    if (all_queries_are_null(cb_data)) {
        if (cb_data->client_free_cb != NULL) {
            cb_data->client_free_cb(cb_data->client_cb_data);
        }
        ss_free(cb_data);
    }

    return cb_data;
}
Exemple #2
0
static void dnserror(struct rblookup *ipl, const char *what) {
  char buf[4*4];
  error(0, "unable to %s for %s (%s): %s",
          what, dns_ntop(AF_INET, &ipl->key, buf, sizeof(buf)),
          ipl->zone, dns_strerror(dns_status(0)));
  ++failures;
}
Exemple #3
0
struct ResolvQuery *
resolv_query(const char *hostname, void (*client_cb)(struct Address *, void *), void (*client_free_cb)(void *), void *client_cb_data) {
    struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;

    /*
     * Wrap udns's call back in our own
     */
    struct ResolvQuery *cb_data = malloc(sizeof(struct ResolvQuery));
    if (cb_data == NULL) {
        err("Failed to allocate memory for DNS query callback data.");
        return NULL;
    }
    cb_data->client_cb = client_cb;
    cb_data->client_free_cb = client_free_cb;
    cb_data->client_cb_data = client_cb_data;

    /* Just resolving A records for now */
    cb_data->query = dns_submit_a4(ctx,
            hostname, 0,
            dns_query_cb, cb_data);
    if (cb_data->query == NULL) {
        err("Failed to submit DNS query: %s", dns_strerror(dns_status(ctx)));
        cb_data->client_free_cb(cb_data->client_cb_data);
        free(cb_data);
        return NULL;
    }

    return cb_data;
}
Exemple #4
0
static void dnscb(struct dns_ctx *ctx, void *result, void *data) {
  int r = dns_status(ctx);
  struct query *q = data;
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  unsigned char dn[DNS_MAXDN];
  const unsigned char *pkt, *cur, *end;

  if (!result) {
    return;
  }

  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = p.dnsp_qtyp = 0;
  nrr = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
    if ((qcls == DNS_C_ANY || qcls == rr.dnsrr_cls) &&
        (q->qtyp == DNS_T_ANY || q->qtyp == rr.dnsrr_typ))
      ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        r = DNS_E_PROTOCOL;
        break;
      }
      else {
        dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
      }
    }
  }
  if (!r && !nrr)
    r = DNS_E_NODATA;
  if (r < 0) {
    free(result);
    return;
  }
  dns_rewind(&p, NULL);
  p.dnsp_qtyp = q->qtyp == DNS_T_ANY ? 0 : q->qtyp;
  p.dnsp_qcls = qcls == DNS_C_ANY ? 0 : qcls;
  while(dns_nextrr(&p, &rr)) {
	const unsigned char *dptr = rr.dnsrr_dptr;
	if (rr.dnsrr_dsz == 4)  {
		char *ip = xmalloc(sizeof(char) * 16);
		sprintf(ip, "%d.%d.%d.%d", dptr[0], dptr[1], dptr[2], dptr[3]);
		
		q->callback(ip, q->data, q->g_ape);
		break;
	}
  }

  free(result);
  query_free(q);
}
Exemple #5
0
static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) {
  struct rblookup *ipl = data;
  if (r) {
    ipl->txt = r;
    ++ipl->parent->listed;
  }
  else if (dns_status(ctx) != DNS_E_NXDOMAIN)
    dnserror(ipl, "lookup DNSBL TXT record");
}
Exemple #6
0
static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
  struct ipcheck *ipc = data;
  if (rr) {
    submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
    free(rr);
  }
  else
    fprintf(stderr, "%s: unable to lookup %s: %s\n",
            progname, ipc->name, dns_strerror(dns_status(ctx)));
}
Exemple #7
0
static int submit(struct ipcheck *ipc) {
  struct in_addr addr;
  if (inet_aton(ipc->name, &addr)) {
    submit_a_queries(ipc, 1, &addr);
    ipc->name = NULL;
  }
  else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc))
    fprintf(stderr, "%s: unable to submit name query for %s: %s\n",
            progname, ipc->name, dns_strerror(dns_status(0)));
  return 0;
}
Exemple #8
0
static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
  struct ipcheck *ipc = data;
  if (rr) {
    submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
    free(rr);
  }
  else {
    error(0, "unable to lookup `%s': %s",
          ipc->name, dns_strerror(dns_status(ctx)));
    ++failures;
  }
}
Exemple #9
0
/*
 * Wrapper for client callback we provide to udns
 */
static void
dns_query_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data) {
    struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
    struct Address *address = NULL;

    if (result == NULL) {
        info("resolv: %s\n", dns_strerror(dns_status(ctx)));
    } else if (result->dnsa4_nrr > 0) {
        struct sockaddr_in sa = {
            .sin_family = AF_INET,
            .sin_port = 0,
            .sin_addr = result->dnsa4_addr[0],
        };

        address = new_address_sa((struct sockaddr *)&sa, sizeof(sa));
        if (address == NULL)
            err("Failed to allocate memory for DNS query result address");
    }

    cb_data->client_cb(address, cb_data->client_cb_data);

    cb_data->client_free_cb(cb_data->client_cb_data);
    free(cb_data);
    free(result);
    free(address);
}

/*
 * DNS timeout callback
 */
static void
resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) {
    struct dns_ctx *ctx = (struct dns_ctx *)w->data;

    dns_timeouts(ctx, 30, ev_now(loop));
}

/*
 * Callback to setup DNS timeout callback
 */
static void
dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data) {
    struct ev_loop *loop = (struct ev_loop *)data;

    if (ev_is_active(&resolv_timeout_watcher))
        ev_timer_stop(loop, &resolv_timeout_watcher);

    if (ctx != NULL && timeout >= 0) {
        ev_timer_set(&resolv_timeout_watcher, timeout, 0.0);
        ev_timer_start(loop, &resolv_timeout_watcher);
    }
}
Exemple #10
0
static int submit(struct ipcheck *ipc) {
  struct in_addr addr;
  if (dns_pton(AF_INET, ipc->name, &addr) > 0) {
    submit_a_queries(ipc, 1, &addr);
    ipc->name = NULL;
  }
  else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc)) {
    error(0, "unable to submit name query for %s: %s\n",
          ipc->name, dns_strerror(dns_status(0)));
    ++failures;
  }
  return 0;
}
Exemple #11
0
static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) {
  struct rblookup *ipl = data;
  if (r) {
    ipl->addr = r;
    ++listed;
    if (do_txt) {
      if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl))
        return;
      dnserror(ipl, "submit DNSBL TXT record");
    }
    ++ipl->parent->listed;
  }
  else if (dns_status(ctx) != DNS_E_NXDOMAIN)
    dnserror(ipl, "lookup DNSBL A record");
  else
    ipl->addr = notlisted;
}
Exemple #12
0
static void
dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data)
{
    struct ResolvQuery *cb_data = (struct ResolvQuery *)data;

    if (result == NULL) {
        if (verbose) {
            LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx)));
        }
    } else if (result->dnsa6_nrr > 0) {
        struct sockaddr **new_responses = ss_realloc(cb_data->responses,
                                                     (cb_data->response_count +
                                                      result->dnsa6_nrr) *
                                                     sizeof(struct sockaddr *));
        if (new_responses == NULL) {
            LOGE("Failed to allocate memory for additional DNS responses");
        } else {
            cb_data->responses = new_responses;

            for (int i = 0; i < result->dnsa6_nrr; i++) {
                struct sockaddr_in6 *sa = ss_malloc(sizeof(struct sockaddr_in6));
                memset(sa, 0, sizeof(struct sockaddr_in6));
                sa->sin6_family = AF_INET6;
                sa->sin6_port   = cb_data->port;
                sa->sin6_addr   = result->dnsa6_addr[i];

                cb_data->responses[cb_data->response_count] =
                    (struct sockaddr *)sa;
                if (cb_data->responses[cb_data->response_count] == NULL) {
                    LOGE(
                        "Failed to allocate memory for DNS query result address");
                } else {
                    cb_data->response_count++;
                }
            }
        }
    }

    ss_free(result);
    cb_data->queries[1] = NULL; /* mark AAAA query as being completed */

    /* Once all queries have completed, call client callback */
    if (all_queries_are_null(cb_data)) {
        return process_client_callback(cb_data);
    }
}
Exemple #13
0
static void dnserror(struct rblookup *ipl, const char *what) {
  fprintf(stderr, "%s: unable to %s for %s (%s): %s\n",
          progname, what, inet_ntoa(ipl->key), ipl->zone,
          dns_strerror(dns_status(0)));
  ++failures;
}
Exemple #14
0
static void dns_cb(struct dns_ctx *ctx, void *result, void *data) {
  int r = dns_status(ctx);
  int len, i;
  struct dns_check_info *ci = data;
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  unsigned char dn[DNS_MAXDN];
  const unsigned char *pkt, *cur, *end;
  char *result_str[MAX_RR] = { NULL };
  char *result_combined = NULL;

  /* If out ci isn't active, we must have timed out already */
  if(!__isactive_ci(ci)) {
    if(result) free(result);
    return;
  }

  ci->timed_out = 0;
  /* If we don't have a result, explode */
  if (!result) {
    ci->error = strdup(dns_strerror(r));
    goto cleanup;
  }

  /* Process the packet */
  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;
  nrr = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
    if ((ci->query_ctype == DNS_C_ANY || ci->query_ctype == rr.dnsrr_cls) &&
        (ci->query_rtype == DNS_T_ANY || ci->query_rtype == rr.dnsrr_typ))
      ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        ci->error = strdup("protocol error");
        break;
      }
      else {
        int32_t on = 1;
        /* This actually updates what we're looking for */
        dns_dntodn(p.dnsp_dnbuf, ci->dn, sizeof(dn));
        noit_stats_set_metric(ci->check, &ci->current, "cname", METRIC_INT32, &on);

        /* Now follow the leader */
        noitL(nldeb, "%s. CNAME %s.\n", dns_dntosp(dn),
              dns_dntosp(p.dnsp_dnbuf));
        dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
        noitL(nldeb, " ---> '%s'\n", dns_dntosp(dn));
      }
    }
  }
  if (!r && !nrr) {
    ci->error = strdup("no data");
  }

  dns_rewind(&p, NULL);
  p.dnsp_qtyp = ci->query_rtype == DNS_T_ANY ? 0 : ci->query_rtype;
  p.dnsp_qcls = ci->query_ctype == DNS_C_ANY ? 0 : ci->query_ctype;
  while(dns_nextrr(&p, &rr) && ci->nrr < MAX_RR)
    decode_rr(ci, &p, &rr, &result_str[ci->nrr]);
  if(ci->sort)
    qsort(result_str, ci->nrr, sizeof(*result_str), cstring_cmp);
  /* calculate the length and allocate on the stack */
  len = 0;
  for(i=0; i<ci->nrr; i++) len += strlen(result_str[i]) + 2;
  result_combined = alloca(len);
  result_combined[0] = '\0';
  /* string it together */
  len = 0;
  for(i=0; i<ci->nrr; i++) {
    int slen;
    if(i) { memcpy(result_combined + len, ", ", 2); len += 2; }
    slen = strlen(result_str[i]);
    memcpy(result_combined + len, result_str[i], slen);
    len += slen;
    result_combined[len] = '\0';
    free(result_str[i]); /* free as we go */
  }
  noit_stats_set_metric(ci->check, &ci->current, "answer", METRIC_STRING, result_combined);

 cleanup:
  if(result) free(result);
  if(ci->timeout_event) {
    eventer_t e = eventer_remove(ci->timeout_event);
    ci->timeout_event = NULL;
    if(e) eventer_free(e);
  }
  ci->check->flags &= ~NP_RUNNING;
  dns_check_log_results(ci);
  __deactivate_ci(ci);
}
static void dns_cache_resolve(struct dns_ctx *ctx, void *result, void *data,
                              enum dns_type rtype) {
  int ttl, acnt, r = dns_status(ctx), idnlen;
  dns_cache_node *n = data;
  unsigned char idn[DNS_MAXDN], dn[DNS_MAXDN];
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  struct in_addr *answers4;
  struct in6_addr *answers6;
  const unsigned char *pkt, *cur, *end;

  if(!result) goto blank;

  dns_dntodn(n->dn, idn, sizeof(idn));
  idnlen = dns_dnlen(idn);

  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;
  nrr = 0;
  ttl = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    int dnlen = dns_dnlen(rr.dnsrr_dn);
    /* if we aren't searching and the don't match...
     * or if we are searching and the prefixes don't match...
     */
    if ((dns_search_flag && !dns_dnequal(idn, rr.dnsrr_dn)) ||
        (dns_search_flag == 0 &&
         (idnlen > dnlen || memcmp(idn, rr.dnsrr_dn, idnlen-1)))) continue;
    if (DNS_C_IN == rr.dnsrr_cls && rtype == rr.dnsrr_typ) ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        break;
      }
      else {
        if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
          ttl = rr.dnsrr_ttl;
        dns_dntodn(p.dnsp_dnbuf, idn, sizeof(idn));
        idnlen = dns_dnlen(idn);
      }
    }
  }
  if(!r && !nrr) goto blank;

  dns_rewind(&p, NULL);
  p.dnsp_qcls = DNS_C_IN;
  p.dnsp_qtyp = rtype;
  if(rtype == DNS_T_A)
    answers4 = calloc(nrr, sizeof(*answers4));
  else if(rtype == DNS_T_AAAA)
    answers6 = calloc(nrr, sizeof(*answers6));
  acnt = 0;
  while(dns_nextrr(&p, &rr) && nrr < MAX_RR) {
    int dnlen = dns_dnlen(rr.dnsrr_dn);
    if ((dns_search_flag && !dns_dnequal(idn, rr.dnsrr_dn)) ||
        (dns_search_flag == 0 &&
         (idnlen > dnlen || memcmp(idn, rr.dnsrr_dn, idnlen-1)))) continue;
    if (p.dnsp_rrl && !rr.dnsrr_dn[0] && rr.dnsrr_typ == DNS_T_OPT) continue;
    if (rtype == rr.dnsrr_typ) {
      if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
        ttl = rr.dnsrr_ttl;
      switch(rr.dnsrr_typ) {
        case DNS_T_A:
          if(rr.dnsrr_dsz != 4) continue;
          memcpy(&answers4[acnt++], rr.dnsrr_dptr, rr.dnsrr_dsz);
          break;
        case DNS_T_AAAA:
          if(rr.dnsrr_dsz != 16) continue;
          memcpy(&answers6[acnt++], rr.dnsrr_dptr, rr.dnsrr_dsz);
          break;
        default:
          break;
      }
    }
  }

  n->ttl = ttl;
  if(rtype == DNS_T_A) {
    if(n->ip4) free(n->ip4);
    n->ip4_cnt = acnt;
    n->ip4 = answers4;
    n->lookup_inflight_v4 = mtev_false;
  }
  else if(rtype == DNS_T_AAAA) {
    if(n->ip6) free(n->ip6);
    n->ip6_cnt = acnt;
    n->ip6 = answers6;
    n->lookup_inflight_v6 = mtev_false;
  }
  else {
    if(result) free(result);
    return;
  }
  DCLOCK();
  mtev_skiplist_remove(&nc_dns_cache, n->target, NULL);
  n->last_updated = time(NULL);
  mtev_skiplist_insert(&nc_dns_cache, n);
  DCUNLOCK();
  mtevL(noit_debug, "Resolved %s/%s -> %d records\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")),
        acnt);
  if(result) free(result);
  return;

 blank:
  DCLOCK();
  if(rtype == DNS_T_A) blank_update_v4(n);
  if(rtype == DNS_T_AAAA) blank_update_v6(n);
  DCUNLOCK();
  mtevL(noit_debug, "Resolved %s/%s -> blank\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")));
  if(result) free(result);
  return;
}
Exemple #16
0
static void dns_cb(struct dns_ctx *ctx, void *result, void *data) {
  int r = dns_status(ctx);
  dns_lookup_ctx_t *dlc = data;
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr = 0;
  unsigned char dn[DNS_MAXDN];
  const unsigned char *pkt, *cur, *end;
  lua_State *L;

  if(!dlc->active) goto cleanup;
  if(!result) goto cleanup;

  L = dlc->ci->coro_state;

  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;

  while(dns_nextrr(&p, &rr) > 0) {
    const char *fieldname = NULL;
    char buff[DNS_MAXDN], *txt_str, *c;
    int totalsize;
    const unsigned char *pkt = p.dnsp_pkt;
    const unsigned char *end = p.dnsp_end;
    const unsigned char *dptr = rr.dnsrr_dptr;
    const unsigned char *dend = rr.dnsrr_dend;
    unsigned char *dn = rr.dnsrr_dn;
    const unsigned char *tmp;

    if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
    if ((dlc->query_ctype == DNS_C_ANY || dlc->query_ctype == rr.dnsrr_cls) &&
        (dlc->query_rtype == DNS_T_ANY || dlc->query_rtype == rr.dnsrr_typ)) {
      lua_newtable(L);
      lua_pushinteger(L, rr.dnsrr_ttl);
      lua_setfield(L, -2, "ttl");

      switch(rr.dnsrr_typ) {
        case DNS_T_A:
          if(rr.dnsrr_dsz == 4) {
            snprintf(buff, sizeof(buff), "%d.%d.%d.%d",
                     dptr[0], dptr[1], dptr[2], dptr[3]);
            lua_pushstring(L, buff);
            lua_setfield(L, -2, "a");
          }
          break;

        case DNS_T_AAAA:
          if(rr.dnsrr_dsz == 16) {
            inet_ntop(AF_INET6, dptr, buff, 16);
            lua_pushstring(L, buff);
            lua_setfield(L, -2, "aaaa");
          }
          break;

        case DNS_T_TXT:
          totalsize = 0;
          for(tmp = dptr; tmp < dend; totalsize += *tmp, tmp += *tmp + 1)
            if(tmp + *tmp + 1 > dend) break;
          /* worst case: every character escaped + '\0' */
          txt_str = alloca(totalsize * 3 + 1);
          if(!txt_str) break;
          c = txt_str;
          for(tmp = dptr; tmp < dend; tmp += *tmp + 1)
            c = encode_txt(c, tmp+1, *tmp);
          lua_pushstring(L, txt_str);
          lua_setfield(L, -2, "txt");
          break;

        case DNS_T_MX:
          lua_pushinteger(L, dns_get16(dptr));
          lua_setfield(L, -2, "preference");
          tmp = dptr + 2;
          if(dns_getdn(pkt, &tmp, end, dn, DNS_MAXDN) <= 0 || tmp != dend)
            break;
          dns_dntop(dn, buff + strlen(buff), sizeof(buff) - strlen(buff));
          lua_pushstring(L, buff);
          lua_setfield(L, -2, "mx");
          break;

        case DNS_T_CNAME: if(!fieldname) fieldname = "cname";
        case DNS_T_PTR: if(!fieldname) fieldname = "ptr";
        case DNS_T_NS: if(!fieldname) fieldname = "ns";
        case DNS_T_MB: if(!fieldname) fieldname = "mb";
        case DNS_T_MD: if(!fieldname) fieldname = "md";
        case DNS_T_MF: if(!fieldname) fieldname = "mf";
        case DNS_T_MG: if(!fieldname) fieldname = "mg";
        case DNS_T_MR: if(!fieldname) fieldname = "mr";
         if(dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN) <= 0) break;
         dns_dntop(dn, buff, sizeof(buff));
         lua_pushstring(L, buff);
         lua_setfield(L, -2, fieldname);
         break;

        default:
          break;
      }
      ++nrr;
    }
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        break;
      }
    }
  }

 cleanup:
  if(result) free(result);
  if(dlc->active) noit_lua_resume(dlc->ci, nrr);
  lookup_ctx_release(dlc);
}
static void dns_cache_resolve(struct dns_ctx *ctx, void *result, void *data,
                              enum dns_type rtype) {
  int i, ttl, acnt, r = dns_status(ctx);
  dns_cache_node *n = data;
  unsigned char idn[DNS_MAXDN], dn[DNS_MAXDN];
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  char **answers;
  const unsigned char *pkt, *cur, *end;

  if(!result) goto blank;

  dns_dntodn(n->dn, idn, sizeof(idn));

  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;
  nrr = 0;
  ttl = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    if (!dns_dnequal(idn, rr.dnsrr_dn)) continue;
    if (DNS_C_IN == rr.dnsrr_cls && rtype == rr.dnsrr_typ) ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        break;
      }
      else {
        if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
          ttl = rr.dnsrr_ttl;
        dns_dntodn(p.dnsp_dnbuf, idn, sizeof(idn));
      }
    }
  }
  if(!r && !nrr) goto blank;

  dns_rewind(&p, NULL);
  p.dnsp_qcls = DNS_C_IN;
  p.dnsp_qtyp = rtype;
  answers = calloc(nrr, sizeof(*answers));
  acnt = 0;
  while(dns_nextrr(&p, &rr) && nrr < MAX_RR) {
    char buff[INET6_ADDRSTRLEN];
    if (!dns_dnequal(idn, rr.dnsrr_dn)) continue;
    if (p.dnsp_rrl && !rr.dnsrr_dn[0] && rr.dnsrr_typ == DNS_T_OPT) continue;
    if (rtype == rr.dnsrr_typ) {
      if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
        ttl = rr.dnsrr_ttl;
      switch(rr.dnsrr_typ) {
        case DNS_T_A:
          if(rr.dnsrr_dsz != 4) continue;
          inet_ntop(AF_INET, rr.dnsrr_dptr, buff, sizeof(buff));
          answers[acnt++] = strdup(buff);
          break;
        case DNS_T_AAAA:
          if(rr.dnsrr_dsz != 16) continue;
          inet_ntop(AF_INET6, rr.dnsrr_dptr, buff, sizeof(buff));
          answers[acnt++] = strdup(buff);
          break;
        default:
          break;
      }
    }
  }

  n->ttl = ttl;
  if(rtype == DNS_T_A) {
    for(i=0;i<n->ip4_cnt;i++) if(n->ip4[i]) free(n->ip4[i]);
    if(n->ip4) free(n->ip4);
    n->ip4_cnt = acnt;
    n->ip4 = answers;
    n->lookup_inflight_v4 = noit_false;
  }
  else if(rtype == DNS_T_AAAA) {
    for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]);
    if(n->ip6) free(n->ip6);
    n->ip6_cnt = acnt;
    n->ip6 = answers;
    n->lookup_inflight_v6 = noit_false;
  }
  noit_skiplist_remove(&nc_dns_cache, n->target, NULL);
  n->last_updated = time(NULL);
  noit_skiplist_insert(&nc_dns_cache, n);
  noitL(noit_debug, "Resolved %s/%s -> %d records\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")),
        acnt);
  if(result) free(result);
  return;

 blank:
  if(rtype == DNS_T_A) blank_update_v4(n);
  if(rtype == DNS_T_AAAA) blank_update_v6(n);
  noitL(noit_debug, "Resolved %s/%s -> blank\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")));
  if(result) free(result);
  return;
}
Exemple #18
0
static PyObject*
Resolver_get_status(Resolver *self, void *closure) {
    int status = dns_status(self->ctx);

    return Py_BuildValue("i", status);
}