Esempio n. 1
0
/**
 * @brief Closes the socket
 *        This call does not release the reference to the socket or free it.
 */
DWORD
VmDnsSockWinClose(
    PVM_SOCKET           pSocket
    )
{
    VMDNS_LOG_DEBUG("Close Connectiom - Socket: %d", (DWORD)pSocket->hSocket);

    if (pSocket->hSocket != INVALID_SOCKET)
    {
        closesocket(pSocket->hSocket);
        pSocket->hSocket = INVALID_SOCKET;
    }

    return 0;
}
Esempio n. 2
0
VOID
VmDnsSockPosixShutdownEventQueue(
    PVM_SOCK_EVENT_QUEUE pQueue
    )
{
    ssize_t bytesWritten = 0;
    if (pQueue)
    {
        InterlockedExchange((LONG*)(&pQueue->bShutdown), TRUE);
        if (pQueue->pSignalWriter)
        {
            char szBuf[] = {0};
            bytesWritten = write(pQueue->pSignalWriter->fd, szBuf, sizeof(szBuf));
            VMDNS_LOG_DEBUG("%s: write %ld bytes\n", __FUNCTION__, bytesWritten);
        }
    }
}
Esempio n. 3
0
BOOLEAN
VmDnsValidateRecord(
    PVMDNS_RECORD   pRecord
    )
{
    DWORD idx = 0;
    DWORD dwError = ERROR_SUCCESS;
    if (pRecord)
    {
        dwError = VmDnsFindRecordMethods(pRecord, &idx);
        if(!dwError)
        {
            return gRecordMethods[idx].pfnValidate(pRecord);
        }
    }

    VMDNS_LOG_DEBUG("%s validation of record failed.", __FUNCTION__);

    return FALSE;
}
Esempio n. 4
0
static
DWORD
VmDnsCacheRefreshThread(
    PVOID   pArgs
    )
{
    DWORD dwError = 0;
    DWORD newUSN = 0;
    PVMDNS_CACHE_CONTEXT pCacheContext = (PVMDNS_CACHE_CONTEXT)pArgs;
    pCacheContext->bRunning = TRUE;
    pCacheContext->dwLastUSN = 0;
    dwError = VmDnsStoreGetReplicationStatus(&(pCacheContext->dwLastUSN));

    while (!pCacheContext->bShutdown)
    {
        if (VMDNS_READY != VmDnsSrvGetState())
        {
            dwError = VmDnsCacheLoadInitialData(pCacheContext);
            if (dwError)
            {
                VMDNS_LOG_DEBUG("DnsCacheRefreshThread loading initial data failed with %u...Retrying", dwError);
                goto wait;
            }
            else
            {
                VMDNS_LOG_INFO("DnsCacheRefreshThread loaded initial data, setting VMDNS state to READY.");
                VmDnsSrvSetState(VMDNS_READY);
            }
        }

        newUSN = 0;
        VmDnsStoreGetReplicationStatus(&newUSN);
        if (pCacheContext->dwLastUSN != 0)
        {
            // Refresh LRU, Cache etc.
            dwError = VmDnsCacheSyncZones(
                            pCacheContext->dwLastUSN,
                            pCacheContext
                            );
            if (dwError)
            {
                VMDNS_LOG_ERROR("DnsCacheRefreshThread zone synchronization failed with %u.", dwError);
            }
        }
        else
        {
            VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to get replication status %u.", dwError);
        }

        if (newUSN != 0)
        {
            pCacheContext->dwLastUSN = newUSN;

            dwError = VmDnsCachePurgeLRU(pCacheContext);
            if (dwError)
            {
                VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to purge LRU cache with %u.", dwError);
            }
        }

wait:
        if (!pCacheContext->bShutdown)
        {
            dwError = VmDnsConditionTimedWait(
                                pCacheContext->pRefreshEvent,
                                pCacheContext->pThreadLock,
                                5 * 1000
                                );
            if (dwError != ETIMEDOUT &&
                dwError != WSAETIMEDOUT &&
                dwError != ERROR_SUCCESS)
            {
                VMDNS_LOG_ERROR("DnsCacheRefreshThread failed to wait with %u. Thread DIEING.", dwError);
                BAIL_ON_VMDNS_ERROR(dwError);
            }
        }
    }

cleanup:
    pCacheContext->bRunning = FALSE;
    return dwError;

error:
    goto cleanup;
}
Esempio n. 5
0
/**
 * @brief Writes data to the socket
 *
 * @param[in]     pSocket      Pointer to socket
 * @param[in]     pBuffer      Buffer from which bytes have to be written
 * @param[in]     dwBufLen     Number of bytes to write from the buffer
 * @param[in,out] pdwBytesWrtten Number of bytes written to the socket
 * In case of UDP sockets, it is mandatory to provide the client address and
 * length.
 *
 * @return 0 on success
 */
