Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
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;
}
Beispiel #7
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;
}
Beispiel #8
0
/* "Second Level" NetBIOS name encoding */
DWORD
LWNetNbStrToNbName2(
    PSTR Fqdn,
    UINT8 suffix,
    PBYTE *retNbNameL2,
    PDWORD retNbNameL2Len)
{
    DWORD dwError = 0;
    DWORD len = 0;
    PSTR p = NULL;
    PSTR token = NULL;
    PSTR tokenPtr = NULL;
    UINT8 *retName = NULL;
    UINT8 *up = NULL;

    /*
     * 32=Max NetBIOS First Level encoding length
     * All . separators are replaced by 1 byte count, so
     * don't need to count number of dots to determine buffer length
     * 2=FirstLevel encoding length + ending length (by definition 0)
     */
    len = LWNB_NETBIOS_ENCNAME_LEN + strlen(Fqdn) + 2;
    dwError = LWNetAllocateMemory(sizeof(CHAR) * len,
                                  (PVOID*)&retName);
    BAIL_ON_LWNET_ERROR(dwError);

    up = retName;

    dwError = LWNetAllocateString(
                  Fqdn,
                  &token);
    BAIL_ON_LWNET_ERROR(dwError);

    p = strchr(token, '.');
    if (p)
    {
        *p++ = '\0';
        Fqdn = token;
    }

    /* Store length of NetBIOS name component before that name */
    *up++ = (UINT8) LWNB_NETBIOS_ENCNAME_LEN;
    LWNetNbStrToNbName(Fqdn, suffix, up);
    up += LWNB_NETBIOS_ENCNAME_LEN;

    /* Work through rest of Fqdn, replacing . with length of stuff before . */
    if (p)
    {
        p = strtok_r(p, ".", &tokenPtr);
    }
    while (p)
    {
        len = strlen(p);
        *up++ = (UINT8) len;
        strncat((char *) up, p, sizeof(CHAR)*len - (up-retName));
        up += len;
        p = strtok_r(NULL, ".", &tokenPtr);
    }
    *up++ = '\0';

    *retNbNameL2 = (UINT8 *) retName;
    *retNbNameL2Len = up - retName;

cleanup:
    LWNET_SAFE_FREE_MEMORY(token);
    return dwError;

error:
    LWNET_SAFE_FREE_MEMORY(retName);
    goto cleanup;
}
Beispiel #9
0
DWORD
LWNetSrvPingCLdapArray(
    IN PCSTR pszDnsDomainName,
    IN DWORD dwDsFlags,
    IN PDNS_SERVER_INFO pServerArray,
    IN DWORD dwServerCount,
    IN OPTIONAL DWORD dwTimeoutSeconds,
    OUT PLWNET_DC_INFO* ppDcInfo,
    OUT PBOOLEAN pbFailedFindWritable
)
{
    DWORD dwError = 0;
    DWORD dwMaxConnCount = 0;
    DWORD dwIncrementalConnCount = 0;
    DWORD dwActualTimeoutSeconds = 0;
    DWORD dwSingleConnTimeoutSeconds = 0;
    DWORD dwSingleConnTimeoutMilliseconds = 0;
    DWORD dwTimeoutMilliseconds = 0;
    LWNET_UNIX_MS_TIME_T StopTime = 0;
    LWNET_UNIX_MS_TIME_T CurrentTime = 0;
    PLWNET_DC_INFO pDcInfo = NULL;
    BOOLEAN bFailedFindWritable = FALSE;
    PLWNET_CLDAP_CONNECTION_CONTEXT pConnections = NULL;
    DWORD dwActualConnCount = 0;
    DWORD dwUsedServers = 0;
    DWORD dwIndexConn = 0;
    struct pollfd *Readfds = NULL;

    // The basic scheme is a big loop over:
    //
    //     1. starting some CLDAP searches
    //     2. polling for responses
    //     3. processing responses
    //
    // When starting CLDAP searches, a portion of the
    // available connections will be started followed
    // by a short poll until the maximum number of
    // connections has been used.  Once the maximum
    // number of connections are in use, the polling
    // timeout will be the single search timeout for
    // the oldest connection.  This will start the
    // maximum number of connections reasonably fast
    // yet prevent excess network traffic if a server
    // responds quickly.
    //
    // Active connections will be tracked in a list
    // that is ordered by start time.  If several
    // servers respond at the same time, the one
    // nearest the end of the list will be the one
    // that responded the fastest.

    dwMaxConnCount = CT_MIN(LWNetConfigGetCLdapMaximumConnections(), dwServerCount);
    dwIncrementalConnCount = CT_MAX(dwMaxConnCount / 5, LWNET_CLDAP_MINIMUM_INCREMENTAL_CONNECTIONS);

    if (dwTimeoutSeconds > 0)
    {
        dwActualTimeoutSeconds = dwTimeoutSeconds;
    }
    else
    {
        dwActualTimeoutSeconds = LWNetConfigGetCLdapSearchTimeoutSeconds();
    }

    dwSingleConnTimeoutSeconds = CT_MIN(LWNetConfigGetCLdapSingleConnectionTimeoutSeconds(), dwActualTimeoutSeconds);
    dwSingleConnTimeoutMilliseconds = dwSingleConnTimeoutSeconds * 1000;

    dwError = LWNetAllocateMemory(
                  dwMaxConnCount * sizeof(*pConnections),
                  OUT_PPVOID(&pConnections));
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetAllocateMemory(
                  dwMaxConnCount * sizeof(*Readfds),
                  OUT_PPVOID(&Readfds));
    BAIL_ON_LWNET_ERROR(dwError);

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

    StopTime = CurrentTime + (dwActualTimeoutSeconds * 1000);

    for (;;)
    {
        LWNetSrvPingCLdapNewConnections(
            pszDnsDomainName,
            dwSingleConnTimeoutMilliseconds,
            dwMaxConnCount,
            dwServerCount,
            dwIncrementalConnCount,
            pServerArray,
            pConnections,
            Readfds,
            &dwActualConnCount,
            &dwUsedServers);

        if (dwActualConnCount == 0)
        {
            dwError = NERR_DCNotFound;
            BAIL_ON_LWNET_ERROR(dwError);
        }

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

        if (CurrentTime > StopTime)
        {
            dwError = NERR_DCNotFound;
            BAIL_ON_LWNET_ERROR(dwError);
        }

        if (dwActualConnCount < dwMaxConnCount &&
                dwUsedServers < dwServerCount)
        {
            // If there are more connections available,
            // use a short timeout
            dwTimeoutMilliseconds = LWNET_CLDAP_SHORT_POLL_TIMEOUT_MILLISECONDS;
        }
        else
        {
            if (pConnections[0].StartTime +
                    dwSingleConnTimeoutMilliseconds > CurrentTime)
            {
                // Use the remaining time for the oldest connection
                dwTimeoutMilliseconds = pConnections[0].StartTime +
                                        dwSingleConnTimeoutMilliseconds -
                                        CurrentTime;
                dwTimeoutMilliseconds = CT_MIN(dwSingleConnTimeoutMilliseconds, StopTime - CurrentTime);
            }
            else
            {
                // The oldest connection has exceeded its limit so
                // use the shortest possible timeout to check which
                // connections have responded now.
                dwTimeoutMilliseconds = 1;
            }
        }

        dwError = LWNetSrvPingCLdapPoll(
                      dwTimeoutMilliseconds,
                      dwActualConnCount,
                      Readfds);
        BAIL_ON_LWNET_ERROR(dwError);

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

        LWNetSrvPingCLdapProcessConnections(
            dwDsFlags,
            CurrentTime,
            dwSingleConnTimeoutMilliseconds,
            dwActualConnCount,
            Readfds,
            pConnections,
            &pDcInfo,
            &bFailedFindWritable);

        if (pDcInfo)
        {
            break;
        }

        dwActualConnCount = LWNetSrvPingCLdapPackArrays(
                                dwActualConnCount,
                                pConnections,
                                Readfds);
    }

error:
    if (pConnections)
    {
        for (dwIndexConn = 0 ; dwIndexConn < dwActualConnCount ; dwIndexConn++)
        {
            LWNetSrvPingCLdapEnd(&pConnections[dwIndexConn]);
        }
        LW_SAFE_FREE_MEMORY(pConnections);
    }
    LW_SAFE_FREE_MEMORY(Readfds);
    if (dwError)
    {
        LWNET_SAFE_FREE_DC_INFO(pDcInfo);
    }
    *ppDcInfo = pDcInfo;
    *pbFailedFindWritable = pDcInfo ? FALSE : bFailedFindWritable;
    return dwError;
}
Beispiel #10
0
DWORD
LWNetDnsSrvQuery(
    IN PCSTR pszDnsDomainName,
    IN OPTIONAL PCSTR pszSiteName,
    IN DWORD dwDsFlags,
    OUT PDNS_SERVER_INFO* ppServerArray,
    OUT PDWORD pdwServerCount
    )
