예제 #1
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;
}
예제 #2
0
파일: dnsSD.c 프로젝트: wuhongyang/iass-web
/**
 * 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;
	}
}
예제 #3
0
/*
	Gets the machine's domain name

	\param[in, out]	name pointer to a buffer that receives a null-terminated string containing the domain name
	\param[in]		size specifies the size of the buffer, in chars (must be large
                    enough to hold NULL-terminated domain name)

	\retval			return 0 ifsuccess,  -1 on error.


*/
int WINAPI
wsh_getdomainname(char* name, int size)
{
    DNS_STATUS status;

    PDNS_RECORD pDnsRecord;
    DNS_FREE_TYPE freetype ;

    DWORD length;
    char hostName[BUFSIZ];

    length = BUFSIZ;
    freetype =  DnsFreeRecordListDeep;


   // Get and display the name of the computer.

   if( GetComputerName(hostName, &length) )
   {

        status = DnsQuery_A(hostName,                 //pointer to OwnerName
                        DNS_TYPE_A,                      //Type of the record to be queried
                        DNS_QUERY_BYPASS_CACHE|DNS_QUERY_NO_LOCAL_NAME,     // Bypasses the resolver cache on the lookup.
                        NULL,                   //contains DNS server IP address
                        &pDnsRecord,                //Resource record comprising the response
                        NULL);                     //reserved for future use

        if (status)
            return -1;
        else
        {
            char* cp;
            cp = index(pDnsRecord->pName, '.');
            if (cp)
            {
                cp++;
                strncpy(name, cp, size);
                name[size-1] = '\0';
                DnsRecordListFree(pDnsRecord, freetype);
                return(0);
            }
            DnsRecordListFree(pDnsRecord, freetype);

        }
   }

    /* try to get local domain from the registry */
    if (_getdomainname(name, size))
        return 0;
    else
        return -1;
}
예제 #4
0
파일: dns.cpp 프로젝트: RankoR/mqutim
  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;
  }
예제 #5
0
파일: query.c 프로젝트: NVIDIA/winex_lgpl
/******************************************************************************
 * DnsQuery_W              [DNSAPI.@]
 *
 */
DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID servers,
                              PDNS_RECORDW *result, PVOID *reserved )
{
    char *nameU;
    DNS_RECORDA *resultA;
    DNS_STATUS status;

    TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name), dns_type_to_str( type ),
           options, servers, result, reserved );

    if (!name || !result)
        return ERROR_INVALID_PARAMETER;

    nameU = dns_strdup_wu( name );
    if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;

    status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved ); 

    if (status == ERROR_SUCCESS)
    {
        *result = (DNS_RECORDW *)DnsRecordSetCopyEx(
            (DNS_RECORD *)resultA, DnsCharSetUtf8, DnsCharSetUnicode );

        if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
        DnsRecordListFree( (DNS_RECORD *)resultA, DnsFreeRecordList );
    }

    dns_free( nameU );
    return status;
}
예제 #6
0
파일: query.c 프로젝트: NVIDIA/winex_lgpl
/******************************************************************************
 * DnsQuery_A           [DNSAPI.@]
 *
 */
DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
                              PDNS_RECORDA *result, PVOID *reserved )
{
    WCHAR *nameW;
    DNS_RECORDW *resultW;
    DNS_STATUS status;

    TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
           options, servers, result, reserved );

    if (!name || !result)
        return ERROR_INVALID_PARAMETER;

    nameW = dns_strdup_aw( name );
    if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;

    status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved ); 

    if (status == ERROR_SUCCESS)
    {
        *result = (DNS_RECORDA *)DnsRecordSetCopyEx(
             (DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );

        if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
        DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
    }

    dns_free( nameW );
    return status;
}
예제 #7
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);
}
예제 #8
0
static void
free_lookup_service (GWin32ResolverRequest *req)
{
  g_free (req->u.service.rrname);
  if (req->u.service.results)
    DnsRecordListFree (req->u.service.results, DnsFreeRecordList);
}
예제 #9
0
WINAPI
hes_resolve(LPSTR HesiodName, LPSTR HesiodNameType)
{
    register char  *cp;
    LPSTR* retvec;
    DNS_STATUS status; 
    
    PDNS_RECORD pDnsRecord; 
    PDNS_RECORD pR;
    DNS_FREE_TYPE freetype ;
    int i = 0;
    freetype =  DnsFreeRecordListDeep;
    

    cp = hes_to_bind(HesiodName, HesiodNameType);
    if (cp == NULL) return(NULL);
    errno = 0;

    
    status = DnsQuery_A(cp,                 //pointer to OwnerName 
                        DNS_TYPE_TEXT,         //Type of the record to be queried
                        DNS_QUERY_STANDARD,     // Bypasses the resolver cache on the lookup. 
                        NULL,                   //contains DNS server IP address
                        &pDnsRecord,                //Resource record comprising the response
                        NULL);                     //reserved for future use
    
    if (status) {
        errno = status;
        Hes_Errno = HES_ER_NOTFOUND;
        return  NULL;
    }
     
    pR = pDnsRecord;
    while (pR)
    {   
        if (pR->wType == DNS_TYPE_TEXT)
            i++;
        pR = pR->pNext;
    }
    i++;
    retvec = LocalAlloc(LPTR, i*sizeof(LPSTR));
    pR = pDnsRecord;
    i = 0;
    while (pR)
    {   
        if (pR->wType == DNS_TYPE_TEXT){
            SIZE_T l = strlen(((pR->Data).Txt.pStringArray)[0]);
            retvec[i] = LocalAlloc(LPTR, l+1);
            strcpy(retvec[i], ((pR->Data).Txt.pStringArray)[0]);
            i++;
        }
        pR = pR->pNext;
    }
    retvec[i] = NULL;
    DnsRecordListFree(pDnsRecord, freetype);
    return retvec;
         
}
예제 #10
0
파일: resolver.c 프로젝트: keenser/Maiccu
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;
}
예제 #11
0
   void 
   _FreeDNSRecord(PDNS_RECORD pRecord)
   {
      if (!pRecord) 
         return;

      DNS_FREE_TYPE freetype = DnsFreeRecordListDeep;
      DnsRecordListFree(pRecord, freetype);
   }
예제 #12
0
파일: query.c 프로젝트: NVIDIA/winex_lgpl
static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options,
                                PDNS_RECORDA *result )
{
    DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;

    unsigned int i, num;
    unsigned char answer[NS_PACKETSZ];
    ns_sect sections[] = { ns_s_an, ns_s_ar };
    ns_msg msg;

    DNS_RECORDA *record = NULL;
    DNS_RRSET rrset;
    int len;

    DNS_RRSET_INIT( rrset );

    len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
    if (len < 0)
    {
        ret = dns_map_h_errno( h_errno );
        goto exit;
    }

    if (dns_ns_initparse( answer, len, &msg ) < 0)
    {
        ret = DNS_ERROR_BAD_PACKET;
        goto exit;
    }

#define RCODE_MASK 0x0f
    if ((msg._flags & RCODE_MASK) != ns_r_noerror)
    {
        ret = dns_map_error( msg._flags & RCODE_MASK );
        goto exit;
    }

    for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++)
    {
        for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
        {
            ret = dns_copy_record( msg, sections[i], num, &record );
            if (ret != ERROR_SUCCESS) goto exit;

            DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
        }
    }

