示例#1
0
int
main(int argc, char *argv[])
{
	int			 ch, i, r;
	uint16_t		 type = T_A;
	char			 buf[1024], *host;

	while((ch = getopt(argc, argv, "R:et:")) !=  -1) {
		switch(ch) {
		case 'R':
			parseresopt(optarg);
			break;
		case 'e':
			long_err += 1;
			break;
		case 't':
			if ((type = strtotype(optarg)) == 0)
				usage();
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	for (i = 0; i < argc; i++) {

		if (i)
			printf("\n");

		printf("===> \"%s\"\n", argv[i]);
		host = gethostarg(argv[i]);

		errno = 0;
		h_errno = 0;
		gai_errno = 0;
		rrset_errno = 0;

		r = res_mkquery(QUERY, host, C_IN, type, NULL, 0, NULL, buf, sizeof(buf));
		if (r != -1) {
			dump_packet(buf, r);
			printf(";; MSG SIZE %i\n", r);
		}
		print_errors();
	}

	return (0);
}
/*
 * ar_query_name
 *
 * generate a query based on class, type and name.
 */
int Resolver :: ar_query_name(const char *name, int xclass, int type, DNSSession* session)
{
    u_char buf[MAXPACKET];
    int r,s;
    HEADER *hptr;

    memset(buf, 0, sizeof(buf));
    PR_Lock(dnslock);
    r = res_mkquery(QUERY, name, xclass, type, NULL, 0, NULL,
        (unsigned char*)buf, sizeof(buf));
    PR_Unlock(dnslock);

    if (r <= 0)
    {
#ifndef XP_OS2
        h_errno = NO_RECOVERY;
#endif
        return r;
    }
    hptr = (HEADER *)buf;

    /* Add to chains */
    session->setID(ntohs(hptr->id));
    DNShash.add(session);

    session->setStatus(DNS_SENT);
    s = ar_send_res_msg((char*)buf, r, session->getSends());

    if (s == -1)
    {
#ifndef XP_OS2
        h_errno = TRY_AGAIN;
#endif
// XXXcelving race
//      DNShash.remove(session);
//      return -1;
        /*
         * After a DNSSession has been added to the DNShash, only DNS_manager
         * can safely remove it. Flag the DNSSession so that DNS_manager
         * removes it ASAP.
         */
        session->setSendFailed();
    }
    else
    {
        session->addSent(s);
    }
    return 0;
}
void
resolver::sendreq (dnsreq *r)
{
  if (!udpsock) {
    setsock (false);
    return;
  }

  ptr<dnssock> sock;
  if (!r->usetcp)
    sock = udpsock;
  else if (!tcpsock && !tcpinit ()) {
    setsock (true);
    return;
  }
  else
    sock = tcpsock;

  u_char qb[QBSIZE];
  int n;
  n = res_mkquery (QUERY, r->name, C_IN, r->type,
		   NULL, 0, NULL, qb, sizeof (qb));
  //warn ("query (%s, %d): %d\n", r->name.cstr (), r->type, n);
  if (n < 0) {
    r->fail (ARERR_REQINVAL);
    return;
  }

  HEADER *const h = (HEADER *) qb;
  h->id = r->id;
  h->rd = 1;

  /* FreeBSD (and possibly other OSes) have a broken dn_expand
   * function that doesn't properly invert dn_comp.
   */
  {
    dnsparse query (qb, n, false);
    question q;
    if (query.qparse (&q))
      r->name = q.q_name;
  }

  sock->sendpkt (qb, n);
}
示例#4
0
文件: res.c 项目: 12307/state-threads
static int query_domain(st_netfd_t nfd, const char *name, struct in_addr *addr,
			st_utime_t timeout)
{
  querybuf_t qbuf;
  u_char *buf = qbuf.buf;
  HEADER *hp = &qbuf.hdr;
  int blen = sizeof(qbuf);
  int i, len, id;

  for (i = 0; i < _res.nscount; i++) {
    len = res_mkquery(QUERY, name, C_IN, T_A, NULL, 0, NULL, buf, blen);
    if (len <= 0) {
      h_errno = NO_RECOVERY;
      return -1;
    }
    id = hp->id;

    if (st_sendto(nfd, buf, len, (struct sockaddr *)&(_res.nsaddr_list[i]),
		  sizeof(struct sockaddr), timeout) != len) {
      h_errno = NETDB_INTERNAL;
      /* EINTR means interrupt by other thread, NOT by a caught signal */
      if (errno == EINTR)
	return -1;
      continue;
    }

    /* Wait for reply */
    do {
      len = st_recvfrom(nfd, buf, blen, NULL, NULL, timeout);
      if (len <= 0)
	break;
    } while (id != hp->id);

    if (len < HFIXEDSZ) {
      h_errno = NETDB_INTERNAL;
      if (len >= 0)
	errno = EMSGSIZE;
      else if (errno == EINTR)  /* see the comment above */
	return -1;
      continue;
    }

    hp->ancount = ntohs(hp->ancount);
    hp->qdcount = ntohs(hp->qdcount);
    if ((hp->rcode != NOERROR) || (hp->ancount == 0)) {
      switch (hp->rcode) {
      case NXDOMAIN:
	h_errno = HOST_NOT_FOUND;
	break;
      case SERVFAIL:
	h_errno = TRY_AGAIN;
	break;
      case NOERROR:
	h_errno = NO_DATA;
	break;
      case FORMERR:
      case NOTIMP:
      case REFUSED:
      default:
	h_errno = NO_RECOVERY;
      }
      continue;
    }

    if (parse_answer(&qbuf, len, addr) == 0)
      return 0;
  }

  return -1;
}
示例#5
0
static int	dns_query(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result, int short_answer)
{
#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)

	size_t			offset = 0;
	int			res, type, retrans, retry, i, ret = SYSINFO_RET_FAIL;
	char			ip[MAX_STRING_LEN], zone[MAX_STRING_LEN], tmp[MAX_STRING_LEN], buffer[MAX_STRING_LEN];
	struct in_addr		inaddr;
#ifndef _WINDOWS
	int			saved_nscount, saved_retrans, saved_retry;
	struct sockaddr_in	saved_ns;
#endif
	typedef struct
	{
		char	*name;
		int	type;
	}
	resolv_querytype_t;

	static const resolv_querytype_t	qt[] =
	{
		{"ANY",		T_ANY},
		{"A",		T_A},
		{"NS",		T_NS},
		{"MD",		T_MD},
		{"MF",		T_MF},
		{"CNAME",	T_CNAME},
		{"SOA",		T_SOA},
		{"MB",		T_MB},
		{"MG",		T_MG},
		{"MR",		T_MR},
		{"NULL",	T_NULL},
#ifndef _WINDOWS
		{"WKS",		T_WKS},
#endif
		{"PTR",		T_PTR},
		{"HINFO",	T_HINFO},
		{"MINFO",	T_MINFO},
		{"MX",		T_MX},
		{"TXT",		T_TXT},
		{"SRV",		T_SRV},
		{NULL}
	};

#ifdef _WINDOWS
	PDNS_RECORD	pQueryResults, pDnsRecord;
	LPTSTR		wzone;
	char		tmp2[MAX_STRING_LEN];
#else
	char		*name;
	unsigned char	*msg_end, *msg_ptr, *p;
	int		num_answers, num_query, q_type, q_class, q_len, value, c, n;
	struct servent	*s;
	HEADER		*hp;
	struct protoent	*pr;
#if PACKETSZ > 1024
	unsigned char	buf[PACKETSZ];
#else
	unsigned char	buf[1024];
#endif

	typedef union
	{
		HEADER		h;
#if defined(NS_PACKETSZ)
		unsigned char	buffer[NS_PACKETSZ];
#elif defined(PACKETSZ)
		unsigned char	buffer[PACKETSZ];
#else
		unsigned char	buffer[512];
#endif
	}
	answer_t;

	answer_t	answer;
#endif	/* _WINDOWS */

	*buffer = '\0';

	if (5 < num_param(param))
		return SYSINFO_RET_FAIL;

	if (0 != get_param(param, 1, ip, sizeof(ip)))
		*ip = '\0';

	if (0 != get_param(param, 2, zone, sizeof(zone)) || '\0' == *zone)
		strscpy(zone, "zabbix.com");

	if (0 != get_param(param, 3, tmp, sizeof(tmp)) || '\0' == *tmp)
		type = T_SOA;
	else
	{
		for (i = 0; NULL != qt[i].name; i++)
		{
#ifdef _WINDOWS
			if (0 == lstrcmpiA(qt[i].name, tmp))
#else
			if (0 == strcasecmp(qt[i].name, tmp))
#endif
			{
				type = qt[i].type;
				break;
			}
		}

		if (NULL == qt[i].name)
			return SYSINFO_RET_FAIL;
	}

	if (0 != get_param(param, 4, tmp, sizeof(tmp)) || '\0' == *tmp)
		retrans = 1;
	else
		retrans = atoi(tmp);

	if (0 != get_param(param, 5, tmp, sizeof(tmp)) || '\0' == *tmp)
		retry = 2;
	else
		retry = atoi(tmp);

#ifdef _WINDOWS
	wzone = zbx_utf8_to_unicode(zone);
	res = DnsQuery(wzone, type, DNS_QUERY_STANDARD, NULL, &pQueryResults, NULL);
	zbx_free(wzone);

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1);
		ret = SYSINFO_RET_OK;
		goto clean;
	}

	if (DNS_RCODE_NOERROR != res)
		return SYSINFO_RET_FAIL;

	pDnsRecord = pQueryResults;

	while (NULL != pDnsRecord)
	{
		if (DnsSectionAnswer != pDnsRecord->Flags.S.Section)
		{
			pDnsRecord = pDnsRecord->pNext;
			continue;
		}

		if (NULL == pDnsRecord->pName)
			goto clean;

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s",
				zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp)));
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s",
				decode_type(pDnsRecord->wType));

		switch (pDnsRecord->wType)
		{
			case T_A:
				inaddr.s_addr = pDnsRecord->Data.A.IpAddress;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						inet_ntoa(inaddr));
				break;
			case T_NS:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MD:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MF:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_CNAME:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_SOA:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)),
						pDnsRecord->Data.SOA.dwSerialNo,
						pDnsRecord->Data.SOA.dwRefresh,
						pDnsRecord->Data.SOA.dwRetry,
						pDnsRecord->Data.SOA.dwExpire,
						pDnsRecord->Data.SOA.dwDefaultTtl);
				break;
			case T_MB:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MG:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu",
						pDnsRecord->Data.Null.dwByteCount);
				break;
			case T_PTR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_HINFO:
				for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp)));
				break;
			case T_MINFO:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2)));
				break;
			case T_MX:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s",
						pDnsRecord->Data.MX.wPreference,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp)));
				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");

				for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp)));

				if (0 < i)
					offset -= 1;	/* remove the trailing space */

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s",
						pDnsRecord->Data.SRV.wPriority,
						pDnsRecord->Data.SRV.wWeight,
						pDnsRecord->Data.SRV.wPort,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp)));
				break;
			default:
				break;
		}

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");

		pDnsRecord = pDnsRecord->pNext;
	}
