Example #1
0
int CSmtpClient::GetSmtpServerName(CEmailMessage* msg, AssyncNotification* scn, 
                                   std::map<WORD, CString>& host_list)
{
  DNS_RECORD *apResult = NULL;

  CString sServer;
  sServer = msg->m_sFrom.Mid(msg->m_sFrom.Find('@')+1);
 
  CString sStatusMsg;
  sStatusMsg.Format(_T("Quering MX record of domain %s"), sServer);
  scn->SetProgress(sStatusMsg, 2);

  int r = DnsQuery(sServer, DNS_TYPE_MX, DNS_QUERY_STANDARD, 
    NULL, (PDNS_RECORD*)&apResult, NULL);
  
  if(r==0)
  {
    while(apResult!=NULL)
    {
      if(apResult->wType==DNS_TYPE_MX)        
      {
        host_list[apResult->Data.MX.wPreference] = 
        CString(apResult->Data.MX.pNameExchange);
      }

      apResult = apResult->pNext;
    }

    return 0;
  }

  sStatusMsg.Format(_T("DNS query failed with code %d"), r);
  scn->SetProgress(sStatusMsg, 2);
  return 1;
}
Example #2
0
bool dnsquery_win(const QString &hostname)
{
    DNS_RECORD *pResult = NULL;
    DNS_STATUS status   = DnsQuery(hostname.toStdWString().c_str(),DNS_TYPE_A,DNS_QUERY_BYPASS_CACHE,NULL,&pResult,NULL);
    DnsRecordListFree(pResult,DnsFreeRecordList);
    return (0 == status);
}
Example #3
0
  DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto,
                             const std::string& domain, const LogSink& logInstance )
  {
    const std::string dname = "_" +  service + "._" + proto + "." + domain;
    bool error = false;

    DNS::HostMap servers;
    DNS_RECORD* pRecord;
    if( DnsQuery( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ) == ERROR_SUCCESS )
    {
      DNS_RECORD* pRec = pRecord;
      do
      {
        if( pRec->wType == DNS_TYPE_SRV )
        {
          servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort;
        }
        pRec = pRec->pNext;
      }
      while( pRec != NULL );
      DnsRecordListFree( pRecord, DnsFreeRecordList );
    }
    else
      error = true;

    if( error || !servers.size() )
    {
      servers = defaultHostMap( domain, logInstance );
    }

    return servers;
  }
Example #4
0
PDNS_RECORD TraverseDnsCacheTable(
    _In_ PDNS_RECORD root
    )
{
    USHORT typeList[] = { DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_MX, DNS_TYPE_SRV, DNS_TYPE_PTR }; // Only interested in these queries, to boost traversing performance
    PDNS_CACHE_ENTRY dnsCacheDataTable = NULL;
    PDNS_CACHE_ENTRY tablePtr;

    if (!DnsGetCacheDataTable_I(&dnsCacheDataTable))
        goto CleanupExit;

    tablePtr = dnsCacheDataTable;

    while (tablePtr)
    {
        for (USHORT i = 0; i < ARRAYSIZE(typeList); i++)
        {
            DNS_STATUS dnsStatus;
            PDNS_RECORD dnsQueryResultPtr;

            dnsStatus = DnsQuery(
                tablePtr->Name,
                typeList[i],
                DNS_QUERY_NO_WIRE_QUERY | 32768, // Undocumented flags
                NULL,
                &dnsQueryResultPtr,
                NULL
                );

            if (dnsStatus == ERROR_SUCCESS)
            {
                PDNS_RECORD dnsRecordPtr = dnsQueryResultPtr;

                while (dnsRecordPtr)
                {
                    if (!RecordSetContains(root, dnsRecordPtr))
                    {
                        PDNS_RECORD temp = root;
                        root = DnsRecordCopy(dnsRecordPtr);
                        root->pNext = temp;
                    }

                    dnsRecordPtr = dnsRecordPtr->pNext;
                }

                DnsRecordListFree(dnsQueryResultPtr, DnsFreeRecordList);
            }
        }

        tablePtr = tablePtr->Next;
    }

CleanupExit:

    if (dnsCacheDataTable)
        DnsRecordListFree(dnsCacheDataTable, DnsFreeRecordList);

    return root;
}
Example #5
0
/**
 * Issues the DNS request to discover the sFlow service settings
 * (collector addresses and ports, sampling rates and polling intervals).
 * The DNS request is configured to bypass the DNS cache and go straight
 * to the wire to avoid using stale entries.
 * If the request succeeds, updates the min TTL in HSP *sp, parses the response,
 * and returns the number of records returned, populating HSPSFlowSettings *settings
 * with the parsed result.
 * If the request fails, returns -1.
 * char *dname contains the DNS query (fully qualified)
 * WORD dtype the DNS query type (SRV for collectors or TEXT for sampling rates
 * and polling intervals)
 * Note that we are using the DnsQuery function to make the DNS request.
 * This function does not take into account the system DNS search path, so the
 * DNS query must be fully qualified (ie include the domain to search).
 */