DWORD
VmDnsSockWinWrite(
    PVM_SOCKET          pSocket,
    struct sockaddr*    pClientAddress,
    socklen_t           addrLength,
    PVM_SOCK_IO_BUFFER  pIoBuffer
    )
{
    DWORD   dwError = 0;
    int sockError = 0;
    PVM_SOCK_IO_CONTEXT pIoContext = NULL;
    DWORD dwBytesWritten = 0;
    DWORD dwFlags = 0;
    WSABUF wsaBuff = { 0 };
    LPOVERLAPPED pOverlapped = NULL;

    if (!pSocket || !pIoBuffer)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer);
    if (pIoBuffer->dwExpectedSize <= pIoBuffer->dwCurrentSize)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    wsaBuff.buf = pIoBuffer->pData + pIoBuffer->dwCurrentSize;
    wsaBuff.len = pIoBuffer->dwExpectedSize - pIoBuffer->dwCurrentSize;
    pOverlapped = (pSocket->pEventQueue) ? &pIoContext->Overlapped : NULL;

    if (pSocket->protocol == VM_SOCK_PROTOCOL_UDP)
    {
        if (!pClientAddress || addrLength <= 0)
        {
            dwError = ERROR_INVALID_PARAMETER;
            BAIL_ON_VMDNS_ERROR(dwError);
        }

        memcpy_s(
            &pIoBuffer->clientAddr,
            sizeof pIoBuffer->clientAddr,
            pClientAddress, addrLength);

        VMDNS_LOG_DEBUG("WSA SendTo - Address: %p, Event: %d, Size: %d",
            (DWORD)pIoBuffer, pIoContext->eventType, pIoBuffer->dwExpectedSize);

        sockError = WSASendTo(
                            pSocket->hSocket,
                            &wsaBuff,
                            1,
                            &dwBytesWritten,
                            dwFlags,
                            (struct sockaddr*)&pIoBuffer->clientAddr,
                            addrLength,
                            pOverlapped,
                            NULL);

        VMDNS_LOG_DEBUG(
                "WSA WSASendTo - Status: %d Byes Transfered : %d ",
                sockError,
                dwBytesWritten);
    }
    else if (pSocket->protocol == VM_SOCK_PROTOCOL_TCP)
    {
        VMDNS_LOG_DEBUG("WSA WSASend - Address: %p, Event: %d, Size: %d",
            (DWORD)pIoBuffer, pIoContext->eventType, pIoBuffer->dwExpectedSize);

        sockError = WSASend(
                        pSocket->hSocket,
                        &wsaBuff,
                        1,
                        &dwBytesWritten,
                        dwFlags,
                        pOverlapped,
                        NULL);

        VMDNS_LOG_DEBUG(
                "WSA WSASendTo - Status: %d Byes Transfered : %d ",
                sockError,
                dwBytesWritten);
    }

    if (sockError == SOCKET_ERROR)
    {
        dwError = WSAGetLastError();
        BAIL_ON_VMDNS_ERROR(dwError);
    }
    else if (pSocket->pEventQueue)
    {
        dwError = ERROR_IO_PENDING;
    }

    pIoContext->IoBuffer.dwCurrentSize += dwBytesWritten;

    pIoBuffer = NULL;

cleanup:

    return dwError;

error:

    goto cleanup;
}
Esempio n. 6
0
/**
 * @brief Reads data from the socket
 *
 * @param[in]     pSocket      Pointer to socket
 * @param[in]     pBuffer      Buffer to read the data into
 * @param[in]     dwBufSize    Maximum size of the passed in buffer
 * @param[in,out] pdwBytesRead Number of bytes read in to the buffer
 * @param[in,out,optional] pClientAddress Client address to fill in optionally
 * @param[in,out,optional] pAddrLength    Length of the client address
 *
 * @return 0 on success
 */