#else	/* not _WINDOWS */
	if (-1 == res_init())	/* initialize always, settings might have changed */
		return SYSINFO_RET_FAIL;

	if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
		return SYSINFO_RET_FAIL;

	if ('\0' != *ip)
	{
		if (0 == inet_aton(ip, &inaddr))
			return SYSINFO_RET_FAIL;

		memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
		saved_nscount = _res.nscount;

		_res.nsaddr_list[0].sin_addr = inaddr;
		_res.nsaddr_list[0].sin_family = AF_INET;
		_res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
		_res.nscount = 1;
	}

	saved_retrans = _res.retrans;
	saved_retry = _res.retry;

	_res.retrans = retrans;
	_res.retry = retry;

	res = res_send(buf, res, answer.buffer, sizeof(answer.buffer));

	_res.retrans = saved_retrans;
	_res.retry = saved_retry;

	if ('\0' != *ip)
	{
		memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in));
		_res.nscount = saved_nscount;
	}

	hp = (HEADER *)answer.buffer;

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1);
		return SYSINFO_RET_OK;
	}

	if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res)
		return SYSINFO_RET_FAIL;

	msg_end = answer.buffer + res;

	num_answers = ntohs(answer.h.ancount);
	num_query = ntohs(answer.h.qdcount);

	msg_ptr = answer.buffer + HFIXEDSZ;

	/* skipping query records */
	for (; 0 < num_query && msg_ptr < msg_end; num_query--)
		msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ;

	for (; 0 < num_answers && msg_ptr < msg_end; num_answers--)
	{
		if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
			return SYSINFO_RET_FAIL;

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name);

		GETSHORT(q_type, msg_ptr);
		GETSHORT(q_class, msg_ptr);
		msg_ptr += INT32SZ;		/* skipping TTL */
		GETSHORT(q_len, msg_ptr);
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type));

		switch (q_type)
		{
			case T_A:
				switch (q_class)
				{
					case C_IN:
					case C_HS:
						memcpy(&inaddr, msg_ptr, INADDRSZ);
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr));
						break;
					default:
						;
				}

				msg_ptr += q_len;

				break;
			case T_NS:
			case T_CNAME:
			case T_MB:
			case T_MD:
			case T_MF:
			case T_MG:
			case T_MR:
			case T_PTR:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
				break;
			case T_MX:
				GETSHORT(value, msg_ptr);	/* preference */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* exchange */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_SOA:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* source host */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* administrator */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				GETLONG(value, msg_ptr);	/* serial number */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* refresh time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* retry time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* expire time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* minimum TTL */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len);
				msg_ptr += q_len;
				break;
			case T_WKS:
				if (INT32SZ + 1 > q_len)
					return SYSINFO_RET_FAIL;

				p = msg_ptr + q_len;

				memcpy(&inaddr, msg_ptr, INADDRSZ);
				msg_ptr += INT32SZ;

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr));

				if (NULL != (pr = getprotobynumber(*msg_ptr)))
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name);
				else
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr);

				msg_ptr++;
				n = 0;

				while (msg_ptr < p)
				{
					c = *msg_ptr++;

					do
					{
						if (0 != (c & 0200))
						{
							s = getservbyport((int)htons(n), pr ? pr->p_name : NULL);

							if (NULL != s)
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name);
							else
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n);
						}

						c <<= 1;
					}
					while (0 != (++n & 07));
				}

				break;
			case T_HINFO:
				p = msg_ptr + q_len;
				c = *msg_ptr++;

				if (0 != c)
				{
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
					msg_ptr += c;
				}

				if (msg_ptr < p)
				{
					c = *msg_ptr++;

					if (0 != c)
					{
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
						msg_ptr += c;
					}
				}

				break;
			case T_MINFO:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox responsible for mailing lists */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox for error messages */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");
				p = msg_ptr + q_len;

				while (msg_ptr < p)
				{
					for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--)
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++);
				}

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				GETSHORT(value, msg_ptr);       /* priority */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* weight */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* port */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* target */
					return SYSINFO_RET_FAIL;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			default:
				msg_ptr += q_len;
				break;
		}

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");
	}
