/* 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 2004-2008
* 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
*/
#include "domainjoin.h"
#ifdef HAVE_TIME_H
#include
#endif
#ifdef HAVE_SYS_TIME_H
#include
#endif
#define GCE(x) GOTO_CLEANUP_ON_CENTERROR((x))
CENTERROR GetServerTime(
PCSTR pszDCName,
time_t *result
)
{
CENTERROR ceError = CENTERROR_SUCCESS;
PSTR netOutput = NULL;
PSTR netCommand = NULL;
PSTR escapedDC = NULL;
PSTR intParseEnd;
GCE(ceError = CTEscapeString(pszDCName, &escapedDC));
GCE(ceError = CTAllocateStringPrintf(&netCommand,
"%s/bin/lwinet time seconds -S %s", PREFIXDIR, escapedDC));
ceError = CTCaptureOutput(netCommand, &netOutput);
if(!CENTERROR_IS_OK(ceError))
GCE(ceError = CENTERROR_DOMAINJOIN_LWINET_TIME_FAILED);
*result = strtoul(netOutput, &intParseEnd, 10);
if(*intParseEnd != '\0' && !isspace((char)*intParseEnd))
{
DJ_LOG_ERROR("Unable to parse lwinet time output '%s'", netOutput);
GCE(ceError = CENTERROR_DOMAINJOIN_LWINET_TIME_FAILED);
}
cleanup:
CT_SAFE_FREE_STRING(netOutput);
CT_SAFE_FREE_STRING(netCommand);
CT_SAFE_FREE_STRING(escapedDC);
return ceError;
}
CENTERROR
DJSetTime(time_t timesec)
{
BOOLEAN timeset = FALSE;
#if !defined(HAVE_CLOCK_SETTIME) && !defined(HAVE_SETTIMEOFDAY)
#error Either clock_settime or settimeofday is needed
#endif
#ifdef HAVE_CLOCK_SETTIME
struct timespec systemspec;
#endif
#if HAVE_SETTIMEOFDAY
struct timeval systemval;
#endif
long long readTime = -1;
#ifdef HAVE_CLOCK_SETTIME
memset(&systemspec, 0, sizeof(systemspec));
systemspec.tv_sec = timesec;
#endif
#if HAVE_SETTIMEOFDAY
memset(&systemval, 0, sizeof(systemval));
systemval.tv_sec = timesec;
#endif
#ifdef HAVE_CLOCK_SETTIME
if(!timeset)
{
if(clock_settime(CLOCK_REALTIME, &systemspec) == -1)
{
DJ_LOG_INFO("Setting time with clock_settime failed %d", errno);
}
else
{
DJ_LOG_INFO("Setting time with clock_settime worked");
timeset = TRUE;
}
}
#endif
#ifdef HAVE_SETTIMEOFDAY
if(!timeset)
{
if(settimeofday(&systemval, NULL) == -1)
{
DJ_LOG_INFO("Setting time with settimeofday failed %d", errno);
}
else
{
DJ_LOG_INFO("Setting time with settimeofday worked");
timeset = TRUE;
}
}
#endif
if(!timeset)
{
DJ_LOG_ERROR("Couldn't find a method to set the time with");
return CENTERROR_DOMAINJOIN_TIME_NOT_SET;
}
//Verify the clock got set
timeset = FALSE;
#ifdef HAVE_CLOCK_GETTIME
if(!timeset && clock_gettime(CLOCK_REALTIME, &systemspec) >= 0)
{
timeset = TRUE;
readTime = systemspec.tv_sec;
}
#endif
#ifdef HAVE_GETTIMEOFDAY
if(!timeset && gettimeofday(&systemval, NULL) >= 0)
{
timeset = TRUE;
readTime = systemval.tv_sec;
}
#endif
if(!timeset)
return CTMapSystemError(errno);
//Make sure the time is now within 5 seconds of what we set
if(labs(readTime - timesec) > 5)
{
DJ_LOG_ERROR("Attempted to set time to %ld, but it is now %ld.", timesec, readTime);
return CENTERROR_DOMAINJOIN_TIME_NOT_SET;
}
return CENTERROR_SUCCESS;
}
CENTERROR
DJSyncTimeToDC(
PCSTR pszDCName,
int allowedDrift
)
{
CENTERROR ceError = CENTERROR_SUCCESS;
time_t serverTime;
time_t localTime;
GCE(ceError = GetServerTime(pszDCName, &serverTime));
if(time(&localTime) == (time_t)-1)
{
GCE(ceError = CTMapSystemError(errno));
}
DJ_LOG_INFO("Server time is %ld. Local time is %ld.", serverTime, localTime);
if(labs(serverTime - localTime) > labs(allowedDrift))
{
//Got to sync the time
GCE(ceError = DJSetTime(serverTime));
}
cleanup:
return ceError;
}