DnsQueryRaw-Funktion (windns.h)
Wichtig
Einige Informationen beziehen sich auf ein Vorabrelease-Produkt, das vor der kommerziellen Freigabe wesentlich geändert werden kann. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Ermöglicht ihnen das Ausführen einer DNS-Abfrage, die entweder ein unformatiertes Paket mit einer DNS-Abfrage oder einen Abfragenamen und -typ akzeptiert. Sie können die Abfrage mit Einstellungen und Konfiguration aus dem Hostsystem erweitern.
- Sie können neue Abfrageoptionen und benutzerdefinierte Server auf ein bereits formatiertes rohes DNS-Abfragepaket anwenden.
- Alternativ können Sie stattdessen einen Abfragenamen und -typ angeben und sowohl die analysierten Datensätze als auch das Unformatierte Ergebnispaket empfangen (sodass Clients mit allen vom Server empfangenen Informationen interagieren können).
Abfragen werden asynchron ausgeführt. und die Ergebnisse werden an eine DNS_QUERY_RAW_COMPLETION_ROUTINE asynchrone Rückruffunktion übergeben, die Sie implementieren. Um eine Abfrage abzubrechen, rufen Sie DnsCancelQueryRaw auf.
Syntax
DNS_STATUS DnsQueryRaw(
DNS_QUERY_RAW_REQUEST *queryRequest,
DNS_QUERY_RAW_CANCEL *cancelHandle
);
Parameter
queryRequest
Typ: _In_ DNS_QUERY_RAW_REQUEST*
Die Abfrageanforderung.
cancelHandle
Typ: _Inout_ DNS_QUERY_RAW_CANCEL*
Wird verwendet, um ein Abbruchhandle abzurufen, das Sie an DnsCancelQueryRaw übergeben können, wenn Sie die Abfrage abbrechen müssen.
Rückgabewert
Ein DNS_STATUS Wert, der den Erfolg oder Fehler angibt. Wenn DNS_REQUEST_PENDING zurückgegeben wird, ruft das System nach Abschluss der Abfrage die DNS_QUERY_RAW_COMPLETION_ROUTINE-Implementierung auf, die Sie im queryCompletionCallback-Member von queryRequest übergeben haben. Dieser Rückruf empfängt die Ergebnisse der Abfrage, wenn er erfolgreich ist, oder Fehler oder Abbrüche.
Hinweise
Die Struktur eines unformatierten Pakets ist die Drahtdarstellung der DNS-Abfrage und -Antwort, wie in RFC 1035 dokumentiert. Auf einen 12-Byte-DNS-Header folgt entweder ein Frageabschnitt für die Abfrage oder eine variable Zahl (kann 0 sein) von Datensätzen für die Antwort. Wenn TCP verwendet wird, muss dem unformatierten Paket ein Feld mit einer Länge von 2 Byte vorangestellt werden. Sie können diese API unter anderem verwenden, um Host-NRPT-Regeln anzuwenden oder verschlüsselte DNS-Abfragen auszuführen.
Beispiele
Beispiel 1
In diesem Beispiel wird eine unformatierte Abfrage aus einem Socket über eine Hilfsfunktion gelesen, und die Antwort wird über denselben Socket zurückgesendet.
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;
}
Beispiel 2
In diesem Beispiel wird die Abfrage mit einem Abfragenamen und -typ initiiert, dann aber mit DnsCancelQueryRaw abgebrochen.
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;
}
Anforderungen
Anforderung | Wert |
---|---|
Zielplattform | Windows |
Kopfzeile | windns.h |
Bibliothek | dnsapi.lib |
DLL | dnsapi.dll |