// Call LWNET_SAFE_FREE_MEMORY on returned server array
{
    DWORD dwError = 0;
    PSTR pszQuestion = NULL;
    const size_t dwBufferSize = (64 * 1024);
    PVOID pBuffer = NULL;
    PDNS_RESPONSE_HEADER pResponse = NULL;
    DWORD dwResponseSize = 0;
    PDLINKEDLIST pAnswersList = NULL;
    PDLINKEDLIST pAdditionalsList = NULL;
    PDLINKEDLIST pSRVRecordList = NULL;
    PDNS_SERVER_INFO pServerArray = NULL;
    DWORD dwServerCount = 0;

    // TODO - Handle trailing dot in domain; handle no dots in domain

    dwError = LWNetDnsGetSrvRecordQuestion(&pszQuestion, pszDnsDomainName,
                                           pszSiteName, dwDsFlags);
    BAIL_ON_LWNET_ERROR(dwError);
   
    dwError = LWNetAllocateMemory(dwBufferSize, &pBuffer);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetDnsQueryWithBuffer(pszQuestion, TRUE, FALSE,
                                      pBuffer, dwBufferSize,
                                      &dwResponseSize);
    BAIL_ON_LWNET_ERROR(dwError);

    pResponse = (PDNS_RESPONSE_HEADER) pBuffer;
    if (LWNetDnsIsTruncatedResponse(pResponse))
    {
        dwError = LWNetDnsQueryWithBuffer(pszQuestion, FALSE, TRUE,
                                          pBuffer, dwBufferSize,
                                          &dwResponseSize);
        BAIL_ON_LWNET_ERROR(dwError);
    }

    // TODO: Add dwResponseSize validation to parsing.

    // Decode DNS response w/o taking into account record type
    dwError = LWNetDnsParseQueryResponse(pResponse,
                                         &pAnswersList,
                                         NULL,
                                         &pAdditionalsList);
    BAIL_ON_LWNET_ERROR(dwError);

    // Decode SRV records
    dwError = LWNetDnsBuildSRVRecordList(pResponse,
                                         pAnswersList,
                                         pAdditionalsList,
                                         &pSRVRecordList);
    BAIL_ON_LWNET_ERROR(dwError);

    // Create list of server names and addresses
    dwError = LWNetDnsBuildServerArray(pSRVRecordList,
                                       &pServerArray, &dwServerCount);
    BAIL_ON_LWNET_ERROR(dwError);

error:
    LWNET_SAFE_FREE_STRING(pszQuestion);
    LWNET_SAFE_FREE_MEMORY(pBuffer);
    LWNET_SAFE_FREE_DNS_RECORD_LINKED_LIST(pAnswersList);
    LWNET_SAFE_FREE_DNS_RECORD_LINKED_LIST(pAdditionalsList);
    LWNET_SAFE_FREE_SRV_INFO_LINKED_LIST(pSRVRecordList);

    if (dwError)
    {
        LWNET_SAFE_FREE_MEMORY(pServerArray);
        dwServerCount = 0;
    }

    *ppServerArray= pServerArray;
    *pdwServerCount = dwServerCount;

    return dwError;
}
Beispiel #11
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;
}
Beispiel #12
0
DWORD
LWNetDnsParseRecord(
    IN PDNS_RESPONSE_HEADER pHeader,
    IN PBYTE pData,
    OUT PDNS_RECORD* ppRecord,
    OUT PDWORD pdwBytesToAdvance
    )
{
    DWORD dwError = 0;
    PBYTE pCurrent = pData;
    PSTR  pszName = NULL;
    PDNS_RECORD pRecord = NULL;
    DWORD dwBytesToAdvance = 0;
    DWORD dwNameBytesToAdvance = 0;
    WORD  wDataLen = 0; /* As read from DNS record response data */

    dwError = LWNetDnsParseName(pHeader, pCurrent, &dwNameBytesToAdvance, &pszName);
    BAIL_ON_LWNET_ERROR(dwError);

    dwBytesToAdvance += dwNameBytesToAdvance;
    dwBytesToAdvance += sizeof(WORD); /* Type  */
    dwBytesToAdvance += sizeof(WORD); /* Class */
    dwBytesToAdvance += sizeof(DWORD); /* TTL   */
    pCurrent += dwBytesToAdvance;

    wDataLen = LWNetDnsReadWORD( pCurrent );
    dwBytesToAdvance += wDataLen + sizeof(WORD);

    dwError = LWNetAllocateMemory(sizeof(DNS_RECORD) + wDataLen, (PVOID*)&pRecord);
    BAIL_ON_LWNET_ERROR(dwError);

    // Fill in new record from buffer
    pCurrent = pData;
    pCurrent += dwNameBytesToAdvance;

    pRecord->pszName = pszName;
    pszName = NULL;

    pRecord->wType = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    pRecord->wClass = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    pRecord->dwTTL = LWNetDnsReadDWORD(pCurrent);
    pCurrent += sizeof(DWORD);

    pRecord->wDataLen = LWNetDnsReadWORD(pCurrent);
    pCurrent += sizeof(WORD);

    pRecord->pData = (PBYTE)pRecord + sizeof(DNS_RECORD);
    memcpy(pRecord->pData, pCurrent, pRecord->wDataLen);

error:
    LWNET_SAFE_FREE_STRING(pszName);
    if (dwError)
    {
        if (pRecord)
        {
            LWNetDnsFreeRecord(pRecord);
            pRecord = NULL;
        }
        dwBytesToAdvance = 0;        
    }

    *pdwBytesToAdvance = dwBytesToAdvance;
    *ppRecord = pRecord;

    return dwError;
}
Beispiel #13
0
DWORD
LWNetDnsGetNameServerList(
    OUT PSTR** pppszNameServerList,
    OUT PDWORD pdwNumServers
    )
