dnsQueryRaw 函式 (windns.h)
重要
有些資訊與發行前版本產品有關,在正式發行前可能會大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
可讓您執行 DNS 查詢,以接受包含 DNS 查詢的原始封包,或查詢名稱和類型。 您可以使用主機系統的設定和組態來增強查詢。
- 您可以將新的查詢選項和自訂伺服器套用至已格式化的原始 DNS 查詢封包。
- 或者,您可以改為提供查詢名稱和類型,並接收剖析的記錄和原始結果封包 (讓客戶端能夠與從伺服器接收的所有資訊互動) 。
查詢會以異步方式執行;和 結果會傳遞至您所實作 DNS_QUERY_RAW_COMPLETION_ROUTINE 異步回呼函式。 若要取消查詢,請呼叫 DnsCancelQueryRaw。
語法
DNS_STATUS DnsQueryRaw(
DNS_QUERY_RAW_REQUEST *queryRequest,
DNS_QUERY_RAW_CANCEL *cancelHandle
);
參數
queryRequest
類型:_In_ DNS_QUERY_RAW_REQUEST*
查詢要求。
cancelHandle
類型:_Inout_ DNS_QUERY_RAW_CANCEL*
用來取得取消句柄,在您需要取消查詢時,您可以傳遞至 DnsCancelQueryRaw 。
傳回值
指出成功或失敗 的DNS_STATUS 值。 如果傳回DNS_REQUEST_PENDING,則當查詢完成時,系統會呼叫您在 queryRequest 的 queryCompletionCallback 成員中傳遞的DNS_QUERY_RAW_COMPLETION_ROUTINE實作。 如果成功,該回呼將會收到查詢的結果,或任何失敗或取消。
備註
原始封包的結構是 RFC 1035 記載的 DNS 查詢和響應的連線表示法。 12 位元組的 DNS 標頭後面接著查詢的問題區段,或 (變數編號 (可以是回應的 0) 記錄。 如果使用 TCP,則原始封包前面必須加上 2 位元組 長度 欄位。 您可以使用此 API 來套用主機 NRPT 規則,或執行加密的 DNS 查詢等等。
範例
範例 1
在此範例中,原始查詢會透過協助程式函式從套接字讀取,而回應會透過相同的套接字傳回。
struct QUERY_RAW_CALLBACK_CONTEXT
{
DNS_QUERY_RAW_RESULT *queryResults;
HANDLE event;
};
VOID
CALLBACK
QueryRawCallback(
_In_ VOID *queryContext,
_In_ DNS_QUERY_RAW_RESULT *queryResults
)
{
QUERY_RAW_CALLBACK_CONTEXT *context = static_cast<QUERY_RAW_CALLBACK_CONTEXT *>(queryContext);
//
// Capture the results of the query. Note that the DNS_QUERY_RAW_RESULT structure needs to
// be freed later with DnsQueryRawResultFree.
//
context->queryResults = queryResults;
SetEvent(context->event);
}
DWORD
HandleDnsQueryFromSocket(
_In_ SOCKET socket
)
{
DWORD errorStatus = ERROR_SUCCESS;
DWORD waitStatus = 0;
DNS_QUERY_RAW_REQUEST request = {0};
DNS_QUERY_RAW_CANCEL cancel = {0};
QUERY_RAW_CALLBACK_CONTEXT context = {0};
CHAR opaqueSourceAddr[DNS_ADDR_MAX_SOCKADDR_LENGTH];
ULONG opaqueSourceAddrSize = sizeof(opaqueSourceAddr);
//
// ReceiveDnsQueryBytesFromSocket is a function that reads bytes from a socket
// that contains a wire-format DNS query, and gets information about the source
// address. It allocates the raw query buffer with HeapAlloc of size
// request.dnsQueryRawSize. Note that this function is just an example, and does
// not exist in the API.
//
errorStatus = ReceiveDnsQueryBytesFromSocket(socket,
&request.dnsQueryRaw,
&request.dnsQueryRawSize,
opaqueSourceAddr,
opaqueSourceAddrSize);
if (errorStatus != ERROR_SUCCESS)
{
goto Exit;
}
context.event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (context.event == NULL)
{
errorStatus = GetLastError();
goto Exit;
}
//
// dnsQueryRaw is being used instead of dnsQueryName and dnsQueryType.
//
request.dnsQueryName = NULL;
request.dnsQueryType = 0;
request.version = DNS_QUERY_RAW_REQUEST_VERSION1;
request.resultsVersion = DNS_QUERY_RAW_RESULTS_VERSION1;
request.queryOptions = DNS_QUERY_BYPASS_CACHE;
request.interfaceIndex = 0;
request.queryCompletionCallback = &QueryRawCallback;
request.queryContext = &context;
request.queryRawOptions = 0;
request.customServersSize = 0;
request.customServers = NULL;
request.protocol = DNS_PROTOCOL_UDP;
memcpy_s(request.maxSa,
sizeof(request.maxSa),
opaqueSourceAddr,
opaqueSourceAddrSize);
errorStatus = DnsQueryRaw(&request, &cancel);
if (errorStatus != DNS_REQUEST_PENDING)
{
goto Exit;
}
waitStatus = WaitForSingleObject(context.event, INFINITE);
if (waitStatus != WAIT_OBJECT_0)
{
errorStatus = GetLastError();
goto Exit;
}
//
// SendDnsResponseBytesToSocket is a function that writes a buffer containing a
// DNS response to a socket. Depending on the queryStatus, it can send other
// messages on the socket to indicate whether the socket should be closed, such as if
// the queryStatus indicates an internal DNS failure. Note that this function is
// just an example, and does not exist in the API.
//
errorStatus = SendDnsResponseBytesToSocket(socket,
context.queryResults->queryStatus,
context.queryResults->queryRawResponse,
context.queryResults->queryRawResponseSize);
Exit:
if (request.dnsQueryRaw != NULL)
{
HeapFree(GetProcessHeap(), 0, request.dnsQueryRaw);
request.dnsQueryRaw = NULL;
}
if (context.queryResults != NULL)
{
DnsQueryRawResultFree(context.queryResults);
context.queryResults = NULL;
}
if (context.event != NULL)
{
CloseHandle(context.event);
context.event = NULL;
}
return errorStatus;
}
範例 2
在此範例中,查詢會以查詢名稱和類型起始,但接著會以 DnsCancelQueryRaw 取消。
struct QUERY_RAW_CALLBACK_CONTEXT
{
DNS_QUERY_RAW_RESULT *queryResults;
HANDLE event;
};
VOID
CALLBACK
QueryRawCallback(
_In_ VOID *queryContext,
_In_ DNS_QUERY_RAW_RESULT *queryResults
)
{
QUERY_RAW_CALLBACK_CONTEXT *context = static_cast<QUERY_RAW_CALLBACK_CONTEXT *>(queryContext);
//
// Capture the results of the query. Note that this structure needs to
// be freed later with DnsQueryRawResultFree.
//
context->queryResults = queryResults;
SetEvent(context->event);
}
DWORD
CallDnsQueryRawAndCancel(
_In_ PWSTR queryName,
_In_ USHORT queryType,
_In_ ULONG interfaceIndex,
_In_ SOCKADDR_INET *sourceAddr,
_In_ ULONG protocol,
_In_ DNS_CUSTOM_SERVER *customServers,
_In_ ULONG customServersSize,
_Inout_ QUERY_RAW_CALLBACK_CONTEXT *context
)
{
DWORD errorStatus = ERROR_SUCCESS;
DWORD waitStatus = 0;
DNS_QUERY_RAW_REQUEST request = {0};
DNS_QUERY_RAW_CANCEL cancel = {0};
request.version = DNS_QUERY_RAW_REQUEST_VERSION1;
request.resultsVersion = DNS_QUERY_RAW_RESULTS_VERSION1;
request.dnsQueryRawSize = 0;
request.dnsQueryRaw = NULL;
request.dnsQueryName = queryName;
request.dnsQueryType = queryType;
request.queryOptions = DNS_QUERY_BYPASS_CACHE;
request.interfaceIndex = interfaceIndex;
request.queryCompletionCallback = &QueryRawCallback;
request.queryContext = context;
request.queryRawOptions = 0;
request.customServersSize = customServersSize;
request.customServers = customServers;
request.protocol = protocol;
request.sourceAddr = *sourceAddr;
errorStatus = DnsQueryRaw(&request, &cancel);
if (errorStatus != DNS_REQUEST_PENDING)
{
goto Exit;
}
//
// Cancel the query with the provided cancel handle.
//
errorStatus = DnsCancelQueryRaw(&cancel);
if (errorStatus != ERROR_SUCCESS)
{
goto Exit;
}
//
// Wait for the callback to indicate that the query has completed. Note that it
// is possible for the query to complete successfully or fail for another reason
// before the DnsCancelQueryRaw call is made, so the queryStatus member of
// DNS_QUERY_RAW_RESULT can be used to determine what happened.
//
waitStatus = WaitForSingleObject(context->event, INFINITE);
if (waitStatus != WAIT_OBJECT_0)
{
errorStatus = GetLastError();
goto Exit;
}
errorStatus = context.queryResults->queryStatus;
if (errorStatus == ERROR_CANCELLED)
{
//
// DNS query was successfully cancelled.
//
}
else if (errorStatus != ERROR_SUCCESS)
{
//
// DNS query failed before it was cancelled.
//
}
else
{
//
// DNS query succeeded before it was cancelled, and can contain valid results.
// The other fields of context.queryResults to be processed as in Example 1.
//
}
//
// The context is owned by the caller of this function, and it will be cleaned up there.
//
Exit:
return errorStatus;
}
規格需求
需求 | 值 |
---|---|
目標平台 | Windows |
標頭 | windns.h |
程式庫 | dnsapi.lib |
Dll | dnsapi.dll |