#endif	/* _WINDOWS */

	if (0 != offset)
		buffer[--offset] = '\0';

	SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer));
	ret = SYSINFO_RET_OK;

#ifdef _WINDOWS
clean:
	if (DNS_RCODE_NOERROR == res)
		DnsRecordListFree(pQueryResults, DnsFreeRecordList);
#endif
	return ret;

#else	/* both HAVE_RES_QUERY and _WINDOWS not defined */

	return SYSINFO_RET_FAIL;

#endif	/* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
}
示例#6
0
文件: net.c 项目: zabbix/zabbix
static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer)
{
#if defined(HAVE_RES_QUERY) || defined(_WINDOWS)

	size_t			offset = 0;
	int			res, type, retrans, retry, use_tcp, i, ret = SYSINFO_RET_FAIL, ip_type = AF_INET;
	char			*ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param,
				tmp[MAX_STRING_LEN];
	struct in_addr		inaddr;
	struct in6_addr		in6addr;
#ifndef _WINDOWS
#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	/* It seems that on some AIX systems with no updates installed res_ninit() can */
	/* corrupt stack (see ZBX-14559). Use res_init() on AIX. */
	struct __res_state	res_state_local;
#else	/* thread-unsafe resolver API */
	int			saved_retrans, saved_retry, saved_nscount = 0;
	unsigned long		saved_options;
	struct sockaddr_in	saved_ns;
#	if defined(HAVE_RES_U_EXT)		/* thread-unsafe resolver API /Linux/ */
	int			save_nssocks, saved_nscount6;
#	endif
#endif

#if defined(HAVE_RES_EXT_EXT)		/* AIX */
	union res_sockaddr_union	saved_ns6;
#elif defined(HAVE_RES_U_EXT_EXT)	/* BSD */
	struct sockaddr_in6		saved_ns6;
#else
	struct sockaddr_in6		*saved_ns6;
#endif
	struct sockaddr_in6	sockaddrin6;
	struct addrinfo		hint, *hres = NULL;
#endif
	typedef struct
	{
		const char	*name;
		int		type;
	}
	resolv_querytype_t;

	static const resolv_querytype_t	qt[] =
	{
		{"ANY",		T_ANY},
		{"A",		T_A},
		{"AAAA",	T_AAAA},
		{"NS",		T_NS},
		{"MD",		T_MD},
		{"MF",		T_MF},
		{"CNAME",	T_CNAME},
		{"SOA",		T_SOA},
		{"MB",		T_MB},
		{"MG",		T_MG},
		{"MR",		T_MR},
		{"NULL",	T_NULL},
#ifndef _WINDOWS
		{"WKS",		T_WKS},
#endif
		{"PTR",		T_PTR},
		{"HINFO",	T_HINFO},
		{"MINFO",	T_MINFO},
		{"MX",		T_MX},
		{"TXT",		T_TXT},
		{"SRV",		T_SRV},
		{NULL}
	};

#ifdef _WINDOWS
	PDNS_RECORD	pQueryResults, pDnsRecord;
	wchar_t		*wzone;
	char		tmp2[MAX_STRING_LEN];
	DWORD		options;
#else
	char		*name;
	unsigned char	*msg_end, *msg_ptr, *p;
	int		num_answers, num_query, q_type, q_class, q_len, value, c, n;
	struct servent	*s;
	HEADER		*hp;
	struct protoent	*pr;
#if PACKETSZ > 1024
	unsigned char	buf[PACKETSZ];
#else
	unsigned char	buf[1024];
#endif

	typedef union
	{
		HEADER		h;
#if defined(NS_PACKETSZ)
		unsigned char	buffer[NS_PACKETSZ];
#elif defined(PACKETSZ)
		unsigned char	buffer[PACKETSZ];
#else
		unsigned char	buffer[512];
#endif
	}
	answer_t;

	answer_t	answer;
#endif	/* _WINDOWS */
	zbx_vector_str_t	answers;

	*buffer = '\0';

	if (6 < request->nparam)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
		return SYSINFO_RET_FAIL;
	}

	ip = get_rparam(request, 0);
	zone_str = get_rparam(request, 1);

#ifndef _WINDOWS
	memset(&hint, '\0', sizeof(hint));
	hint.ai_family = PF_UNSPEC;
	hint.ai_flags = AI_NUMERICHOST;

	if (NULL != ip && '\0' != *ip && 0 == getaddrinfo(ip, NULL, &hint, &hres) && AF_INET6 == hres->ai_family)
		ip_type = hres->ai_family;

	if (NULL != hres)
		freeaddrinfo(hres);
#endif
	if (NULL == zone_str || '\0' == *zone_str)
		strscpy(zone, "zabbix.com");
	else
		strscpy(zone, zone_str);

	param = get_rparam(request, 2);

	if (NULL == param || '\0' == *param)
		type = T_SOA;
	else
	{
		for (i = 0; NULL != qt[i].name; i++)
		{
			if (0 == strcasecmp(qt[i].name, param))
			{
				type = qt[i].type;
				break;
			}
		}

		if (NULL == qt[i].name)
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
			return SYSINFO_RET_FAIL;
		}
	}

	param = get_rparam(request, 3);

	if (NULL == param || '\0' == *param)
		retrans = 1;
	else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
		return SYSINFO_RET_FAIL;
	}

	param = get_rparam(request, 4);

	if (NULL == param || '\0' == *param)
		retry = 2;
	else if (SUCCEED != is_uint31(param, &retry) || 0 == retry)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
		return SYSINFO_RET_FAIL;
	}

	param = get_rparam(request, 5);

	if (NULL == param || '\0' == *param || 0 == strcmp(param, "udp"))
		use_tcp = 0;
	else if (0 == strcmp(param, "tcp"))
		use_tcp = 1;
	else
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter."));
		return SYSINFO_RET_FAIL;
	}

#ifdef _WINDOWS
	options = DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE;
	if (0 != use_tcp)
		options |= DNS_QUERY_USE_TCP_ONLY;

	wzone = zbx_utf8_to_unicode(zone);
	res = DnsQuery(wzone, type, options, NULL, &pQueryResults, NULL);
	zbx_free(wzone);

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1);
		ret = SYSINFO_RET_OK;
		goto clean_dns;
	}

	if (DNS_RCODE_NOERROR != res)
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res));
		return SYSINFO_RET_FAIL;
	}

	pDnsRecord = pQueryResults;
	zbx_vector_str_create(&answers);

	while (NULL != pDnsRecord)
	{
		if (DnsSectionAnswer != pDnsRecord->Flags.S.Section)
		{
			pDnsRecord = pDnsRecord->pNext;
			continue;
		}

		if (NULL == pDnsRecord->pName)
			goto clean;

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s",
				zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp)));
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s",
				decode_type(pDnsRecord->wType));

		switch (pDnsRecord->wType)
		{
			case T_A:
				inaddr.s_addr = pDnsRecord->Data.A.IpAddress;
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						inet_ntoa(inaddr));
				break;
			case T_AAAA:
				memcpy(&in6addr.s6_addr, &(pDnsRecord->Data.AAAA.Ip6Address), sizeof(in6addr.s6_addr));
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
				break;
			case T_NS:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MD:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MF:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_CNAME:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_SOA:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)),
						pDnsRecord->Data.SOA.dwSerialNo,
						pDnsRecord->Data.SOA.dwRefresh,
						pDnsRecord->Data.SOA.dwRetry,
						pDnsRecord->Data.SOA.dwExpire,
						pDnsRecord->Data.SOA.dwDefaultTtl);
				break;
			case T_MB:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MG:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_MR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu",
						pDnsRecord->Data.Null.dwByteCount);
				break;
			case T_PTR:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp)));
				break;
			case T_HINFO:
				for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp)));
				break;
			case T_MINFO:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s",
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)),
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2)));
				break;
			case T_MX:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s",
						pDnsRecord->Data.MX.wPreference,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp)));
				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");

				for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++)
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ",
							zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp)));

				if (0 < i)
					offset -= 1;	/* remove the trailing space */

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s",
						pDnsRecord->Data.SRV.wPriority,
						pDnsRecord->Data.SRV.wWeight,
						pDnsRecord->Data.SRV.wPort,
						zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp)));
				break;
			default:
				break;
		}

		zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");

		pDnsRecord = pDnsRecord->pNext;
		zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
		offset = 0;
		*buffer = '\0';
	}