// Call LWNET_SAFE_FREE_STRING_ARRAY on returned server list
{
    DWORD   dwError = 0;
    PSTR*   ppszNameServerList = NULL;
    DWORD   dwNumServers = 0;
    FILE*   fp = NULL;
    BOOLEAN bFileExists = FALSE;
    PCSTR   pszConfigFilePath = "/etc/resolv.conf";
    const   DWORD dwMaxLineLen = 1024;
    CHAR    szBuf[dwMaxLineLen + 1];
    regex_t rx;
    PDLINKEDLIST pNameServerList = NULL;
    PSTR    pszNameServer = NULL;
    
    memset(&rx, 0, sizeof(rx));
    
    if (regcomp(&rx, "^nameserver[[:space:]].*$", REG_EXTENDED) < 0) {
        dwError = ERROR_BAD_FORMAT;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    
    dwError = LwCheckFileTypeExists(
                    pszConfigFilePath,
                    LWFILE_REGULAR,
                    &bFileExists);
    BAIL_ON_LWNET_ERROR(dwError);
    
    if (!bFileExists) {
        *pppszNameServerList = NULL;
        *pdwNumServers = 0;
        goto cleanup;
    }
    
    if ((fp = fopen(pszConfigFilePath, "r")) == NULL) {
        dwError = LwMapErrnoToLwError(errno);
        BAIL_ON_LWNET_ERROR(dwError);
    } 
    
    while (1)
    {
          if (fgets(szBuf, dwMaxLineLen, fp) == NULL) {
             if (!feof(fp)) {
                dwError = LwMapErrnoToLwError(errno);
                BAIL_ON_LWNET_ERROR(dwError);
             } else {
                break;
             }
          }
          
          LwStripWhitespace(szBuf, TRUE, TRUE);
          
          if (!LWNetDnsConfigLineIsComment(szBuf) &&
              !regexec(&rx, szBuf, (size_t)0, NULL, 0))
          {
             PSTR pszLocation = NULL;
             PCSTR pszSearchString = "nameserver";
             
             if ((pszLocation = strstr(szBuf, pszSearchString))) {
                pszLocation += strlen(pszSearchString);
                
                if (!IsNullOrEmptyString(pszLocation)) {
                   dwError = LWNetAllocateString(pszLocation, &pszNameServer);
                   BAIL_ON_LWNET_ERROR(dwError);
                }
                
                dwError = LWNetDLinkedListAppend(
                                    &pNameServerList,
                                    pszNameServer);
                BAIL_ON_LWNET_ERROR(dwError);
                
                pszNameServer = NULL;
                
                dwNumServers++;
             }
          }
    }
    
    if (dwNumServers)
    {
        PDLINKEDLIST pListMember = NULL;
        DWORD iMember = 0;

        dwError = LWNetAllocateMemory(dwNumServers * sizeof(PSTR), (PVOID*)&ppszNameServerList);
        BAIL_ON_LWNET_ERROR(dwError);

        pListMember = pNameServerList;
        while (pListMember)
        {
            ppszNameServerList[iMember++] = (PSTR)pListMember->pItem;
            pListMember->pItem = NULL;
            pListMember = pListMember->pNext;
        }
    }

    *pppszNameServerList = ppszNameServerList;
    *pdwNumServers = dwNumServers;

cleanup:

    regfree(&rx);
    
    LWNetDLinkedListFree(pNameServerList);
    
    LWNET_SAFE_FREE_STRING(pszNameServer);
    
    if (fp) {
        fclose(fp);
    }

    return dwError;
    
error:

    *pppszNameServerList = NULL;
    *pdwNumServers = 0;
    
    if (ppszNameServerList) {
       LWNetFreeStringArray(ppszNameServerList, dwNumServers);
    }

    goto cleanup;
}
Beispiel #14
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;
}
Beispiel #15
0
DWORD
LWNetBuildDCInfo(
    IN PBYTE pBuffer,
    IN DWORD dwBufferSize,
    OUT PLWNET_DC_INFO* ppDCInfo
)
{
    DWORD dwError = 0;
    PLWNET_DC_INFO pDCInfo = NULL;
    PACKED_ARRAY netLogon = { 0 };

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

    netLogon.pStart = pBuffer;
    netLogon.pCur = pBuffer;
    netLogon.totalSize = dwBufferSize;

    dwError = LWNetReadLEDword(&pDCInfo->dwDomainControllerAddressType, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadLEDword(&pDCInfo->dwFlags, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadGUID((PBYTE)&pDCInfo->pucDomainGUID[0], &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszDnsForestName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszFullyQualifiedDomainName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszDomainControllerName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszNetBIOSDomainName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszNetBIOSHostName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszUserName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszDCSiteName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadString(&pDCInfo->pszClientSiteName, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadLEDword(&pDCInfo->dwVersion, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadLEWord(&pDCInfo->wLMToken, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

    dwError = LWNetReadLEWord(&pDCInfo->wNTToken, &netLogon);
    BAIL_ON_LWNET_ERROR(dwError);

error:
    if (dwError)
    {
        LWNET_SAFE_FREE_DC_INFO(pDCInfo);
    }

    *ppDCInfo = pDCInfo;

    return dwError;
}
Beispiel #16
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;
}
Beispiel #17
0
DWORD
LWNetReadString(
    OUT PSTR *ppszDest,
    IN PACKED_ARRAY *pArray
)
{
    // Decode a string according to RFC1035
    DWORD dwError = 0;
    PSTR pszOut = NULL;
    size_t outOffset = 0;
    BYTE *followingCur;
    size_t followOffset;
    size_t copyLen;
    BYTE **pCur = &pArray->pCur;

    // A valid string can't be longer than the packet it comes from
    dwError = LWNetAllocateMemory(pArray->totalSize, (PVOID*)&pszOut);
    BAIL_ON_LWNET_ERROR(dwError);

    while (**pCur != '\0')
    {
        switch (**pCur & 0xC0)
        {
        case 0xC0:
            // This is a string reference
            followOffset = (((WORD)(*pCur)[0] << 8) | (*pCur)[1]) & 0x3FFF;
            if (followOffset >= pArray->totalSize)
            {
                //Offset out of bounds
                dwError = DNS_ERROR_BAD_PACKET;
                goto error;
            }
            *pCur += 2;
            pCur = &followingCur;
            followingCur = pArray->pStart +  followOffset;
            if ((**pCur & 0xC0) == 0xC0)
            {
                // This is definitely redundant, and it could be an infinite
                // loop.
                dwError = DNS_ERROR_BAD_PACKET;
                goto error;
            }
            break;
        case 0x00:
            // This is a string component
            copyLen = (*pCur)[0];
            (*pCur)++;
            if (copyLen + 2 + outOffset > pArray->totalSize)
            {
                // This goes out of bounds of the output buffer. There must be
                // an infinite loop in the encoding.
                dwError = DNS_ERROR_BAD_PACKET;
                goto error;
            }
            if (copyLen + 1 + *pCur - pArray->pStart > pArray->totalSize)
            {
                // The label goes out of bounds of the message
                dwError = DNS_ERROR_BAD_PACKET;
                goto error;
            }
            if (outOffset > 0)
            {
                //Add a dot to separate the components
                pszOut[outOffset++] = '.';
            }
            memcpy(pszOut + outOffset, *pCur, copyLen);
            *pCur += copyLen;
            outOffset += copyLen;
            break;
        default:
            // Illegal reserved value
            dwError = DNS_ERROR_BAD_PACKET;
            goto error;
        }
    }
    *pCur += 1;
    pszOut[outOffset++] = '\0';

error:
    if (dwError)
    {
        LWNET_SAFE_FREE_STRING(pszOut);
    }
    *ppszDest = pszOut;
    return dwError;
}
Beispiel #18
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;
}
Beispiel #19
0
DWORD
LWNetDnsBuildServerArray(
    IN PDLINKEDLIST pSrvRecordList,
    OUT PDNS_SERVER_INFO* ppServerArray,
    OUT PDWORD pdwServerCount
    )
{
    DWORD dwError = 0;
    DWORD dwServerCount = 0;
    PDNS_SERVER_INFO pServerArray = NULL;
    PDLINKEDLIST pListMember = NULL;
    PDNS_SRV_INFO_RECORD pSrvRecord = NULL;
    DWORD dwServerIndex = 0;
    DWORD dwStringSize = 0;
    DWORD dwRequiredSize = 0;
    PSTR pStringLocation = NULL;

    for (pListMember = pSrvRecordList; pListMember; pListMember = pListMember->pNext)
    {
        pSrvRecord = (PDNS_SRV_INFO_RECORD)pListMember->pItem;

        dwStringSize += strlen(pSrvRecord->pszAddress) + 1;
        dwStringSize += strlen(pSrvRecord->pszTarget) + 1;

        dwServerCount++;
    }

    if (dwServerCount < 1)
    {
        // nothing to do, so we are done
        dwError = 0;
        goto error;
    }

    dwRequiredSize = dwServerCount * sizeof(DNS_SERVER_INFO) + dwStringSize;

    dwError = LWNetAllocateMemory(dwRequiredSize, (PVOID*)&pServerArray);
    BAIL_ON_LWNET_ERROR(dwError);

    pStringLocation = CT_PTR_ADD(pServerArray, dwServerCount * sizeof(DNS_SERVER_INFO));
    dwServerIndex = 0;
    for (pListMember = pSrvRecordList; pListMember; pListMember = pListMember->pNext)
    {
        PSTR source;

        pSrvRecord = (PDNS_SRV_INFO_RECORD)pListMember->pItem;
        
        // Copy the strings into the buffer
        pServerArray[dwServerIndex].pszAddress = pStringLocation;
        for (source = pSrvRecord->pszAddress; source[0]; source++)
        {
            pStringLocation[0] = source[0];
            pStringLocation++;
        }
        pStringLocation[0] = source[0];
        pStringLocation++;

        pServerArray[dwServerIndex].pszName = pStringLocation;
        for (source = pSrvRecord->pszTarget; source[0]; source++)
        {
            pStringLocation[0] = source[0];
            pStringLocation++;
        }
        pStringLocation[0] = source[0];
        pStringLocation++;

        dwServerIndex++;
    }

    // TODO: Turns this into ASSERT
    if (CT_PTR_OFFSET(pServerArray, pStringLocation) != dwRequiredSize)
    {
        LWNET_LOG_ERROR("ASSERT - potential buffer overflow");
    }

error:    
    if (dwError)
    {
        LWNET_SAFE_FREE_MEMORY(pServerArray);
        dwServerCount = 0;
    }

    *ppServerArray = pServerArray;
    *pdwServerCount = dwServerCount;

    return dwError;
}