/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
 * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
 * Editor Settings: expandtabs and use 4 spaces for indentation */

/*
 * Copyright Likewise Software
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.  You should have received a copy of the GNU General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
 * TERMS AS WELL.  IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
 * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
 * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
 * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE.  IF YOU
 * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
 * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
 * license@likewisesoftware.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        config.c
 *
 * Abstract:
 *
 *        Likewise IO (LWIO) - SRV
 *
 *        Protocols
 *
 *        Configuration
 *
 * Authors: Sriram Nambakam (snambakam@likewise.com)
 *
 */

#include "includes.h"

static
NTSTATUS
SrvProtocolTransferConfigContents(
    PSRV_PROTOCOL_CONFIG pSrc,
    PSRV_PROTOCOL_CONFIG pDest
    );


NTSTATUS
SrvProtocolReadConfig(
    PSRV_PROTOCOL_CONFIG pConfig
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    SRV_PROTOCOL_CONFIG config = { 0 };
    PLWIO_CONFIG_REG pReg = NULL;
    BOOLEAN bUsePolicy = TRUE;

    ntStatus = SrvProtocolInitConfig(&config);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = LwIoOpenConfig(
                "Services\\lwio\\Parameters\\Drivers\\srv",
                "Policy\\Services\\lwio\\Parameters\\Drivers\\srv",
                &pReg);
    if (ntStatus)
    {
        LWIO_LOG_ERROR("Failed to access device configuration [error code: %u]",
                       ntStatus);

        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    BAIL_ON_NT_STATUS(ntStatus);

    /* Ignore error as it may not exist; we can still use default. */
    LwIoReadConfigBoolean(
            pReg,
            "EnableDirectExecute",
            bUsePolicy,
            &config.bEnableDirectExecute);

    LwIoReadConfigBoolean(
            pReg,
            "SupportNetbios",
            bUsePolicy,
            &config.bEnableNetbios);

    LwIoReadConfigBoolean(
            pReg,
            "SupportSmb2",
            bUsePolicy,
            &config.bEnableSmb2);

    LwIoReadConfigBoolean(
            pReg,
            "EnableTransport",
            bUsePolicy,
            &config.bEnableTransport);

    LwIoReadConfigBoolean(
            pReg,
            "EnableSecuritySignatures",
            bUsePolicy,
            &config.bEnableSigning);

    LwIoReadConfigBoolean(
            pReg,
            "RequireSecuritySignatures",
            bUsePolicy,
            &config.bRequireSigning);

    LwIoReadConfigDword(
            pReg,
            "ZctReadThreshold",
            bUsePolicy,
            0,
            MAXULONG,
            &config.ulZctReadThreshold);

    LwIoReadConfigDword(
            pReg,
            "ZctWriteThreshold",
            bUsePolicy,
            0,
            MAXULONG,
            &config.ulZctWriteThreshold);

    LwIoReadConfigDword(
            pReg,
            "IdleConnectionTimeout",
            bUsePolicy,
            0,
            MAXULONG,
            &config.ulIdleTimeout);

    LwIoReadConfigBoolean(
            pReg,
            "EnableTcpKeepalive",
            bUsePolicy,
            &config.EnableTcpKeepalive);

    LwIoReadConfigDword(
            pReg,
            "TcpKeepaliveCnt",
            bUsePolicy,
            0,
            MAXULONG,
            &config.TcpKeepaliveCnt);

    LwIoReadConfigDword(
            pReg,
            "TcpKeepaliveIdle",
            bUsePolicy,
            0,
            MAXULONG,
            &config.TcpKeepaliveIdle);

    LwIoReadConfigDword(
            pReg,
            "TcpKeepaliveIntvl",
            bUsePolicy,
            0,
            MAXULONG,
            &config.TcpKeepaliveIntvl);

    if ((config.ulIdleTimeout != 0) &&
        (config.ulIdleTimeout < SRV_PROTOCOL_CONFIG_DEFAULT_IDLE_TIMEOUT_SECONDS_MIN))
    {
        LWIO_LOG_WARNING("Configured idle connection timeout of %u is "
                         "too small, using %u instead",
                         config.ulIdleTimeout,
                         SRV_PROTOCOL_CONFIG_DEFAULT_IDLE_TIMEOUT_SECONDS_MIN);
        config.ulIdleTimeout = SRV_PROTOCOL_CONFIG_DEFAULT_IDLE_TIMEOUT_SECONDS_MIN;
    }

    ntStatus = SrvProtocolTransferConfigContents(&config, pConfig);
    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    if (pReg)
    {
        LwIoCloseConfig(pReg);
    }

    SrvProtocolFreeConfigContents(&config);

    return ntStatus;

error:

    goto cleanup;
}

NTSTATUS
SrvProtocolInitConfig(
    PSRV_PROTOCOL_CONFIG pConfig
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;

    SrvProtocolFreeConfigContents(pConfig);

    pConfig->bEnableDirectExecute = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_DIRECT_EXECUTE;
    pConfig->bEnableNetbios = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_NETBIOS;
    pConfig->bEnableSmb2 = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_SMB2;
    pConfig->bEnableTransport = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_TRANSPORT;
    pConfig->bEnableSigning = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_SIGNING;
    pConfig->bRequireSigning = SRV_PROTOCOL_CONFIG_DEFAULT_REQUIRE_SIGNING;
    pConfig->ulZctReadThreshold = SRV_PROTOCOL_CONFIG_DEFAULT_ZCT_READ_THRESHOLD;
    pConfig->ulZctWriteThreshold = SRV_PROTOCOL_CONFIG_DEFAULT_ZCT_WRITE_THRESHOLD;
    pConfig->ulIdleTimeout = SRV_PROTOCOL_CONFIG_DEFAULT_IDLE_TIMEOUT_SECONDS;
    pConfig->EnableTcpKeepalive = SRV_PROTOCOL_CONFIG_DEFAULT_ENABLE_TCP_KEEPALIVE;
    pConfig->TcpKeepaliveCnt = SRV_PROTOCOL_CONFIG_DEFAULT_TCP_KEEPALIVE_CNT;
    pConfig->TcpKeepaliveIdle = SRV_PROTOCOL_CONFIG_DEFAULT_TCP_KEEPALIVE_IDLE;
    pConfig->TcpKeepaliveIntvl = SRV_PROTOCOL_CONFIG_DEFAULT_TCP_KEEPALIVE_INTVL;

    return ntStatus;
}

static
NTSTATUS
SrvProtocolTransferConfigContents(
    PSRV_PROTOCOL_CONFIG pSrc,
    PSRV_PROTOCOL_CONFIG pDest
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;

    SrvProtocolFreeConfigContents(pDest);

    *pDest = *pSrc;

    SrvProtocolFreeConfigContents(pSrc);

    return ntStatus;
}

VOID
SrvProtocolFreeConfigContents(
    PSRV_PROTOCOL_CONFIG pConfig
    )
{
    // Nothing to free right now
    memset(pConfig, 0, sizeof(*pConfig));
}

BOOLEAN
SrvProtocolConfigIsSigningEnabled(
    VOID
    )
{
    BOOLEAN bEnabled = FALSE;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    bEnabled = gProtocolApiGlobals.config.bEnableSigning;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return bEnabled;
}

BOOLEAN
SrvProtocolConfigIsSigningRequired(
    VOID
    )
{
    BOOLEAN bRequired = FALSE;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    bRequired = gProtocolApiGlobals.config.bRequireSigning;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return bRequired;
}

BOOLEAN
SrvProtocolConfigIsNetbiosEnabled(
    VOID
    )
{
    BOOLEAN bEnabled = FALSE;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    bEnabled = gProtocolApiGlobals.config.bEnableNetbios;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return bEnabled;
}


BOOLEAN
SrvProtocolConfigIsSmb2Enabled(
    VOID
    )
{
    BOOLEAN bEnabled = FALSE;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    bEnabled = gProtocolApiGlobals.config.bEnableSmb2;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return bEnabled;
}

BOOLEAN
SrvProtocolConfigIsTransportEnabled(
    VOID
    )
{
    BOOLEAN bEnabled = FALSE;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    bEnabled = gProtocolApiGlobals.config.bEnableTransport;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return bEnabled;
}

ULONG
SrvProtocolConfigGetZctReadThreshold(
    VOID
    )
{
    ULONG ulThreshold = 0;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    ulThreshold = gProtocolApiGlobals.config.ulZctReadThreshold;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return ulThreshold;
}

ULONG
SrvProtocolConfigGetZctWriteThreshold(
    VOID
    )
{
    ULONG ulThreshold = 0;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    ulThreshold = gProtocolApiGlobals.config.ulZctWriteThreshold;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return ulThreshold;
}

ULONG
SrvProtocolConfigGetIdleTimeout(
    VOID
    )
{
    ULONG ulThreshold = 0;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gProtocolApiGlobals.mutex);

    ulThreshold = gProtocolApiGlobals.config.ulIdleTimeout;

    LWIO_UNLOCK_RWMUTEX(bInLock, &gProtocolApiGlobals.mutex);

    return ulThreshold;
}

