Exemple #1
0
int
ares_parse_mx_reply (const unsigned char *abuf, int alen,
                     struct ares_mx_reply **mx_out)
{
  unsigned int qdcount, ancount, i;
  const unsigned char *aptr, *vptr;
  int status, rr_type, rr_class, rr_len;
  long len;
  char *hostname = NULL, *rr_name = NULL;
  struct ares_mx_reply *mx_head = NULL;
  struct ares_mx_reply *mx_last = NULL;
  struct ares_mx_reply *mx_curr;

  /* Set *mx_out to NULL for all failure cases. */
  *mx_out = NULL;

  /* Give up if abuf doesn't have room for a header. */
  if (alen < HFIXEDSZ)
    return ARES_EBADRESP;

  /* Fetch the question and answer count from the header. */
  qdcount = DNS_HEADER_QDCOUNT (abuf);
  ancount = DNS_HEADER_ANCOUNT (abuf);
  if (qdcount != 1)
    return ARES_EBADRESP;
  if (ancount == 0)
    return ARES_ENODATA;

  /* Expand the name from the question, and skip past the question. */
  aptr = abuf + HFIXEDSZ;
  status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
  if (status != ARES_SUCCESS)
    return status;

  if (aptr + len + QFIXEDSZ > abuf + alen)
    {
      free (hostname);
      return ARES_EBADRESP;
    }
  aptr += len + QFIXEDSZ;

  /* Examine each answer resource record (RR) in turn. */
  for (i = 0; i < ancount; i++)
    {
      /* Decode the RR up to the data field. */
      status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
      if (status != ARES_SUCCESS)
        {
          break;
        }
      aptr += len;
      if (aptr + RRFIXEDSZ > abuf + alen)
        {
          status = ARES_EBADRESP;
          break;
        }
      rr_type = DNS_RR_TYPE (aptr);
      rr_class = DNS_RR_CLASS (aptr);
      rr_len = DNS_RR_LEN (aptr);
      aptr += RRFIXEDSZ;

      /* Check if we are really looking at a MX record */
      if (rr_class == C_IN && rr_type == T_MX)
        {
          /* parse the MX record itself */
          if (rr_len < 2)
            {
              status = ARES_EBADRESP;
              break;
            }

          /* Allocate storage for this MX answer appending it to the list */
          mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY);
          if (!mx_curr)
            {
              status = ARES_ENOMEM;
              break;
            }
          if (mx_last)
            {
              mx_last->next = mx_curr;
            }
          else
            {
              mx_head = mx_curr;
            }
          mx_last = mx_curr;

          vptr = aptr;
          mx_curr->priority = DNS__16BIT(vptr);
          vptr += sizeof(unsigned short);

          status = ares_expand_name (vptr, abuf, alen, &mx_curr->host, &len);
          if (status != ARES_SUCCESS)
            break;
        }

      /* Don't lose memory in the next iteration */
      free (rr_name);
      rr_name = NULL;