exit:
    DNS_RRSET_TERMINATE( rrset );

    if (ret != ERROR_SUCCESS)
        DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
    else
        *result = (DNS_RECORDA *)rrset.pFirstRR;

    return ret;
}
예제 #13
0
static void
do_lookup_records (GTask         *task,
                   gpointer       source_object,
                   gpointer       task_data,
                   GCancellable  *cancellable)
{
  LookupRecordsData *lrd = task_data;
  GList *records;
  GError *error = NULL;

#if defined(G_OS_UNIX)
  gint len = 512;
  gint herr;
  GByteArray *answer;
  gint rrtype;

  rrtype = g_resolver_record_type_to_rrtype (lrd->record_type);
  answer = g_byte_array_new ();
  for (;;)
    {
      g_byte_array_set_size (answer, len * 2);
      len = res_query (lrd->rrname, C_IN, rrtype, answer->data, answer->len);

      /* If answer fit in the buffer then we're done */
      if (len < 0 || len < (gint)answer->len)
        break;

      /*
       * On overflow some res_query's return the length needed, others
       * return the full length entered. This code works in either case.
       */
    }

  herr = h_errno;
  records = g_resolver_records_from_res_query (lrd->rrname, rrtype, answer->data, len, herr, &error);
  g_byte_array_free (answer, TRUE);

#else

  DNS_STATUS status;
  DNS_RECORD *results = NULL;
  WORD dnstype;

  dnstype = g_resolver_record_type_to_dnstype (lrd->record_type);
  status = DnsQuery_A (lrd->rrname, dnstype, DNS_QUERY_STANDARD, NULL, &results, NULL);
  records = g_resolver_records_from_DnsQuery (lrd->rrname, dnstype, status, results, &error);
  if (results != NULL)
    DnsRecordListFree (results, DnsFreeRecordList);

#endif

  if (records)
    g_task_return_pointer (task, records, (GDestroyNotify) free_records);
  else
    g_task_return_error (task, error);
}
예제 #14
0
파일: DNS.cpp 프로젝트: joegen/oss_core
DNS_STATUS DnsQuery_A(const char * service,
                              unsigned short requestType,
                             unsigned long options,
                            void *,
                     DNS_RECORD * results,
                            void *)
{
  if (results == 0)
    return -1;

  *results = 0;

  struct __res_state statbuf;
  res_ninit(&statbuf);

  union {
    HEADER hdr;
    unsigned char buf[PACKETSZ];
  } reply;

  int replyLen = res_nsearch(&statbuf, service, C_IN, requestType, (unsigned char *)&reply, sizeof(reply));

  if (replyLen < 1)
    return -1;

  unsigned char * replyStart = reply.buf;
  unsigned char * replyEnd   = reply.buf + replyLen;
  unsigned char * cp         = reply.buf + sizeof(HEADER);

  // ignore questions in response
  uint16_t i;
  for (i = 0; i < ntohs(reply.hdr.qdcount); i++) {
    char qName[MAXDNAME];
    if (!GetDN(replyStart, replyEnd, cp, qName))
      return -1;
    cp += QFIXEDSZ;
  }

  if (!ProcessDNSRecords(
       replyStart,
       replyEnd,
       cp,
       ntohs(reply.hdr.ancount),
       ntohs(reply.hdr.nscount),
       ntohs(reply.hdr.arcount),
       results)) {
    DnsRecordListFree(*results, 0);
    res_nclose(&statbuf);
    return -1;
  }

  res_nclose(&statbuf);
  return 0;
}
예제 #15
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;
}
예제 #16
0
파일: network.cpp 프로젝트: doveman/akbash
int net_reQueryMxRecord(char * domain, struct  in_addr * mxIP)
{
	DNS_STATUS dns_rc = 0;
	DNS_RECORD * pQueryResultsSet;	
	char smtp_fqdn[SMTP_MAX_FQDN+1] = {0};

	debug_log(LOG_DBG, "net_reQueryMxRecord(): querying mx records for email domain: \'%s\'", domain);

    dns_rc = DnsQuery_A(domain, DNS_TYPE_MX, DNS_QUERY_STANDARD, NULL, &pQueryResultsSet, NULL);

	if (dns_rc == 0)
	{
		strncpy_s(smtp_fqdn, sizeof(smtp_fqdn), pQueryResultsSet->Data.MX.pNameExchange,  strlen(pQueryResultsSet->Data.MX.pNameExchange));

		debug_log(LOG_DBG, "net_reQueryMxRecord(): email domain: \'%s\', mail server: \'%s\'", domain, smtp_fqdn);
		DnsRecordListFree(pQueryResultsSet, DnsFreeRecordList);

		debug_log(LOG_DBG, "net_reQueryMxRecord(): looking up an IP for \'%s\'", smtp_fqdn);
		dns_rc = DnsQuery_A(smtp_fqdn, DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pQueryResultsSet, NULL);
		if (dns_rc == 0)
		{
			mxIP->S_un.S_addr = pQueryResultsSet->Data.A.IpAddress;

			debug_log(LOG_DBG, "net_reQueryMxRecord(): mail exchanger: \'%s\', ip: %s",  smtp_fqdn, inet_ntoa(*mxIP));
			DnsRecordListFree(pQueryResultsSet, DnsFreeRecordList);
		} else
		{
			debug_log(LOG_ERR, "net_reQueryMxRecord(): failed to resolve ip for mail exchanger: \'%s\', rc: %d)",  smtp_fqdn, dns_rc);
			debug_log(LOG_SVR, "net_reQueryMxRecord(): sending of email notifications will be disabled.");
			return SOCK_DNS_ERROR;
		}
	} else
	{
		debug_log(LOG_ERR, "net_reQueryMxRecord(): failed to resolve mx record for domain: \'%s\', rc: %d)",  domain, dns_rc);
		debug_log(LOG_SVR, "net_reQueryMxRecord(): sending of email notifications will be disabled.");
		return SOCK_DNS_ERROR;
	}

	return SOCK_NO_ERROR;
} // end of net_reQueryMxRecord()
예제 #17
0
파일: gethna.c 프로젝트: Akasurde/krb5
/*
	an internal function used by rgethostbyname that does the actual DnsQuery call and populates the hostent
	structure.

	\param[in]	Name of the owner of the record set being queried
	\param[in, out] populated hostent structure

	\retval		DNS_STATUS value returned by DnsQuery

*/
DNS_STATUS doquery(const char* queryname, struct hostent* host)
{
    DNS_STATUS status;
    PDNS_RECORD pDnsRecord, pDnsIter;
    DNS_FREE_TYPE freetype ;
    struct in_addr host_addr;
    char querynamecp[DNS_MAX_NAME_BUFFER_LENGTH];
    size_t len;

    freetype =  DnsFreeRecordListDeep;
    strcpy(querynamecp, queryname);
    status = DnsQuery_A(queryname,          //pointer to OwnerName
			DNS_TYPE_A,         //Type of the record to be queried
                        DNS_QUERY_STANDARD,
                        NULL,               //contains DNS server IP address
                        &pDnsRecord,        //Resource record comprising the response
                        NULL);              //reserved for future use

    if (status)
	return status;

    /* If the query name includes a trailing separator in order to prevent
     * a local domain search, remove the separator during the file name
     * comparisons. */
    len = strlen(querynamecp);
    if (querynamecp[len-1] == '.')
	querynamecp[len-1] = '\0';

    for (pDnsIter = pDnsRecord; pDnsIter; pDnsIter=pDnsIter->pNext) {
	/* if we get an A record, keep it */
	if (pDnsIter->wType == DNS_TYPE_A && stricmp(querynamecp, pDnsIter->pName)==0)
	    break;

	/* if we get a CNAME, look for a corresponding A record */
	if (pDnsIter->wType == DNS_TYPE_CNAME && stricmp(queryname, pDnsIter->pName)==0) {
	    strcpy(querynamecp, pDnsIter->Data.CNAME.pNameHost);
	}
    }
    if (pDnsIter == NULL)
	return DNS_ERROR_RCODE_NAME_ERROR;

    strcpy(host->h_name, pDnsIter->pName);
    host->h_addrtype = AF_INET;
    host->h_length = sizeof(u_long);
    host->h_aliases[0] = NULL;
    host_addr.S_un.S_addr = (pDnsIter->Data.A.IpAddress);
    memcpy(host->h_addr_list[0], (char*)&host_addr, sizeof(pDnsIter->Data.A.IpAddress));
    host->h_addr_list[1] = NULL;
    DnsRecordListFree(pDnsRecord, freetype);

    return 0;
}
예제 #18
0
파일: DNS.cpp 프로젝트: DarkGreising/Reaper
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);
}
예제 #19
0
ToxHexAddress ResolveToxAddressFromDns(const char *dnsQuery)
{
	ToxHexAddress address = ToxHexAddress::Empty();

	DNS_RECORDA *record = NULL;
	DNS_STATUS status = DnsQuery_A(dnsQuery, DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD*)&record, NULL);
	while (status == ERROR_SUCCESS && record)
	{
		DNS_TXT_DATAA *txt = &record->Data.Txt;
		if (record->wType == DNS_TYPE_TEXT && txt->dwStringCount)
		{
			address = ResolveToxAddressFromDnsRecordV1(txt->pStringArray[0]);
			break;
		}
		record = record->pNext;
	}
	DnsRecordListFree((PDNS_RECORD*)record, DnsFreeRecordList);

	return address;
}
예제 #20
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);
  
  PDNS_RECORD pRecOrig = apResult;

  if(r==0)
  {
    while(apResult!=NULL)
    {
      if(apResult->wType==DNS_TYPE_MX)        
      {
        CString sServerName = CString(apResult->Data.MX.pNameExchange);        
        host_list[apResult->Data.MX.wPreference] = sServerName;
      }

      apResult = apResult->pNext;
    }

    DnsRecordListFree(pRecOrig, DnsFreeRecordList);

    return 0;
  } 

  sStatusMsg.Format(_T("DNS query failed with code %d"), r);
  scn->SetProgress(sStatusMsg, 2);
  return 1;
}
예제 #21
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 = NULL;
    DNS_STATUS status = DnsQuery_UTF8( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL );
    if( status == ERROR_SUCCESS )
    {
      // NOTE: DnsQuery_UTF8 and DnsQuery_A really should have been defined with
      // PDNS_RECORDA instead of PDNS_RECORD, since that's what it is (even with _UNICODE defined).
      // We'll correct for that mistake with a cast.
      DNS_RECORDA* pRec = (DNS_RECORDA*)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
    {
      logInstance.warn( LogAreaClassDns, "DnsQuery_UTF8() failed: " + util::int2string( status ) );
      error = true;
    }

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

    return servers;
  }