static int dnsSD_Request(HSP *sp, HSPSFlowSettings *settings,
						 char *dname, WORD rtype)
{
	PDNS_RECORD pDnsRecord;
	DNS_FREE_TYPE dnsFreeType;
	dnsFreeType = DnsFreeRecordListDeep;
	DNS_STATUS status = DnsQuery(dname, rtype, DNS_QUERY_WIRE_ONLY, NULL, &pDnsRecord, NULL);
	if (status) {
		//fail
		logErr(LOG_ERR, status, "dnsSD_Request: DNSQuery(%s, %u) failed error=%u", dname, rtype, status);
		return -1;
	} else {
		 //process results and free
		int answerCount = 0;
		PDNS_RECORD nextRecord = pDnsRecord;
		while (nextRecord != NULL) {
			//update the minimum ttl
			DWORD ttl = nextRecord->dwTtl;
			if (sp->DNSSD_ttl == 0 || ttl < sp->DNSSD_ttl) {
				sp->DNSSD_ttl = ttl;
			}
			switch(rtype) {
			case DNS_TYPE_TEXT:
				if (nextRecord->wType == DNS_TYPE_TEXT) {
					answerCount++;
					DWORD stringCount = nextRecord->Data.TXT.dwStringCount;
					for (DWORD i = 0; i < stringCount; i++) {
						if (LOG_INFO <= debug) {
							myLog(LOG_INFO, "dnsDS_Request: DNS_TYPE_TEXT %s",
								nextRecord->Data.TXT.pStringArray[i]);
						}
						dnsSD_parseTxt(settings,
									   nextRecord->Data.TXT.pStringArray[i]);
					}
				}
				break;
			case DNS_TYPE_SRV:
				if (nextRecord->wType == DNS_TYPE_SRV) {
					answerCount++;
					if (LOG_INFO <= debug) {
						myLog(LOG_INFO, "dnsDS_Request: DNS_TYPE_SRV %s %u",
							nextRecord->Data.SRV.pNameTarget, nextRecord->Data.SRV.wPort);
					}
					insertCollector(settings, nextRecord->Data.SRV.pNameTarget, 
						nextRecord->Data.SRV.wPort);
				}
				break;
			default:
				DnsRecordListFree(pDnsRecord, dnsFreeType);
				myLog(LOG_ERR, "dnsDS_Request: unsupported query type %u", rtype);
				return -1;
			}
			nextRecord = nextRecord->pNext;
		}
		DnsRecordListFree(pDnsRecord, dnsFreeType);
		return answerCount;
	}
}
Example #6
0
int getrrs(const char *label, int rrtype, void gotrec(unsigned int num, int type, const char *record))
{
	DNS_STATUS	status;			/* Return value of DnsQuery_A() function */
	PDNS_RECORD	pResult, pRec;		/* Pointer to DNS_RECORD structure */
	unsigned int	rrnum = 0, i;
	uint16_t	type;

	status = DnsQuery(label,		/* Pointer to OwnerName */
		rrtype,				/* Type of the record to be queried */
		DNS_QUERY_STANDARD,		/* Standard Query */
		NULL,				/* Contains DNS server IP address */
		&pResult,			/* Resource record that contains the response */
		NULL);				/* Reserved for future use */

	if (status) return -1;
	else
	{
		for (pRec = pResult; pRec; pRec = pRec->pNext)
		{
			rrnum++;
			type = pRec->wType;

			if (rrtype != type && rrtype != ns_t_any) continue;

			switch (type)
			{
			case ns_t_txt:
				for (i=0; i < pRec->Data.TXT.dwStringCount; i++)
				{
					gotrec(rrnum, type, pRec->Data.TXT.pStringArray[i]);
				}
				break;

			case ns_t_a:
				gotrec(rrnum, type, (const char *)&pRec->Data.A.IpAddress);
				break;

			case ns_t_aaaa:
				gotrec(rrnum, type, (const char *)&pRec->Data.AAAA.Ip6Address);
				break;

			case ns_t_mx:
				gotrec(rrnum, type, pRec->Data.MX.pNameExchange);
				break;

			case ns_t_ns:
				gotrec(rrnum, type, pRec->Data.NS.pNameHost);
				break;
			}
		}
	}

	/* Free memory allocated for DNS records. */
	DnsRecordListFree(pResult, DnsFreeRecordListDeep);

	return 0;
}
Example #7
0
int CSmtpClient::ResolveSmtpServerName(LPCTSTR szEmailAddress, std::map<WORD, CString>& host_list)
{
	// This methods takes an E-mail address and resolve the domain name(s)
	// associated with this address.

    DNS_RECORD *apResult = NULL;

	// Convert to CString
	CString sEmailAddress = szEmailAddress;
	// Crop server name part from the E-mail address
    CString sServer;
    sServer = sEmailAddress.Mid(sEmailAddress.Find('@')+1);

	// Add a message to log
    CString sStatusMsg;
    sStatusMsg.Format(_T("Quering MX record of domain %s"), sServer);
    m_scn->SetProgress(sStatusMsg, 2);

	// Resolve the domain name(s) of the SMTP servers associated with
	// the E-mail address. Use MX record of DNS.
    int r = DnsQuery(sServer, DNS_TYPE_MX, DNS_QUERY_STANDARD, 
        NULL, (PDNS_RECORD*)&apResult, NULL);

    PDNS_RECORD pRecOrig = apResult;
	// Check result
    if(r==0)
    {
		// Walk through returned DNS records
        while(apResult!=NULL)
        {
			// Look for MX record
            if(apResult->wType==DNS_TYPE_MX)        
            {
				// Save domain name to our list
                CString sServerName = CString(apResult->Data.MX.pNameExchange);        
                host_list[apResult->Data.MX.wPreference] = sServerName;
            }

			// Next record
            apResult = apResult->pNext;
        }

		// Free resources
        DnsRecordListFree(pRecOrig, DnsFreeRecordList);

		// Done
        return 0;
    } 

	// Failed to resolve the address
    sStatusMsg.Format(_T("DNS query failed with code %d"), r);
    m_scn->SetProgress(sStatusMsg, 2);
    return 1;
}
Example #8
0
int main( int argc, char **argv ) {
  PDNS_RECORD QueryReply, AddrResponse;
  DWORD Addr;

  assert (DnsQuery ("www.reactos.com", DNS_TYPE_A, DNS_QUERY_STANDARD,
		    NULL, &QueryReply, NULL) == ERROR_SUCCESS);
  AddrResponse = QueryReply;
  while( AddrResponse ) {
    if( AddrResponse->wType == DNS_TYPE_A ) {
      Addr = ntohl( AddrResponse->Data.A.IpAddress );
      printf( "www.reactos.com == %d.%d.%d.%d\n",
	      (int)(Addr >> 24) & 0xff,
	      (int)(Addr >> 16) & 0xff,
	      (int)(Addr >> 8) & 0xff,
	      (int)Addr & 0xff );
    }
    AddrResponse = AddrResponse->pNext;
  }
Example #9
0
void DNS::IPToHostname(LPWSTR ip, std::wstring *hostname)
{
	PDNS_RECORD dnsInfo;
	DWORD ret;
	WCHAR *token;
	WCHAR *context;
	std::wstring address;
	std::vector<LPWSTR> octets;

	LPWSTR tmpString = new WCHAR[lstrlen(ip)+1];
	ZeroMemory(tmpString, lstrlen(ip)+1);
	lstrcpy(tmpString, ip);

	hostname->clear();
	// Gotta flip the IP around for reverse DNS lookups.
	token = wcstok_s(tmpString, L".", &context);

	while(token != NULL)
	{
		octets.push_back(token);
		token = wcstok_s(NULL, L".", &context);
	}

	address.append(octets[3]);
	address.append(L".");
	address.append(octets[2]);
	address.append(L".");
	address.append(octets[1]);
	address.append(L".");
	address.append(octets[0]);
	address.append(L".in-addr.arpa");

	if((ret = DnsQuery((PWCHAR)address.c_str(), DNS_TYPE_PTR, DNS_QUERY_STANDARD, NULL, &dnsInfo, NULL)) != 0)
	{
		Util::Error(ret, L"DnsQuery()");
		wprintf(L"ret = %x\n", ret);
	}
	else
	{
		hostname->append(dnsInfo->Data.PTR.pNameHost);
		DnsRecordListFree(dnsInfo);
	}
	delete(tmpString);
}
Example #10
0
int main( int argc, char **argv ) {
    PDNS_RECORD QueryReply, AddrResponse;
    DWORD Addr;

    assert (DnsValidateName( "||||", DnsNameDomain ) == DNS_ERROR_INVALID_NAME_CHAR);
    assert (DnsValidateName( "a.b.c", DnsNameDomainLabel ) == DNS_ERROR_INVALID_NAME);
    assert (DnsValidateName( "1234", DnsNameDomainLabel ) == ERROR_SUCCESS);
    assert (DnsValidateName( "fubar", DnsNameDomain ) == ERROR_SUCCESS);
    assert (DnsQuery ("www.reactos.com", DNS_TYPE_A, DNS_QUERY_STANDARD,
                      NULL, &QueryReply, NULL) == ERROR_SUCCESS);
    AddrResponse = QueryReply;
    while( AddrResponse ) {
        if( AddrResponse->wType == DNS_TYPE_A ) {
            Addr = ntohl( AddrResponse->Data.A.IpAddress );
            printf( "www.reactos.com == %d.%d.%d.%d\n",
                    (int)(Addr >> 24) & 0xff,
                    (int)(Addr >> 16) & 0xff,
                    (int)(Addr >> 8) & 0xff,
                    (int)Addr & 0xff );
        }
        AddrResponse = AddrResponse->pNext;
    }
Example #11
0
int srv_getaddrinfo(const char *node, const char *service,
		    const struct addrinfo *hints,
		    struct addrinfo **res)
{
    char *srv_name;
    size_t srv_name_size;
    char tgt_port[6];
#ifdef WIN32
    PDNS_RECORD resp, entry;
    char *tgt_name;
#else
    char tgt_name[BINKD_FQDNLEN + 1];
    unsigned char resp[SRVGAI_DNSRESPLEN];
    ns_msg nsb;
    ns_rr rrb;
    int rlen, i, rrlen;
    const unsigned char *p;
    struct in_addr dummy_addr;
#endif
    int rc;
    struct addrinfo *ai, **ai_last = res;

    /* we need sensible information for all parameters */
    if (!node || (node && !*node) || !service || (service && !*service) ||
	    !hints || !res)
	return getaddrinfo(node, service, hints, res);

    /* only domain names are supported */
    if (hints->ai_flags & AI_NUMERICHOST)
	return getaddrinfo(node, service, hints, res);

    /* detect IP addresses */
    if ((hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) && 
#ifdef WIN32
	    inet_addr(node) != INADDR_NONE
#else
	    inet_aton(node, &dummy_addr) != 0
#endif
	    )
	return getaddrinfo(node, service, hints, res);
#ifdef AF_INET6
    if ((hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) && 
	    strchr(node, ':'))
	return getaddrinfo(node, service, hints, res);
#endif

    /* only named services are supported */
    if ((hints->ai_flags & AI_NUMERICSERV) || *service == '0' ||
	    atoi(service) > 0)
	return getaddrinfo(node, service, hints, res);

    /* only TCP and UDP are supported */
    if (hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
	return getaddrinfo(node, service, hints, res);

    /*              _ <service>           ._  tcp . <node>           \0 */
    srv_name_size = 1 + strlen(service) + 2 + 3 + 1 + strlen(node) + 1;
    srv_name = malloc(srv_name_size);
    if (!srv_name)
	return EAI_MEMORY;

    /* construct domain name for SRV query */
    snprintf(srv_name, srv_name_size, "_%s._%s.%s", service,
	    hints->ai_socktype == SOCK_STREAM ? "tcp" : "udp", node);

#ifdef WIN32
    rc = DnsQuery(srv_name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &resp, NULL);
#else
    rlen = res_search(srv_name, ns_c_in, ns_t_srv, resp, sizeof(resp));
#endif
    free(srv_name);

    /* fallback if DNS query does not return a single entry */
#ifdef WIN32
    if (rc != ERROR_SUCCESS)
#else
    if (rlen < 1)
#endif
	return getaddrinfo(node, service, hints, res);

#ifndef WIN32
    /* fallback in case we cannot parse the response */
    if (ns_initparse(resp, rlen, &nsb) < 0)
	return getaddrinfo(node, service, hints, res);
#endif

    /* iterate through result set -- might be incomplete */
#ifdef WIN32
    for (entry = resp; entry != NULL; entry = entry->pNext) {
	switch (entry->wType) {
	case DNS_TYPE_SRV:
	    snprintf(tgt_port, sizeof(tgt_port), "%d", entry->Data.SRV.wPort);
	    tgt_name = entry->Data.SRV.pNameTarget;
#else
    for (i = 0; i < ns_msg_count(nsb, ns_s_an); i++) {
	rc = ns_parserr(&nsb, ns_s_an, i, &rrb);
	if (rc < 0)
	    continue;

	if (ns_rr_class(rrb) != ns_c_in)
	    continue;

	switch (ns_rr_type(rrb)) {
	case ns_t_srv:
	    rrlen = ns_rr_rdlen(rrb);
	    if (rrlen < 8)	/* 2+2+2 and at least 2 for host */
		break;

	    /* extract host and port */
	    p = ns_rr_rdata(rrb);
	    rc = dn_expand(resp, resp+rlen, p+6, tgt_name, sizeof(tgt_name));
	    if (rc < 2)
		break;
	    snprintf(tgt_port, sizeof(tgt_port), "%u", 
		    (unsigned int)p[4] << 8 | (unsigned int)p[5]);
#endif

	    /* resolve and add to end of list */
	    if (getaddrinfo(tgt_name, tgt_port, hints, ai_last) != 0)
		break;

	    /* get end of list */
	    for (ai=*ai_last; ai != NULL; ai = ai->ai_next)
		ai_last = &(ai->ai_next);

	    break;
	default:    /* someone stupid might use CNAME */
	    break;
	}
    }

#ifdef WIN32
    /* free result set */
    DnsRecordListFree(resp, DnsFreeRecordList);
#endif

    /* fallback in case no resolution via SRV is possible */
    if (ai_last == res)
	return getaddrinfo(node, service, hints, res);

    return 0;
}
Example #12
0
int
eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length)
{
	char zone[1024];

	PDNS_RECORD answer, tmp;	/* answer buffer from nameserver */

	int n;

	char tr[100];

	memset(srv_record, 0, max_length);
	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);

	snprintf(zone, 1024, "%s", domain);

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s NAPTR'\n", zone));

	if (DnsQuery(zone, DNS_TYPE_NAPTR, DNS_QUERY_STANDARD, NULL, &answer, NULL) !=
		0) {
		return OSIP_UNKNOWN_HOST;
	}

	n = 0;
	for (tmp = answer; tmp != NULL; tmp = tmp->pNext) {
		char *buf = (char *) &tmp->Data;

		int len;
		OSVERSIONINFOEX ovi;
		typedef struct {
			unsigned short order;
			unsigned short pref;
			char flag[256];
			char service[1024];
			char regexp[1024];
			char replacement[1024];
		} osip_naptr_t;

		osip_naptr_t anaptr;

		if (tmp->wType != DNS_TYPE_NAPTR)
			continue;

		memset(&anaptr, 0, sizeof(osip_naptr_t));
		memset(&ovi, 0, sizeof(ovi));
		ovi.dwOSVersionInfoSize = sizeof(ovi);
		GetVersionEx((LPOSVERSIONINFO) & ovi);

		/* Minimum: client: Windows 2000 Professional */
		/* Minimum: server: Windows 2000 Server */
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"check OS support for NAPTR: %i %i %i\n",
					ovi.dwMajorVersion, ovi.dwMinorVersion, ovi.dwBuildNumber));
		if (ovi.dwMajorVersion > 5) {

#if (_WIN32_WINNT >= 0x0600)
			/* RUN only on Vista? */
			/* compile starting from SDK 6.0A? even on XP... */
			anaptr.order = tmp->Data.NAPTR.wOrder;
			anaptr.pref = tmp->Data.NAPTR.wPreference;
			strncpy(anaptr.flag, tmp->Data.NAPTR.pFlags, sizeof(anaptr.flag) - 1);
			strncpy(anaptr.service, tmp->Data.NAPTR.pService,
					sizeof(anaptr.service) - 1);
			strncpy(anaptr.regexp, tmp->Data.NAPTR.pRegularExpression,
					sizeof(anaptr.regexp) - 1);
			strncpy(anaptr.replacement, tmp->Data.NAPTR.pReplacement,
					sizeof(anaptr.replacement) - 1);

#endif
		}

		else {
			memcpy((void *) &anaptr.order, buf, 2);
			anaptr.order = ntohs(anaptr.order);	/* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */
			buf += sizeof(unsigned short);
			memcpy((void *) &anaptr.pref, buf, 2);
			anaptr.pref = ntohs(anaptr.pref);	/* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */
			buf += sizeof(unsigned short);

			len = *buf;
			if (len < 0 || len > 255)
				break;
			buf++;
			strncpy(anaptr.flag, buf, len);
			anaptr.flag[len] = '\0';
			buf += len;

			len = *buf;
			if (len < 0 || len > 1023)
				break;
			buf++;
			strncpy(anaptr.service, buf, len);
			anaptr.service[len] = '\0';
			buf += len;

			len = *buf;
			if (len < 0 || len > 1023)
				break;
			buf++;
			strncpy(anaptr.regexp, buf, len);
			anaptr.regexp[len] = '\0';
			buf += len;

			len =
				_eX_dn_expand((char *) &tmp->Data,
							  ((char *) &tmp->Data) + tmp->wDataLength, buf,
							  anaptr.replacement, 1024 - 1);

			if (len < 0)
				break;
			buf += len;
		}

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"NAPTR %s ->%i/%i/%s/%s/%s/%s\n",
					zone, anaptr.order, anaptr.pref, anaptr.flag,
					anaptr.service, anaptr.regexp, anaptr.replacement));

		if (osip_strncasecmp(tr, "udp", 4) == 0
			&& osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tcp", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "udp-tls", 8) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tls", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "sctp", 5) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		}

		n++;
	}

	DnsRecordListFree(answer, DnsFreeRecordList);

	if (n == 0)
		return OSIP_UNKNOWN_HOST;

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"protocol: %s is not supported by domain %s\n", protocol, domain));
	return OSIP_SUCCESS;
}
Example #13
0
//------------------------------------------------------------------------------
DWORD WINAPI Scan_dns(LPVOID lParam)
{
  unsigned int local_id = (unsigned int)lParam;

  //check if local or not :)
  if (!LOCAL_SCAN || WINE_OS)
  {
    h_thread_test[local_id] = 0;
    check_treeview(htrv_test, H_tests[local_id], TRV_STATE_UNCHECK);//db_scan
    return 0;
  }

  //init
  if(!SQLITE_FULL_SPEED)sqlite3_exec(db_scan,"BEGIN TRANSACTION;", NULL, NULL, NULL);
  sqlite3 *db = (sqlite3 *)db_scan;
  unsigned int session_id = current_session_id;

  //make file directory
  char file[MAX_PATH]="";
  char ip[IPV6_SIZE_MAX],name[MAX_PATH];
  snprintf(file,MAX_PATH,"%s\\WINDOWS\\system32\\drivers\\etc\\hosts",getenv("SYSTEMDRIVE"));

  #ifdef CMD_LINE_ONLY_NO_DB
  printf("\"DNS\";\"file\";\"ip\";\"name\";\"last_file_update\";\"malware_check\";\"session_id\";\r\n");
  #endif // CMD_LINE_ONLY_NO_DB

  //open host file and read all hosts
  HANDLE Hfic = CreateFile(file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
  if (Hfic != INVALID_HANDLE_VALUE)
  {
    DWORD taille_fic = GetFileSize(Hfic,NULL);
    if (taille_fic != INVALID_FILE_SIZE)
    {
      char *buffer = (char *) HeapAlloc(GetProcessHeap(), 0, taille_fic+1);
      if (buffer != NULL)
      {
        //get last update
        char last_file_update[DATE_SIZE_MAX]="";
        FILETIME LastWriteTime;
        if(GetFileTime(Hfic,NULL,NULL,&LastWriteTime))filetimeToString_GMT(LastWriteTime, last_file_update, DATE_SIZE_MAX);

        //read data line by line
        DWORD copiee;
        char lines[MAX_PATH];
        if (ReadFile(Hfic, buffer, taille_fic,&copiee,0))
        {
          char *r = buffer;
          char *s,*c;
          while (*r)
          {
            //read line
            memset(lines,0,MAX_PATH);
            strncpy(lines,r,MAX_PATH);
            s = lines;
            while (*s && *s != '\r')s++;
            *s = 0;
            r = r+strlen(lines)+2;

            //comment or not :)
            if (lines[0]!='#' && strlen(lines) > 8)
            {
              //get IP
              strncpy(ip,lines,IPV6_SIZE_MAX);
              c = ip;

              while (*c && *c != ' ' && *c!= '\t' && (*c == '.' || *c == ':' || (*c<='9' && *c>='0')))c++;
              if (*c)
              {
                *c = 0;
                //get name
                c = lines+strlen(ip);
                while (*c && (*c == ' ' || *c == '\t'))c++;

                memset(name,0,MAX_PATH);
                strncpy(name,c,MAX_PATH);
                addHosttoDB(file, ip, name, last_file_update,session_id,db);
              }
            }
          }
        }
        HeapFree(GetProcessHeap(), 0, buffer);
      }
    }
    CloseHandle(Hfic);
  }

  //get cache
  HMODULE hDLL = LoadLibrary( "DNSAPI.DLL" );
  if (!hDLL) return 0;

  //function
  //typedef int(*DNS_GET_CACHE_DATA_TABLE)(PDNS_RECORD*);
  typedef int(WINAPI *DNS_GET_CACHE_DATA_TABLE)(PDNS_RECORD);
  DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE)GetProcAddress(hDLL,"DnsGetCacheDataTable");

  if (DnsGetCacheDataTable != NULL)
  {
    PDNS_RECORD pcache = NULL;
    DNS_RECORD* dnsRecords = NULL, *dnsr;
    IN_ADDR ipAddress;
    char last_file_update[DATE_SIZE_MAX]="";

    if (DnsGetCacheDataTable(&pcache) == TRUE)
    {
      PDNS_RECORD cache = pcache;
      while (cache)
      {
        memset(name,0,MAX_PATH);
        snprintf(name,MAX_PATH,"%S",cache->pName);
        if (name[0] != 0)
        {
          //get IP + TTL
          if(DnsQuery(name,DNS_TYPE_A,0,NULL,&dnsRecords,NULL) == ERROR_SUCCESS)
          {
            dnsr = dnsRecords;
            while (dnsr != NULL)
            {
              ipAddress.S_un.S_addr = dnsr->Data.A.IpAddress;
              if (inet_ntoa(ipAddress) != NULL)
              {
                snprintf(ip,IP_SIZE_MAX,"%s",inet_ntoa(ipAddress));
                snprintf(last_file_update,DATE_SIZE_MAX,"%lu (s)",dnsr->dwTtl);
                addHosttoDB("", ip, name, last_file_update,session_id,db);
              }
              dnsr = dnsr->pNext;
            }
            //free
            DnsRecordListFree(dnsRecords,DnsFreeRecordList);
          }
        }
        cache = cache->pNext;
      }
    }
  }
  FreeLibrary(hDLL);

  if(!SQLITE_FULL_SPEED)sqlite3_exec(db_scan,"END TRANSACTION;", NULL, NULL, NULL);
  check_treeview(htrv_test, H_tests[local_id], TRV_STATE_UNCHECK);//db_scan
  h_thread_test[local_id] = 0;
  return 0;
}
Example #14
0
BOOL CHwSMTP::SendSpeedEmail
		(
			LPCTSTR	lpszAddrFrom,
			LPCTSTR	lpszAddrTo,
			LPCTSTR	lpszSubject,
			LPCTSTR	lpszBody,
			LPCTSTR	lpszCharSet,
			CStringArray *pStrAryAttach,
			LPCTSTR	pStrAryCC,
			UINT	nSmtpSrvPort,
			LPCTSTR	pSend
		)
{

	BOOL ret=true;
	CString To;
	To += GET_SAFE_STRING(lpszAddrTo);
	To += _T(";");
	To += GET_SAFE_STRING(pStrAryCC);

	std::map<CString,std::vector<CString>> Address;

	int start = 0;
	while( start >= 0 )
	{
		CString one= To.Tokenize(_T(";"),start);
		one=one.Trim();
		if(one.IsEmpty())
			continue;

		CString addr;
		addr = GetServerAddress(one);
		if(addr.IsEmpty())
			continue;

		Address[addr].push_back(one);

	}

	std::map<CString,std::vector<CString>>::iterator itr1  =  Address.begin();
	for(  ;  itr1  !=  Address.end();  ++itr1 )
	{
		PDNS_RECORD pDnsRecord;
		PDNS_RECORD pNext;

		DnsQuery(itr1->first ,
						DNS_TYPE_MX,DNS_QUERY_STANDARD,
						NULL,			//Contains DNS server IP address.
						&pDnsRecord,	//Resource record that contains the response.
						NULL
						);

		CString to;
		to.Empty();
		for(int i=0;i<itr1->second.size();i++)
		{
			to+=itr1->second[i];
			to+=_T(";");
		}
		if(to.IsEmpty())
			continue;

		pNext=pDnsRecord;
		while(pNext)
		{
			if(pNext->wType == DNS_TYPE_MX)
				if(SendEmail(pNext->Data.MX.pNameExchange,NULL,NULL,false,
					lpszAddrFrom,to,lpszSubject,lpszBody,lpszCharSet,pStrAryAttach,pStrAryCC,
					25,pSend,lpszAddrTo))
					break;
			pNext=pNext->pNext;
		}
		if(pNext == NULL)
			ret = false;

		//SendEmail(itr1.first,NULL,NULL,false,lpszAddrFrom,,lpszFromname);
		DnsRecordListFree(pDnsRecord,DnsFreeRecordList);
	}

	return ret;
}
Example #15
0
const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *argv[])
{
	if (sRunningTCPObjects.count(obj->mId) >= 1)
		TCPObject_Disconnect(sRunningTCPObjects[obj->mId].get());
		
	DX::TCPObject *operand = new DX::TCPObject((unsigned int)obj);

	// Copy the hostname over
	char *desired_hostname = (char*)malloc(strlen(argv[2]) + 1);
	memcpy(desired_hostname, argv[2], strlen(argv[2]) + 1);

	// Create the connection info
	ConnectionInformation *connection = new ConnectionInformation;
	connection->target_hostname = desired_hostname;
	connection->buffer_length = 0;
	connection->is_connected = false;
	connection->socket = 0;

	// Hack: Store the Ptr to our connection information struct in the old unused state value
	operand->state = (unsigned int)connection;

	//ConnectionInformation *connection = (ConnectionInformation*)parameters;
	char *target_hostname = strlwr(connection->target_hostname);

	// Is it an IP we got?
	if (strstr(target_hostname, "ip:"))
		target_hostname += 3; // Chop off the 'ip:' segment

	// Did we get a port #?
	unsigned int desired_port = 0;
	char *port_delineator = strstr(target_hostname, ":");
	if (port_delineator)
	{
		port_delineator[0] = 0x00; // NULL Terminate the IP Segment
		port_delineator += 1;
		desired_port = atoi(port_delineator);
	}
	else
	{
		Con::errorf(0, "No Port");
		operand->CallMethod("onConnectFailed", 1, S32ToCharPtr(1));
		return "NO_PORT";
	}

	// Perform a DNS Lookup
	wchar_t hostname_dns[128];
	std::mbstowcs(hostname_dns, target_hostname, strlen(target_hostname) + 1);

	PDNS_RECORD dns_record;
	if (DnsQuery(hostname_dns, DNS_TYPE_A, DNS_QUERY_BYPASS_CACHE, NULL, &dns_record, NULL))
	{
		Con::errorf(0, "DNS Resolution Failed");
		operand->CallMethod("onDNSFailed", 0);
		return "FAILED_DNS";
	}
	IN_ADDR result_address;
	result_address.S_un.S_addr = dns_record->Data.A.IpAddress;

	DNS_FREE_TYPE freetype;
	DnsRecordListFree(dns_record, freetype);

	target_hostname = inet_ntoa(result_address);

	SOCKADDR_IN target_host;
	target_host.sin_family = AF_INET;
	target_host.sin_port = htons(desired_port);
	target_host.sin_addr.s_addr = inet_addr(target_hostname);

	Con::errorf(0, "Target %s on port %u SimID %u", target_hostname, desired_port, operand->identifier);

	// Create the Socket
	connection->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (connection->socket == INVALID_SOCKET)
	{
		Con::errorf(0, "Failed to create Socket!");
		operand->CallMethod("onConnectFailed", 2, S32ToCharPtr(2), S32ToCharPtr(WSAGetLastError()));
		return "FAILED_SOCKET_CREATION";
	}

	// Set Blocking Mode (a non-zero for imode = non-blocking)
	u_long imode = 1;
	ioctlsocket(connection->socket, FIONBIO, &imode);

	sRunningTCPObjects[obj->mId] = std::unique_ptr<DX::TCPObject>(operand);

	// Attempt the Connection
	connect(connection->socket, (SOCKADDR*)&target_host, sizeof(target_host));

	if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, NULL, NULL) < 0)
	{
		operand->CallMethod("onConnectFailed", 2, S32ToCharPtr(3), S32ToCharPtr(WSAGetLastError()));
		return "CANNOT_CONNECT";
	}
	else
	{
		operand->CallMethod("onConnected", 0);
		return "SUCCESS";
	}

	return "UNKNOWN_ERROR";
}
Example #16
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) */
}
Example #17
0
/* we always return a null-terminated string which has been malloc'ed.  The string
 * is always in the tag=value form.  If a temporary or permanent error occurs,
 * the string will be exactly "e=perm;" or "e=temp;".
 * Note that it never returns NULL.
 */