      /* Move on to the next record */
      aptr += rr_len;
    }

  if (hostname)
    free (hostname);
  if (rr_name)
    free (rr_name);

  /* clean up on error */
  if (status != ARES_SUCCESS)
    {
      if (mx_head)
        ares_free_data (mx_head);
      return status;
    }

  /* everything looks fine, return the data */
  *mx_out = mx_head;

  return ARES_SUCCESS;
}
Exemple #2
0
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;
}
Exemple #3
0
static const unsigned char *display_rr(const unsigned char *aptr,
				       const unsigned char *abuf, int alen,
				       dns_resp_t *response)
{
	const unsigned char *p;
	char *name;
	int type, dnsclass, ttl, dlen, status;
	long len;
	struct in_addr addr;

	/* Parse the RR name. */
	status = ares_expand_name(aptr, abuf, alen, &name, &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) {
		xfree(name);
		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) {
		xfree(name);
		return NULL;
	}

	/* Display the RR name, class, and type. */
	sprintf(msg, "\t%-15s.\t%d", name, ttl);
	addtobuffer(response->msgbuf, msg);
	if (dnsclass != C_IN) {
		sprintf(msg, "\t%s", class_name(dnsclass));
		addtobuffer(response->msgbuf, msg);
	}
	sprintf(msg, "\t%s", type_name(type));
	addtobuffer(response->msgbuf, msg);
	xfree(name);

	/* 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, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		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;
		sprintf(msg, "\t%.*s", (int) len, p + 1);
		addtobuffer(response->msgbuf, msg);
		p += len + 1;
		len = *p;
		if (p + len + 1 > aptr + dlen) return NULL;
		sprintf(msg, "\t%.*s", (int) len, p + 1);
		addtobuffer(response->msgbuf, msg);
		break;

	  case T_MINFO:
		/* The RR data is two domain names. */
		p = aptr;
		status = ares_expand_name(p, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		p += len;
		status = ares_expand_name(p, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		break;

	  case T_MX:
		/* The RR data is two bytes giving a preference ordering, and then a domain name.  */
		if (dlen < 2) return NULL;
		sprintf(msg, "\t%d", (aptr[0] << 8) | aptr[1]);
		addtobuffer(response->msgbuf, msg);
		status = ares_expand_name(aptr + 2, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		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, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.\n", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		p += len;
		status = ares_expand_name(p, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t\t\t\t\t\t%s.\n", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		p += len;
		if (p + 20 > aptr + dlen) return NULL;
		sprintf(msg, "\t\t\t\t\t\t( %d %d %d %d %d )",
			(p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3],
			(p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7],
			(p[8] << 24) | (p[9] << 16) | (p[10] << 8) | p[11],
			(p[12] << 24) | (p[13] << 16) | (p[14] << 8) | p[15],
			(p[16] << 24) | (p[17] << 16) | (p[18] << 8) | p[19]);
		addtobuffer(response->msgbuf, msg);
		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;
			sprintf(msg, "\t%.*s", (int)len, p + 1);
			addtobuffer(response->msgbuf, msg);
			p += len + 1;
		}
		break;

	  case T_A:
		/* The RR data is a four-byte Internet address. */
		if (dlen != 4) return NULL;
		memcpy(&addr, aptr, sizeof(struct in_addr));
		sprintf(msg, "\t%s", inet_ntoa(addr));
		addtobuffer(response->msgbuf, msg);
		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.
		 */
      
		sprintf(msg, "\t%d", DNS__16BIT(aptr));
		addtobuffer(response->msgbuf, msg);
		sprintf(msg, " %d", DNS__16BIT(aptr + 2));
		addtobuffer(response->msgbuf, msg);
		sprintf(msg, " %d", DNS__16BIT(aptr + 4));
		addtobuffer(response->msgbuf, msg);
      
		status = ares_expand_name(aptr + 6, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) return NULL;
		sprintf(msg, "\t%s.", name);
		addtobuffer(response->msgbuf, msg);
		xfree(name);
		break;
      
	  default:
		sprintf(msg, "\t[Unknown RR; cannot parse]");
		addtobuffer(response->msgbuf, msg);
	}
	sprintf(msg, "\n");
	addtobuffer(response->msgbuf, msg);

	return aptr + dlen;
}
Exemple #4
0
static const unsigned char *parse_rr(const unsigned char *aptr, const unsigned char *abuf, int alen) {
	char *name;
	long len;
	int status, type, dnsclass, dlen;
	struct in_addr addr;

	dbg("ca_tmpname: %s\n", ca_tmpname);
	status = ares_expand_name(aptr, abuf, alen, &name, &len);
	if (status != ARES_SUCCESS) {
		printf("error: failed to expand query name\n");
		exit_code(2, __PRETTY_FUNCTION__, "failed to expand query name");
	}
	aptr += len;
	if (aptr + NS_RRFIXEDSZ > abuf + alen) {
		printf("error: not enough data in DNS answer 1\n");
		free(name);
		return NULL;
	}
	type = DNS_RR_TYPE(aptr);
	dnsclass = DNS_RR_CLASS(aptr);
	dlen = DNS_RR_LEN(aptr);
	aptr += NS_RRFIXEDSZ;
	if (aptr + dlen > abuf + alen) {
		printf("error: not enough data in DNS answer 2\n");
		free(name);
		return NULL;
	}
	if (dnsclass != CARES_CLASS_C_IN) {
		printf("error: unsupported dnsclass (%i) in DNS answer\n", dnsclass);
		free(name);
		return NULL;
	}
	if (type != CARES_TYPE_SRV && type != CARES_TYPE_A && type != CARES_TYPE_CNAME) {
		printf("error: unsupported DNS response type (%i)\n", type);
		free(name);
		return NULL;
	}
	if (type == CARES_TYPE_SRV) {
		free(name);
		caport = DNS__16BIT(aptr + 4);
		dbg("caport: %i\n", caport);
		status = ares_expand_name(aptr + 6, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) {
			printf("error: failed to expand SRV name\n");
			return NULL;
		}
		dbg("SRV name: %s\n", name);
		if (is_ip(name)) {
			caadr = inet_addr(name);
			free(name);
		}
		else {
			ca_tmpname = name;
		}
	}
	else if (type == CARES_TYPE_CNAME) {
		if ((ca_tmpname != NULL) &&
				(STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0)) {
			ca_tmpname = malloc(strlen(name));
			if (ca_tmpname == NULL) {
				printf("error: failed to allocate memory\n");
				exit_code(2, __PRETTY_FUNCTION__, "memory allocation failure");
			}
			strcpy(ca_tmpname, name);
			free(name);
		}
		else {
			free(name);
			status = ares_expand_name(aptr, abuf, alen, &name, &len);
			if (status != ARES_SUCCESS) {
				printf("error: failed to expand CNAME\n");
				return NULL;
			}
			dbg("CNAME: %s\n", name);
			if (is_ip(name)) {
				caadr = inet_addr(name);
				free(name);
			}
			else {
				ca_tmpname = name;
			}
		}
	}
	else if (type == CARES_TYPE_A) {
		if (dlen == 4 && STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0) {
			memcpy(&addr, aptr, sizeof(struct in_addr));
			caadr = addr.s_addr;
		}
		free(name);
	}
	return aptr + dlen;
}
Exemple #5
0
int getaddress(char *host, int rport, int transport, struct addrinfo *ret) {
	struct addrinfo *result;
	struct addrinfo *res;
	int error;

	struct addrinfo hints = {
		.ai_family = AF_UNSPEC,
		.ai_socktype = transport == SIP_TCP_TRANSPORT ? SOCK_STREAM : SOCK_DGRAM
	};

	if (rport) {
		char strport[INT_DIGITS10];
		snprintf(strport, INT_DIGITS10, "%i", rport);
		error = getaddrinfo(host, strport, &hints, &result);
	} else {
		error = getaddrinfo(host, "sip", &hints, &result);
	}

	/* resolve the domain name into a list of addresses */
	if (error != 0) {
		if (error == EAI_SYSTEM) {
			perror("getaddrinfo");
		} else {
			fprintf(stderr, "error in getaddrinfo for %s: %s\n", host, gai_strerror(error));
		}
		return -1;
	}

	/* loop over all returned results and do inverse lookup */
	for (res = result; res != NULL; res = res->ai_next) {
		char hostname[NI_MAXHOST];

		error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0);
		if (error != 0) {
			fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
			continue;
		} if (*hostname != '\0') {
			memset(ret, 0, sizeof(struct addrinfo));
			memcpy(ret, res, sizeof(struct addrinfo));

			ret->ai_addr = malloc(res->ai_addrlen);
			memcpy(ret->ai_addr, res->ai_addr, res->ai_addrlen);
			break;
		}
	}

	freeaddrinfo(result);
	return 0;
}

#ifdef HAVE_CARES_H
static const unsigned char *parse_rr(const unsigned char *aptr, const unsigned char *abuf, int alen) {
	char *name;
	long len;
	int status, type, dnsclass, dlen;
	struct in_addr addr;

	dbg("ca_tmpname: %s\n", ca_tmpname);
	status = ares_expand_name(aptr, abuf, alen, &name, &len);
	if (status != ARES_SUCCESS) {
		printf("error: failed to expand query name\n");
		exit_code(2, __PRETTY_FUNCTION__, "failed to expand query name");
	}
	aptr += len;
	if (aptr + NS_RRFIXEDSZ > abuf + alen) {
		printf("error: not enough data in DNS answer 1\n");
		free(name);
		return NULL;
	}
	type = DNS_RR_TYPE(aptr);
	dnsclass = DNS_RR_CLASS(aptr);
	dlen = DNS_RR_LEN(aptr);
	aptr += NS_RRFIXEDSZ;
	if (aptr + dlen > abuf + alen) {
		printf("error: not enough data in DNS answer 2\n");
		free(name);
		return NULL;
	}
	if (dnsclass != CARES_CLASS_C_IN) {
		printf("error: unsupported dnsclass (%i) in DNS answer\n", dnsclass);
		free(name);
		return NULL;
	}
	if ((ca_tmpname == NULL && type != CARES_TYPE_SRV) ||
		(ca_tmpname != NULL &&
		 	(type != CARES_TYPE_A && type != CARES_TYPE_CNAME))) {
		printf("error: unsupported DNS response type (%i)\n", type);
		free(name);
		return NULL;
	}
	if (type == CARES_TYPE_SRV) {
		free(name);
		caport = DNS__16BIT(aptr + 4);
		dbg("caport: %i\n", caport);
		status = ares_expand_name(aptr + 6, abuf, alen, &name, &len);
		if (status != ARES_SUCCESS) {
			printf("error: failed to expand SRV name\n");
			return NULL;
		}
		dbg("SRV name: %s\n", name);
		if (is_ip(name)) {
			caadr = inet_addr(name);
			free(name);
		}
		else {
			ca_tmpname = name;
		}
	}
	else if (type == CARES_TYPE_CNAME) {
		if ((ca_tmpname != NULL) &&
				(STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0)) {
			ca_tmpname = malloc(strlen(name));
			if (ca_tmpname == NULL) {
				printf("error: failed to allocate memory\n");
				exit_code(2, __PRETTY_FUNCTION__, "memory allocation failure");
			}
			strcpy(ca_tmpname, name);
			free(name);
		}
		else {
			free(name);
			status = ares_expand_name(aptr, abuf, alen, &name, &len);
			if (status != ARES_SUCCESS) {
				printf("error: failed to expand CNAME\n");
				return NULL;
			}
			dbg("CNAME: %s\n", name);
			if (is_ip(name)) {
				caadr = inet_addr(name);
				free(name);
			}
			else {
				ca_tmpname = name;
			}
		}
	}
	else if (type == CARES_TYPE_A) {
		if (dlen == 4 && STRNCASECMP(ca_tmpname, name, strlen(ca_tmpname)) == 0) {
			memcpy(&addr, aptr, sizeof(struct in_addr));
			caadr = addr.s_addr;
		}
		free(name);
	}
	return aptr + dlen;
}
Exemple #6
0
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;
    }
}