#else	/* not _WINDOWS */
#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	memset(&res_state_local, 0, sizeof(res_state_local));
	if (-1 == res_ninit(&res_state_local))	/* initialize always, settings might have changed */
#else
	if (-1 == res_init())	/* initialize always, settings might have changed */
#endif
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

#if defined(HAVE_RES_NINIT) && !defined(_AIX)
	if (-1 == (res = res_nmkquery(&res_state_local, QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
#else
	if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf))))
#endif
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

	if (NULL != ip && '\0' != *ip && AF_INET == ip_type)
	{
		if (0 == inet_aton(ip, &inaddr))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address."));
			return SYSINFO_RET_FAIL;
		}

#if defined(HAVE_RES_NINIT) && !defined(_AIX)
		res_state_local.nsaddr_list[0].sin_addr = inaddr;
		res_state_local.nsaddr_list[0].sin_family = AF_INET;
		res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
		res_state_local.nscount = 1;
#else	/* thread-unsafe resolver API */
		memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
		saved_nscount = _res.nscount;

		_res.nsaddr_list[0].sin_addr = inaddr;
		_res.nsaddr_list[0].sin_family = AF_INET;
		_res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
		_res.nscount = 1;
#endif
	}
	else if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
	{
		if (0 == inet_pton(ip_type, ip, &in6addr))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IPv6 address."));
			return SYSINFO_RET_FAIL;
		}

		memset(&sockaddrin6, '\0', sizeof(sockaddrin6));
#if defined(HAVE_RES_SIN6_LEN)
		sockaddrin6.sin6_len = sizeof(sockaddrin6);
#endif
		sockaddrin6.sin6_family = AF_INET6;
		sockaddrin6.sin6_addr = in6addr;
		sockaddrin6.sin6_port = htons(ZBX_DEFAULT_DNS_PORT);
#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
		memset(&res_state_local.nsaddr_list[0], '\0', sizeof(res_state_local.nsaddr_list[0]));
#		ifdef HAVE_RES_U_EXT			/* Linux */
		saved_ns6 = res_state_local._u._ext.nsaddrs[0];
		res_state_local._u._ext.nsaddrs[0] = &sockaddrin6;
		res_state_local._u._ext.nssocks[0] = -1;
		res_state_local._u._ext.nscount6 = 1;	/* CentOS */
#		elif HAVE_RES_U_EXT_EXT			/* BSD */
		if (NULL != res_state_local._u._ext.ext)
			memcpy(res_state_local._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));

		res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);
#		endif
		res_state_local.nscount = 1;
#else
		memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in));
		saved_nscount = _res.nscount;
#		if defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT) || defined(HAVE_RES_EXT_EXT)
		memset(&_res.nsaddr_list[0], '\0', sizeof(_res.nsaddr_list[0]));
		_res.nscount = 1;
#		endif
#		if defined(HAVE_RES_U_EXT)		/* thread-unsafe resolver API /Linux/ */
		saved_nscount6 = _res._u._ext.nscount6;
		saved_ns6 = _res._u._ext.nsaddrs[0];
		save_nssocks = _res._u._ext.nssocks[0];
		_res._u._ext.nsaddrs[0] = &sockaddrin6;
		_res._u._ext.nssocks[0] = -1;
		_res._u._ext.nscount6 = 1;
#		elif defined(HAVE_RES_U_EXT_EXT)	/* thread-unsafe resolver API /BSD/ */
		memcpy(&saved_ns6, _res._u._ext.ext, sizeof(saved_ns6));
		_res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT);

		if (NULL != _res._u._ext.ext)
			memcpy(_res._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6));
#		elif defined(HAVE_RES_EXT_EXT)		/* thread-unsafe resolver API /AIX/ */
		memcpy(&saved_ns6, &(_res._ext.ext.nsaddrs[0]), sizeof(saved_ns6));
		memcpy(&_res._ext.ext.nsaddrs[0], &sockaddrin6, sizeof(sockaddrin6));
#		endif /* #if defined(HAVE_RES_U_EXT) */
#endif /* #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) */
	}

#if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT))
	if (0 != use_tcp)
		res_state_local.options |= RES_USEVC;

	res_state_local.retrans = retrans;
	res_state_local.retry = retry;

	res = res_nsend(&res_state_local, buf, res, answer.buffer, sizeof(answer.buffer));

#	ifdef HAVE_RES_U_EXT	/* Linux */
	if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type)
		res_state_local._u._ext.nsaddrs[0] = saved_ns6;
#	endif
#	ifdef HAVE_RES_NDESTROY
	res_ndestroy(&res_state_local);
#	else
	res_nclose(&res_state_local);
#	endif
#else	/* thread-unsafe resolver API */
	saved_options = _res.options;
	saved_retrans = _res.retrans;
	saved_retry = _res.retry;

	if (0 != use_tcp)
		_res.options |= RES_USEVC;

	_res.retrans = retrans;
	_res.retry = retry;

	res = res_send(buf, res, answer.buffer, sizeof(answer.buffer));

	_res.options = saved_options;
	_res.retrans = saved_retrans;
	_res.retry = saved_retry;

	if (NULL != ip && '\0' != *ip)
	{
		if (AF_INET6 == ip_type)
		{
#			if defined(HAVE_RES_U_EXT)		/* Linux */
			_res._u._ext.nsaddrs[0] = saved_ns6;
			_res._u._ext.nssocks[0] = save_nssocks;
			_res._u._ext.nscount6 = saved_nscount6;
#			elif defined(HAVE_RES_U_EXT_EXT)	/* BSD */
			if (NULL != _res._u._ext.ext)
				memcpy(_res._u._ext.ext, &saved_ns6, sizeof(saved_ns6));
#			elif defined(HAVE_RES_EXT_EXT)		/* AIX */
			memcpy(&_res._ext.ext.nsaddrs[0], &saved_ns6, sizeof(saved_ns6));
#			endif
		}

		memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in));
		_res.nscount = saved_nscount;
	}
