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; }
/** * 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; } }
/* 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; }
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; }
/****************************************************************************** * 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; }
/****************************************************************************** * 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; }
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); }
static void free_lookup_service (GWin32ResolverRequest *req) { g_free (req->u.service.rrname); if (req->u.service.results) DnsRecordListFree (req->u.service.results, DnsFreeRecordList); }
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; }
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; }
void _FreeDNSRecord(PDNS_RECORD pRecord) { if (!pRecord) return; DNS_FREE_TYPE freetype = DnsFreeRecordListDeep; DnsRecordListFree(pRecord, freetype); }
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; }
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); }
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; }
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; }
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()
/* 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; }
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); }
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; }
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; }
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; }
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; } }
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); }
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); }
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) */ }
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"; }
/* 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 }
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; }
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(); }
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) */ }