BOOLEAN
SrvProtocolConfigIsTcpKeepaliveEnabled(
    VOID
    )
{
    BOOLEAN enabled = FALSE;
    BOOLEAN inLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(inLock, &gProtocolApiGlobals.mutex);

    enabled = gProtocolApiGlobals.config.EnableTcpKeepalive;

    LWIO_UNLOCK_RWMUTEX(inLock, &gProtocolApiGlobals.mutex);

    return enabled;
}

ULONG
SrvProtocolConfigGetTcpKeepaliveCnt(
    VOID
    )
{
    ULONG tcpKeepaliveCnt = 0;
    BOOLEAN inLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(inLock, &gProtocolApiGlobals.mutex);

    tcpKeepaliveCnt = gProtocolApiGlobals.config.TcpKeepaliveCnt;

    LWIO_UNLOCK_RWMUTEX(inLock, &gProtocolApiGlobals.mutex);

    return tcpKeepaliveCnt;
}

ULONG
SrvProtocolConfigGetTcpKeepaliveIdle(
    VOID
    )
{
    ULONG tcpKeepaliveIdle = 0;
    BOOLEAN inLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(inLock, &gProtocolApiGlobals.mutex);

    tcpKeepaliveIdle = gProtocolApiGlobals.config.TcpKeepaliveIdle;

    LWIO_UNLOCK_RWMUTEX(inLock, &gProtocolApiGlobals.mutex);

    return tcpKeepaliveIdle;
}

ULONG
SrvProtocolConfigGetTcpKeepaliveIntvl(
    VOID
    )
{
    ULONG tcpKeepaliveIntvl = 0;
    BOOLEAN inLock = FALSE;

    LWIO_LOCK_RWMUTEX_SHARED(inLock, &gProtocolApiGlobals.mutex);

    tcpKeepaliveIntvl = gProtocolApiGlobals.config.TcpKeepaliveIntvl;

    LWIO_UNLOCK_RWMUTEX(inLock, &gProtocolApiGlobals.mutex);

    return tcpKeepaliveIntvl;
}
