static int* VmDnsGetLockKey( pthread_key_t* pLockKey ) { DWORD dwError = ERROR_SUCCESS; int* pCounter = NULL; int* pCount = (int*)pthread_getspecific(*pLockKey); if (!pCount) { dwError = VmDnsAllocateMemory(sizeof(int), (void**)&(pCounter)); BAIL_ON_VMDNS_ERROR(dwError); dwError = pthread_setspecific(*pLockKey, pCounter); dwError = POSIX_TO_WIN32_ERROR(dwError); BAIL_ON_VMDNS_ERROR(dwError); pCounter = NULL; pCount = (int*)pthread_getspecific(*pLockKey); } cleanup: return pCount; error: VMDNS_SAFE_FREE_MEMORY(pCounter); goto cleanup; }
DWORD VmDnsAllocateRWLock( PVMDNS_RWLOCK* ppLock ) { DWORD dwError = 0; PVMDNS_RWLOCK pLock = NULL; BAIL_ON_VMDNS_INVALID_POINTER(ppLock, dwError); dwError = VmDnsAllocateMemory(sizeof(VMDNS_RWLOCK), (void**)&pLock); BAIL_ON_VMDNS_ERROR(dwError); dwError = pthread_rwlock_init(&pLock->rwLock, NULL); dwError = POSIX_TO_WIN32_ERROR(dwError); BAIL_ON_VMDNS_ERROR(dwError); dwError = pthread_key_create(&pLock->readKey, VmDnsFreeLockCount); dwError = POSIX_TO_WIN32_ERROR(dwError); BAIL_ON_VMDNS_ERROR(dwError); dwError = pthread_key_create(&pLock->writeKey, VmDnsFreeLockCount); dwError = POSIX_TO_WIN32_ERROR(dwError); BAIL_ON_VMDNS_ERROR(dwError); *ppLock = pLock; cleanup: return dwError; error: VMDNS_SAFE_FREE_MEMORY(pLock); goto cleanup; }
VOID VmDnsFreeMutex( PVMDNS_MUTEX pMutex ) { VmDnsFreeMutexContent(pMutex); VMDNS_SAFE_FREE_MEMORY( pMutex ); }
VOID VmDnsPropertyListFree( PVMDNS_PROPERTY_LIST pList ) { DWORD i = 0; if (pList) { for (i = 0; i < pList->dwCurrentSize; ++i) { VmDnsPropertyObjectRelease(pList->ppProperties[i]); } VMDNS_SAFE_FREE_MEMORY(pList->ppProperties); VMDNS_SAFE_FREE_MEMORY(pList); } }
VOID VmDnsFreeCondition( PVMDNS_COND pCondition ) { VmDnsFreeConditionContent( pCondition ); VMDNS_SAFE_FREE_MEMORY( pCondition ); }
DWORD VmDnsCreateThread( PVMDNS_THREAD pThread, BOOLEAN bDetached, VmDnsStartRoutine* pStartRoutine, PVOID pArgs ) { DWORD dwError = ERROR_SUCCESS; PVMDNS_THREAD_START_INFO pThreadStartInfo = NULL; pthread_attr_t thrAttr; BOOLEAN bThreadAttrInited = FALSE; if ( ( pThread == NULL ) || ( pStartRoutine == NULL ) ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } if( bDetached != FALSE ) { pthread_attr_init(&thrAttr); bThreadAttrInited = TRUE; pthread_attr_setdetachstate(&thrAttr, PTHREAD_CREATE_DETACHED); } dwError = VmDnsAllocateMemory( sizeof(VMDNS_THREAD_START_INFO), ((PVOID*)&pThreadStartInfo) ); BAIL_ON_VMDNS_ERROR(dwError); pThreadStartInfo->pStartRoutine = pStartRoutine; pThreadStartInfo->pArgs = pArgs; dwError = pthread_create( pThread, ((bDetached == FALSE) ? NULL : &thrAttr), ThreadFunction, pThreadStartInfo ); BAIL_ON_VMDNS_ERROR(dwError); // we started successfully -> pThreadStartInfo is now owned by // ThreadFunction pThreadStartInfo = NULL; error: if(bThreadAttrInited != FALSE) { pthread_attr_destroy(&thrAttr); } VMDNS_SAFE_FREE_MEMORY( pThreadStartInfo ); return dwError; }
DWORD VmDnsPropertyListAdd( PVMDNS_PROPERTY_LIST pList, PVMDNS_PROPERTY_OBJECT pProperty ) { PVMDNS_PROPERTY_OBJECT *pNewList = NULL; DWORD dwError = 0; BAIL_ON_VMDNS_INVALID_POINTER(pList, dwError); BAIL_ON_VMDNS_INVALID_POINTER(pProperty, dwError); if (pList->dwCurrentSize >= pList->dwMaxSize) { pList->dwMaxSize = 2 * pList->dwMaxSize; dwError = VmDnsAllocateMemory( sizeof(PVMDNS_PROPERTY_OBJECT) * pList->dwMaxSize, (PVOID*)&pNewList); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsCopyMemory( pNewList, sizeof(PVMDNS_PROPERTY_OBJECT) * pList->dwMaxSize, pList->ppProperties, sizeof(PVMDNS_PROPERTY_OBJECT) * pList->dwCurrentSize); BAIL_ON_VMDNS_ERROR(dwError); VMDNS_SAFE_FREE_MEMORY(pList->ppProperties); pList->ppProperties = pNewList; pNewList = NULL; } VmDnsPropertyObjectAddRef(pProperty); pList->ppProperties[pList->dwCurrentSize] = pProperty; ++pList->dwCurrentSize; cleanup: return dwError; error: VMDNS_SAFE_FREE_MEMORY(pNewList); goto cleanup; }
VOID VmDnsSockWinFreeIoBuffer( PVM_SOCK_IO_BUFFER pIoBuffer ) { PVM_SOCK_IO_CONTEXT pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); VMDNS_LOG_INFO("Freeing Io Buffer - Address: %p, Event: %d, Size: %d", (DWORD)pIoBuffer, pIoContext->eventType, pIoBuffer->dwCurrentSize); VMDNS_SAFE_FREE_MEMORY(pIoContext); }
static PVOID ThreadFunction( PVOID pArgs ) { DWORD dwError = ERROR_SUCCESS; PVMDNS_START_ROUTINE pThreadStart = NULL; PVOID pThreadArgs = NULL; union { DWORD dwError; PVOID pvRet; } retVal = { 0 }; if( pArgs == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } pThreadStart = ((PVMDNS_THREAD_START_INFO)pArgs)->pStartRoutine; pThreadArgs = ((PVMDNS_THREAD_START_INFO)pArgs)->pArgs; if( pThreadStart == NULL ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } VMDNS_SAFE_FREE_MEMORY( pArgs ); dwError = pThreadStart( pThreadArgs ); BAIL_ON_VMDNS_ERROR(dwError); error: VMDNS_SAFE_FREE_MEMORY( pArgs ); retVal.dwError = dwError; return retVal.pvRet; }
static VOID VmDnsFreeForwarderPacketContext( PVMDNS_FORWARDER_PACKET_CONTEXT pForwarderContext ) { if (pForwarderContext) { VMDNS_SAFE_FREE_MEMORY(pForwarderContext); } }
VOID VmDnsClearPtrRecord( PVMDNS_RECORD pRecord ) { if (pRecord) { VMDNS_SAFE_FREE_STRINGA(pRecord->pszName); VMDNS_SAFE_FREE_MEMORY(pRecord->Data.PTR.pNameHost); } }
static VOID VmDnsFreeForwarderEntry( PVMDNS_FORWARDER_ENTRY pForwarderEntry ) { if (pForwarderEntry) { (void) VmDnsForwarderMetricsDelete(pForwarderEntry); VMDNS_SAFE_FREE_STRINGA(pForwarderEntry->pszForwarder); VMDNS_SAFE_FREE_MEMORY(pForwarderEntry); } }
VOID VmDnsSockPosixFreeIoBuffer( PVM_SOCK_IO_BUFFER pIoBuffer ) { // VMDNS_LOG_DEBUG("pIoBuffer:%p released from thread %p", pIoBuffer, pthread_self()); if (pIoBuffer && pIoBuffer->pClientSocket) { VmDnsSockPosixReleaseSocket(pIoBuffer->pClientSocket); } PVM_SOCK_IO_CONTEXT pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); VMDNS_SAFE_FREE_MEMORY(pIoContext); }
VOID VmDnsRecordObjectRelease( PVMDNS_RECORD_OBJECT pRecordObj ) { if (pRecordObj) { if (0 == InterlockedDecrement(&pRecordObj->lRefCount)) { VMDNS_FREE_RECORD(pRecordObj->pRecord); VMDNS_SAFE_FREE_MEMORY(pRecordObj); } } }
static VOID VmDnsSockWinFreeSocket( PVM_SOCKET pSocket ) { if (pSocket->hSocket != INVALID_SOCKET) { CancelIo((HANDLE)pSocket->hSocket); closesocket(pSocket->hSocket); pSocket->hSocket = INVALID_SOCKET; } VMDNS_SAFE_FREE_MEMORY(pSocket); }
static VOID VmDnsFreeMemberShips( PSTR* ppszMemberships, DWORD dwMemberships ) { DWORD i = 0; for(i = 0; i < dwMemberships; ++i) { VMDNS_SAFE_FREE_STRINGA(ppszMemberships[i]); } VMDNS_SAFE_FREE_MEMORY(ppszMemberships); }
VMDNS_API VOID VmDnsCloseServer(PVMDNS_SERVER_CONTEXT pServerContext) { if(pServerContext) { if (pServerContext->hBinding) { DWORD dwError = 0; rpc_binding_free(&pServerContext->hBinding, &dwError); pServerContext->hBinding = NULL; } VMDNS_SAFE_FREE_MEMORY(pServerContext); } }
static DWORD VmDnsPeekResponseCode( DWORD dwResponseSize, PBYTE pResponseBytes, PDWORD pdwResponseCode ) { DWORD dwError = ERROR_SUCCESS; PVMDNS_HEADER pDnsHeader = NULL; PVMDNS_MESSAGE_BUFFER pDnsMessageBuffer = NULL; if (!pdwResponseCode) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsGetDnsMessageBuffer( pResponseBytes, dwResponseSize, &pDnsMessageBuffer ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsReadDnsHeaderFromBuffer( pDnsMessageBuffer, &pDnsHeader ); BAIL_ON_VMDNS_ERROR(dwError); *pdwResponseCode = pDnsHeader->codes.RCODE; cleanup: if (pDnsMessageBuffer) { VmDnsFreeBufferStream(pDnsMessageBuffer); } VMDNS_SAFE_FREE_MEMORY(pDnsHeader); return dwError; error : goto cleanup; }
VOID VmDnsSockPosixFreeIoBuffer( PVM_SOCK_IO_BUFFER pIoBuffer ) { PVM_SOCK_IO_CONTEXT pIoContext = NULL; if (pIoBuffer) { if (pIoBuffer->pClientSocket) { VmDnsSockPosixReleaseSocket(pIoBuffer->pClientSocket); } pIoContext = CONTAINING_RECORD(pIoBuffer, VM_SOCK_IO_CONTEXT, IoBuffer); VMDNS_SAFE_FREE_MEMORY(pIoContext); } }
VOID VmDnsForwarderCleanup( PVMDNS_FORWARDER_CONTEXT pForwarder ) { DWORD i = 0; if (pForwarder) { for (i = 0; i < pForwarder->dwCount; ++i) { if (pForwarder->pForwarderEntries[i]) { VmDnsFreeForwarderEntry(pForwarder->pForwarderEntries[i]); } } VMDNS_FREE_RWLOCK(pForwarder->pLock); VMDNS_SAFE_FREE_MEMORY(pForwarder); } }
VOID VmDnsSockWinCloseEventQueue( PVM_SOCK_EVENT_QUEUE pQueue ) { if (pQueue) { if (pQueue->hEventListen != WSA_INVALID_EVENT) { WSACloseEvent(pQueue->hEventListen); } if (pQueue->hIOCP) { CloseHandle(pQueue->hIOCP); } VMDNS_SAFE_FREE_MEMORY(pQueue); } }
DWORD VmDnsForwardRequest( PVMDNS_FORWARDER_PACKET_CONTEXT pForwarderPacketContext, BOOL bUseUDP, PVM_SOCK_IO_BUFFER pIoBuffer ) { DWORD dwError = 0; PSTR pszForwarder = NULL; VM_SOCK_CREATE_FLAGS flags = (bUseUDP) ? VM_SOCK_CREATE_FLAGS_UDP : VM_SOCK_CREATE_FLAGS_TCP; PVM_SOCKET pSocket = NULL; DWORD dwQuerySize = 0; PBYTE pQueryBuffer = NULL; struct sockaddr_storage address; socklen_t addLenth = sizeof address; PVM_SOCK_IO_BUFFER pIoRequest = NULL; PVM_SOCK_IO_BUFFER pOldRequest = NULL; PVMDNS_FORWARDER_PACKET_CONTEXT pCurrentContext = NULL; if (!pIoBuffer || (bUseUDP && (pIoBuffer->dwTotalBytesTransferred > VMDNS_UDP_PACKET_SIZE))|| !pIoBuffer->pData || !pForwarderPacketContext) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } dwQuerySize = pIoBuffer->dwTotalBytesTransferred; pQueryBuffer = pIoBuffer->pData; pCurrentContext = VmDnsAcquireForwarderPacketContext(pForwarderPacketContext); dwError = VmDnsGetForwarderAtIndex( gpSrvContext->pForwarderContext, pCurrentContext->dwCurrentIndex++, &pszForwarder ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsSockOpenClient( pszForwarder, VMW_DNS_PORT, flags, &pSocket); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsSockSetNonBlocking(pSocket); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsSockGetAddress( pSocket, &address, &addLenth); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsSockAllocateIoBuffer( bUseUDP? VM_SOCK_EVENT_TYPE_UDP_FWD_RESPONSE_DATA_READ: VM_SOCK_EVENT_TYPE_TCP_FWD_RESPONSE_DATA_READ, (PVM_SOCK_EVENT_CONTEXT)pCurrentContext, dwQuerySize, &pIoRequest); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsCopyMemory( pIoRequest->pData, pIoRequest->dwExpectedSize, pQueryBuffer, dwQuerySize); BAIL_ON_VMDNS_ERROR(dwError); memcpy( &pIoRequest->clientAddr, &pIoBuffer->clientAddr, pIoBuffer->addrLen); pIoRequest->addrLen = pIoBuffer->addrLen; pIoRequest->pClientSocket = VmDnsSockAcquire(pIoBuffer->pClientSocket); dwError = VmDnsSockSetData( pSocket, pIoRequest, (PVOID*)&pOldRequest ); BAIL_ON_VMDNS_ERROR(dwError); (VOID)VmDnsLogDnsMessage(VMDNS_LOG_LEVEL_INFO, "DNS FWD REQ: ", pQueryBuffer, dwQuerySize); dwError = VmDnsSockWrite( pSocket, NULL, 0, pIoRequest); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsSockEventQueueAdd( gpSrvContext->pSockContext->pEventQueue, TRUE, pSocket ); BAIL_ON_VMDNS_ERROR(dwError); // VmDnsOPStatisticUpdate(FORWARDER_QUERY_COUNT); cleanup: VMDNS_SAFE_FREE_MEMORY(pszForwarder); if (pOldRequest) { VMDNS_LOG_IO_RELEASE(pOldRequest); VmDnsSockReleaseIoBuffer(pOldRequest); } if (pSocket) { VmDnsSockRelease(pSocket); } return dwError; error: if (pCurrentContext) { VmDnsReleaseForwarderPacketContext(pCurrentContext); } if (pIoRequest) { VMDNS_LOG_IO_RELEASE(pIoRequest); VmDnsSockReleaseIoBuffer(pIoRequest); } goto cleanup; }
static DWORD _GetForwarders( PVMDNS_SERVER_CONTEXT pServerContext, PCSTR pszZone, PVMDNS_FORWARDERS* ppForwarders ) { DWORD dwError = 0; PVMDNS_FORWARDERS pDnsForwarders = NULL; PVMDNS_FORWARDERS pDnsForwardersOutput = NULL; PSTR* ppszForwarders = NULL; DWORD dwCount = 0; dwError = VmDnsValidateContext(pServerContext); BAIL_ON_VMDNS_ERROR(dwError); BAIL_ON_VMDNS_INVALID_POINTER(ppForwarders, dwError); DCETHREAD_TRY { if (pszZone) { dwError = VmDnsRpcGetZoneForwarders( pServerContext->hBinding, (PDNS_STRING)pszZone, &pDnsForwarders); } else { dwError = VmDnsRpcGetForwarders( pServerContext->hBinding, &pDnsForwarders); } } DCETHREAD_CATCH_ALL(THIS_CATCH) { dwError = VmDnsRpcGetErrorCode(THIS_CATCH); } DCETHREAD_ENDTRY; BAIL_ON_VMDNS_ERROR(dwError); if (pDnsForwarders) { DWORD i = 0; PSTR szTemp = NULL; if (pDnsForwarders->dwCount > 0) { dwError = VmDnsAllocateMemory( pDnsForwarders->dwCount * sizeof(PSTR), (PVOID*)&ppszForwarders); BAIL_ON_VMDNS_ERROR(dwError); for (i = 0; i < pDnsForwarders->dwCount; ++i) { dwError = VmDnsAllocateStringA( pDnsForwarders->ppszName[i], &szTemp ); BAIL_ON_VMDNS_ERROR(dwError); ppszForwarders[i] = szTemp; ++dwCount; } } dwError = VmDnsAllocateMemory( sizeof(VMDNS_FORWARDERS), (PVOID*)&pDnsForwardersOutput); BAIL_ON_VMDNS_ERROR(dwError); pDnsForwardersOutput->dwCount = pDnsForwarders->dwCount; pDnsForwardersOutput->ppszName = ppszForwarders; } *ppForwarders = pDnsForwardersOutput; cleanup: if (pDnsForwarders) { VmDnsRpcFreeForwarders(pDnsForwarders); } return dwError; error: if (ppszForwarders) { VmDnsFreeStringCountedArrayA(ppszForwarders, dwCount); } if (pDnsForwardersOutput) { VMDNS_SAFE_FREE_MEMORY(pDnsForwardersOutput); } goto cleanup; }
DWORD VmDnsSerializeDnsRecord( PVMDNS_RECORD pDnsRecord, PBYTE* ppBytes, DWORD* pdwSize, BOOL bTokenizeDomainName ) { DWORD dwError = 0; PVMDNS_MESSAGE_BUFFER pVmDnsBuffer = NULL; PBYTE pBytes = NULL; DWORD dwSize = 0; if (!pDnsRecord || !ppBytes || !pdwSize ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR (dwError); } dwError = VmDnsAllocateBufferStream( 0, &pVmDnsBuffer ); BAIL_ON_VMDNS_ERROR(dwError); pVmDnsBuffer->bTokenizeDomainName = bTokenizeDomainName; dwError = VmDnsWriteRecordToBuffer( pDnsRecord, pVmDnsBuffer ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsCopyBufferFromBufferStream( pVmDnsBuffer, NULL, &dwSize ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsAllocateMemory( dwSize, (PVOID *)&pBytes ); BAIL_ON_VMDNS_ERROR(dwError); dwError = VmDnsCopyBufferFromBufferStream( pVmDnsBuffer, pBytes, &dwSize ); BAIL_ON_VMDNS_ERROR(dwError); *ppBytes = pBytes; *pdwSize = dwSize; cleanup: if (pVmDnsBuffer) { VmDnsFreeBufferStream(pVmDnsBuffer); } return dwError; error: if (ppBytes) { *ppBytes = NULL; } if (pdwSize) { *pdwSize = 0; } VMDNS_SAFE_FREE_MEMORY(pBytes); goto cleanup; }
/** * @brief Opens a client socket * * @param[in] pszHost Target host name or IP Address. * An empty string will imply the local host. * @param[in] usPort 16 bit port number * @param[in] dwFlags 32 bit flags specifying socket creation preferences * @param[out] ppSocket Pointer to created socket context * * @return 0 on success */ DWORD VmDnsSockWinOpenClient( PCSTR pszHost, USHORT usPort, VM_SOCK_CREATE_FLAGS dwFlags, PVM_SOCKET* ppSocket ) { DWORD dwError = 0; DWORD dwSockFlags = 0; int nAddressFamily = AF_INET; int nConnectionType = SOCK_STREAM; struct addrinfo hints = { 0 }; struct addrinfo* pAddrInfo = NULL; struct addrinfo* pInfo = NULL; struct addrinfo* pClientAddress = NULL; CHAR szPort[32] = { 0 }; SOCKET socket = INVALID_SOCKET; PVM_SOCKET pSocket = NULL; if (!pszHost || !usPort || !ppSocket) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDNS_ERROR(dwError); } if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6) { hints.ai_family = AF_INET6; } else if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV4) { hints.ai_family = AF_INET; } else { hints.ai_family = AF_UNSPEC; } if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP) { nConnectionType = hints.ai_socktype = SOCK_DGRAM; } else { nConnectionType = hints.ai_socktype = SOCK_STREAM; } hints.ai_flags = AI_CANONNAME | AI_NUMERICSERV; sprintf_s(szPort, sizeof(szPort), "%d", usPort); if (getaddrinfo(pszHost, szPort, &hints, &pAddrInfo) != 0) { dwError = WSAGetLastError(); BAIL_ON_VMDNS_ERROR(dwError); } for (pInfo = pAddrInfo; (socket == INVALID_SOCKET && pInfo != NULL); pInfo = pInfo->ai_next) { socket = WSASocketW( pInfo->ai_family, pInfo->ai_socktype, pInfo->ai_protocol, NULL, 0, dwSockFlags); if (socket == INVALID_SOCKET) { continue; } if (nConnectionType == SOCK_STREAM) { if (connect(socket, pInfo->ai_addr, pInfo->ai_addrlen) < 0) { dwError = WSAGetLastError(); continue; } } pClientAddress = pInfo; } if (socket == INVALID_SOCKET) { dwError = ERROR_CONNECTION_UNAVAIL; BAIL_ON_VMDNS_ERROR(dwError); } dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket); BAIL_ON_VMDNS_ERROR(dwError); pSocket->refCount = 1; pSocket->type = VM_SOCK_TYPE_CLIENT; if (nConnectionType == SOCK_STREAM) { pSocket->protocol = VM_SOCK_PROTOCOL_TCP; } else { pSocket->protocol = VM_SOCK_PROTOCOL_UDP; } dwError = VmDnsSockWinCopyTargetAddress(pClientAddress, pSocket); BAIL_ON_VMDNS_ERROR(dwError); pSocket->hSocket = socket; socket = INVALID_SOCKET; *ppSocket = pSocket; pSocket = NULL; cleanup: if (pAddrInfo) { freeaddrinfo(pAddrInfo); } return dwError; error : if (socket != INVALID_SOCKET) { closesocket(socket); } VMDNS_SAFE_FREE_MEMORY(pSocket); goto cleanup; }