Esempio n. 1
0
NTSTATUS
LWNetSvcmStart(
    PLW_SVCM_INSTANCE pInstance,
    ULONG ArgCount,
    PWSTR* ppArgs,
    ULONG FdCount,
    int* pFds
    )
{
    DWORD dwError = 0;

    dwError = LWNetSrvSetDefaults();
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetSrvInitialize();
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetSrvStartListenThread();
    BAIL_ON_LWNET_ERROR(dwError);

    // Post service started event to eventlog
    LWNetSrvLogProcessStartedEvent();

cleanup:

    return LwWin32ErrorToNtStatus(dwError);

error:

    goto cleanup;
}
Esempio n. 2
0
DWORD
LWNetSrvGetPrefixPath(
    PSTR* ppszPath
    )
{
    DWORD dwError = 0;
    PSTR pszPath = NULL;
    BOOLEAN bInLock = FALSE;
  
    LWNET_LOCK_SERVERINFO(bInLock);
    
    if (IsNullOrEmptyString(gpLwnetServerInfo->szPrefixPath)) {
      dwError = ERROR_PATH_NOT_FOUND;
      BAIL_ON_LWNET_ERROR(dwError);
    }
    
    dwError = LWNetAllocateString(gpLwnetServerInfo->szPrefixPath, &pszPath);
    BAIL_ON_LWNET_ERROR(dwError);

    *ppszPath = pszPath;

 cleanup:
    
    LWNET_UNLOCK_SERVERINFO(bInLock);
    
    return dwError;

 error:

    LWNET_SAFE_FREE_STRING(pszPath);

    *ppszPath = NULL;

    goto cleanup;
}
Esempio n. 3
0
DWORD
LWNetSrvStartNetBiosThread(
    VOID)
{
    DWORD dwError = 0;
    pthread_t thread;
    pthread_attr_t attrib;

    gpNbCtx->udpTimeout = LWNetConfigIsNetBiosUdpTimeout();

    dwError = LwErrnoToWin32Error(pthread_attr_init(&attrib));
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LwErrnoToWin32Error(pthread_attr_setdetachstate(
                  &attrib, PTHREAD_CREATE_DETACHED));
    BAIL_ON_LWNET_ERROR(dwError);
    dwError = LwErrnoToWin32Error(pthread_create(&thread,
                         &attrib,
                         LWNetSrvStartNetBiosThreadRoutine,
                         (void *) gpNbCtx));
    BAIL_ON_LWNET_ERROR(dwError);

cleanup:
    return dwError;
error:
    goto cleanup;
}
Esempio n. 4
0
/* Decompose a NetBIOS Second Layer name into an array of name components */
DWORD
LWNetNbName2ToParts(
    PBYTE NbNameL2,
    PSTR **retNbNameParts,
    PDWORD retNbNamePartsLen)
{
    DWORD dwError = 0;
    DWORD numParts = 0;
    DWORD len = 0;
    DWORD i = 0;
    UINT8 *ptr = NULL;
    PSTR *NBNameParts = NULL;

    /* Count number of parts in NetBIOS name */
    ptr = NbNameL2;
    while (*ptr)
    {
        len = (int) *ptr++;
        ptr += len;
        numParts++;
    }
    len++;

    dwError = LWNetAllocateMemory((numParts+1) * sizeof(*NBNameParts),
                                  (PVOID*)&NBNameParts);
    BAIL_ON_LWNET_ERROR(dwError);

    /* Reset and allocate strings for the various parts */
    ptr = NbNameL2;
    i = 0;
    while (*ptr)
    {
        len = (int) *ptr++;

        dwError = LWNetAllocateMemory((len + 1) * sizeof(char),
                      (PVOID*)&NBNameParts[i]);
        BAIL_ON_LWNET_ERROR(dwError);

        strncat(NBNameParts[i++], (char *) ptr, len);
        ptr += len;
    }
    ptr++;
    *retNbNameParts = NBNameParts;
    *retNbNamePartsLen = ptr - NbNameL2;

cleanup:
    return dwError;

error:
    if (NBNameParts)
    {
        for (i=0; NBNameParts[i]; i++)
        {
            LWNET_SAFE_FREE_MEMORY(NBNameParts[i]);
        }
        LWNET_SAFE_FREE_MEMORY(NBNameParts);
    }
    goto cleanup;
}
Esempio n. 5
0
DWORD
LWNetDnsGetSrvRecordQuestion(
    OUT PSTR* ppszQuestion,
    IN PCSTR pszDomainName,
    IN OPTIONAL PCSTR pszSiteName,
    IN DWORD dwDsFlags
    )
{
    DWORD dwError = 0;
    PSTR question = NULL;
    PCSTR kind = "dc";
    PCSTR service = "_ldap";

    if (dwDsFlags & DS_PDC_REQUIRED)
    {
        kind = "pdc";
        service = "_ldap";
    }
    else if (dwDsFlags & DS_GC_SERVER_REQUIRED)
    {
        kind = "gc";
        service = "_ldap";
    }
    else if (dwDsFlags & DS_KDC_REQUIRED)
    {
        kind = "dc";
        service = "_kerberos";
    }
    else
    {
        kind = "dc";
        service = "_ldap";
    }

    if (IsNullOrEmptyString(pszSiteName))
    {
        dwError = LwAllocateStringPrintf(&question,
                                            "%s._tcp.%s._msdcs.%s",
                                            service, kind,
                                            pszDomainName);
        BAIL_ON_LWNET_ERROR(dwError);
    }
    else
    {
        dwError = LwAllocateStringPrintf(&question,
                                            "%s._tcp.%s._sites.%s._msdcs.%s",
                                            service, pszSiteName, kind,
                                            pszDomainName);
        BAIL_ON_LWNET_ERROR(dwError);
    }

error:
    if (dwError)
    {
        LWNET_SAFE_FREE_STRING(question);
    }
    *ppszQuestion = question;
    return dwError;
}
Esempio n. 6
0
DWORD
LWNetDnsBuildSRVRecord(
    IN PDNS_RESPONSE_HEADER pHeader,
    IN PDNS_RECORD pAnswerRecord,
    IN PDLINKEDLIST pAdditionalsList,
    OUT PDNS_SRV_INFO_RECORD* ppSRVInfoRecord
    )
{
    DWORD dwError = 0;
    PDNS_SRV_INFO_RECORD pSRVInfoRecord = NULL;
    PBYTE pCurrent = NULL;
    DWORD dwNameLen = 0;
    
    if (pAnswerRecord->wDataLen < (4 * sizeof(WORD)))
    {
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    dwError = LWNetAllocateMemory(sizeof(DNS_SRV_INFO_RECORD), (PVOID*)&pSRVInfoRecord);
    BAIL_ON_LWNET_ERROR(dwError);

    pCurrent = pAnswerRecord->pData;

    pSRVInfoRecord->wPriority = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    pSRVInfoRecord->wWeight = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    pSRVInfoRecord->wPort = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    dwError = LWNetDnsParseName(pHeader,
                                pCurrent,
                                &dwNameLen,
                                &pSRVInfoRecord->pszTarget);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetDnsGetAddressForServer(pAdditionalsList,
                                          pSRVInfoRecord->pszTarget,
                                          &pSRVInfoRecord->pszAddress);
    BAIL_ON_LWNET_ERROR(dwError);

error:
    if (dwError)
    {
        if (pSRVInfoRecord)
        {
           LWNetDnsFreeSRVInfoRecord(pSRVInfoRecord);
           pSRVInfoRecord = NULL;
        }
    }

    *ppSRVInfoRecord = pSRVInfoRecord;

    return dwError;
}
Esempio n. 7
0
DWORD
LWNetNbConstructNameQuery(
    IN PSTR pszNetBiosHost,
    IN UINT8 bBroadcast,
    IN UINT8 queryType,
    OUT UINT16 *RetTransactionId,
    OUT UINT8 *NetBiosQuery,
    OUT PDWORD NetBiosQueryLen)
{
    DWORD dwError = 0;
    DWORD len = 0;
    DWORD NbNameLevel2Len = 0;
    UINT8 *NbNameLevel2 = NULL;
    UINT8 BuiltNBHeader[LWNB_NAME_MAX_LENGTH] = {0};
    UINT16 TransactionId = 0;

    dwError = LWNetNbStrToNbName2(
                  pszNetBiosHost,
                  queryType,
                  &NbNameLevel2,
                  &NbNameLevel2Len);
    BAIL_ON_LWNET_ERROR(dwError);

    TransactionId = LWNetNbNextTransactionId(gpNbCtx);
    dwError = LWNetNbConstructNameQueryHeader(
              TransactionId,
              bBroadcast ? LWNB_QUERY_BROADCAST : LWNB_QUERY_WINS,
              LWNB_OPCODE_QUERY,
              1,           // QDCOUNT: Number of names being looked up
              sizeof(BuiltNBHeader),
              BuiltNBHeader);
    BAIL_ON_LWNET_ERROR(dwError);

    /* Assemble the complete marshaled NetBIOS query packet */
    memcpy(&NetBiosQuery[len], BuiltNBHeader, LWNB_NAME_QUERY_HEADER_SIZE);
    len += LWNB_NAME_QUERY_HEADER_SIZE;
    memcpy(&NetBiosQuery[len], NbNameLevel2, NbNameLevel2Len);
    len += NbNameLevel2Len;
    memcpy(&NetBiosQuery[len], NetBiosQueryFooter, sizeof(NetBiosQueryFooter));
    len += sizeof(NetBiosQueryFooter);

    *NetBiosQueryLen = len;
    *RetTransactionId = TransactionId;

cleanup:
    LWNET_SAFE_FREE_MEMORY(NbNameLevel2);
    return dwError;

error:
    goto cleanup;
}
Esempio n. 8
0
DWORD
LWNetGetErrorMessageForLoggingEvent(
    DWORD dwErrCode,
    PSTR* ppszErrorMsg
    )
{
    DWORD dwErrorBufferSize = 0;
    DWORD dwError = 0;
    DWORD dwLen = 0;
    PSTR  pszErrorMsg = NULL;
    PSTR  pszErrorBuffer = NULL;

    dwErrorBufferSize = LwGetErrorString(dwErrCode, NULL, 0);

    if (!dwErrorBufferSize)
        goto cleanup;

    dwError = LWNetAllocateMemory(
                dwErrorBufferSize,
                (PVOID*)&pszErrorBuffer);
    BAIL_ON_LWNET_ERROR(dwError);

    dwLen = LwGetErrorString(dwErrCode, pszErrorBuffer, dwErrorBufferSize);

    if ((dwLen == dwErrorBufferSize) && !IsNullOrEmptyString(pszErrorBuffer))
    {
        dwError = LwAllocateStringPrintf(
                     &pszErrorMsg,
                     "Error: %s [error code: %d]",
                     pszErrorBuffer,
                     dwErrCode);
        BAIL_ON_LWNET_ERROR(dwError);
    }

    *ppszErrorMsg = pszErrorMsg;

cleanup:

    LWNET_SAFE_FREE_STRING(pszErrorBuffer);

    return dwError;

error:

    LWNET_SAFE_FREE_STRING(pszErrorMsg);

    *ppszErrorMsg = NULL;

    goto cleanup;
}
Esempio n. 9
0
DWORD
LWNetDnsParseRecords(
    IN PDNS_RESPONSE_HEADER pHeader,
    IN WORD wNRecords,
    IN PBYTE pData,
    OUT PDLINKEDLIST* ppRecordList,
    OUT PDWORD pdwBytesToAdvance
    )
{
    DWORD dwError = 0;
    PBYTE pCurrent = pData;
    PDLINKEDLIST pRecordList = NULL;
    PDNS_RECORD pRecord = NULL;
    DWORD dwBytesToAdvance = 0;
    WORD iRecord = 0;

    for (iRecord = 0; iRecord < wNRecords; iRecord++)
    {
        DWORD dwLen = 0;
        
        dwError = LWNetDnsParseRecord(pHeader, pCurrent, &pRecord, &dwLen);
        BAIL_ON_LWNET_ERROR(dwError);

        dwError = LWNetDLinkedListAppend(&pRecordList, pRecord);
        BAIL_ON_LWNET_ERROR(dwError);

        pRecord = NULL;

        pCurrent += dwLen;
        dwBytesToAdvance += dwLen;
    }

error:    
    if (dwError)
    {
        if (pRecord)
        {
            LWNetDnsFreeRecord(pRecord);
        }
        LWNET_SAFE_FREE_DNS_RECORD_LINKED_LIST(pRecordList);
        dwBytesToAdvance = 0;
    }

    *ppRecordList = pRecordList;
    *pdwBytesToAdvance = dwBytesToAdvance;

    return dwError;
}
Esempio n. 10
0
DWORD
LWNetSrvStopListenThread(
    void
    )
{
    DWORD dwError = 0;

    if (gpServer)
    {
        dwError = MAP_LWMSG_ERROR(lwmsg_peer_stop_listen(gpServer));
        BAIL_ON_LWNET_ERROR(dwError);
    }

error:

    if (gpServer)
    {
        lwmsg_peer_delete(gpServer);
        gpServer = NULL;
    }

    if (gpProtocol)
    {
        lwmsg_protocol_delete(gpProtocol);
        gpProtocol = NULL;
    }

    return dwError;
}
Esempio n. 11
0
DWORD
LWNetSrvOpenServer(
    uid_t peerUID,
    gid_t peerGID,
    PHANDLE phServer
    )
{
    DWORD dwError = 0;
    PLWNET_SRV_API_STATE pServerState = NULL;
    
    dwError = LWNetAllocateMemory(
                    sizeof(LWNET_SRV_API_STATE),
                    (PVOID*)&pServerState);
    BAIL_ON_LWNET_ERROR(dwError);
    
    pServerState->peerUID = peerUID;
    pServerState->peerGID = peerGID;
    
    *phServer = (HANDLE)pServerState;
    
cleanup:

    return dwError;
    
error:

    *phServer = (HANDLE)NULL;
    
    if (pServerState) {
        LWNetSrvCloseServer((HANDLE)pServerState);
    }
    
    goto cleanup;
}
Esempio n. 12
0
DWORD
AddFlag(
    DWORD dwFlag,
    PDWORD pdwFlags
    )
{
    DWORD dwError = 0;
    DWORD dwFlags = *pdwFlags;
    
    if(dwFlags & dwFlag)
    {
        printf("Duplicate flag entered: [0x%.8X]\n", dwFlag);
        dwError = ERROR_INVALID_PARAMETER;
    }
    else if(!(dwFlag & LWNET_SUPPORTED_DS_INPUT_FLAGS))
    {
        printf("Invalid flag entered: [0x%.8X]\n", dwFlag);
        dwError = ERROR_INVALID_PARAMETER;
    }
    BAIL_ON_LWNET_ERROR(dwError);
    
    dwFlags |= dwFlag;
    
    *pdwFlags = dwFlags;
    
    
error:
    return dwError;
    
}
Esempio n. 13
0
VOID
LWNetSrvLogProcessStartedEvent(
    VOID
    )
{
    DWORD dwError = 0;
    PSTR pszDescription = NULL;

    dwError = LwAllocateStringPrintf(
                 &pszDescription,
                 "The Likewise site manager service was started.");
    BAIL_ON_LWNET_ERROR(dwError);

    LWNetSrvLogInformationEvent(
            LWNET_EVENT_INFO_SERVICE_STARTED,
            SERVICE_EVENT_CATEGORY,
            pszDescription,
            NULL);

cleanup:

    LWNET_SAFE_FREE_STRING(pszDescription);

    return;

error:

    goto cleanup;
}
Esempio n. 14
0
VOID
LWNetSrvLogProcessStoppedEvent(
    DWORD dwExitCode
    )
{
    DWORD dwError = 0;
    PSTR pszDescription = NULL;
    PSTR pszData = NULL;

    dwError = LwAllocateStringPrintf(
                 &pszDescription,
                 "The Likewise site manager service was stopped");
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetGetErrorMessageForLoggingEvent(
                         dwExitCode,
                         &pszData);
    BAIL_ON_LWNET_ERROR(dwError);

    if (dwExitCode)
    {
        LWNetSrvLogErrorEvent(
                LWNET_EVENT_ERROR_SERVICE_STOPPED,
                SERVICE_EVENT_CATEGORY,
                pszDescription,
                pszData);
    }
    else
    {
        LWNetSrvLogInformationEvent(
                LWNET_EVENT_INFO_SERVICE_STOPPED,
                SERVICE_EVENT_CATEGORY,
                pszDescription,
                pszData);
    }

cleanup:

    LWNET_SAFE_FREE_STRING(pszDescription);
    LWNET_SAFE_FREE_STRING(pszData);

    return;

error:

    goto cleanup;
}
Esempio n. 15
0
DWORD
LWNetSrvGetDCNameDiscover(
    IN PCSTR pszDnsDomainName,
    IN OPTIONAL PCSTR pszSiteName,
    IN OPTIONAL PCSTR pszPrimaryDomain,
    IN DWORD dwDsFlags,
    IN DWORD dwBlackListCount,
    IN OPTIONAL PSTR* ppszAddressBlackList,
    OUT PLWNET_DC_INFO* ppDcInfo,
    OUT OPTIONAL PDNS_SERVER_INFO* ppServerArray,
    OUT OPTIONAL PDWORD pdwServerCount,
    OUT PBOOLEAN pbFailedFindWritable
)
{
    DWORD dwError = 0;

    /* First try with the "Preferred DC list" */

    dwError = LWNetSrvGetDCNameDiscoverInternal(
                  pszDnsDomainName,
                  pszSiteName,
                  pszPrimaryDomain,
                  dwDsFlags,
                  dwBlackListCount,
                  ppszAddressBlackList,
                  LWNetGetPreferredDcList,
                  ppDcInfo,
                  ppServerArray,
                  pdwServerCount,
                  pbFailedFindWritable);
    if (dwError == ERROR_SUCCESS)
    {
        goto cleanup;
    }

    /* Try again using the standard DNS SRV queries */

    dwError = LWNetSrvGetDCNameDiscoverInternal(
                  pszDnsDomainName,
                  pszSiteName,
                  pszPrimaryDomain,
                  dwDsFlags,
                  dwBlackListCount,
                  ppszAddressBlackList,
                  LWNetDnsSrvQuery,
                  ppDcInfo,
                  ppServerArray,
                  pdwServerCount,
                  pbFailedFindWritable);
    BAIL_ON_LWNET_ERROR(dwError);

cleanup:

    return dwError;

error:

    goto cleanup;
}
Esempio n. 16
0
static
DWORD
LWNetSrvPingCLdapPoll(
    IN DWORD dwTimeoutMilliseconds,
    IN DWORD dwFdCount,
    IN struct pollfd *Readfds
)
{
    DWORD dwError = 0;
    int sret = 0;
    LWNET_UNIX_MS_TIME_T CurrentTime = 0;
    LWNET_UNIX_MS_TIME_T StopTime = 0;
    DWORD dwRemainder = 0;

    dwError = LWNetGetSystemTimeInMs(&StopTime);
    BAIL_ON_LWNET_ERROR(dwError);

    StopTime += dwTimeoutMilliseconds;

    do
    {
        dwError = LWNetGetSystemTimeInMs(&CurrentTime);
        BAIL_ON_LWNET_ERROR(dwError);

        if (CurrentTime < StopTime)
        {
            dwRemainder = StopTime - CurrentTime;
            sret = poll(Readfds, dwFdCount, dwRemainder);
        }
        else
        {
            sret = 0;
        }
    } while (sret < 0 && errno == EINTR);

    if (sret < 0)
    {
        dwError = LwMapErrnoToLwError(errno);
    }
    BAIL_ON_LWNET_ERROR(dwError);

error:

    return dwError;
}
Esempio n. 17
0
DWORD
LWNetDnsBuildSRVRecordList(
    IN PDNS_RESPONSE_HEADER pHeader,
    IN PDLINKEDLIST pAnswersList,
    IN PDLINKEDLIST pAdditionalsList,
    OUT PDLINKEDLIST* ppSRVRecordList
    )
{
    DWORD dwError = 0;
    PDNS_SRV_INFO_RECORD pSRVRecord = NULL;
    PDLINKEDLIST pListMember = NULL;
    PDLINKEDLIST pSRVRecordList = NULL;
    
    pListMember = pAnswersList;
    while (pListMember)
    {
        dwError = LWNetDnsBuildSRVRecord(pHeader,
                                         (PDNS_RECORD)pListMember->pItem,
                                         pAdditionalsList,
                                         &pSRVRecord);
        if (dwError)
        {
            // Already logged on ERROR_NOT_FOUND
            if (dwError != ERROR_NOT_FOUND)
            {
                LWNET_LOG_ERROR("Failed to build SRV record information");
            }
            // Skip
            dwError = 0;
        }
        else
        {
            dwError = LWNetDLinkedListAppend(&pSRVRecordList, pSRVRecord);
            BAIL_ON_LWNET_ERROR(dwError);

            pSRVRecord = NULL;
        }
        
        pListMember = pListMember->pNext;
    }
    
error:
    if (pSRVRecord)
    {
        LWNetDnsFreeSRVInfoRecord(pSRVRecord);
    }
    if (dwError)
    {
        LWNET_SAFE_FREE_SRV_INFO_LINKED_LIST(pSRVRecordList);
    }

    *ppSRVRecordList = pSRVRecordList;

    return dwError;
}
Esempio n. 18
0
static
DWORD
LWNetFindServersInDomain(
    IN PDNS_SERVER_INFO pServerArray,
    IN DWORD dwServerCount,
    IN PCSTR pszDomainName,
    OUT PDNS_SERVER_INFO* ppServersInDomain,
    OUT PDWORD pdwServersInDomainCount
)
{
    DWORD dwError = 0;
    DWORD i = 0;
    DWORD dwServersInDomainCount = 0;
    DWORD dwServerIndex = 0;
    PDNS_SERVER_INFO pServersInDomain = NULL;

    for (i = 0; i < dwServerCount; i++)
    {
        if (LWNetServerIsInDomain(&pServerArray[i], pszDomainName))
        {
            dwServersInDomainCount++;
        }
    }

    if (dwServersInDomainCount)
    {
        dwError = LWNetAllocateMemory(dwServersInDomainCount * sizeof(*pServerArray), OUT_PPVOID(&pServersInDomain));
        BAIL_ON_LWNET_ERROR(dwError);

        for (i = 0; i < dwServerCount; i++)
        {
            if (LWNetServerIsInDomain(&pServerArray[i], pszDomainName))
            {
                pServersInDomain[dwServerIndex++] = pServerArray[i];
            }
        }
    }

    *ppServersInDomain = pServersInDomain;
    *pdwServersInDomainCount = dwServersInDomainCount;

cleanup:

    return dwError;

error:

    *ppServersInDomain = NULL;
    *pdwServersInDomainCount = 0;

    LWNET_SAFE_FREE_MEMORY(pServersInDomain);

    goto cleanup;
}
Esempio n. 19
0
NTSTATUS
LWNetSvcmRefresh(
    PLW_SVCM_INSTANCE pInstance
    )
{
    DWORD dwError = 0;
    HANDLE hServer = NULL;

    LWNET_LOG_INFO("Refreshing configuration");

    dwError = LWNetSrvOpenServer(
                getuid(),
                getgid(),
                &hServer);
    BAIL_ON_LWNET_ERROR(dwError);

     dwError = LWNetSrvRefreshConfiguration(hServer);
     BAIL_ON_LWNET_ERROR(dwError);

    LWNET_LOG_INFO("Refreshed configuration successfully");

cleanup:

    if (hServer != NULL)
    {
        LWNetSrvCloseServer(hServer);
    }

    return LwWin32ErrorToNtStatus(dwError);

error:

    LWNET_LOG_ERROR("Failed to refresh configuration. [Error code:%u]", dwError);

    goto cleanup;
}
Esempio n. 20
0
VOID
LWNetSrvLogProcessFailureEvent(
    DWORD dwErrCode
    )
{
    DWORD dwError = 0;
    PSTR pszDescription = NULL;
    PSTR pszData = NULL;

    dwError = LwAllocateStringPrintf(
                 &pszDescription,
                 "The Likewise site manager service stopped running due to an error");
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetGetErrorMessageForLoggingEvent(
                         dwErrCode,
                         &pszData);
    BAIL_ON_LWNET_ERROR(dwError);

    LWNetSrvLogErrorEvent(
            LWNET_EVENT_ERROR_SERVICE_START_FAILURE,
            SERVICE_EVENT_CATEGORY,
            pszDescription,
            pszData);

cleanup:

    LWNET_SAFE_FREE_STRING(pszDescription);
    LWNET_SAFE_FREE_STRING(pszData);

    return;

error:

    goto cleanup;
}
Esempio n. 21
0
DWORD
LWNetSrvStartNetBios(
    VOID)
{
    DWORD dwError = 0;

    if (LWNetConfigIsNetBiosEnabled())
    {
        dwError = LWNetSrvNetBiosInit();
        BAIL_ON_LWNET_ERROR(dwError);

        dwError = LWNetSrvStartNetBiosThread();
        BAIL_ON_LWNET_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    LWNetSrvNetBiosCleanup();
    LWNET_LOG_ERROR("Failed initializing NetBIOS listener thread %s",
                    LwErrnoToName(dwError));
    goto cleanup;
}
Esempio n. 22
0
DWORD
LWNetDnsParseName(
    IN PDNS_RESPONSE_HEADER pHeader,
    IN PBYTE pData,
    OUT PDWORD pdwBytesToAdvance,
    OUT OPTIONAL PSTR* ppszName
    )
{
    DWORD dwError = 0;
    DWORD dwBytesToAdvance = 0;
    DWORD dwNameLen = 0;
    PSTR pszName = NULL;

    /* Figure out the size and how many bytes the parse will advance */
    LWNetDnsParseNameWorker(pHeader, pData, &dwBytesToAdvance, &dwNameLen, NULL);

    if (ppszName)
    {
        /* Now allocate the memory, overallocating to ensure NULL termination in case
           the DNS packet does not termiante */
        dwError = LWNetAllocateMemory((dwNameLen+3) * sizeof(CHAR), (PVOID*)&pszName);
        BAIL_ON_LWNET_ERROR(dwError);

        /* Fill in the name */
        LWNetDnsParseNameWorker(pHeader, pData, NULL, NULL, pszName);

        /* Ensure NULL termination */
        pszName[dwNameLen] = 0;
    }
    
error:
    if (dwError)
    {
        LWNET_SAFE_FREE_MEMORY(pszName);
    }

    *pdwBytesToAdvance = dwBytesToAdvance;

    if (ppszName)
    {
        *ppszName = pszName;
    }

    return dwError;
}
Esempio n. 23
0
DWORD
LWNetSrvInitialize(
    VOID
    )
{
    DWORD dwError = 0;
    
    dwError = LWNetSrvApiInit();
    BAIL_ON_LWNET_ERROR(dwError);
    
cleanup:

    return dwError;
    
error:

    goto cleanup;
}
Esempio n. 24
0
DWORD
LWNetReadGUID(
    OUT PBYTE pbtDest,
    IN PACKED_ARRAY* pArray
)
{
    DWORD dwError = 0;

    if (BYTES_REMAINING((*pArray)) < LWNET_GUID_SIZE)
    {
        dwError = DNS_ERROR_BAD_PACKET;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    memcpy(pbtDest, pArray->pCur, LWNET_GUID_SIZE);
    pArray->pCur += LWNET_GUID_SIZE;

error:
    return dwError;
}
Esempio n. 25
0
DWORD
LWNetSrvNetBiosInit(VOID)
{
    struct {
        unsigned mutexInit : 1;
        unsigned mutexAckInit : 1;
        unsigned cvInit : 1;
        unsigned cvAckInit : 1;
    } initialized = {0};

    DWORD dwError = 0;
    PLWNET_SRV_NETBIOS_CONTEXT pNbCtx = NULL;

    dwError = LWNetAllocateMemory(
                  sizeof(*pNbCtx),
                  (PVOID*) &pNbCtx);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LwErrnoToWin32Error(pthread_mutex_init(&pNbCtx->mutex, NULL));
    BAIL_ON_LWNET_ERROR(dwError);
    initialized.mutexInit = TRUE;

    dwError = LwErrnoToWin32Error(pthread_cond_init(&pNbCtx->cv, NULL));
    BAIL_ON_LWNET_ERROR(dwError);
    initialized.cvInit = TRUE;

    dwError = LwErrnoToWin32Error(pthread_mutex_init(&pNbCtx->mutexAck, NULL));
    BAIL_ON_LWNET_ERROR(dwError);
    initialized.mutexAckInit = TRUE;

    dwError = LwErrnoToWin32Error(pthread_cond_init(&pNbCtx->cvAck, NULL));
    BAIL_ON_LWNET_ERROR(dwError);
    initialized.cvAckInit = TRUE;

    dwError = LwErrnoToWin32Error(pthread_mutex_init(
                  &pNbCtx->mutexTransactionId, NULL));
    BAIL_ON_LWNET_ERROR(dwError);

    gpNbCtx = pNbCtx;

cleanup:
    return dwError;

error:
    if (initialized.mutexInit)
    {
        pthread_mutex_destroy(&pNbCtx->mutex);
    }
    if (initialized.mutexAckInit)
    {
        pthread_mutex_destroy(&pNbCtx->mutexAck);
    }
    if (initialized.cvInit)
    {
        pthread_cond_destroy(&pNbCtx->cv);
    }
    if (initialized.cvAckInit)
    {
        pthread_cond_destroy(&pNbCtx->cvAck);
    }
    LWNET_SAFE_FREE_MEMORY(pNbCtx);
    goto cleanup;
}
Esempio n. 26
0
VOID *LWNetSrvStartNetBiosThreadRoutine(VOID *ctx)
{
    DWORD dwError = 0;
    struct pollfd pollfds[1];
    int sts = 0;
    int sock = 0;
    UINT8 *NetBiosReply = NULL;
    struct sockaddr_in dgAddr;
    int NetBiosReplyAddrLen = 0;
    void *pNetBiosReplyAddrLen = &NetBiosReplyAddrLen;
    PLWNET_SRV_NETBIOS_CONTEXT pNbCtx = (PLWNET_SRV_NETBIOS_CONTEXT) ctx;
    int allowBroadcast = 1;
    UINT8 Flags = 0;
    UINT16 respTransactionId = 0;
    PSTR NbName = NULL;
    struct in_addr *addrs = NULL;
    DWORD addrsLen = 0;
    struct timeval  tp = {0};
    struct timespec cvTimeout = {0};

    dwError = LWNetAllocateMemory(
                  LWNB_NETBIOS_UDP_MAX,
                  (PVOID*) &NetBiosReply);

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1)
    {
        dwError = ERROR_INVALID_HANDLE;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    sts = setsockopt(sock,
              SOL_SOCKET,
              SO_BROADCAST,
              &allowBroadcast,
              sizeof(allowBroadcast));
    if (sts == -1)
    {
        dwError = ERROR_INVALID_HANDLE;
        BAIL_ON_LWNET_ERROR(dwError);
    }


    pthread_mutex_lock(&pNbCtx->mutex);
    pNbCtx->sock = sock;
    pthread_mutex_unlock(&pNbCtx->mutex);

    do
    {
        memset(pollfds, 0, sizeof(pollfds));
        pollfds[0].fd = sock;
        pollfds[0].events = POLLIN;

        sts = poll(pollfds, 1, -1);
        if (sts > 0 && pollfds[0].revents)
        {
            sts = recvfrom(
                  sock,
                  NetBiosReply,
                  LWNB_NETBIOS_UDP_MAX,
                  0,  /* flags */
                  (struct sockaddr *) &dgAddr,
                  pNetBiosReplyAddrLen);
            if (sts > 0)
            {
                dwError = LWNetNbParseNameQueryResponse(
                              NetBiosReply,
                              sts,
                              0, // remove this argument
                              &respTransactionId,
                              &NbName,
                              NULL,
                              &Flags,
                              &addrs,
                              &addrsLen);
                pthread_mutex_lock(&pNbCtx->mutex);
                pNbCtx->respError = dwError;
                pNbCtx->transactionId = respTransactionId;
                pNbCtx->addrs = addrs;
                pNbCtx->addrsLen = addrsLen;
                pNbCtx->bNbRepsponse = TRUE;
                pthread_mutex_lock(&pNbCtx->mutexAck);
                pthread_mutex_unlock(&pNbCtx->mutex);
                pthread_cond_broadcast(&pNbCtx->cv);

                // Wait for LWNetNbResolveName ack address received
                do
                {
                    gettimeofday(&tp, NULL);
                    cvTimeout.tv_sec =
                        tp.tv_sec + pNbCtx->udpTimeout;
                    cvTimeout.tv_nsec = tp.tv_usec * 1000;
                    sts = pthread_cond_timedwait(
                              &pNbCtx->cvAck,
                              &pNbCtx->mutexAck,
                              &cvTimeout);
                } while (!pNbCtx->bAck && sts != ETIMEDOUT);
                pNbCtx->bAck = FALSE;
                pthread_mutex_unlock(&pNbCtx->mutexAck);
            }
        }
    } while (!pNbCtx->bShutdown);
    LWNET_LOG_INFO("Stopping NetBIOS listener thread");

cleanup:
    LWNET_SAFE_FREE_MEMORY(NetBiosReply);
    LWNET_SAFE_FREE_STRING(NbName);
    if (sock != -1)
    {
        close(sock);
    }
    return NULL;

error:
    goto cleanup;
}
Esempio n. 27
0
DWORD
LWNetNbParseNameQueryResponse(
    IN PBYTE buf,
    IN DWORD len,
    IN UINT16 TransactionId,
    OUT UINT16 *retTransactionId,
    OUT PSTR *retNbName,
    OUT UINT32 *retTTL,
    OUT UINT8 *retFlags,
    OUT struct in_addr **retAddrs,
    OUT PDWORD retAddrsLen)
{
    DWORD dwError = 0;
    DWORD i = 0;
    DWORD j = 0;
    UINT16 parseTransactionId = 0;
    UINT16 opCodeFlags = 0;
    UINT16 bResponse = 0;
    UINT16 nbQDCount = 0;
    UINT16 nbANCount = 0;
    UINT16 nbNSCount = 0;
    UINT16 nbARCount = 0;
    UINT16 nbNB = 0;
    UINT16 nbIN = 0;
    UINT32 nbTTL = 0;
    UINT16 nbNB_Flags = 0;
    UINT32 IpAddress = 0;
    UINT16 RDLength = 0;
    UINT8 queryType = 0;
    PSTR NetBiosName = NULL;
    PSTR NbName = NULL;
    DWORD numAddrs = 0;
    DWORD nbNameLen = 0;
    struct in_addr *addrs = NULL;

    memcpy(&parseTransactionId, &buf[i], sizeof(parseTransactionId));
    i += sizeof(parseTransactionId);

    parseTransactionId = ntohs(parseTransactionId);
    if (retTransactionId)
    {
        *retTransactionId = parseTransactionId;
    }

    memcpy(&opCodeFlags, &buf[i], sizeof(opCodeFlags));
    i += sizeof(opCodeFlags);

    opCodeFlags = ntohs(opCodeFlags);
    bResponse = opCodeFlags & (1 << LWNB_SHIFT_REQUEST_TYPE) ? 1 : 0;

#if 0
    /* Deal with other flags later... Not sure it matters at this point */

    opCodeFlags |= (bBroadcast & 1) << LWNB_SHIFT_FLAG_BROADCAST;
    opCodeFlags |= 1                << LWNB_SHIFT_FLAG_RECURSION_DESIRED;
    opCodeFlags |= (opcode & 4)     << LWNB_SHIFT_OPCODE;
#endif

    if (bResponse != LWNB_OPCODE_RESPONSE)
    {
        /* Something is seriously wrong if this is not a NetBIOS response */
        dwError = ERROR_BAD_NET_RESP;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    memcpy(&nbQDCount, &buf[i], sizeof(nbQDCount));
    i += sizeof(nbQDCount);
    nbQDCount = ntohs(nbQDCount);

    memcpy(&nbANCount, &buf[i], sizeof(nbANCount));
    i += sizeof(nbANCount);
    nbANCount = ntohs(nbANCount);
    if (nbANCount != 1)
    {
        /* There must be exactly 1 answer to the sent query */
        dwError = ERROR_BAD_NET_RESP;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    memcpy(&nbNSCount, &buf[i], sizeof(nbNSCount));
    i += sizeof(nbNSCount);
    nbNSCount = ntohs(nbNSCount);

    memcpy(&nbARCount, &buf[i], sizeof(nbARCount));
    i += sizeof(nbARCount);
    nbARCount = ntohs(nbARCount);

    dwError = LWNetNbName2ToStr(
                 &buf[i],
                 &NetBiosName,
                 &queryType,
                 &nbNameLen);
    BAIL_ON_LWNET_ERROR(dwError);
    i += nbNameLen;

    memcpy(&nbNB, &buf[i], sizeof(nbNB));
    i += sizeof(nbNB);
    nbNB = ntohs(nbNB);

    memcpy(&nbIN, &buf[i], sizeof(nbIN));
    i += sizeof(nbIN);
    nbIN = ntohs(nbIN);

    if (nbNB != 0x0020 || nbIN != 0x0001)
    {
        /* RFC 1002 says these must be the values for these fields */
        dwError = ERROR_BAD_NET_RESP;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    memcpy(&nbTTL, &buf[i], sizeof(nbTTL));
    i += sizeof(nbTTL);
    nbTTL = ntohl(nbTTL);
    if (retTTL)
    {
        *retTTL = nbTTL;
    }

    memcpy(&RDLength, &buf[i], sizeof(RDLength));
    i += sizeof(RDLength);
    RDLength = ntohs(RDLength);
    numAddrs = RDLength / (sizeof(nbNB_Flags) + sizeof(IpAddress));
    dwError = LWNetAllocateMemory(
                  numAddrs * sizeof(struct in_addr),
                  (PVOID*) &addrs);
    BAIL_ON_LWNET_ERROR(dwError);

    j = 0;
    do
    {
        memcpy(&nbNB_Flags, &buf[i], sizeof(nbNB_Flags));
        i += sizeof(nbNB_Flags);
        nbNB_Flags = ntohs(nbNB_Flags);
        nbNB_Flags >>= 13;
        *retFlags = nbNB_Flags;

        memcpy(&IpAddress, &buf[i], sizeof(IpAddress));
        i += sizeof(IpAddress);
        addrs[j++].s_addr = IpAddress;
        RDLength -= sizeof(nbNB_Flags) + sizeof(IpAddress);
    }
    while (RDLength > 0);
    *retNbName = NetBiosName;
    *retAddrs = addrs;
    *retAddrsLen = j;

cleanup:
    return dwError;

error:
    LWNET_SAFE_FREE_MEMORY(NetBiosName);
    LWNET_SAFE_FREE_MEMORY(NbName);
    LWNET_SAFE_FREE_MEMORY(addrs);
    goto cleanup;
}
Esempio n. 28
0
/* Convert NetBIOS level 2 encoded name to a string */
DWORD
LWNetNbName2ToStr(
    IN PBYTE buf,
    OUT PSTR *ppNbName,
    OUT PUINT8 pSuffix,
    OUT PDWORD dwBytesConsumed)
{
    DWORD dwError = 0;
    PSTR *NbNameParts2 = NULL;
    PSTR NbName = NULL;
    CHAR netBiosName[LWNB_NAME_MAX_LENGTH] = {0};
    DWORD addrsLen = 0;
    DWORD nbNameOffset = 0;
    DWORD i = 0;

    dwError = LWNetNbName2ToParts(&buf[i], &NbNameParts2, &addrsLen);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetAllocateMemory(
                  addrsLen * sizeof(char),
                  (PVOID*) &NbName);
    BAIL_ON_LWNET_ERROR(dwError);

    nbNameOffset = 0;
    for (i=0; NbNameParts2[i]; i++)
    {
        if (i==0)
        {
            /*
             * Convert first part of name, which is in NetBIOS layer 1 encoding
             * to a null-terminated string.
             */
            LWNetNbNameToStr((UINT8 *) NbNameParts2[i], netBiosName, pSuffix);
            strncat(NbName, netBiosName, addrsLen - nbNameOffset);
            nbNameOffset += strlen(netBiosName);
        }
        else
        {
            /* The rest of the name is just text, so copy it */
            strncat(NbName, ".", addrsLen - nbNameOffset);
            nbNameOffset++;

            strncat(NbName,
                    NbNameParts2[i],
                    addrsLen - nbNameOffset);
            nbNameOffset += strlen(NbNameParts2[i]);
        }
    }
    *ppNbName = NbName;
    *dwBytesConsumed = addrsLen;

cleanup:
    for (i=0; NbNameParts2[i]; i++)
    {
        LWNET_SAFE_FREE_MEMORY(NbNameParts2[i]);
    }
    LWNET_SAFE_FREE_MEMORY(NbNameParts2);
    return dwError;

error:
    LW_SAFE_FREE_MEMORY(NbName);
    goto cleanup;
}
Esempio n. 29
0
DWORD
LWNetNbResolveName(
    IN PSTR pszHostName,
    IN UINT16 flags,
    OUT struct in_addr **retAddrs,
    OUT PDWORD retAddrsLen)
{
    DWORD dwError = 0;
    /* Derive this value from flags; hard code to FILE_SERVICE for now */
    unsigned char queryType = LWNB_RESOLVE_FILE_SERVICE;
    PSTR winsPrimary = NULL;
    PSTR winsSecondary = NULL;

    if (!gpNbCtx)
    {
        dwError = ERROR_INVALID_HANDLE;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    if (flags)
    {
        if (flags & LWNB_NETBIOS_FLAGS_RESOLVE_FILE_SERVICE)
        {
            queryType = LWNB_RESOLVE_FILE_SERVICE;
        }
        else if (flags & LWNB_NETBIOS_FLAGS_RESOLVE_WORKSTATION)
        {
            queryType = LWNB_RESOLVE_WORKSTATION;
        }
        else if (flags & LWNB_NETBIOS_FLAGS_RESOLVE_DC)
        {
            queryType = LWNB_RESOLVE_DC;
        }
    }

    if (flags & LWNB_NETBIOS_FLAGS_MODE_WINS)
    {
        LwNetConfigGetWinsServers(&winsPrimary, &winsSecondary);
        dwError = LWNetNbResolveNameUdp(
                      pszHostName,
                      winsPrimary,
                      queryType,
                      retAddrs,
                      retAddrsLen);
        if (dwError)
        {
            dwError = LWNetNbResolveNameUdp(
                          pszHostName,
                          winsSecondary,
                          queryType,
                          retAddrs,
                          retAddrsLen);
        }
    }

    if (dwError && (flags & LWNB_NETBIOS_FLAGS_MODE_BROADCAST))
    {
        dwError = LWNetNbResolveNameUdp(
                      pszHostName,
                      NULL,
                      queryType,
                      retAddrs,
                      retAddrsLen);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
Esempio n. 30
0
static DWORD
LWNetNbResolveNameUdp(
    PSTR pszHostName,
    PSTR winsServer,
    UINT8 queryType,
    OUT struct in_addr **retAddrs,
    OUT PDWORD retAddrsLen)
{
    DWORD dwError = 0;
    UINT16 transactionId = 0;
    UINT8 *NetBiosQuery = NULL;
    DWORD NetBiosQueryLen = 0;
    struct sockaddr_in dgAddr;
    struct timespec cvTimeout = {0};
    struct timeval  tp = {0};
    struct in_addr *resAddrs = NULL;
    struct in_addr *tmpResAddrs = NULL;
    int sts = 0;
    DWORD i = 0;
    DWORD resAddrsLen = 0;
    DWORD resAddrsAllocLen = 128;
    DWORD commType = 0;
    BOOLEAN bLocked = FALSE;

    dwError = LWNetAllocateMemory(
                  LWNB_NETBIOS_UDP_MAX,
                  (PVOID*) &NetBiosQuery);
    BAIL_ON_LWNET_ERROR(dwError);

    memset(&dgAddr, 0, sizeof(dgAddr));
    dgAddr.sin_family = AF_INET;
    dgAddr.sin_port = htons(137);

    if (winsServer && *winsServer)
    {
        sts = inet_aton(winsServer, &dgAddr.sin_addr);
        if (sts == -1)
        {
            dwError = LwErrnoToWin32Error(ERROR_INCORRECT_ADDRESS);
            BAIL_ON_LWNET_ERROR(dwError);
        }

        commType = LWNB_QUERY_WINS;
        dwError = LWNetNbConstructNameQuery(
                      pszHostName,
                      commType,
                      queryType,
                      &transactionId,
                      NetBiosQuery,
                      &NetBiosQueryLen);
        BAIL_ON_LWNET_ERROR(dwError);
    }
    else
    {
        dgAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
        commType = LWNB_QUERY_BROADCAST;
        dwError = LWNetNbConstructNameQuery(
                      pszHostName,
                      commType,
                      queryType,
                      &transactionId,
                      NetBiosQuery,
                      &NetBiosQueryLen);
        BAIL_ON_LWNET_ERROR(dwError);
    }


    // If this is not enough memory, realloc below fixes that
    dwError = LWNetAllocateMemory(
                  resAddrsAllocLen * sizeof(struct in_addr),
                  (PVOID*) &resAddrs);
    BAIL_ON_LWNET_ERROR(dwError);

    pthread_mutex_lock(&gpNbCtx->mutex);
    bLocked = TRUE;
    sts = sendto(gpNbCtx->sock,
                 NetBiosQuery,
                 NetBiosQueryLen,
                 0,  /* flags */
                 (struct sockaddr *) &dgAddr,
                 sizeof(dgAddr));
    if (sts == -1)
    {
        dwError = ERROR_NET_WRITE_FAULT;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    do
    {
        gettimeofday(&tp, NULL);
        cvTimeout.tv_sec = tp.tv_sec + gpNbCtx->udpTimeout;
        cvTimeout.tv_nsec = tp.tv_usec * 1000;
        do {
            sts = pthread_cond_timedwait(
                      &gpNbCtx->cv,
                      &gpNbCtx->mutex,
                      &cvTimeout);
        } while (!gpNbCtx->bNbRepsponse && sts != ETIMEDOUT);

        if (sts == 0 && gpNbCtx->transactionId == transactionId)
        {
            gpNbCtx->bNbRepsponse = FALSE;


            if ((commType == LWNB_QUERY_WINS && gpNbCtx->respError == 0) ||
                (commType == LWNB_QUERY_BROADCAST))
            {
                if ((gpNbCtx->addrsLen + resAddrsLen) > resAddrsAllocLen)
                {
                    resAddrsAllocLen = resAddrsAllocLen * 2 + gpNbCtx->addrsLen;
                    tmpResAddrs = LwRtlMemoryRealloc(
                                      resAddrs,
                                      resAddrsAllocLen);
                    if (!tmpResAddrs)
                    {
                        dwError = ERROR_NOT_ENOUGH_MEMORY;
                        BAIL_ON_LWNET_ERROR(dwError);
                    }
                    resAddrs = tmpResAddrs;
                    tmpResAddrs = NULL;
                }
                for (i=0; i<gpNbCtx->addrsLen; i++)
                {
                    memcpy(&resAddrs[resAddrsLen++],
                           &gpNbCtx->addrs[i],
                           sizeof(struct in_addr));
                }
            }
            pthread_mutex_lock(&gpNbCtx->mutexAck);
            gpNbCtx->bAck = TRUE;
            pthread_mutex_unlock(&gpNbCtx->mutexAck);
            pthread_cond_signal(&gpNbCtx->cvAck);

            if (commType == LWNB_QUERY_WINS && gpNbCtx->respError)
            {
                // Bail when WINS query fails to resolve the hostname
                dwError = gpNbCtx->respError;
                BAIL_ON_LWNET_ERROR(dwError);
            }
        }
    } while (commType == LWNB_QUERY_BROADCAST && sts != ETIMEDOUT);
    bLocked = FALSE;
    pthread_mutex_unlock(&gpNbCtx->mutex);

    if (resAddrsLen == 0)
    {
        dwError = ERROR_BAD_NET_NAME;
        BAIL_ON_LWNET_ERROR(dwError);
    }

    *retAddrs = resAddrs;
    *retAddrsLen = resAddrsLen;

cleanup:
    if (bLocked)
    {
        pthread_mutex_unlock(&gpNbCtx->mutex);
    }
    LWNET_SAFE_FREE_MEMORY(NetBiosQuery);
    return dwError;

error:
    LWNET_SAFE_FREE_MEMORY(resAddrs);
    goto cleanup;
}