コード例 #1
0
int
ares_parse_soa_reply(const unsigned char *abuf, int alen,
		     struct ares_soa_reply **soa_out)
{
  const unsigned char *aptr;
  long len;
  char *qname = NULL, *rr_name = NULL;
  struct ares_soa_reply *soa = NULL;
  int qdcount, ancount;
  int status;

  if (alen < HFIXEDSZ)
    return ARES_EBADRESP;

  /* parse message header */
  qdcount = DNS_HEADER_QDCOUNT(abuf);
  ancount = DNS_HEADER_ANCOUNT(abuf);
  if (qdcount != 1 || ancount != 1)
    return ARES_EBADRESP;
  aptr = abuf + HFIXEDSZ;

  /* query name */
  status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len);
  if (status != ARES_SUCCESS)
    goto failed_stat;
  aptr += len;

  /* skip qtype & qclass */
  if (aptr + QFIXEDSZ > abuf + alen)
    goto failed;
  aptr += QFIXEDSZ;

  /* rr_name */
  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
  if (status != ARES_SUCCESS)
    goto failed_stat;
  aptr += len;

  /* skip rr_type, rr_class, rr_ttl, rr_rdlen */
  if (aptr + RRFIXEDSZ > abuf + alen)
    goto failed;
  aptr += RRFIXEDSZ;

  /* allocate result struct */
  soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
  if (!soa)
    {
      status = ARES_ENOMEM;
      goto failed_stat;
    }

  /* nsname */
  status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, &len);
  if (status != ARES_SUCCESS)
    goto failed_stat;
  aptr += len;

  /* hostmaster */
  status = ares__expand_name_for_response(aptr, abuf, alen, &soa->hostmaster, &len);
  if (status != ARES_SUCCESS)
    goto failed_stat;
  aptr += len;

  /* integer fields */
  if (aptr + 5 * 4 > abuf + alen)
    goto failed;
  soa->serial = DNS__32BIT(aptr + 0 * 4);
  soa->refresh = DNS__32BIT(aptr + 1 * 4);
  soa->retry = DNS__32BIT(aptr + 2 * 4);
  soa->expire = DNS__32BIT(aptr + 3 * 4);
  soa->minttl = DNS__32BIT(aptr + 4 * 4);

  free(qname);
  free(rr_name);

  *soa_out = soa;

  return ARES_SUCCESS;

failed:
  status = ARES_EBADRESP;