DWORD
VmDnsSockWinRead(
    PVM_SOCKET          pSocket,
    PVM_SOCK_IO_BUFFER  pIoBuffer
    )
{
    DWORD   dwError = 0;
    int sockError = 0;
    PVM_SOCK_IO_CONTEXT pIoContext = NULL;
    DWORD dwBytesRead = 0, dwBytesToRead = 0;
    DWORD dwFlags = 0;
    WSABUF wsaBuff = { 0 };
    LPOVERLAPPED pOverlapped = NULL;

    if (!pSocket || !pIoBuffer)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer);
    if (pIoBuffer->dwExpectedSize <= pIoBuffer->dwCurrentSize)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    wsaBuff.buf = pIoBuffer->pData + pIoBuffer->dwCurrentSize;
    wsaBuff.len = pIoBuffer->dwExpectedSize - pIoBuffer->dwCurrentSize;
    pOverlapped = (pSocket->pEventQueue) ? &pIoContext->Overlapped : NULL;

    if (pSocket->protocol == VM_SOCK_PROTOCOL_UDP)
    {
        VMDNS_LOG_DEBUG(
                "WSA WSARecvFrom - Socket: %d Address: %p, Event: %d, Size: %d",
                pSocket->hSocket,
                (DWORD)pIoBuffer,
                pIoContext->eventType,
                pIoBuffer->dwExpectedSize);

        pIoContext->IoBuffer.addrLen = sizeof pIoContext->IoBuffer.clientAddr;

        sockError = WSARecvFrom(
                            pSocket->hSocket,
                            &wsaBuff,
                            1,
                            &dwBytesRead,
                            &dwFlags,
                            (struct sockaddr*)&pIoContext->IoBuffer.clientAddr,
                            &pIoContext->IoBuffer.addrLen,
                            pOverlapped,
                            NULL);

        VMDNS_LOG_DEBUG(
                "WSA WSARecvFrom - Status: %d Byes Transfered : %d ",
                sockError,
                dwBytesRead);

        if (sockError == SOCKET_ERROR)
        {
            dwError = WSAGetLastError();
            BAIL_ON_VMDNS_ERROR(dwError);
        }
        else if (pSocket->pEventQueue)
        {
            dwError = ERROR_IO_PENDING;
        }
    }
    else if (pSocket->protocol == VM_SOCK_PROTOCOL_TCP)
    {

        VMDNS_LOG_DEBUG(
                "WSA WSARecv - Socket: %d Address: %p, Event: %d, Size: %d",
                pSocket->hSocket,
                (DWORD)pIoBuffer,
                pIoContext->eventType,
                pIoBuffer->dwExpectedSize);

        sockError = WSARecv(
                        pSocket->hSocket,
                        &wsaBuff,
                        1,
                        &dwBytesRead,
                        &dwFlags,
                        pOverlapped,
                        NULL);

        VMDNS_LOG_DEBUG(
                "WSA WSARecv - Status: %d Byes Transfered : %d ",
                sockError,
                dwBytesRead);

        if (sockError == SOCKET_ERROR)
        {
            dwError = WSAGetLastError();
            BAIL_ON_VMDNS_ERROR(dwError);
        }
        else if (pSocket->pEventQueue)
        {
            dwError = ERROR_IO_PENDING;
        }
    }

    pIoContext->IoBuffer.dwCurrentSize += dwBytesRead;

cleanup:

    return dwError;

error:

    goto cleanup;
}
Esempio n. 7
0
/**
 * @brief Waits for an event on the event queue
 *
 * @param[in] pQueue   Pointer to event queue
 * @param[in,optional] iTimeoutMS
 *       Timeout in milliseconds.
 *       Waits forever if (-1) is passed in.
 * @param[out]    ppSocket   Pointer to socket that has an event
 * @param[in,out] pEventType Event type detected on socket
 *
 * @return 0 on success
 */