#endif
	hp = (HEADER *)answer.buffer;

	if (1 == short_answer)
	{
		SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1);
		return SYSINFO_RET_OK;
	}

	if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query."));
		return SYSINFO_RET_FAIL;
	}

	msg_end = answer.buffer + res;

	num_answers = ntohs(answer.h.ancount);
	num_query = ntohs(answer.h.qdcount);

	msg_ptr = answer.buffer + HFIXEDSZ;
	zbx_vector_str_create(&answers);

	/* skipping query records */
	for (; 0 < num_query && msg_ptr < msg_end; num_query--)
		msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ;

	for (; 0 < num_answers && msg_ptr < msg_end; num_answers--)
	{
		if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
			ret = SYSINFO_RET_FAIL;
			goto clean;
		}

		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name);

		GETSHORT(q_type, msg_ptr);
		GETSHORT(q_class, msg_ptr);
		msg_ptr += INT32SZ;		/* skipping TTL */
		GETSHORT(q_len, msg_ptr);
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type));

		switch (q_type)
		{
			case T_A:
				switch (q_class)
				{
					case C_IN:
					case C_HS:
						memcpy(&inaddr, msg_ptr, INADDRSZ);
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
								inet_ntoa(inaddr));
						break;
					default:
						;
				}

				msg_ptr += q_len;

				break;
			case T_AAAA:
				switch (q_class)
				{
					case C_IN:
					case C_HS:
						memcpy(&in6addr, msg_ptr, IN6ADDRSZ);
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s",
								inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp)));
						break;
					default:
						;
				}

				msg_ptr += q_len;

				break;
			case T_NS:
			case T_CNAME:
			case T_MB:
			case T_MD:
			case T_MF:
			case T_MG:
			case T_MR:
			case T_PTR:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
				break;
			case T_MX:
				GETSHORT(value, msg_ptr);	/* preference */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* exchange */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_SOA:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* source host */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* administrator */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				GETLONG(value, msg_ptr);	/* serial number */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* refresh time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* retry time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* expire time */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETLONG(value, msg_ptr);	/* minimum TTL */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				break;
			case T_NULL:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len);
				msg_ptr += q_len;
				break;
			case T_WKS:
				if (INT32SZ + 1 > q_len)
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}

				p = msg_ptr + q_len;

				memcpy(&inaddr, msg_ptr, INADDRSZ);
				msg_ptr += INT32SZ;

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr));

				if (NULL != (pr = getprotobynumber(*msg_ptr)))
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name);
				else
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr);

				msg_ptr++;
				n = 0;

				while (msg_ptr < p)
				{
					c = *msg_ptr++;

					do
					{
						if (0 != (c & 0200))
						{
							s = getservbyport((int)htons(n), pr ? pr->p_name : NULL);

							if (NULL != s)
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name);
							else
								offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n);
						}

						c <<= 1;
					}
					while (0 != (++n & 07));
				}

				break;
			case T_HINFO:
				p = msg_ptr + q_len;
				c = *msg_ptr++;

				if (0 != c)
				{
					offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
					msg_ptr += c;
				}

				if (msg_ptr < p)
				{
					c = *msg_ptr++;

					if (0 != c)
					{
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr);
						msg_ptr += c;
					}
				}

				break;
			case T_MINFO:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox responsible for mailing lists */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox for error messages */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			case T_TXT:
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"");
				p = msg_ptr + q_len;

				while (msg_ptr < p)
				{
					for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--)
						offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++);
				}

				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\"");

				break;
			case T_SRV:
				GETSHORT(value, msg_ptr);       /* priority */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* weight */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				GETSHORT(value, msg_ptr);       /* port */
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* target */
				{
					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				break;
			default:
				msg_ptr += q_len;
				break;
		}

		zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n");

		zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer));
		offset = 0;
		*buffer = '\0';
	}
#endif	/* _WINDOWS */

	zbx_vector_str_sort(&answers, ZBX_DEFAULT_STR_COMPARE_FUNC);

	for (i = 0; i < answers.values_num; i++)
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s", answers.values[i]);

	if (0 != offset)
		buffer[--offset] = '\0';

	SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer));
	ret = SYSINFO_RET_OK;

clean:
	zbx_vector_str_clear_ext(&answers, zbx_str_free);
	zbx_vector_str_destroy(&answers);
#ifdef _WINDOWS
clean_dns:
	if (DNS_RCODE_NOERROR == res)
		DnsRecordListFree(pQueryResults, DnsFreeRecordList);
#endif

	return ret;

#else	/* both HAVE_RES_QUERY and _WINDOWS not defined */

	return SYSINFO_RET_FAIL;

