/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright 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 . * * 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@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * lwnet-plugin.c * * Abstract: * * Likewise Site Manager * * Plugin Support * * Authors: Gerald Carter * Danilo Almeida */ #include "includes.h" #include "lwnet-plugin.h" // // Plugin State // typedef struct _LWNET_PLUGIN_STATE { PSTR pszLibraryPath; PVOID LibraryHandle; PLWNET_PLUGIN_INTERFACE pInterface; } LWNET_PLUGIN_STATE, *PLWNET_PLUGIN_STATE; static LWNET_PLUGIN_STATE gLWNetPluginState; // // Local Prototypes // static DWORD LWNetPreferredDcPluginBuildServerArray( IN PLWNET_PLUGIN_SERVER_ADDRESS pDcArray, IN DWORD dwDcCount, OUT PDNS_SERVER_INFO* ppServerArray, OUT PDWORD pdwServerCount ); // // Function Implementations // DWORD LWNetInitializePlugin( IN PCSTR pszPath ) { DWORD dwError = 0; PCSTR pszError = NULL; LWNET_PLUGIN_GET_INTERFACE_CALLBACK pInitializeCallback = NULL; LWNetCleanupPlugin(); if (!pszPath) { LWNET_LOG_VERBOSE("No plugin configured"); dwError = 0; goto error; } LWNET_LOG_VERBOSE("Loading plugin '%s'", pszPath); dwError = LWNetAllocateString(pszPath, &gLWNetPluginState.pszLibraryPath); BAIL_ON_LWNET_ERROR(dwError); dlerror(); gLWNetPluginState.LibraryHandle = dlopen(gLWNetPluginState.pszLibraryPath, RTLD_NOW | RTLD_GLOBAL); if (!gLWNetPluginState.LibraryHandle) { int error = errno; pszError = dlerror(); LWNET_LOG_ERROR("Failed to load %s (%s (%d))", gLWNetPluginState.pszLibraryPath, LWNET_SAFE_LOG_STRING(pszError), error); dwError = ERROR_DLL_INIT_FAILED; BAIL_ON_LWNET_ERROR(dwError); } dlerror(); pInitializeCallback = (LWNET_PLUGIN_GET_INTERFACE_CALLBACK) dlsym(gLWNetPluginState.LibraryHandle, LWNET_PLUGIN_GET_INTERFACE_FUNCTION_NAME); if (!pInitializeCallback) { pszError = dlerror(); LWNET_LOG_ERROR("Failed to load " LWNET_PLUGIN_GET_INTERFACE_FUNCTION_NAME " function from %s (%s)", gLWNetPluginState.pszLibraryPath, LWNET_SAFE_LOG_STRING(pszError)); dwError = ERROR_DLL_INIT_FAILED; BAIL_ON_LWNET_ERROR(dwError); } dwError = pInitializeCallback( LWNET_PLUGIN_VERSION, &gLWNetPluginState.pInterface); BAIL_ON_LWNET_ERROR(dwError); error: if (dwError) { LWNetCleanupPlugin(); } return dwError; } VOID LWNetCleanupPlugin( ) { if (gLWNetPluginState.pInterface) { gLWNetPluginState.pInterface->Cleanup(gLWNetPluginState.pInterface); gLWNetPluginState.pInterface = NULL; } if (gLWNetPluginState.LibraryHandle) { int err = dlclose(gLWNetPluginState.LibraryHandle); if (err) { LWNET_LOG_ERROR("Failed to dlclose() %s", gLWNetPluginState.pszLibraryPath); } gLWNetPluginState.LibraryHandle = NULL; } LWNET_SAFE_FREE_STRING(gLWNetPluginState.pszLibraryPath); } DWORD LWNetGetPreferredDcList( IN PCSTR pszDnsDomainName, IN OPTIONAL PCSTR pszSiteName, IN DWORD dwDsFlags, OUT PDNS_SERVER_INFO* ppServerArray, OUT PDWORD pdwServerCount ) { DWORD dwError = 0; PLWNET_PLUGIN_SERVER_ADDRESS pDcArray = NULL; DWORD dwDcCount = 0; PDNS_SERVER_INFO pServerArray = NULL; DWORD dwServerCount = 0; if (!gLWNetPluginState.pInterface) { dwError = NERR_DCNotFound; BAIL_ON_LWNET_ERROR(dwError); } dwError = gLWNetPluginState.pInterface->GetDcList( gLWNetPluginState.pInterface, pszDnsDomainName, pszSiteName, dwDsFlags, &pDcArray, &dwDcCount); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetPreferredDcPluginBuildServerArray( pDcArray, dwDcCount, &pServerArray, &dwServerCount); BAIL_ON_LWNET_ERROR(dwError); error: if (dwError) { LWNET_SAFE_FREE_MEMORY(pServerArray); dwServerCount = 0; } if (pDcArray) { gLWNetPluginState.pInterface->FreeDcList( gLWNetPluginState.pInterface, pDcArray, dwDcCount); } *ppServerArray = pServerArray; *pdwServerCount = dwServerCount; return dwError; } static DWORD LWNetPreferredDcPluginBuildServerArray( IN PLWNET_PLUGIN_SERVER_ADDRESS pDcArray, IN DWORD dwDcCount, OUT PDNS_SERVER_INFO* ppServerArray, OUT PDWORD pdwServerCount ) { DWORD dwError = 0; PDNS_SERVER_INFO pServerArray = NULL; DWORD dwServerCount = 0; DWORD i = 0; DWORD dwStringSize = 0; DWORD dwRequiredSize = 0; PSTR pStringLocation = NULL; if (dwDcCount < 1) { dwError = NERR_DCNotFound; BAIL_ON_LWNET_ERROR(dwError); } for (i = 0; i < dwDcCount; i++) { PLWNET_PLUGIN_SERVER_ADDRESS pDcInfo = &pDcArray[i]; if (!pDcInfo->pszDnsName) { LWNET_LOG_ERROR("Missing DNS name for preferred DC plugin " "at entry number %u (IP = '%s')", i, LWNET_SAFE_LOG_STRING(pDcInfo->pszIpAddress)); dwError = ERROR_INTERNAL_ERROR; BAIL_ON_LWNET_ERROR(dwError); } if (!pDcInfo->pszIpAddress) { LWNET_LOG_ERROR("Missing IP address for preferred DC plugin " "at entry number %u (name = '%s')", i, LWNET_SAFE_LOG_STRING(pDcInfo->pszDnsName)); dwError = ERROR_INTERNAL_ERROR; BAIL_ON_LWNET_ERROR(dwError); } dwStringSize += strlen(pDcInfo->pszDnsName) + 1; dwStringSize += strlen(pDcInfo->pszIpAddress) + 1; } dwServerCount = dwDcCount; 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)); for (i = 0; i < dwDcCount; i++) { PLWNET_PLUGIN_SERVER_ADDRESS pDcInfo = &pDcArray[i]; PSTR source; // Copy the strings into the buffer pServerArray[i].pszName = pStringLocation; for (source = pDcInfo->pszDnsName; source[0]; source++) { pStringLocation[0] = source[0]; pStringLocation++; } pStringLocation[0] = source[0]; pStringLocation++; pServerArray[i].pszAddress = pStringLocation; for (source = pDcInfo->pszIpAddress; source[0]; source++) { pStringLocation[0] = source[0]; pStringLocation++; } pStringLocation[0] = source[0]; pStringLocation++; } // 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; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */