Condividi tramite


Funzione DnsQueryRaw (windns.h)

Importante

Alcune informazioni si riferiscono a un prodotto in versione preliminare che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Consente di eseguire una query DNS che accetta un pacchetto non elaborato contenente una query DNS o un nome e un tipo di query. È possibile aumentare la query con le impostazioni e la configurazione dal sistema host.

  • È possibile applicare nuove opzioni di query e server personalizzati a un pacchetto di query DNS non elaborato già formattato.
  • In alternativa, è possibile specificare un nome e un tipo di query e ricevere sia i record analizzati che i pacchetti di risultati non elaborati (consentendo ai client di interagire con tutte le informazioni ricevute dal server).

Le query vengono eseguite in modo asincrono; e i risultati vengono passati a una DNS_QUERY_RAW_COMPLETION_ROUTINE funzione di callback asincrona implementata. Per annullare una query, chiamare DnsCancelQueryRaw.

Sintassi

DNS_STATUS DnsQueryRaw(
  DNS_QUERY_RAW_REQUEST *queryRequest,
  DNS_QUERY_RAW_CANCEL  *cancelHandle
);

Parametri

queryRequest

Tipo: _In_ DNS_QUERY_RAW_REQUEST*

Richiesta di query.

cancelHandle

Tipo: _Inout_ DNS_QUERY_RAW_CANCEL*

Usato per ottenere un handle di annullamento, che è possibile passare a DnsCancelQueryRaw deve essere necessario annullare la query.

Valore restituito

Valore DNS_STATUS che indica l'esito positivo o negativo. Se DNS_REQUEST_PENDING viene restituito, al termine della query, il sistema chiama l'implementazione DNS_QUERY_RAW_COMPLETION_ROUTINE passata nel membro queryCompletionCallback di queryRequest. Il callback riceverà i risultati della query in caso di esito positivo o errori o annullamenti.

Commenti

La struttura di un pacchetto non elaborato è la rappresentazione in transito della query e della risposta DNS, come documentato da RFC 1035. Un'intestazione DNS a 12 byte è seguita da una sezione della domanda per la query o da un numero variabile (può essere 0) di record per la risposta. Se viene usato TCP, il pacchetto non elaborato deve essere preceduto da un campo di lunghezza a 2 byte. È possibile usare questa API per applicare regole NRPT host o per eseguire query DNS crittografate, tra le altre cose.

Esempi

Esempio 1

In questo esempio una query non elaborata viene letta da un socket tramite una funzione helper e la risposta viene inviata tramite lo stesso socket.

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;
}

Esempio 2

In questo esempio la query viene avviata con un nome e un tipo di query, ma viene quindi annullata con 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;
}

Requisiti

Requisito Valore
Piattaforma di destinazione Windows
Intestazione windns.h
Libreria dnsapi.lib
DLL dnsapi.dll