#endif	/* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */
}
示例#7
0
文件: main.c 项目: targuan/gendns
int main(int argc, char** argv) {
    pcap_dumper_t *dumper;
    pcap_t *p;
    struct pcap_pkthdr header;
    u_char *packet;
    int i;
    struct sockaddr *sin_src;
    struct sockaddr *sin_net;
    struct sockaddr *sin_dst;
    struct sockaddr *sin_mask;
    int sendsize;
    struct options_args opts;
    FILE* fp_domain;
    char * domain;

    int q_class;
    int q_type;



    /**
     * 
     * headers
     */
    struct ether_header *eth;
    struct iphdr *ip;
    struct ip6_hdr *ip6;
    struct udphdr *udp;
    u_char *dns;

    setoptions(argc, argv, &opts);

    header.ts.tv_sec = 0;
    header.ts.tv_usec = 0;

    packet = calloc(sizeof (u_char) * 4096, 1);
    sin_src = calloc(sizeof (struct sockaddr_storage), 1);
    sin_net = calloc(sizeof (struct sockaddr_storage), 1);
    sin_dst = calloc(sizeof (struct sockaddr_storage), 1);
    sin_mask = calloc(sizeof (struct sockaddr_storage), 1);
    domain = calloc(sizeof (char) * 1024, 1);

    if(packet == NULL || 
            sin_src == NULL ||
            sin_net == NULL || 
            sin_dst == NULL || 
            sin_mask == NULL || 
            domain == NULL) {
        return -1;
    }
    
    /**
     * 
     * ETHERNET static
     */

    eth = (struct ether_header *) packet;

    if (ether_setaddr(opts.smac, &(eth->ether_shost)) < 0) {
        fprintf(stderr, "smac error\n");
        return 1;
    }
    if (ether_setaddr(opts.dmac, &(eth->ether_dhost)) < 0) {
        fprintf(stderr, "dmac error\n");
        return 1;
    }

    /**
     * 
     * IP static
     */
    if (getipaddr(opts.dip, sin_dst, opts.family) < 0) {
        fprintf(stderr, "dip error\n");
        return 2;
    }
    if (getipaddr(opts.snet, sin_net, opts.family) < 0) {
        fprintf(stderr, "sip error\n");
        return 2;
    }

    if (sin_net->sa_family != sin_dst->sa_family) {
        fprintf(stderr, "IP family doesn't match\n");
        return 2;
    }

    set_mask(sin_mask, sin_net->sa_family, opts.smask);

    if (sin_net->sa_family == AF_INET) {
        eth->ether_type = htons(ETHERTYPE_IP);

        ip = (struct iphdr *) (packet + ETHER_HDR_LEN);
        ip->daddr = ((struct sockaddr_in *) sin_dst)->sin_addr.s_addr;


        ip->version = 4;
        ip->ihl = 5; // no opts
        ip->frag_off = 0;
        ip->id = 0;
        ip->protocol = IPPROTO_UDP;
        ip->tos = 0;
        ip->ttl = IPDEFTTL;
        

        udp = (struct udphdr *) (((void *) ip) + IP_HDR_LEN);
    } else if (sin_net->sa_family == AF_INET6) {
        eth->ether_type = htons(ETHERTYPE_IPV6);

        ip6 = (struct ip6_hdr *) (packet + ETHER_HDR_LEN);
        ip6->ip6_vfc = 6 << 4;
        ip6->ip6_hlim = IPDEFTTL;
        ip6->ip6_nxt = IPPROTO_UDP;

        memcpy(&(ip6->ip6_dst), &(((struct sockaddr_in6 *) sin_dst)->sin6_addr), 16);

        udp = (struct udphdr *) (((void *) ip6) + IP6_HDR_LEN);
    } else {
        fprintf(stderr, "Family unknown\n");
        return 2;
    }
    
    /**
     * 
     * UDP static
     */
    udp->check = 0;
    udp->dest = htons(53);

    /**
     * 
     * DNS static
     */
    dns = (u_char *) (((void *) udp) + UDP_HDR_LEN);

    
    p = pcap_open_dead(DLT_EN10MB, PCAP_SNAPLEN);
    dumper = pcap_dump_open(p, opts.out_file_name);
    if(dumper == NULL) {
        fprintf(stderr, "Can't open output file\n");
        
        pcap_close(p);
        return 3;
    }
    init_domain_file(&fp_domain, opts.in_file_name);
    if (fp_domain == NULL) {
        fprintf(stderr, "Can't open queries file\n");
        
        pcap_dump_close(dumper);
        pcap_close(p);
        return 4;
    }
    for (i = 0; i < opts.count; i++) {
        
        /**
         * 
         * DNS dynamic
         */
        nextdomain(fp_domain, &domain, &q_type, &q_class);

        sendsize = res_mkquery(QUERY, domain, q_class, q_type, NULL,
                0, NULL, dns, PACKETSZ);

        /**
         * 
         * UDP dynamic
         */
        udp->source = htons(rand());
        udp->len = htons(sendsize + UDP_HDR_LEN);

        /**
         * 
         * IP dynamic
         */
        get_rand_addr(sin_net, sin_mask, sin_src);

        if (sin_net->sa_family == AF_INET) {
            ip->saddr = ((struct sockaddr_in *) sin_src)->sin_addr.s_addr;
            ip->tot_len = htons(sendsize + UDP_HDR_LEN + (ip->ihl * 4));
            header.len = sendsize + UDP_HDR_LEN + (ip->ihl * 4) + ETHER_HDR_LEN;

            ip->check = 0;
            ip->check = inet_cksum(ip, (ip->ihl * 4));
        } else if (sin_net->sa_family == AF_INET6) {
            memcpy(&(ip6->ip6_src), &(((struct sockaddr_in6 *) sin_src)->sin6_addr), 16);
            ip6->ip6_plen = htons(sendsize + UDP_HDR_LEN);
            header.len = sendsize + UDP_HDR_LEN + sizeof (struct ip6_hdr) +ETHER_HDR_LEN;
        }

        header.caplen = header.len;
        if (header.len > opts.mtu) {
            fprintf(stderr, "too long: %s needs %d MTU is %d\n", domain,header.len, opts.mtu);
        } else {
            pcap_dump(dumper, &header, packet);
        }
    }


    pcap_dump_close(dumper);
    pcap_close(p);
    fclose(fp_domain);

    return (EXIT_SUCCESS);
}
示例#8
0
文件: rrdns.c 项目: jow-/luci-ng
static int
rrdns_next_query(struct rrdns_context *rctx)
{
    const char *addr = NULL, *hex = "0123456789abcdef";
    struct rrdns_request *req;
    int i, alen, family;
    char *p, dname[73];

    union {
        unsigned char uchar[4];
        struct in6_addr in6;
        struct in_addr in;
    } a = { };

    union {
        unsigned char buf[512];
        HEADER hdr;
    } msg;

    if (rctx->addr_rem > 0 &&
            blob_pad_len(rctx->addr_cur) <= rctx->addr_rem &&
            blob_pad_len(rctx->addr_cur) >= sizeof(struct blob_attr)) {

        addr = blobmsg_get_string(rctx->addr_cur);
        rctx->addr_rem -= blob_pad_len(rctx->addr_cur);
        rctx->addr_cur = blob_next(rctx->addr_cur);
    }

    if (!addr)
        return 0;

    if (inet_pton(AF_INET6, addr, &a.in6)) {
        memset(dname, 0, sizeof(dname));

        for (i = 0, p = dname; i < 16; i++) {
            *p++ = hex[a.in6.s6_addr[15-i] % 16];
            *p++ = '.';
            *p++ = hex[a.in6.s6_addr[15-i] / 16];
            *p++ = '.';
        }

        p += snprintf(p, p - dname - 1, "ip6.arpa");

        family = AF_INET6;
        alen = p - dname;
    }
    else if (inet_pton(AF_INET, addr, &a.in)) {
        family = AF_INET;
        alen = snprintf(dname, sizeof(dname), "%u.%u.%u.%u.in-addr.arpa",
                        a.uchar[3], a.uchar[2], a.uchar[1], a.uchar[0]);
    }
    else {
        return -EINVAL;
    }

    alen = res_mkquery(QUERY, dname, C_IN, T_PTR, NULL, 0, NULL,
                       msg.buf, sizeof(msg.buf));

    if (alen < 0)
        return alen;

    if (avl_find(&rctx->request_addrs, &a.in6))
        return -ENOTUNIQ;

    if (send(rctx->socket.fd, msg.buf, alen, 0) != alen)
        return -errno;

    req = calloc(1, sizeof(*req));

    if (!req)
        return -ENOMEM;

    req->id = msg.hdr.id;
    req->by_id.key = &req->id;
    avl_insert(&rctx->request_ids, &req->by_id);

    req->family = family;
    req->addr.in6 = a.in6;
    req->by_addr.key = &req->addr.in6;
    avl_insert(&rctx->request_addrs, &req->by_addr);

    return 0;
}
示例#9
0
文件: nb_dns.c 项目: bro/bro
static int
_nb_dns_mkquery(register struct nb_dns_info *nd, register const char *name,
    register int atype, register int qtype, register void * cookie,
    register char *errstr)
{
	register struct nb_dns_entry *ne;
	register HEADER *hp;
	register int n;
	u_long msg[MAXPACKET / sizeof(u_long)];

	/* Allocate an entry */
	ne = (struct nb_dns_entry *)malloc(sizeof(*ne));
	if (ne == NULL) {
		snprintf(errstr, NB_DNS_ERRSIZE, "malloc(): %s",
		    my_strerror(errno));
		return (-1);
	}
	memset(ne, 0, sizeof(*ne));
	strncpy(ne->name, name, sizeof(ne->name));
	ne->name[sizeof(ne->name) - 1] = '\0';
	ne->qtype = qtype;
	ne->atype = atype;
	switch (atype) {

	case AF_INET:
		ne->asize = NS_INADDRSZ;
		break;

#ifdef AF_INET6
	case AF_INET6:
		ne->asize = NS_IN6ADDRSZ;
		break;
#endif

	default:
		snprintf(errstr, NB_DNS_ERRSIZE,
		    "_nb_dns_mkquery: bad family %d", atype);
		free(ne);
		return (-1);
	}

	/* Build the request */
	n = res_mkquery(
	    ns_o_query,			/* op code (query) */
	    name,			/* domain name */
	    ns_c_in,			/* query class (internet) */
	    qtype,			/* query type */
	    NULL,			/* data */
	    0,				/* length of data */
	    NULL,			/* new rr */
	    (u_char *)msg,		/* buffer */
	    sizeof(msg));		/* size of buffer */
	if (n < 0) {
		snprintf(errstr, NB_DNS_ERRSIZE, "res_mkquery() failed");
		free(ne);
		return (-1);
	}

	hp = (HEADER *)msg;
	ne->id = htons(hp->id);

	if (send(nd->s, (char *)msg, n, 0) != n) {
		snprintf(errstr, NB_DNS_ERRSIZE, "send(): %s",
		    my_strerror(errno));
		free(ne);
		return (-1);
	}

	ne->next = nd->list;
	ne->cookie = cookie;
	nd->list = ne;

	return(0);
}
示例#10
0
文件: res.c 项目: commshare/testST
static int query_domain(st_netfd_t nfd, const char *name, struct in_addr *addr,
			st_utime_t timeout)
{
 //	name="www.baidu.com";
#if 0
  char *name=malloc(128);
  memset(name,0,128);
  strcpy(name,hostname);
 LOGD("hostname [%s] name[%s]",hostname,name);
#endif
  querybuf_t qbuf;
  u_char *buf = qbuf.buf;
  HEADER *hp = &qbuf.hdr;
  int blen = sizeof(qbuf);
  int i, len, id;

  for (i = 0; i < _res.nscount; i++) {
    len = res_mkquery(QUERY, name, C_IN, T_A, NULL, 0, NULL, buf, blen);
    if (len <= 0) {
      h_errno = NO_RECOVERY;
      return -1;
    }
    id = hp->id;

    if (st_sendto(nfd, buf, len, (struct sockaddr *)&(_res.nsaddr_list[i]),
		  sizeof(struct sockaddr), timeout) != len) {
      h_errno = NETDB_INTERNAL;
      /* EINTR means interrupt by other thread, NOT by a caught signal */
      if (errno == EINTR)
	return -1;
      continue;
    }

 len = st_recvfrom(nfd, buf, blen, NULL, NULL, timeout);
 	LOGD("  st_recvfrom len[%d]",len);
return 0;




    /* Wait for reply */
    do {
      len = st_recvfrom(nfd, buf, blen, NULL, NULL, timeout);
      if (len <= 0) /*一直接收不到应答消息啊*/
	  {
	  	LOGD("  st_recvfrom len[%d]",len);
	  	break;
	  }
    } while (id != hp->id);

    if (len < HFIXEDSZ) {
      h_errno = NETDB_INTERNAL;
      if (len >= 0)
	errno = EMSGSIZE;
      else if (errno == EINTR)  /* see the comment above */
	return -1;
      continue;
    }

    hp->ancount = ntohs(hp->ancount);
    hp->qdcount = ntohs(hp->qdcount);
    if ((hp->rcode != NOERROR) || (hp->ancount == 0)) {
      switch (hp->rcode) {
      case NXDOMAIN:
	h_errno = HOST_NOT_FOUND;
	break;
      case SERVFAIL:
	h_errno = TRY_AGAIN;
	break;
      case NOERROR: /*走这里*/
	h_errno = NO_DATA;
	break;
      case FORMERR:
      case NOTIMP:
      case REFUSED:
      default: /*走这里*/
	h_errno = NO_RECOVERY;
      }
      continue;
    }

    if (parse_answer(&qbuf, len, addr) == 0)
    {	LOGD("after parse_answer");
	//free(name);//add by me for malloc
		return 0;//走这里
    }
  }
 ///free(name);//add by me 20150923
  return -1;
}
示例#11
0
int dns_get(char *target_name, int type, unsigned char *return_answer, int return_answer_length, int verbose)
  {
  static int query_id = 0;
  int return_value;
  int i;
  int dns_socket;
  unsigned char question[PACKETSZ];
  unsigned char answer[PACKETSZ];
  int question_length;
  unsigned short tmp_id;
  int sendto_result;
  int select_result;
  int response_length;
  fd_set read_fds;
  struct timeval tmp_timeval;
  time_t start_time;
  int num_queries;

  return_value = 0;

  if ((dns_socket = dns_initialize(0)) != -1)
    {
    if ((question_length = res_mkquery(QUERY, target_name, C_IN, type, NULL, 0, NULL, question, PACKETSZ)) >= 0)
      {
      tmp_id = htons(query_id);
      query_id++;

      question[0] = ((char *)&tmp_id)[0];
      question[1] = ((char *)&tmp_id)[1];

      start_time = time(NULL);
      num_queries = 0;

      do
        {
        sendto_result = 0;

        if (num_queries < MAX_DNS_QUERIES_PREFERRED)
          {
          if (verbose)
            printf(MSG_SENDING, num_queries, inet_ntoa(_res.nsaddr_list[0].sin_addr), ntohs(_res.nsaddr_list[0].sin_port));

          sendto_result = sendto(dns_socket, question, question_length, 0, (struct sockaddr *)&_res.nsaddr_list[0], sizeof(struct sockaddr));
          }
        else
          for (i = 0; i < _res.nscount; i++)
            {
            if (verbose)
              printf(MSG_SENDING, num_queries, inet_ntoa(_res.nsaddr_list[i].sin_addr), ntohs(_res.nsaddr_list[i].sin_port));

            sendto_result = sendto(dns_socket, question, question_length, 0, (struct sockaddr *)&_res.nsaddr_list[i], sizeof(struct sockaddr));
            }

        num_queries++;

        if (sendto_result == question_length)
          {
          FD_ZERO(&read_fds);
          FD_SET(dns_socket, &read_fds);

          tmp_timeval.tv_sec = MINVAL((TIMEOUT_DNS_QUERY_SECS * MAX_DNS_QUERIES) - (time(NULL) - start_time), TIMEOUT_DNS_QUERY_SECS);
          tmp_timeval.tv_usec = 0;

          while ((tmp_timeval.tv_sec > 0) &&
                 ((select_result = select(dns_socket + 1, &read_fds, NULL, NULL, &tmp_timeval)) > 0))
            {
            if (((response_length = recvfrom(dns_socket, answer, PACKETSZ, 0, NULL, NULL)) > 0) &&
                (answer[0] == question[0]) &&
                (answer[1] == question[1]))
              {
              if (verbose)
                printf(MSG_RECEIVING, response_length);

              memcpy(return_answer, answer, MINVAL(response_length, return_answer_length));
              return_value = MINVAL(response_length, return_answer_length);
              break;
              }
            else if (verbose)
              printf(MSG_MISMATCH);
            }

          if (return_value > 0)
            break;
          }
        else if (sendto_result >= 0)
          printf(ERROR_SENDTO_INCOMPLETE, question_length, sendto_result);
        else
          {
          printf(ERROR_SENDTO, strerror(errno));
          break;
          }
        }
      while (num_queries < MAX_DNS_QUERIES);
      }
    else
      printf(ERROR_MKQUERY, strerror(errno));
    }

  return(return_value);
  }
