/*
 * Copyright (c) Likewise Software.  All rights Reserved.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the license, or (at
 * your option) any later version.
 *
 * This library 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 Lesser
 * General Public License for more details.  You should have received a copy
 * of the GNU Lesser 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
 * LESSER 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@likewise.com
 */

/*
 * Copyright (C) Likewise Software. All rights reserved.
 *
 * Module Name:
 *
 *        lwnet-plugin.h
 *
 * Abstract:
 *
 *        Likewise Netlogon Plugin Interface
 *
 * Authors: Danilo Almeida (dalmeida@likewise.com)
 *
 */

/**
 * @file lwnet-plugin.h
 * @brief Preferred Domain Controller Plugin interface
 */

#ifndef __LWNET_PLUGIN_H__
#define __LWNET_PLUGIN_H__

/**
 * @defgroup netlogonplugin Preferred Domain Controller Plugin interface
 * @ingroup oem
 * @brief Preferred Domain Controller Plugin interface
 *
 * This API defines the interface a preferred domain controller plugin
 * must implement.  The interface supports getting a preferred DC list
 * to use instead of using information from DNS.  If the DCs returned
 * are unsuitable, the standard algorithm (using DNS) will be used as
 * a fallback.  There is a very simple plugin example at
 * netlogon/tests/plugin/plugin.c.
 *
 * Netlogon attempts to find the domain controller which responds
 * the quickest to CLDAP pings with a preference for domain
 * controllers in the same site.  The algorithm is rather complex.
 *
 * If the request includes a site, then the query order is:
 * -# Preferred domain controller plugin with the requested site
 * -# DNS with the requested site
 *
 * @note The resulting domain controllers are not checked for whether they
 * are within the requested site so the plugin is free to ignore the site.
 *
 * If the request does not include a site, Netlogon first queries the
 * plugin without a site.  What happens next depends on the results.
 * If the plugin does not return any domain controllers, Netlogon queries DNS.
 * If the plugin returns domain controllers, Netlogon checks them with
 * CLDAP pings and if none respond Netlogon queries DNS.  If one or more do
 * respond and if the best result is not in the same site, Netlogon searches
 * again with the same site.  The resulting query order for this case is:
 * -# Preferred domain controller plugin without a site
 * -# Preferred domain controller plugin with the same site
 * -# DNS with the same site
 *
 * @note Unless the plugin returns domain controllers in response to
 * the query with the same site, same site domain controllers located
 * via DNS will take precedence over preferred domain controllers in
 * other sites.
 */

/*@{*/
#include <lw/types.h>
#include <lw/attrs.h>

/**
 * @brief Server address
 */
typedef struct _LWNET_PLUGIN_SERVER_ADDRESS {
    /**
     * @brief Server's DNS name
     */
    LW_PSTR pszDnsName;
    /**
     * @brief Server's IP address
     */
    LW_PSTR pszIpAddress;
} LWNET_PLUGIN_SERVER_ADDRESS;

/**
 * @brief Server address pointer
 *
 * Pointer to an #LWNET_PLUGIN_SERVER_ADDRESS.
 */
typedef LWNET_PLUGIN_SERVER_ADDRESS* PLWNET_PLUGIN_SERVER_ADDRESS;

/**
 * @brief Plugin method table
 *
 * Primary interface/contract between the Netlogon service and a
 * plugin.
 */
typedef struct _LWNET_PLUGIN_INTERFACE LWNET_PLUGIN_INTERFACE;

/**
 * @brief Plugin method table pointer
 *
 * Pointer to an #LWNET_PLUGIN_INTERFACE.
 */
typedef LWNET_PLUGIN_INTERFACE* PLWNET_PLUGIN_INTERFACE;


/**
 * @brief Shutdown plugin method
 *
 * Method to shutdown the plugin.
 *
 * @param[in,out] pInterface Plugin interface pointer.
 */
typedef LW_VOID (*LWNET_PLUGIN_CLEANUP_CALLBACK)(
    LW_IN LW_OUT PLWNET_PLUGIN_INTERFACE pInterface
    );