DWORD
VmDnsSockWinWaitForEvent(
    PVM_SOCK_EVENT_QUEUE pQueue,
    int                  iTimeoutMS,
    PVM_SOCKET*          ppSocket,
    PVM_SOCK_EVENT_TYPE  pEventType,
    PVM_SOCK_IO_BUFFER*  ppIoBuffer
    )
{
    DWORD dwError = 0;
    BOOL bRetVal = TRUE;
    DWORD dwIoSize = 0;
    PVM_SOCKET pSocket = NULL;
    PVM_SOCK_IO_CONTEXT pIoContext = NULL;

    if (!pQueue ||
        !pQueue->hIOCP ||
        !ppIoBuffer ||
        !pEventType)
    {
        dwError = ERROR_INTERNAL_ERROR;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    bRetVal = GetQueuedCompletionStatus(
                        pQueue->hIOCP,
                        &dwIoSize,
                        (PULONG_PTR)&pSocket,
                        (LPOVERLAPPED*)&pIoContext,
                        iTimeoutMS);
    if (!bRetVal)
    {
        dwError = GetLastError();
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    VMDNS_LOG_DEBUG("IO Completed Socket:%d, Address:%p Event: %d, Size: %d",
                pSocket ? pSocket->hSocket : 0,
                &pIoContext->IoBuffer,
                pIoContext->eventType,
                dwIoSize);

    if (dwIoSize)
    {
        pIoContext->IoBuffer.dwTotalBytesTransferred += dwIoSize;
    }
    else
    {
        pIoContext->IoBuffer.dwTotalBytesTransferred = 0;
    }

    *ppIoBuffer = &pIoContext->IoBuffer;
    *ppSocket = pSocket;
    *pEventType = pIoContext->eventType;

cleanup:

    return dwError;

error:

    if (ppIoBuffer)
    {
        *ppIoBuffer = NULL;
    }

    if (ppSocket)
    {
        *ppSocket = NULL;
    }

    goto cleanup;
}
Esempio n. 8
0
DWORD
VmDnsSockWinAcceptConnection(
    PVM_SOCKET              pListenSocket,
    SOCKET                  clientSocket,
    struct sockaddr*        pClientAddr,
    int                     addrlen
    )
{
    DWORD dwError = 0;
    HANDLE hTemp = NULL;
    const char chOpt = 1;
    PVM_SOCKET pClientSocket = NULL;
    PVM_SOCK_IO_BUFFER pIoBuffer = NULL;
    PVM_SOCK_IO_CONTEXT pIoContext = NULL;

    if (!pListenSocket ||
        !pListenSocket->hSocket ||
        !pListenSocket->pEventQueue ||
        !pListenSocket->pEventQueue->hIOCP
        || clientSocket == INVALID_SOCKET)
    {
        dwError = ERROR_INVALID_SERVER_STATE;
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    dwError = VmDnsAllocateMemory(
                    sizeof(*pClientSocket),
                    (PVOID*)&pClientSocket);
    BAIL_ON_VMDNS_ERROR(dwError);

    pClientSocket->hSocket = clientSocket;
    pClientSocket->pEventQueue = pListenSocket->pEventQueue;
    pClientSocket->protocol = pListenSocket->protocol;
    pClientSocket->type = VM_SOCK_TYPE_SERVER;
    memcpy_s(&pClientSocket->addr, sizeof pClientSocket->addr, pClientAddr, addrlen);
    pClientSocket->addrLen = addrlen;
    pClientSocket->refCount = 1;

    clientSocket = INVALID_SOCKET;

    if (setsockopt(
                pClientSocket->hSocket,
                IPPROTO_TCP,
                TCP_NODELAY,
                &chOpt,
                sizeof(char)))
    {
        dwError = WSAGetLastError();
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    hTemp = CreateIoCompletionPort(
                    (HANDLE)pClientSocket->hSocket,
                    pListenSocket->pEventQueue->hIOCP,
                    (ULONG_PTR)pClientSocket,
                    0
                    );
    if (hTemp != pListenSocket->pEventQueue->hIOCP)
    {
        dwError = GetLastError();
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    dwError = VmDnsSockWinAllocateIoBuffer(
                    VM_SOCK_EVENT_TYPE_TCP_NEW_CONNECTION,
                    0,
                    &pIoBuffer);
    BAIL_ON_VMDNS_ERROR(dwError);

    pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer);

    VMDNS_LOG_DEBUG("New Connectiom - Socket: %d Address: %p, Event: %d, Size: %d",
                    pClientSocket->hSocket,
                    (DWORD)pIoBuffer,
                    pIoContext->eventType,
                    pIoBuffer->dwCurrentSize);

    if (!PostQueuedCompletionStatus(
                    pListenSocket->pEventQueue->hIOCP,
                    0,
                    (ULONG_PTR)pClientSocket,
                    (LPOVERLAPPED)pIoContext))
    {
        dwError = GetLastError();
        BAIL_ON_VMDNS_ERROR(dwError);
    }

    pClientSocket = NULL;
    pIoBuffer = NULL;

cleanup:

    return dwError;

error:

    if (pClientSocket)
    {
        VmDnsSockWinFreeSocket(pClientSocket);
    }

    if (pIoBuffer)
    {
        VmDnsSockWinFreeIoBuffer(pIoBuffer);
    }

    goto cleanup;
}