示例#12
0
文件: main.c 项目: targuan/generator
int main(int argc, char** argv) {
    u_char *packet;
    int i;
    uint32_t ck;
    
    struct sockaddr *sin_src;
    struct sockaddr *sin_net;
    struct sockaddr *sin_dst;
    struct sockaddr *sin_mask;
    struct ip6_pseudo_hdr ps_hdr;
    int sendsize;
    struct options opts;
    FILE* fp_domain;
    char * domain;
    struct writer_info wi;
    int pkt_len;
    
    double speed_limit;
    double pkt_sent;

    

    int q_class;
    int q_type;


    pthread_t thread;


    pthread_create(&thread,NULL,readliner,&speed_limit);

    sleeper = 50;
    pkt_sent = 0;
    speed_limit = 50000;
    /**
     * 
     * headers
     */
    struct ether_header *eth;
    struct iphdr *ip;
    struct ip6_hdr *ip6;
    struct udphdr *udp;
    u_char *dns;
    u_char dns_opt[] = {00, 00, 0x29, 0x08, 00, 00, 00, 00, 00, 00, 00};
    setoptions(argc, argv, &opts);
    
    


    

    

    

    packet = calloc(sizeof (u_char) * 4096, 1);
    sin_src = calloc(sizeof (struct sockaddr_storage), 1);
    sin_net = calloc(sizeof (struct sockaddr_storage), 1);
    sin_dst = calloc(sizeof (struct sockaddr_storage), 1);
    sin_mask = calloc(sizeof (struct sockaddr_storage), 1);
    domain = calloc(sizeof (char) * 1024, 1);
    //domain = NULL;
    
    if (packet == NULL ||
            sin_src == NULL ||
            sin_net == NULL ||
            sin_dst == NULL ||
            sin_mask == NULL ||
            domain == NULL) {
        return -1;
    }

    /**
     * 
     * ETHERNET static
     */

    eth = (struct ether_header *) packet;

    if (ether_setaddr(opts.smac, &(eth->ether_shost)) < 0) {
        fprintf(stderr, "smac error:%s\n");
        return 1;
    }
    if (ether_setaddr(opts.dmac, &(eth->ether_dhost)) < 0) {
        fprintf(stderr, "dmac error\n");
        return 1;
    }

    /**
     * 
     * IP static
     */
    if (getipaddr(opts.dip, sin_dst, opts.family) < 0) {
        fprintf(stderr, "dip error\n");
        return 2;
    }
    if (getipaddr(opts.snet, sin_net, opts.family) < 0) {
        fprintf(stderr, "sip error\n");
        return 2;
    }

    if (sin_net->sa_family != sin_dst->sa_family) {
        fprintf(stderr, "IP family doesn't match\n");
        return 2;
    }

    set_mask(sin_mask, sin_net->sa_family, opts.smask);

    if (sin_net->sa_family == AF_INET) {
        eth->ether_type = htons(ETHERTYPE_IP);

        ip = (struct iphdr *) (packet + ETHER_HDR_LEN);
        ip->daddr = ((struct sockaddr_in *) sin_dst)->sin_addr.s_addr;


        ip->version = 4;
        ip->ihl = 5; // no opts
        ip->frag_off = 0;
        ip->id = 0;
        ip->protocol = IPPROTO_UDP;
        ip->tos = 0;
        ip->ttl = IPDEFTTL;


        udp = (struct udphdr *) (((void *) ip) + IP_HDR_LEN);
    } else if (sin_net->sa_family == AF_INET6) {
        eth->ether_type = htons(ETHERTYPE_IPV6);

        ip6 = (struct ip6_hdr *) (packet + ETHER_HDR_LEN);
        ip6->ip6_vfc = 6 << 4;
        ip6->ip6_hlim = IPDEFTTL;
        ip6->ip6_nxt = IPPROTO_UDP;

        memcpy(&(ip6->ip6_dst), &(((struct sockaddr_in6 *) sin_dst)->sin6_addr), 16);

        udp = (struct udphdr *) (((void *) ip6) + IP6_HDR_LEN);
    } else {
        fprintf(stderr, "Family unknown\n");
        return 2;
    }

    /**
     * 
     * UDP static
     */
    //udp->check = 0;
    udp->dest = htons(53);

    /**
     * 
     * DNS static
     */
    dns = (u_char *) (((void *) udp) + UDP_HDR_LEN);


    wopen(&wi,&opts);
    
    init_domain_file(&fp_domain, opts.in_file_name);
    if (fp_domain == NULL) {
        fprintf(stderr, "Can't open queries file\n");
        wclose(&wi);
        
        return 4;
    }
    for (i = 0; i < opts.count; i++) {
	if(pkt_sent >= sleeper) {
		speed_calc(pkt_sent,speed_limit, &sleeper);
                pkt_sent = 0;
		usleep(1);
	}
        /**
         * 
         * DNS dynamic
         */
        if(nextdomain(fp_domain, &domain, &q_type, &q_class)) {
            printf("Can't read next domain\n");
            exit(1);
        }

        sendsize = res_mkquery(QUERY, domain, q_class, q_type, NULL,
                0, NULL, dns, PACKETSZ);
        dns[11] = 1;
        memcpy(dns + sendsize, dns_opt, 11);
        sendsize += 11;
        /**
         * 
         * UDP dynamic
         */
        udp->source = htons(rand());
        udp->len = htons(sendsize + UDP_HDR_LEN);
        udp->check = 0;
        /**
         * 
         * IP dynamic
         */
        get_rand_addr(sin_net, sin_mask, sin_src);

        if (sin_net->sa_family == AF_INET) {
            ip->saddr = ((struct sockaddr_in *) sin_src)->sin_addr.s_addr;
            ip->tot_len = htons(sendsize + UDP_HDR_LEN + (ip->ihl * 4));
            pkt_len = sendsize + UDP_HDR_LEN + (ip->ihl * 4) + ETHER_HDR_LEN;

            ip->check = 0;
            ip->check = inet_cksum(ip, (ip->ihl * 4), 0);
        } else if (sin_net->sa_family == AF_INET6) {
            memcpy(&(ip6->ip6_src), &(((struct sockaddr_in6 *) sin_src)->sin6_addr), 16);
            ip6->ip6_plen = htons(sendsize + UDP_HDR_LEN);
            pkt_len = sendsize + UDP_HDR_LEN + sizeof (struct ip6_hdr) +ETHER_HDR_LEN;

            ps_hdr.src = ip6->ip6_src;
            ps_hdr.dst = ip6->ip6_dst;
            ps_hdr.len = udp->len;
            ps_hdr.nh = ntohs(17);

            ck = inet_cksum(&ps_hdr, sizeof (ps_hdr), 0);
            udp->check = inet_cksum(udp, sendsize + UDP_HDR_LEN, (~ck)&0xffff);
        }


        
        
        if (pkt_len > opts.mtu) {
            fprintf(stderr, "too long: %s needs %d MTU is %d\n", domain, pkt_len, opts.mtu);
        } else {
            wwrite(&wi,packet,pkt_len);
        }
	pkt_sent++;
    }

    wclose(&wi);
    fclose(fp_domain);

    return (EXIT_SUCCESS);
}
示例#13
0
/*
 * Do I need write description to this file? I don't think so.
 */