char *dns_text(char *dn)
{
// added by nhatier for compilation under MSVC
#ifdef _MSC_VER
   DNS_RECORD * l_Records = NULL;
   DNS_STATUS l_Result = DnsQuery(dn, DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &l_Records, NULL);
   if (l_Result == ERROR_SUCCESS)
   {
      if (l_Records->wType == DNS_TYPE_TEXT)
      {
         unsigned int i;
         char buf[4096];
         buf[0] = 0;
         for (i = 0; i < l_Records->Data.TXT.dwStringCount; i++)
         {
            strcat(buf, l_Records->Data.TXT.pStringArray[i]);
         }
         DnsRecordListFree(l_Records, DnsFreeRecordList);
         return dk_strdup(buf);
      }
      else
      {
         DnsRecordListFree(l_Records, DnsFreeRecordList);
         return dk_strdup("e=perm;");
      }
   }
   else if (l_Result == DNS_ERROR_RECORD_TIMED_OUT)
   {
      DnsRecordListFree(l_Records, DnsFreeRecordList);
      return dk_strdup("e=temp;");
   }
   else
   {
      DnsRecordListFree(l_Records, DnsFreeRecordList);
      return dk_strdup("e=perm;");
   }
#else //end added by nhatier
    u_char response[PACKETSZ+1]; /* response */
    int responselen;		/* buffer length */

    int i, rc;			/* misc variables */
    int ancount, qdcount;	/* answer count and query count */
    u_short type, rdlength;		/* fields of records returned */
    u_char *eom, *cp;

    u_char buf[PACKETSZ+1];	/* we're storing a TXT record here, not just a DNAME */
    u_char *bufptr;

    responselen = res_query(dn, C_IN, T_TXT, response, sizeof(response));
    if (responselen  < 0){
      if (h_errno == TRY_AGAIN) return dk_strdup("e=temp;");
      else return dk_strdup("e=perm;");
    }

    qdcount = getshort( response + 4); /* http://crynwr.com/rfc1035/rfc1035.html#4.1.1. */
    ancount = getshort( response + 6);

    eom = response + responselen;
    cp  = response + HFIXEDSZ;

    while( qdcount-- > 0 && cp < eom ) {
      rc = dn_expand( response, eom, cp, (char *)buf, MAXDNAME );
      if( rc < 0 ) {
	return dk_strdup("e=perm;");
      }
      cp += rc + QFIXEDSZ;
    }

    while( ancount-- > 0 && cp < eom ) {
      rc = dn_expand( response, eom, cp, (char *)buf, MAXDNAME );
      if( rc < 0 ) {
	return dk_strdup("e=perm;");
      }

      cp += rc;

      if (cp + RRFIXEDSZ >= eom) return dk_strdup("e=perm;");

      type = getshort(cp + 0); /* http://crynwr.com/rfc1035/rfc1035.html#4.1.3. */
      rdlength = getshort(cp + 8);
      cp += RRFIXEDSZ;

      if( type != T_TXT ) {
	cp += rdlength;
	continue;
      }

      bufptr = buf;
      while (rdlength && cp < eom) {
	int cnt;

	cnt = *cp++;		 /* http://crynwr.com/rfc1035/rfc1035.html#3.3.14. */
	if( bufptr-buf + cnt + 1 >= PACKETSZ )
	  return dk_strdup("e=perm;");
	if (cp + cnt > eom)
	  return dk_strdup("e=perm;");
	memcpy( bufptr, cp, cnt);
	rdlength -= cnt + 1;
	bufptr += cnt;
	cp += cnt;
	*bufptr = '\0';
      }

      return (char *) dk_strdup( buf );
    }
    return dk_strdup("e=perm;");
#endif
}
void PlatformDomainNameServiceQuery::runBlocking() {
	if (!serviceValid) {
		emitError();
		return;
	}

	SWIFT_LOG(debug) << "Querying " << service << std::endl;

	std::vector<DomainNameServiceQuery::Result> records;

#if defined(SWIFTEN_PLATFORM_WINDOWS)
	DNS_RECORD* responses;
	// FIXME: This conversion doesn't work if unicode is deffed above
	if (DnsQuery(service.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) {
		emitError();
		return;
	}

	DNS_RECORD* currentEntry = responses;
	while (currentEntry) {
		if (currentEntry->wType == DNS_TYPE_SRV) {
			DomainNameServiceQuery::Result record;
			record.priority = currentEntry->Data.SRV.wPriority;
			record.weight = currentEntry->Data.SRV.wWeight;
			record.port = currentEntry->Data.SRV.wPort;
				
			// The pNameTarget is actually a PCWSTR, so I would have expected this 
			// conversion to not work at all, but it does.
			// Actually, it doesn't. Fix this and remove explicit cast
			// Remove unicode undef above as well
			record.hostname = std::string((const char*) currentEntry->Data.SRV.pNameTarget);
			records.push_back(record);
		}
		currentEntry = currentEntry->pNext;
	}
	DnsRecordListFree(responses, DnsFreeRecordList);

#else
	// Make sure we reinitialize the domain list every time
	res_init();

	ByteArray response;
	response.resize(NS_PACKETSZ);
	int responseLength = res_query(const_cast<char*>(service.c_str()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(vecptr(response)), response.size());
	if (responseLength == -1) {
		SWIFT_LOG(debug) << "Error" << std::endl;
		emitError();
		return;
	}

	// Parse header
	HEADER* header = reinterpret_cast<HEADER*>(vecptr(response));
	unsigned char* messageStart = vecptr(response);
	unsigned char* messageEnd = messageStart + responseLength;
	unsigned char* currentEntry = messageStart + NS_HFIXEDSZ;

	// Skip over the queries
	int queriesCount = ntohs(header->qdcount);
	while (queriesCount > 0) {
		int entryLength = dn_skipname(currentEntry, messageEnd);
		if (entryLength < 0) {
			emitError();
			return;
		}
		currentEntry += entryLength + NS_QFIXEDSZ;
		queriesCount--;
	}

	// Process the SRV answers
	int answersCount = ntohs(header->ancount);
	while (answersCount > 0) {
		DomainNameServiceQuery::Result record;

		int entryLength = dn_skipname(currentEntry, messageEnd);
		currentEntry += entryLength;
		currentEntry += NS_RRFIXEDSZ;

		// Priority
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.priority = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2;

		// Weight
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.weight = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2;

		// Port
		if (currentEntry + 2 >= messageEnd) {
			emitError();
			return;
		}
		record.port = boost::numeric_cast<int>(ns_get16(currentEntry));
		currentEntry += 2; 

		// Hostname
		if (currentEntry >= messageEnd) {
			emitError();
			return;
		}
		ByteArray entry;
		entry.resize(NS_MAXDNAME);
		entryLength = dn_expand(messageStart, messageEnd, currentEntry, reinterpret_cast<char*>(vecptr(entry)), entry.size());
		if (entryLength < 0) {
			emitError();
			return;
		}
		record.hostname = std::string(reinterpret_cast<const char*>(vecptr(entry)));
		records.push_back(record);
		currentEntry += entryLength;
		answersCount--;
	}
#endif

	BoostRandomGenerator generator;
	DomainNameServiceQuery::sortResults(records, generator);
	//std::cout << "Sending out " << records.size() << " SRV results " << std::endl;
	eventLoop->postEvent(boost::bind(boost::ref(onResult), records), shared_from_this());
}
Example #19
0
   bool
   DNSResolver::Resolve_(const String &sSearchFor, std::vector<String> &vecFoundNames, WORD wType, int iRecursion)
   {
      if (iRecursion > 10)
      {
         String sMessage = Formatter::Format("Too many recursions during query. Query: {0}, Type: {1}", sSearchFor, wType);
         ErrorManager::Instance()->ReportError(ErrorManager::Low, 4401, "DNSResolver::Resolve_", sMessage);

         return false;
      }

      PDNS_RECORD pDnsRecord = NULL;
      PIP4_ARRAY pSrvList = NULL;

      DWORD fOptions = DNS_QUERY_STANDARD;
      
      DNS_STATUS nDnsStatus = DnsQuery(sSearchFor, wType, fOptions, NULL, &pDnsRecord, NULL);

      PDNS_RECORD pDnsRecordsToDelete = pDnsRecord;

      if (nDnsStatus != 0)
      {
         if (pDnsRecordsToDelete)
            _FreeDNSRecord(pDnsRecordsToDelete);

         bool bDNSError = IsDNSError_(nDnsStatus);

         if (bDNSError)
         {
            String sMessage;
            sMessage.Format(_T("DNS - Query failure. Query: %s, Type: %d, DnsQuery return value: %d."), sSearchFor.c_str(), wType, nDnsStatus);
            LOG_TCPIP(sMessage);
            return false;
         }

         return true;
      }

      std::vector<DnsRecordWithPreference> foundDnsRecordsWithPreference;

      do
      {
         switch (pDnsRecord->wType)
         {
            case DNS_TYPE_A:
            {
               SOCKADDR_IN addr;
               memset(&addr, 0, sizeof addr);

               addr.sin_family = AF_INET;
               addr.sin_addr = *((in_addr*)&(pDnsRecord->Data.AAAA.Ip6Address));

               char buf[128];
               DWORD bufSize = sizeof(buf);

               if (WSAAddressToStringA((sockaddr*)&addr, sizeof addr, NULL, buf, &bufSize) == 0)
               {
                  DnsRecordWithPreference rec(0, buf);
                  foundDnsRecordsWithPreference.push_back(rec);
               }
               
               break;
            }
            case DNS_TYPE_AAAA:
            {
               SOCKADDR_IN6 addr;
               memset(&addr, 0, sizeof addr);

               addr.sin6_family = AF_INET6;
               addr.sin6_addr = *((in_addr6*)&(pDnsRecord->Data.AAAA.Ip6Address));

               char buf[128];
               DWORD bufSize = sizeof(buf);

               if (WSAAddressToStringA((sockaddr*)&addr, sizeof addr, NULL, buf, &bufSize) == 0)
               {
                  DnsRecordWithPreference rec(0, buf);
                  foundDnsRecordsWithPreference.push_back(rec);
               }
               
               break;
            }
            case DNS_TYPE_CNAME:
            {
               String sDomainName = pDnsRecord->Data.CNAME.pNameHost;
               if (!Resolve_(sDomainName, vecFoundNames, wType, iRecursion+1))
                  return false;

               break;
            }
            case DNS_TYPE_MX: 
            {
               String sName = pDnsRecord->pName;
               bool bNameMatches = (sName.CompareNoCase(sSearchFor) == 0);

               if (pDnsRecord->Flags.S.Section == DNSREC_ANSWER && bNameMatches)
               {
                  DnsRecordWithPreference rec(pDnsRecord->Data.MX.wPreference, pDnsRecord->Data.MX.pNameExchange);
                  foundDnsRecordsWithPreference.push_back(rec);
               }

               break;
            }
         case DNS_TYPE_TEXT: 
            {
               AnsiString retVal;

               for (u_int i = 0; i < pDnsRecord->Data.TXT.dwStringCount; i++)
                  retVal += pDnsRecord->Data.TXT.pStringArray[i];
               
               DnsRecordWithPreference rec (0, retVal);
               foundDnsRecordsWithPreference.push_back(rec);

               break;
            }
         case DNS_TYPE_PTR: 
            {
               AnsiString retVal;
               retVal = pDnsRecord->Data.PTR.pNameHost;

               DnsRecordWithPreference rec(0, retVal);
               foundDnsRecordsWithPreference.push_back(rec);
               break;
            }
            default:
            {
               ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5036, "DNSResolver::Resolve_", Formatter::Format("Queried for {0} but received type {1}", wType, pDnsRecord->wType));
               break;
            }
         }

         pDnsRecord = pDnsRecord->pNext;
      }
      while (pDnsRecord != nullptr);

      std::sort(foundDnsRecordsWithPreference.begin(), foundDnsRecordsWithPreference.end(), SortDnsRecordWithPreference);

      for (DnsRecordWithPreference item : foundDnsRecordsWithPreference)
      {
         vecFoundNames.push_back(item.Value);
      }

      _FreeDNSRecord(pDnsRecordsToDelete);
      pDnsRecordsToDelete = 0;

      return true;
   }
Example #20
0
File: net.c Project: 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) */
}
Example #21
0
int
eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol)
{
	char zone[1024];
	PDNS_RECORD answer, tmp;	/* answer buffer from nameserver */
	int n;
	char tr[100];

	memset(zone, 0, sizeof(zone));
	memset(record, 0, sizeof(struct osip_srv_record));

	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (eXosip.dns_capabilities <= 0)
		return OSIP_UNKNOWN_HOST;	/* disabled */

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);
	if (eXosip.dns_capabilities >= 2)
		n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1);
	else
		n = -1;					/* avoid NAPTR */
	if (n == OSIP_SUCCESS && zone[0] == '\0') {
		/* protocol is not listed in NAPTR answer: not supported */
		return OSIP_UNKNOWN_HOST;
	}

	if (n != OSIP_SUCCESS) {
		if (osip_strcasecmp(tr, "TLS") == 0)
			snprintf(zone, sizeof(zone) - 1, "_sips._tcp.%s", domain);
		else if (osip_strcasecmp(tr, "DTLS") == 0)
			snprintf(zone, sizeof(zone) - 1, "_sips._udp.%s", domain);
		else
			snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain);

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"Using locally generated SRV record %s\n", zone));
	}

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s IN SRV'\n", zone));

	if (DnsQuery(zone, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &answer, NULL) != 0) {
		return OSIP_UNKNOWN_HOST;
	}

	n = 0;
	for (tmp = answer; tmp != NULL; tmp = tmp->pNext) {
		struct osip_srv_entry *srventry;

		DNS_SRV_DATA *data;

		if (tmp->wType != DNS_TYPE_SRV)
			continue;
		srventry = &record->srventry[n];
		data = &tmp->Data.SRV;
		snprintf(srventry->srv, sizeof(srventry->srv), "%s", data->pNameTarget);

		srventry->priority = data->wPriority;
		srventry->weight = data->wWeight;
		if (srventry->weight)
			srventry->rweight = 1 + rand() % (10000 * srventry->weight);
		else
			srventry->rweight = 0;
		srventry->port = data->wPort;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"SRV record %s IN SRV -> %s:%i/%i/%i/%i\n",
					zone, srventry->srv, srventry->port, srventry->priority,
					srventry->weight, srventry->rweight));

		n++;
		if (n == 10)
			break;
	}

	DnsRecordListFree(answer, DnsFreeRecordList);

	if (n == 0)
		return OSIP_UNKNOWN_HOST;
	osip_srv_record_sort(record, n);
	snprintf(record->name, sizeof(record->name), "%s", domain);
	return OSIP_SUCCESS;
}