/* sntpcLib.c - Simple Network Time Protocol (SNTP) client library */
/* Copyright 1984-1997 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01j,16mar99,spm doc: removed references to configAll.h (SPR #25663)
01e,14dec97,jdi doc: cleanup.
01d,10dec97,kbw making man page changes
01c,27aug97,spm corrections for man page generation
01b,15jul97,spm code cleanup, documentation, and integration; entered in
source code control
01a,24may97,kyc written
*/
/*
DESCRIPTION
This library implements the client side of the Simple Network Time
Protocol (SNTP), a protocol that allows a system to maintain the
accuracy of its internal clock based on time values reported by one
or more remote sources. The library is included in the VxWorks image
if INCLUDE_SNTPC is defined at the time the image is built.
USER INTERFACE
The sntpcTimeGet() routine retrieves the time reported by a remote source and
converts that value for POSIX-compliant clocks. The routine will either send a
request and extract the time from the reply, or it will wait until a message is
received from an SNTP/NTP server executing in broadcast mode.
INCLUDE FILES: sntpcLib.h
SEE ALSO: clockLib, RFC 1769
*/
/* includes */
#include "vxWorks.h"
#include "sysLib.h"
#include "ioLib.h"
#include "inetLib.h"
#include "hostLib.h"
#include "sockLib.h"
#include "errnoLib.h"
#include "tasklib.h"
#include "sntpcLib.h"
#include "lstlib.h"
#include "msgqlib.h"
#include "config.h"
#include "clitypedef.h"
/* globals */
LIST *gptSntpClientStatList;
u_short sntpcPort;
ulong_t gulSntpListenSwitch=ERROR;
ulong_t gulSntpServerSwitch=ERROR;
ulong_t gulSntpServerAddress=0xe0000101;
char *gpcSntpcServerAddress=NULL;
/* forward declarations */
struct timespec gtLastCurrTime ;
#ifdef INCLUDE_CNLC_SNTPC
LOCAL STATUS sntpcListen (u_int, struct timespec *);
LOCAL STATUS sntpcFetch (struct in_addr *, u_int, struct timespec *);
LOCAL STATUS sntpClientListenTask();
/*******************************************************************************
*
* sntpcInit - set up the SNTP client
*
* This routine is called to link the SNTP client module into the VxWorks
* image. It assigns the UDP source and destination port according to the
* corresponding SNTP_PORT setting.
*
* RETURNS: OK, always.
*
* ERRNO: N/A
*
* NOMANUAL
*/
STATUS sntpcInit
(
u_short port /* UDP source/destination port */
)
{
STATUS rc=OK;
STATUS sntpValue=OK;
ulong_t ulAddress;
ulong_t ulOperVal=OK;
sntpcPort = htons (port);
gptSntpClientStatList=malloc(sizeof(LIST));
if(gptSntpClientStatList==NULL)
return ERROR;
lstInit(gptSntpClientStatList);
sntpValue=OK;
sntpcSetConfig(SNTPC_LISTEN,&sntpValue);
sntpValue=ERROR;
sntpcSetConfig(SNTPC_LISTEN,&sntpValue);
ulAddress=inet_addr("192.168.8.20");
sntpcSetConfig(SNTPC_ADDRESS, &ulAddress);
sntpcSetConfig(SNTPC_SWITCH, &ulOperVal);
rc = taskSpawn ("tSntpCLsn", sntpClientListenTaskpriority, sntpClientListenTaskOptions,
sntpClientListenTaskStackSize, (FUNCPTR) sntpClientListenTask,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return (rc);
}
/*******************************************************************************
*
* sntpcFractionToNsec - convert time from the NTP format to POSIX time format
*
* This routine converts the fractional part of the NTP timestamp format to a
* value in nanoseconds compliant with the POSIX clock. While the NTP time
* format provides a precision of about 200 pico-seconds, rounding error in the
* conversion routine reduces the precision to tenths of a micro-second.
*
* RETURNS: Value for struct timespec corresponding to NTP fractional part
*
* ERRNO: N/A
*
* INTERNAL
*
* Floating-point calculations can't be used because some boards (notably
* the SPARC architectures) disable software floating point by default to
* speed up context switching. These boards abort with an exception when
* floating point operations are encountered.
*
* NOMANUAL
*/
LOCAL ULONG sntpcFractionToNsec
(
ULONG sntpFraction /* base 2 fractional part of the NTP timestamp */
)
{
ULONG factor = 0x8AC72305; /* Conversion factor from base 2 to base 10 */
ULONG divisor = 10; /* Initial exponent for mantissa. */
ULONG mask = 1000000000; /* Pulls digits of factor from left to right. */
int loop;
ULONG nsec = 0;
BOOL shift = FALSE; /* Shifted to avoid overflow? */
/*
* Adjust large values so that no intermediate calculation exceeds
* 32 bits. (This test is overkill, since the fourth MSB can be set
* sometimes, but it's fast).
*/
if (sntpFraction & 0xF0000000)
{
sntpFraction /= 10;
shift = TRUE;
}
/*
* In order to increase portability, the following conversion avoids
* floating point operations, so it is somewhat obscure.
*
* Incrementing the NTP fractional part increases the corresponding
* decimal value by 2^(-32). By interpreting the fractional part as an
* integer representing the number of increments, the equivalent decimal
* value is equal to the product of the fractional part and 0.2328306437.
* That value is the mantissa for 2^(-32). Multiplying by 2.328306437E-10
* would convert the NTP fractional part into the equivalent in seconds.
*
* The mask variable selects each digit from the factor sequentially, and
* the divisor shifts the digit the appropriate number of decimal places.
* The initial value of the divisor is 10 instead of 1E10 so that the
* conversion produces results in nanoseconds, as required by POSIX clocks.
*/
for (loop = 0; loop < 10; loop++) /* Ten digits in mantissa */
{
nsec += sntpFraction * (factor/mask)/divisor; /* Use current digit. */
factor %= mask; /* Remove most significant digit from the factor. */
mask /= 10; /* Reduce length of mask by one. */
divisor *= 10; /* Increase preceding zeroes by one. */
}
/* Scale result upwards if value was adjusted before processing. */
if (shift)
nsec *= 10;
return (nsec);
}
/*******************************************************************************
*
* sntpcTimeGet - retrieve the current time from a remote source
*
* This routine stores the current time as reported by an SNTP/NTP server in
* the location indicated by <pCurrTime>. The reported time is first converted
* to the elapsed time since January 1, 1970, 00:00, GMT, which is the base value
* used by UNIX systems. If <pServerAddr> is NULL, the routine listens for
* messages sent by an SNTP/NTP server in broadcast mode. Otherwise, this
* routine sends a request to the specified SNTP/NTP server and extracts the
* reported time from the reply. In either case, an error is returned if no
* message is received within the interval specified by <timeout>. Typically,
* SNTP/NTP servers operating in broadcast mode send update messages every 64
* to 1024 seconds. An infinite timeout value is specified by WAIT_FOREVER.
*
* RETURNS: OK, or ERROR if unsuccessful.
*
* ERRNO:
* S_sntpcLib_INVALID_PARAMETER
* S_sntpcLib_INVALID_ADDRESS
*/
STATUS sntpcTimeGet
(
char * pServerAddr, /* server IP address or hostname */
u_int timeout, /* timeout interval in ticks */
struct timespec * pCurrTime /* storage for retrieved time value */
)
{
STATUS result;
struct in_addr target;
if (pCurrTime == NULL || (timeout < 0 && timeout != WAIT_FOREVER))
{
errnoSet (S_sntpcLib_INVALID_PARAMETER);
return (ERROR);
}
if (pServerAddr == NULL)
评论11
最新资源