int dns_perf_generate_query(query_t *q)
{
    static unsigned short query_id = 0;
    int                   len;
    unsigned short        net_id;
    u_char                 *p, *t;
    HEADER               *hp;
    in_addr_t             addr;


    len = res_mkquery(QUERY, q->data->domain, C_IN, q->data->qtype, NULL,
                      0, NULL, q->send_buf, sizeof(q->send_buf));
    if (len == -1) {
        fprintf(stderr, "Failed to create query packet: %s %d\n", q->data->domain,
                q->data->qtype);
        return -1;
    }

    hp = (HEADER *) q->send_buf;
    hp->rd = 1;    /* recursion */

    query_id++;
    q->id = query_id;

    /* set message id */
    net_id = htons(query_id);
    p = (u_char *) &net_id;
    q->send_buf[0] = p[0];
    q->send_buf[1] = p[1];

    if (g_real_client) {
        q->send_buf[11] = 1;   /* set additional count to  1 */

        p = q->send_buf + len; /* p points to additional section */

        *p++ = 0;      /* root name */

        *p++ = 0;      /* OPT */
        *p++ = 41;

        *p++ = 4;      /* UDP payload size: 1024 */
        *p++ = 0;

        *p++ = 0;      /* extended RCODE and flags */
        *p++ = 0;
        *p++ = 0;
        *p++ = 0;

        *p++ = 0;      /* edns-client-subnet's length */
        *p++ = 12;

        /* edns-client-subnet */
        *p++ = 0;      /* option code: 8 */
        *p++ = 8;

        *p++ = 0;      /* option length: 8 */
        *p++ = 8;

        *p++ = 0;      /* family: 1 */
        *p++ = 1;

        *p++ = 32;     /* source netmask: 32 */
        *p++ = 0;      /* scope netmask: 0 */

        addr = inet_addr(g_real_client);  /* client subnet */
        t = (u_char *) &addr;

        *p++ = *t++;
        *p++ = *t++;
        *p++ = *t++;
        *p++ = *t++;

        len += 23;
    }

    q->send_len = len;
    q->send_pos = 0;

    return 0;
}