failed_stat:
  ares_free_data(soa);
  if (qname)
    free(qname);
  if (rr_name)
    free(rr_name);
  return status;
}
コード例 #2
0
ファイル: adig.c プロジェクト: changloong/gool
static const unsigned char *display_rr(const unsigned char *aptr,
                                       const unsigned char *abuf, int alen)
{
  const unsigned char *p;
  int type, dnsclass, ttl, dlen, status;
  long len;
  char addr[46];
  union {
    unsigned char * as_uchar;
             char * as_char;
  } name;

  /* Parse the RR name. */
  status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
  if (status != ARES_SUCCESS)
    return NULL;
  aptr += len;

  /* Make sure there is enough data after the RR name for the fixed
   * part of the RR.
   */
  if (aptr + RRFIXEDSZ > abuf + alen)
    {
      ares_free_string(name.as_char);
      return NULL;
    }

  /* Parse the fixed part of the RR, and advance to the RR data
   * field. */
  type = DNS_RR_TYPE(aptr);
  dnsclass = DNS_RR_CLASS(aptr);
  ttl = DNS_RR_TTL(aptr);
  dlen = DNS_RR_LEN(aptr);
  aptr += RRFIXEDSZ;
  if (aptr + dlen > abuf + alen)
    {
      ares_free_string(name.as_char);
      return NULL;
    }

  /* Display the RR name, class, and type. */
  printf("\t%-15s.\t%d", name.as_char, ttl);
  if (dnsclass != C_IN)
    printf("\t%s", class_name(dnsclass));
  printf("\t%s", type_name(type));
  ares_free_string(name.as_char);

  /* Display the RR data.  Don't touch aptr. */
  switch (type)
    {
    case T_CNAME:
    case T_MB:
    case T_MD:
    case T_MF:
    case T_MG:
    case T_MR:
    case T_NS:
    case T_PTR:
      /* For these types, the RR data is just a domain name. */
      status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.", name.as_char);
      ares_free_string(name.as_char);
      break;

    case T_HINFO:
      /* The RR data is two length-counted character strings. */
      p = aptr;
      len = *p;
      if (p + len + 1 > aptr + dlen)
        return NULL;
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s", name.as_char);
      ares_free_string(name.as_char);
      p += len;
      len = *p;
      if (p + len + 1 > aptr + dlen)
        return NULL;
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s", name.as_char);
      ares_free_string(name.as_char);
      break;

    case T_MINFO:
      /* The RR data is two domain names. */
      p = aptr;
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.", name.as_char);
      ares_free_string(name.as_char);
      p += len;
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.", name.as_char);
      ares_free_string(name.as_char);
      break;

    case T_MX:
      /* The RR data is two bytes giving a preference ordering, and
       * then a domain name.
       */
      if (dlen < 2)
        return NULL;
      printf("\t%d", DNS__16BIT(aptr));
      status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.", name.as_char);
      ares_free_string(name.as_char);
      break;

    case T_SOA:
      /* The RR data is two domain names and then five four-byte
       * numbers giving the serial number and some timeouts.
       */
      p = aptr;
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.\n", name.as_char);
      ares_free_string(name.as_char);
      p += len;
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t\t\t\t\t\t%s.\n", name.as_char);
      ares_free_string(name.as_char);
      p += len;
      if (p + 20 > aptr + dlen)
        return NULL;
      printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
             (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4),
             (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12),
             (unsigned long)DNS__32BIT(p+16));
      break;

    case T_TXT:
      /* The RR data is one or more length-counted character
       * strings. */
      p = aptr;
      while (p < aptr + dlen)
        {
          len = *p;
          if (p + len + 1 > aptr + dlen)
            return NULL;
          status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
          if (status != ARES_SUCCESS)
            return NULL;
          printf("\t%s", name.as_char);
          ares_free_string(name.as_char);
          p += len;
        }
      break;

    case T_A:
      /* The RR data is a four-byte Internet address. */
      if (dlen != 4)
        return NULL;
      printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
      break;

    case T_AAAA:
      /* The RR data is a 16-byte IPv6 address. */
      if (dlen != 16)
        return NULL;
      printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
      break;

    case T_WKS:
      /* Not implemented yet */
      break;

    case T_SRV:
      /* The RR data is three two-byte numbers representing the
       * priority, weight, and port, followed by a domain name.
       */

      printf("\t%d", DNS__16BIT(aptr));
      printf(" %d", DNS__16BIT(aptr + 2));
      printf(" %d", DNS__16BIT(aptr + 4));

      status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t%s.", name.as_char);
      ares_free_string(name.as_char);
      break;

    case T_NAPTR:

      printf("\t%d", DNS__16BIT(aptr)); /* order */
      printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */

      p = aptr + 4;
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t\t\t\t\t\t%s\n", name.as_char);
      ares_free_string(name.as_char);
      p += len;

      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t\t\t\t\t\t%s\n", name.as_char);
      ares_free_string(name.as_char);
      p += len;

      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t\t\t\t\t\t%s\n", name.as_char);
      ares_free_string(name.as_char);
      p += len;

      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
      if (status != ARES_SUCCESS)
        return NULL;
      printf("\t\t\t\t\t\t%s", name.as_char);
      ares_free_string(name.as_char);
      break;


    default:
      printf("\t[Unknown RR; cannot parse]");
      break;
    }
  printf("\n");

  return aptr + dlen;
}
コード例 #3
0
ファイル: test_lookup.c プロジェクト: kalloc/tester
inline static const unsigned char *CheckPatternAfterParseAnswer(struct DNSTask *dnstask, const unsigned char *aptr, const unsigned char *abuf, int alen) {

    const unsigned char *p;
    int type, dnsclass, ttl, dlen, status;
    long len;
    char addr[46];

    /*
    if (task->LObjId == 1148) raise(SIGTRAP);
     */

    union {
        unsigned char * as_uchar;
        char * as_char;
    } name;

    status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
    if (status != ARES_SUCCESS)
        return NULL;
    aptr += len;

    if (aptr + RRFIXEDSZ > abuf + alen) {
        ares_free_string(name.as_char);
        return NULL;
    }

    type = DNS_RR_TYPE(aptr);
    dnsclass = DNS_RR_CLASS(aptr);
    ttl = DNS_RR_TTL(aptr);
    dlen = DNS_RR_LEN(aptr);
    aptr += RRFIXEDSZ;
    if (aptr + dlen > abuf + alen) {
        ares_free_string(name.as_char);
        return NULL;
    }
    ares_free_string(name.as_char);

    switch (type) {
        case T_CNAME:
        case T_MB:
        case T_MD:
        case T_MF:
        case T_MG:
        case T_MR:
        case T_NS:
        case T_PTR:

            status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS) {
                debug("error T_%s compare, %s andd ttl %d error - %d", type_name(type), dnstask->taskPattern, dnstask->taskTTL, status);
                return NULL;
            }
            debug("T_%s compare, %s:%08x on %s and ttl %d on %d", type_name(type), dnstask->taskPattern, dnstask->taskPattern, name.as_char, ttl, dnstask->taskTTL);
            if ((dnstask->taskPattern[0] == 0 or !memcmp(name.as_char, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) {
                dnstask->task->code = STATE_DONE;
            }
            ares_free_string(name.as_char);
            break;

        case T_HINFO:
            /* The RR data is two length-counted character strings. */
            p = aptr;
            len = *p;
            if (p + len + 1 > aptr + dlen)
                return NULL;
            debug("\t%.*s", (int) len, p + 1);
            p += len + 1;
            len = *p;
            if (p + len + 1 > aptr + dlen)
                return NULL;
            debug("\t%.*s", (int) len, p + 1);
            break;

        case T_MINFO:
            /* The RR data is two domain names. */
            p = aptr;
            status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            debug("\t%s.", name.as_char);
            ares_free_string(name.as_char);
            p += len;
            status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            debug("\t%s.", name.as_char);
            ares_free_string(name.as_char);
            break;

        case T_MX:
            if (dlen < 2) {
                return NULL;
            }
            status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS) {
                return NULL;
            }

            debug("T_MX compare %s on %s and ttl %d on %d\n", dnstask->taskPattern, name.as_char, ttl, dnstask->taskTTL);
            if ((dnstask->taskPattern[0] = 0 or !memcmp(name.as_char, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) {
                dnstask->task->code = STATE_DONE;
            }
            ares_free_string(name.as_char);


            break;

        case T_SOA:
            /* The RR data is two domain names and then five four-byte
             * numbers giving the serial number and some timeouts.
             */
            p = aptr;
            status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            debug("\t%s.", name.as_char);
            ares_free_string(name.as_char);
            p += len;
            status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            debug("\t\t\t\t\t\t%s.", name.as_char);
            ares_free_string(name.as_char);
            p += len;
            if (p + 20 > aptr + dlen)
                return NULL;
            debug("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
                    (unsigned long) DNS__32BIT(p), (unsigned long) DNS__32BIT(p + 4),
                    (unsigned long) DNS__32BIT(p + 8), (unsigned long) DNS__32BIT(p + 12),
                    (unsigned long) DNS__32BIT(p + 16));
            break;

        case T_TXT:
            /* The RR data is one or more length-counted character
             * strings. */
            p = aptr;
            while (p < aptr + dlen) {
                len = *p;
                if (p + len + 1 > aptr + dlen)
                    return NULL;

                //printf("\t%.*s", (int) len, p + 1);
                debug("T_TXT compare %s on %s and ttl %d on %d", dnstask->taskPattern, p + 1, ttl, dnstask->taskTTL);
                if (!memcmp(p + 1, dnstask->taskPattern, dnstask->taskPatternLen) and ttl == dnstask->taskTTL) {
                    dnstask->task->code = STATE_DONE;
                }

                p += len + 1;
            }
            break;

        case T_A:
            /* The RR data is a four-byte Internet address. */
            inet_ntop(AF_INET, aptr, addr, sizeof (addr));
            debug("T_A compare %s on %s (size %d) and ttl %d on %d", dnstask->taskPattern, addr, dnstask->taskPatternLen, ttl, dnstask->taskTTL);
            /*
                        if (dnstask->task->LObjId == 1056) raise(SIGSEGV);
             */

            if (dlen == 4 and(dnstask->taskPattern[0] == 0 or !memcmp(addr, dnstask->taskPattern, dnstask->taskPatternLen)) and(dnstask->taskTTL == 0 or ttl == dnstask->taskTTL)) {
                dnstask->task->code = STATE_DONE;
            }
            break;

        case T_AAAA:
            /* The RR data is a 16-byte IPv6 address. */
            if (dlen != 16)
                return NULL;
            debug("\t%s", inet_ntop(AF_INET6, aptr, addr, sizeof (addr)));
            break;

        case T_WKS:
            /* Not implemented yet */
            break;

        case T_SRV:
            /* The RR data is three two-byte numbers representing the
             * priority, weight, and port, followed by a domain name.
             */

            printf("\t%d", DNS__16BIT(aptr));
            printf(" %d", DNS__16BIT(aptr + 2));
            printf(" %d", DNS__16BIT(aptr + 4));

            status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            printf("\t%s.", name.as_char);
            ares_free_string(name.as_char);
            break;

        case T_NAPTR:

            printf("\t%d", DNS__16BIT(aptr)); /* order */
            printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */

            p = aptr + 4;
            status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            printf("\t\t\t\t\t\t%s\n", name.as_char);
            ares_free_string(name.as_char);
            p += len;

            status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            printf("\t\t\t\t\t\t%s\n", name.as_char);
            ares_free_string(name.as_char);
            p += len;

            status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            printf("\t\t\t\t\t\t%s\n", name.as_char);
            ares_free_string(name.as_char);
            p += len;

            status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
            if (status != ARES_SUCCESS)
                return NULL;
            printf("\t\t\t\t\t\t%s", name.as_char);
            ares_free_string(name.as_char);
            break;


        default:
            printf("\t[Unknown RR; cannot parse]");
            break;
    }
    if (dnstask->task->code != STATE_DONE) {
        return aptr + dlen;
    } else {
        return NULL;
    }
}