/**
 * @brief Get domain controller list method
 *
 * Method to get a list of domain controllers.
 *
 * Note that dwDsFlags can safely be ignored in a typical plugin.  The site
 * is typically irrelevant if the plugin wants to just return a hardcoded
 * list for a domain.  As far as the domain name, this is up to the plugin
 * depending on the desired semantics for the preferred DC list.  The plugin
 * could just ignore it, but that might cause network traffic if a list
 * of DCs is returned that does not apply for a domain.
 *
 * @param[in] pInterface Plugin interface pointer.
 * @param[in] pszDnsDomainName DNS name of the domain.
 * @param[in] pszSiteName Optional, site name.
 * @param[in] dwDsFlags   DsGetDcName flags.
 * @param[out] ppDcArray  Set to an array of domain controllers.
 * @param[out] pdwDcCount Set to the number of domain controllers in the array.
 *
 * @retval LW_ERROR_SUCCESS Success.
 * @retval NERR_DCNotFound No domain controllers were found.
 * @retval ... Error.
 */
typedef LW_DWORD (*LWNET_PLUGIN_GET_DC_LIST_CALLBACK)(
    LW_IN PLWNET_PLUGIN_INTERFACE pInterface,
    LW_IN LW_PCSTR pszDnsDomainName,
    LW_IN LW_OPTIONAL LW_PCSTR pszSiteName,
    LW_IN LW_DWORD dwDsFlags,
    LW_OUT PLWNET_PLUGIN_SERVER_ADDRESS* ppDcArray,
    LW_OUT LW_PDWORD pdwDcCount
    );

/**
 * @brief Free domain controller list method
 *
 * Method to free a list of domain controllers.
 *
 * @param[in] pInterface Plugin interface pointer.
 * @param[in,out] pDcArray Array of domain controllers.
 * @param[in] dwDcCount    The number of domain controllers in the array.
 */
typedef LW_VOID (*LWNET_PLUGIN_FREE_DC_LIST_CALLBACK)(
    LW_IN PLWNET_PLUGIN_INTERFACE pInterface,
    LW_IN LW_OUT PLWNET_PLUGIN_SERVER_ADDRESS pDcArray,
    LW_IN LW_DWORD dwDcCount
    );

/**
 * @brief Plugin method table
 *
 * Primary interface/contract between the Netlogon service and a
 * plugin.
 */
struct _LWNET_PLUGIN_INTERFACE {
    /**
     * @brief Shutdown plugin method
     */
    LWNET_PLUGIN_CLEANUP_CALLBACK Cleanup;
    /**
     * @brief Get domain controller list method
     */
    LWNET_PLUGIN_GET_DC_LIST_CALLBACK GetDcList;
    /**
     * @brief Free domain controller list method
     */
    LWNET_PLUGIN_FREE_DC_LIST_CALLBACK FreeDcList;
};

/**
 * @brief Plugin version number
 */
#define _LWNET_PLUGIN_VERSION 1

/**
 * @brief Plugin version
 */
#define LWNET_PLUGIN_VERSION \
    ((DWORD) (sizeof(LWNET_PLUGIN_INTERFACE) << 16) | _LWNET_PLUGIN_VERSION)

/**
 * @brief Plugin initial entry point
 *
 * Function prototype of the main entry point within the
 * preferred domain controller plugin.  The Netlogon service
 * invokes this function after dynamically loading the
 * provider.  The plugin is expected to return an interface
 * table of methods which are called during various phases
 * of domain controller selection by Netlogon.
 *
 * @param[in] dwVersion The plugin version (#LWNET_PLUGIN_VERSION).
 * @param[out] ppInterface Set to the interface table.
 *
 * @return A plugin-specific error code.
 */
typedef LW_DWORD (*LWNET_PLUGIN_GET_INTERFACE_CALLBACK)(
    LW_IN LW_DWORD dwVersion,
    LW_OUT PLWNET_PLUGIN_INTERFACE* ppInterface
    );

/**
 * @brief Plugin initial entry point name
 *
 * Name of the symbol that Netlogon will search for in the plugin
 * after dynamically loading it.  The plugin must export this
 * symbol which should have a function prototype corresponding to
 * the signature of #LWNET_PLUGIN_GET_INTERFACE_CALLBACK.
 */
#define LWNET_PLUGIN_GET_INTERFACE_FUNCTION_NAME "LWNetPluginGetInterface"

/*@}*/

#endif /* __LWNET_PLUGIN_H__ */