예제 #22
0
static BOOLEAN SearchRootQuery(
    _In_ PWCHAR RemoteAddressString, 
    _In_ PPH_STRING *Result
    )
{
    if (!PhTryAcquireFastLockShared(&CacheListLock))
        return FALSE;

    PDNS_RECORD r = _SearchRootQuery(RemoteAddressString, DnsCacheList);

    PhReleaseFastLockShared(&CacheListLock);

    if (r)
    {
        *Result = GenerateCacheName(r);
        DnsRecordListFree(r, DnsFreeRecordList);
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
예제 #23
0
int main(int argc, char *argv[]) {
   
   HANDLE creds;
   DNS_RECORDA *result;
   DNS_STATUS status;
   
   HANDLE ContextHandle;
   DWORD Options=DNS_UPDATE_SECURITY_ON;
   PVOID pReserved=NULL;
   IN_ADDR ipaddr;
   IP4_ARRAY *servers=NULL;
   SEC_WINNT_AUTH_IDENTITY_A *Credentials=NULL;
   WORD i;
      
   printf(" Microsoft Dynamic DNS Updates - Proof of Concept\n");
   printf(" http://www.514.es - (c) 2007 Andres Tarasco Acuña\n\n");
   if (argc==1) usage(argv);
      
   //Init Credentials Struct
   Credentials = (SEC_WINNT_AUTH_IDENTITY_A *)malloc(sizeof(SEC_WINNT_AUTH_IDENTITY_A));
   memset(Credentials,'\0',sizeof(SEC_WINNT_AUTH_IDENTITY_A));
   Credentials->Flags=SEC_WINNT_AUTH_IDENTITY_ANSI;   
   for(i=1;i<argc;i++) {
      if ( (argv[i][0]=='-') ) {
         switch (argv[i][1]) {
         case 's':
         case 'S':
            strcpy(TargetDnsServer,argv[i+1]);
            servers=(PIP4_ARRAY)malloc(sizeof(IP4_ARRAY));
            servers->AddrCount=1;
            servers->AddrArray[0]=inet_addr(TargetDnsServer);
            break;
         case 'D':
         case 'd':
            strcpy(DeleteDnsRecord,argv[i+1]);
            break;                    
         case 'q':
         case 'Q':
            strcpy(TargetDnsRecord,argv[i+1]);
            break;
         case 'u':
         case 'U':
            strcpy(NewIpAddress,argv[i+1]);
            break;
         case 'c':
         case 'C':
            strcpy(CreateDnsRecord,argv[i+1]);
            if (NewIpAddress[0]=='\0') strcpy(NewIpAddress,"127.0.0.1");
            if (argv[i][2]!='\0') {
               switch (argv[i][2]) {
               case 'c': CreationType=DNS_TYPE_CNAME;
                  break;
               case 'a': CreationType=DNS_TYPE_A;
                  break;
               }
            }
            break;           
            /*
            case 'f':
               CreateThread( NULL,0,HttpRelayToProxy,(LPVOID) &i,0,&dwThreadId);
               break;
            case 'au': //Uauthorization serName
            Credentials->User=argv[i+1]; Credentials->UserLength=strlen(argv[i+1]);   break;
            case 'ap':
            Credentials->Password=argv[i+1];Credentials->PasswordLength=strlen(argv[i+1]); break;
            case 'ad':
            Credentials->Domain=argv[i+1]; Credentials->DomainLength=strlen(argv[i+1]);  break;     
            */
         default:
            printf("[-] Invalid argument: %s\n",argv[i]);
            usage(argv);
            break;
         }
         i++;            
      } else usage(argv);
   }
   
   printf("[+] Gathering Credentials..\n");
   //http://msdn2.microsoft.com/en-us/library/ms682007.aspx
   if (Credentials->UserLength==0) {
      status=DnsAcquireContextHandle(FALSE,NULL,&ContextHandle); //Context with default Credentials
   } else {
      status=DnsAcquireContextHandle(FALSE,Credentials,&ContextHandle); //Context with Custom Credentials
   }
   
   if (status == ERROR_SUCCESS) {          
      if (CREATERECORD) {
         
         result=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));
         memset(result,'\0',sizeof(DNS_RECORDA));
         result->wType=CreationType; //DNS_TYPE_A by default
         if (CreationType==DNS_TYPE_CNAME) {
            printf("[+] Creating DNS CName Record for %s (%s)\n",CreateDnsRecord,NewIpAddress);
            result->Data.Cname.pNameHost=NewIpAddress;
         } else {
            printf("[+] Creating DNS A Record for %s (%s)\n",CreateDnsRecord,NewIpAddress);
            result->Data.A.IpAddress=inet_addr(NewIpAddress);
         } 
         result->pName=CreateDnsRecord;
         result->wDataLength=4;
         result->Flags.S.Section=1;
         result->Flags.S.CharSet=DnsCharSetAnsi;
         result->pNext=NULL;       

         status=DnsModifyRecordsInSet_A(result,  //add record
            NULL, //delete record
            Options,
            ContextHandle,
            servers,
            NULL);
         if (status ==ERROR_SUCCESS) {
            printf("[+] Host Created. Rechecking Record...\n");
            DnsRecordListFree(result,DnsFreeRecordList);
            result=DnsQueryA(CreateDnsRecord,servers);
         } else {
            printf("[-] Error: Unable to create  %s (%i)\n",CreateDnsRecord,status);
         }      
      } else if (DELETERECORD) {         
         printf("[+] Trying to resolve Host: %s before deleting\n",DeleteDnsRecord);
         result=DnsQueryA(DeleteDnsRecord,servers);
         if (result!=NULL) {
            printf("[+] Trying to Delete Record. Are You Sure? (Y/N)...");
            i=getchar(); if (i!='y') return(-1);
            printf("[+] Deleting record %s\n",DeleteDnsRecord);   
            status=DnsModifyRecordsInSet_A(NULL,  //add record
               result, //delete record
               Options,
               ContextHandle,
               servers,
               NULL);      
            if (status ==ERROR_SUCCESS) {
               printf("[+] Host Deleted. Rechecking Record %s...\n",DeleteDnsRecord);
               DnsRecordListFree(result,DnsFreeRecordList);
               result=DnsQueryA(DeleteDnsRecord,servers);
            } else {
               printf("[-] Error: Unable to Delete %s\n",DeleteDnsRecord);
            }
         } else {
            printf("[-] Host %s not found\n",DeleteDnsRecord);
         }

      } else if (UPDATERECORD) {
         //         exit(1);
         printf("[+] Trying to resolve Host: %s before updating\n",TargetDnsRecord);
         result=DnsQueryA(TargetDnsRecord,servers);
         if (result->wType==DNS_TYPE_A ) {
            printf("[+] Trying to update record. Are You Sure? (Y/N)...");
            i=getchar(); if (i!='y') return(-1);
            result->Data.A.IpAddress=inet_addr(NewIpAddress);//Modify Dns record
            ipaddr.S_un.S_addr = (result->Data.A.IpAddress);
            printf("[+] Trying to set ip address of the host %s to %s \n", TargetDnsRecord,NewIpAddress);//inet_ntoa(ipaddr));
            printf("[+] Trying to Modify Record...\n");
            status=DnsReplaceRecordSetA(result,
               Options, //Attempts nonsecure dynamic update. If refused, then attempts secure dynamic update.
               ContextHandle,
               servers,//pServerList,
               NULL);//pReserved
            if (status ==ERROR_SUCCESS) {
               printf("[+] Host Updated. Rechecking Record...\n");
               DnsRecordListFree(result,DnsFreeRecordList);
               result=DnsQueryA(TargetDnsRecord,servers);
            } else {
               printf("[-] Error: Unable to Delete %s\n",TargetDnsRecord);
            }

         } else {
            printf("[-] Unable to Update Record (Type %x)\n",result->wType);
            }
      } else if (QUERYRECORD) {
         printf("[+] Query Information for host %s...\n",TargetDnsRecord);
         result=DnsQueryA(TargetDnsRecord,servers);
         DnsRecordListFree(result,DnsFreeRecordList);         
      } else {
         printf("[-] Unknown Options\n");
         return(-1);
      }           
   } else {
      printf("[-] Error Calling DnsAcquireContextHandle\n");   
   }
   return (1);
}
예제 #24
0
QT_BEGIN_NAMESPACE

void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply)
{
    // Perform DNS query.
    PDNS_RECORD dns_records = 0;
    const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size());
    IP4_ARRAY srvList;
    memset(&srvList, 0, sizeof(IP4_ARRAY));
    if (!nameserver.isNull()) {
        if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) {
            // The below code is referenced from: http://support.microsoft.com/kb/831226
            srvList.AddrCount = 1;
            srvList.AddrArray[0] = htonl(nameserver.toIPv4Address());
        } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) {
            // For supoprting IPv6 nameserver addresses, we'll need to switch
            // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
            // address in the nameserver list
            qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported";
            reply->error = QDnsLookup::ResolverError;
            reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
            return;
        }
    }
    const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL);
    switch (status) {
    case ERROR_SUCCESS:
        break;
    case DNS_ERROR_RCODE_FORMAT_ERROR:
        reply->error = QDnsLookup::InvalidRequestError;
        reply->errorString = tr("Server could not process query");
        return;
    case DNS_ERROR_RCODE_SERVER_FAILURE:
        reply->error = QDnsLookup::ServerFailureError;
        reply->errorString = tr("Server failure");
        return;
    case DNS_ERROR_RCODE_NAME_ERROR:
        reply->error = QDnsLookup::NotFoundError;
        reply->errorString = tr("Non existent domain");
        return;
    case DNS_ERROR_RCODE_REFUSED:
        reply->error = QDnsLookup::ServerRefusedError;
        reply->errorString = tr("Server refused to answer");
        return;
    default:
        reply->error = QDnsLookup::InvalidReplyError;
        reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
        return;
    }

    // Extract results.
    for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
        const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
        if (ptr->wType == QDnsLookup::A) {
            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(ntohl(ptr->Data.A.IpAddress));
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::AAAA) {
            Q_IPV6ADDR addr;
            memcpy(&addr, &ptr->Data.AAAA.Ip6Address, sizeof(Q_IPV6ADDR));

            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(addr);
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::CNAME) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
            reply->canonicalNameRecords.append(record);
        } else if (ptr->wType == QDnsLookup::MX) {
            QDnsMailExchangeRecord record;
            record.d->name = name;
            record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
            record.d->preference = ptr->Data.Mx.wPreference;
            record.d->timeToLive = ptr->dwTtl;
            reply->mailExchangeRecords.append(record);
        } else if (ptr->wType == QDnsLookup::NS) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
            reply->nameServerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::PTR) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
            reply->pointerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::SRV) {
            QDnsServiceRecord record;
            record.d->name = name;
            record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
            record.d->port = ptr->Data.Srv.wPort;
            record.d->priority = ptr->Data.Srv.wPriority;
            record.d->timeToLive = ptr->dwTtl;
            record.d->weight = ptr->Data.Srv.wWeight;
            reply->serviceRecords.append(record);
        } else if (ptr->wType == QDnsLookup::TXT) {
            QDnsTextRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
                record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
            }
            reply->textRecords.append(record);
        }
    }

    DnsRecordListFree(dns_records, DnsFreeRecordList);
}
예제 #25
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) */
}
예제 #26
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";
}
예제 #27
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
}
예제 #28
0
파일: sablob.c 프로젝트: hoangduit/reactos
PDNS_BLOB
WINAPI
SaBlob_Query(IN LPWSTR Name,
             IN WORD DnsType,
             IN ULONG Flags,
             IN PVOID *Reserved,
             IN DWORD AddressFamily)
{
    PDNS_RECORD DnsRecord = NULL;
    INT ErrorCode;
    PDNS_BLOB DnsBlob = NULL;
    LPWSTR LocalName, LocalNameCopy;

    /* If they want reserved data back, clear it out in case we fail */
    if (Reserved) *Reserved = NULL;

    /* Query DNS */
    ErrorCode = DnsQuery_W(Name,
                           DnsType,
                           Flags,
                           NULL,
                           &DnsRecord,
                           Reserved);
    if (ErrorCode != ERROR_SUCCESS)
    {
        /* We failed... did the caller use reserved data? */
        if (Reserved && *Reserved)
        {
            /* He did, and it was valid. Free it */
            DnsApiFree(*Reserved);
            *Reserved = NULL;
        }

        /* Normalize error code */
        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
        goto Quickie;
    }

    /* Now create the Blob from the DNS Records */
    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
    if (!DnsBlob)
    {
        /* Failed, get error code */
        ErrorCode = GetLastError();
        goto Quickie;
    }

    /* Make sure it has a name */
    if (!DnsBlob->Name)
    {
        /* It doesn't, fail */
        ErrorCode = DNS_INFO_NO_RECORDS;
        goto Quickie;
    }

    /* Check if the name is local or loopback */
    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
    {
        /* Nothing left to do, exit! */
        goto Quickie;
    }

    /* This is a local name...query it */
    LocalName = DnsQueryConfigAllocEx(DnsConfigFullHostName_W, NULL, NULL);
    if (LocalName)
    {
        /* Create a copy for the caller */
        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
        if (LocalNameCopy)
        {
            /* Overwrite the one in the blob */
            DnsBlob->Name = LocalNameCopy;
        }
        else
        {
            /* We failed to make a copy, free memory */
            DnsApiFree(LocalName);
        }
    }

Quickie:
    /* Free the DNS Record if we have one */
    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);

    /* Check if this is a failure path with an active blob */
    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
    {
        /* Free the blob */
        SaBlob_Free(DnsBlob);
        DnsBlob = NULL;
    }

    /* Set the last error and return */
    SetLastError(ErrorCode);
    return DnsBlob;
}
예제 #29
0
파일: DNS.cpp 프로젝트: joegen/oss_core
bool dns_srv_lookup(const std::string& name, dns_srv_record_list& recordList)
{
  static OSS::Private::DnsSrvExpireCache srvCache(3600 * 1000);

  if (name.empty())
  {
    //
    // Treat an empty name as a flush request
    //
    srvCache.clear();
    //
    // Return false so that it does not break any accidental call to flush with empty name.
    // A real request to flush wont care about the return value
    //
    return false;
  }

  recordList.clear();

  //
  // Check if we have something in cache
  //
  OSS::Private::DnsSrvPtr cached = srvCache.get(name);
  if (cached)
  {
    recordList = *cached;
    return !recordList.empty();
  }


  OSS::Private::DNS_RECORD results = 0;
  DNS_STATUS status = DnsQuery_A(name.c_str(),
                                 DNS_TYPE_SRV,
                                 DNS_QUERY_STANDARD,
                                 0,
                                 &results,
                                 0);
  if (status != 0)
    return false;

  // find records matching the correct type
  OSS::Private::DNS_RECORD dnsRecord = results;
  while (dnsRecord != 0)
  {
    dns_srv_record record;
    if (!handle_dns_srv_record(dnsRecord, results, record) )
      break;
    recordList.insert(record);
    dnsRecord = dnsRecord->pNext;
  }

  if (results != 0)
    DnsRecordListFree(results, DnsFreeRecordList);

  if (!recordList.empty())
  {
    //
    // cache it
    //
    srvCache.add(name, OSS::Private::DnsSrvPtr(new dns_srv_record_list(recordList)));
    return true;
  }

  return !recordList.empty();
}
예제 #30
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) */
}