diff options
author | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
---|---|---|
committer | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
commit | ae1e4e08a1005a0c487f03ba189d7536e7fdcba6 (patch) | |
tree | f1c296f8a966a9a39876b0e98e16d9c5da1776dd /ecos/packages/net/sntp | |
parent | f157da5337118d3c5cd464266796de4262ac9dbd (diff) |
Added the OS files
Diffstat (limited to 'ecos/packages/net/sntp')
-rw-r--r-- | ecos/packages/net/sntp/current/ChangeLog | 96 | ||||
-rw-r--r-- | ecos/packages/net/sntp/current/cdl/sntp.cdl | 126 | ||||
-rwxr-xr-x | ecos/packages/net/sntp/current/doc/sntp.sgml | 205 | ||||
-rw-r--r-- | ecos/packages/net/sntp/current/include/sntp.h | 68 | ||||
-rw-r--r-- | ecos/packages/net/sntp/current/src/sntp.c | 548 | ||||
-rw-r--r-- | ecos/packages/net/sntp/current/tests/sntp1.c | 188 |
6 files changed, 1231 insertions, 0 deletions
diff --git a/ecos/packages/net/sntp/current/ChangeLog b/ecos/packages/net/sntp/current/ChangeLog new file mode 100644 index 0000000..92b8631 --- /dev/null +++ b/ecos/packages/net/sntp/current/ChangeLog @@ -0,0 +1,96 @@ +2009-03-09 John Dallaway <john@dallaway.org.uk> + + * cdl/sntp.cdl: Reference test executable filenames for compatibility + with the eCos Configuration Tool. + +2006-11-08 Andre Mas <andrejohn.mas@gmail.com> + + * src/sntp.c: Removed optional KeyIdentifer and MessageDigest + fields, which weren't being used, and caused certain servers + not to respond when these fields were included with null values. + +2005-07-30 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/sntp.c: Compiler warning fixes. + +2004-02-26 Yuxin Jiang <yjiang@matrics.com> + + * src/sntp.c: When a new server is added to the list of unicast + servers don't wait 30 minutes before querying it for the first + time. + +2003-10-15 Dan Jakubiec <djakubiec@yahoo.com> + Andrew Lunn <andrew.lunn@ascom.ch> + + * src/sntp.c: Added DHCP support for SNTP unicast mode. + * src/sntp.cdl: Added DHCP support for SNTP unicast mode. + * src/sntp.h: Removed UDP port constant. + * src/sntp1.c: Added test code for SNTP unicast mode. + * src/sntp.sgml: Added documentation for SNTP unicast mode. + +2003-09-29 Dan Jakubiec <firstname.lastname@systech.com> + + * src/sntp.c: Added support for SNTP unicast mode. + * src/sntp.h: Added support for SNTP unicast mode. + * src/sntp.cdl: Added support for SNTP unicast mode. + +2003-05-19 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/sntp.c: Added support for IPv6 multicast NTP packets. + +2003-04-09 Michael Checky <Michael_Checky@Thermoking.com> + + * src/sntp.c: In function sntp_fn() changed 'version' to + 'new_srv.version' in the CYG_TRACE1() call. + +2003-02-25 Jonathan Larmour <jifl@eCosCentric.com> + + * include/sntp.h: Include <cyg/infra/cyg_type.h> for __externC. + +2003-02-25 Gary Thomas <gary@mlbassoc.com> + + * tests/sntp1.c (net_test): Strip the trailing "\n" making it more + readable. + +2003-02-25 Andrew Lunn <andrew.lunn@ascom.ch> + + * doc/sntp.sgml: Added license banner and added missing </para> + * include/sntp.h (cyg_sntp_start): C++ safe + * cdl/sntp.cdl: Stricture requirements and same description as in + ecos.db. Only build the test if CYGPKH_NET_BUILD_HW_TESTS + * tests/sntp1.c (net_test): Check we have the required + packages. Require the time to be within 90 days of the build + date of the test + + +2003-02-16 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/sntp.c: First import of SNTP client code. + * include/sntp.c: Ditto + * test/sntp1.c: Ditto + * cdl/sntp.cdl: Ditto + * doc/sntp.sgml: Ditto + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003, 2009 Free Software Foundation, Inc. +// +// 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 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, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/ecos/packages/net/sntp/current/cdl/sntp.cdl b/ecos/packages/net/sntp/current/cdl/sntp.cdl new file mode 100644 index 0000000..8d2ec7c --- /dev/null +++ b/ecos/packages/net/sntp/current/cdl/sntp.cdl @@ -0,0 +1,126 @@ +# ==================================================================== +# +# sntp.cdl +# +# Simple Network Time Protocol +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003, 2009 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Andrew Lunn +# Contributors: +# Date: 2003-02-11 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_NET_SNTP { + display "Simple Network Time Protocol Client (SNTP)" + description " + This package provides a SNTP client which can recieve broadcast time + information and set the system clock." + doc ref/net-sntp.html + include_dir cyg/sntp + + requires CYGPKG_NET + requires CYGPKG_LIBC_TIME + requires CYGSEM_LIBC_TIME_TIME_WORKING + requires CYGSEM_LIBC_TIME_SETTIME_WORKING + compile sntp.c + + cdl_component CYGPKG_NET_SNTP_UNICAST { + display "Enable SNTP client unicast support" + flavor bool + default_value 0 + description " + This option enables SNTP unicast mode in + for the SNTP client. This mode will send + SNTP requests to NTP/SNTP servers in + addition to listening for SNTP broadcasts." + + cdl_option CYGNUM_NET_SNTP_UNICAST_MAXDHCP { + display "Maximum number of NTP servers to use from DHCP" + flavor booldata + requires CYGPKG_NET_DHCP + legal_values 1 to 8 + default_value 2 + description " + This option specifies the maximum number of + NTP servers to get from DHCP. These servers + are used to configure the unicast SNTP client. + Disabling this option disables DHCP usage." + } + } + + cdl_component CYGPKG_NET_SNTP_OPTIONS { + display "SNTP support build options" + flavor none + no_define + + cdl_option CYGPKG_NET_SNTP_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the SNTP package. + These flags are used in addition + to the set of global flags." + } + + cdl_option CYGPKG_NET_SNTP_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the SNTP package. These flags are removed from + the set of global flags if present." + } + } + + cdl_option CYGPKG_NET_SNTP_TESTS { + display "sntp tests" + flavor data + no_define + calculated { CYGPKG_NET_BUILD_HW_TESTS ? "tests/sntp1" : "" } + } +} + +# ==================================================================== +# EOF sntp.cdl diff --git a/ecos/packages/net/sntp/current/doc/sntp.sgml b/ecos/packages/net/sntp/current/doc/sntp.sgml new file mode 100755 index 0000000..d778b3e --- /dev/null +++ b/ecos/packages/net/sntp/current/doc/sntp.sgml @@ -0,0 +1,205 @@ +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- sntp.sgml --> +<!-- --> +<!-- Simple Network Time Protocol Client --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 2003 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<PART ID="net-sntp-client"> +<TITLE>Simple Network Time Protocol Client</TITLE> +<PARTINTRO> +<PARA> +The SNTP package provides implementation of a client for RFC 2030, the +Simple Network Time Protocol (SNTP). The client listens for broadcasts +or IPv6 multicasts from an NTP server and uses the information received to +set the system clock. It can also be configured to send SNTP time +requests to specific NTP servers using SNTP's unicast mode. +</PARA> +</PARTINTRO> +<CHAPTER id="net-sntp"> +<TITLE>The SNTP Client</TITLE> +<SECT1 id="sntp-starting"> +<TITLE>Starting the SNTP client</TITLE> +<para> +The sntp client is implemented as a thread which listens for NTP +broadcasts and IPv6 multicasts, and optionally sends SNTP unicast +requests to specific NTP servers. This thread may be automatically +started by the system if it receives a list of (S)NTP servers from the +DHCP server and unicast mode is enabled. Otherwise it must be started +by the user application. The header file +<filename>cyg/sntp/sntp.h</filename> declares the function to be +called. The thread is then started by calling the function: +</para> +<programlisting> +void cyg_sntp_start(void); +</programlisting> +<para> +It is safe to call this function multiple times. Once started, the +thread will run forever. +</para> +</sect1> + +<sect1 id="net-sntp-operation"> +<title>What it does</title> +<para> +The SNTP client listens for NTP IPv4 broadcasts from any NTP servers, +or IPv6 multicasts using the address fe0x:0X::101, where X can be +2 (Link Local), 5 (Site-Local) or 0xe (Global). Such +packets contain a timestamp indicating the current time. The packet +also contains information about where the server is in the hierarchy +of time servers. A server at the root of the time server tree normally +has an atomic clock. Such a server is said to be at stratum 0. A time +server which is synchronised to a stratum 0 server is said to be at +stratum 1 etc. The client will accept any NTP packets from +servers using version 3 or 4 of the protocol. When receiving packets +from multiple servers, it will use the packets from the server with +the lowest stratum. However, if there are no packets from this server +for 10 minutes and another server is sending packets, the client will +change servers. +</para> +<para> +If SNTP unicast mode is enabled via the CYGPKG_NET_SNTP_UNICAST +option, the SNTP client can additionally be configured with a list +of specific NTP servers to query. The general algorithm is as follows: if +the system clock has not yet been set via an NTP time update, then +the client will send out NTP requests every 30 seconds to all +configured NTP servers. Once an NTP time update has been received, +the client will send out additional NTP requests every 30 minutes +in order to update the system clock. These requests are resent +every 30 seconds until a response is received. +</para> +<para> +The system clock in eCos is accurate to 1 second. The SNTP client will +change the system clock when the time difference with the received +timestamp is greater than 2 seconds. The change is made as a step. +</para> +</sect1> + +<sect1 id="net-sntp-unicast"> +<title>Configuring the unicast list of NTP servers</title> +<para> +If SNTP unicast mode is enabled via the CYGPKG_NET_SNTP_UNICAST +option, the SNTP client can be configured with a list of +NTP servers to contact for time updates. +</para> +<para> +By default, this list is configured with NTP server information +received from DHCP. The number of NTP servers that are extracted +from DHCP can be configured with the CYGOPT_NET_SNTP_UNICAST_MAXDHCP +option. This option can also be used to disable DHCP usage entirely. +</para> +<para> +The list of NTP servers can be manually configured with the following +API function. Note that manual configuration will override any +servers that were automatically configured by DHCP. But later +reconfigurations by DHCP will override manual configurations. Hence it +is not recommended to manually configure servers when +CYGOPT_NET_SNTP_UNICAST is enabled. +</para> +<programlisting> +#include <cyg/sntp/sntp.h> + +void cyg_sntp_set_servers(struct sockaddr *server_list, cyg_uint32 num_servers); +</programlisting> +<para> +This function takes an array of sockaddr structures specifying the +IP address and UDP port of each NTP server to query. Currently, +both IPv4 and IPv6 sockaddr structures are supported. The +num_servers argument specifies how many sockaddr's are contained +in the array. The server_list array must be maintained by the caller. +Once the array is registered with this function, it must not be +modified by the caller until it is replaced or unregistered +by another call to this function. +</para> +<para> +Calling this function with a server_list of NULL and a num_servers +value of 0 unregisters any previously configured server_list array. +</para> +<para> +Finally, note that if this function is called with a non-empty server +list, it will implicitly start the SNTP client if it has not already +been started (i.e. it will call cyg_sntp_start()). +</para> +</sect1> + +<sect1 id="net-sntp-warning"> +<title>Warning: timestamp wrap around</title> +<para> +The timestamp in the NTP packet is a 32bit integer which represents +the number of seconds after 00:00 01/01/1900. This 32bit number will +wrap around at 06:28:16 Feb 7 2036. At this point in time, the eCos +time will jump back to around 00:00:00 Jan 1 1900 when the next +NTP packet is received. +</para> +<para> +YOU HAVE BEEN WARNED! +</para> +</SECT1> +<sect1 id="net-sntp-testing"> +<title>The SNTP test program</title> +<para> +The SNTP package contains a simple test program. Testing an SNTP +client is not easy, so the test program should be considered as more a +proof of concept. It shows that an NTP packet has been received, +and is accurate to within a few days. +</para> +<para> +The test program starts the network interfaces using the standard +call. It then starts the SNTP thread. A loop is then entered printing +the current system time every second for two minutes. When the client +receives an NTP packet the time will jump from 1970 to hopefully the +present day. Once the two minutes have expired, two simple tests are +made. If the time is still less than 5 minutes since 00:00:00 +01/01/1970 the test fails. This indicates no NTP messages have +been received. Check that the server is actually sending packet, using +the correct port (123), correct IPv6 multicast address, and at a +sufficiently frequent rate that the +target has a chance to receive a message within the 2 minute +interval. If all this is correct, assume the target is broken. +</para> +<para> +The second test is that the current system time is compared with the +build time as reported by the CPP macro __DATE__. If the build date is +in the future relative to the system time, the test fails. If the +build date is more than 90 days in the past relative to the system +time the test also fails. If such failures are seen, use walk-clock +time to verify the time printed during the test. If this seems correct +check the build date for the test. This is printed at startup. If all +else fails check that the computer used to build the test has the +correct time. +</para> +<para> +If SNTP unicast mode is enabled, the above tests are run twice. The +first time, the SNTP client is configured with NTP server addresses +from DHCP. The second time, unicast mode is disabled and only +multicasts are listened for. Note that the unicast test is partially +bogus in the sense that any multicast packet received will also make +the unicast test pass. To reduce the chance of this happening the +test will wait for a sorter time for replies. This is not ideal, but +it is the best that can be done with an automated test. +</para> +</SECT1> +</CHAPTER> +</PART> diff --git a/ecos/packages/net/sntp/current/include/sntp.h b/ecos/packages/net/sntp/current/include/sntp.h new file mode 100644 index 0000000..66576a2 --- /dev/null +++ b/ecos/packages/net/sntp/current/include/sntp.h @@ -0,0 +1,68 @@ +#ifndef CYGONCE_SNTP_SNTP_H +#define CYGONCE_SNTP_SNTP_H +//============================================================================= +// +// sntp.h +// +// SNTP - Simple Network Time Protocol +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): andrew.lunn +// Contributors: +// Date: 2003-02-11 +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/net_sntp.h> +#include <cyg/infra/cyg_type.h> + +// Multicast address used by IPv6 +#define IN6ADDR_NTP_MULTICAST \ + {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01 }}} + +/* Call this function to start the SNTP Client */ +__externC void +cyg_sntp_start(void); + +#ifdef CYGPKG_NET_SNTP_UNICAST +__externC void cyg_sntp_set_servers(struct sockaddr *server_list, cyg_uint32 num_servers); +#endif + +#endif diff --git a/ecos/packages/net/sntp/current/src/sntp.c b/ecos/packages/net/sntp/current/src/sntp.c new file mode 100644 index 0000000..303a8fd --- /dev/null +++ b/ecos/packages/net/sntp/current/src/sntp.c @@ -0,0 +1,548 @@ +//============================================================================= +// +// sntp.c +// +// Simple Network Time Protocol +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): andrew.lunn +// Contributors: +// Date: 2003-02-12 +// Description: Provides a Simple Network Time Protocol Client +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/system.h> +#include <pkgconf/net_sntp.h> +#include <network.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/cyg_trac.h> +#include <cyg/sntp/sntp.h> +#include <time.h> + +/* NTP/SNTPv4 Packet Format (RFC2030) */ +typedef struct +{ + cyg_uint32 Seconds; /* Since 00:00:00 Jan 01 1900 */ + cyg_uint32 Fraction; +} NTP_TIMESTAMP; + +typedef struct +{ + /* Control combines LeapIndicator, Version, and Mode */ + cyg_uint8 Control; + cyg_uint8 Stratum; + cyg_uint8 Poll; + cyg_uint8 Precision; + + cyg_uint32 RootDelay; + cyg_uint32 RootDispersion; + cyg_uint32 ReferenceIdentifier; + + NTP_TIMESTAMP ReferenceTimestamp; + NTP_TIMESTAMP OriginateTimestamp; + NTP_TIMESTAMP ReceiveTimestamp; + NTP_TIMESTAMP TransmitTimestamp; + +// cyg_uint32 KeyIdentifier; /* Optional */ +// cyg_uint8 MessageDigest[16]; /* Optional */ +} NTP_PACKET; +#define NTP_PACKET_MINLEN 48 /* Packet size - optional fields */ + +/* Leap Indicator Field [Bits 7:6] */ +#define NTP_LI_NOLEAP 0x00 +#define NTP_LI_61SECS 0x40 +#define NTP_LI_59SECS 0x80 +#define NTP_LI_ALARM 0xC0 + +/* Version Field [Bits 5:3] */ +#define NTP_VERSION_GET(pkt) ((((pkt)->Control)>>3)&0x7) +#define NTP_VERSION_SET(ver) (((ver)&0x7)<<3) + +/* Mode Field [Bits 2:0] */ +#define NTP_MODE_RESERVED 0 +#define NTP_MODE_SYMACTIVE 1 /* Symmetric Active */ +#define NTP_MODE_SYMPASSIVE 2 /* Symmetric Passive */ +#define NTP_MODE_CLIENT 3 +#define NTP_MODE_SERVER 4 +#define NTP_MODE_BROADCAST 5 +#define NTP_MODE_NTPCTRL 6 /* Reserved for NTP control message */ +#define NTP_MODE_PRIVATE 7 /* Reserved for private use */ +#define NTP_MODE_GET(pkt) (((pkt)->Control)&0x7) +#define NTP_MODE_SET(mode) ((mode)&0x7) + +/* Time Base Conversion Macros + * + * The NTP timebase is 00:00 Jan 1 1900. The local + * time base is 00:00 Jan 1 1970. Convert between + * these two by added or substracting 70 years + * worth of time. Note that 17 of these years were + * leap years. + */ +#define TIME_BASEDIFF ((((cyg_uint32)70*365 + 17) * 24*3600)) +#define TIME_NTP_TO_LOCAL(t) ((t)-TIME_BASEDIFF) +#define TIME_LOCAL_TO_NTP(t) ((t)+TIME_BASEDIFF) + + +struct sntp_srv_s { + struct sockaddr addr; + int stratum; + int version; + cyg_uint32 timestamp; +}; +static int sntp_initialized = 0; + + +#ifdef CYGPKG_NET_SNTP_UNICAST +/* When using SNTP unicast mode, sntp_servers + * points to an array of char pointers that + * specify NTP server addresses to send + * requests to. sntp_num_servers specifies + * the number of hostnames in the array. + */ +static struct sockaddr *sntp_servers = NULL; +static cyg_uint32 sntp_num_servers = 0; +static cyg_mutex_t sntp_mutex; +static time_t NextTimeUpdate = 0; + +/* SNTP Timeouts + * + * SNTP_WAITPERIOD is the number of seconds to wait + * before retransmitting unanswered NTP requests + * whenever we are due for an update. + * + * SNTP_UPDATEPERIOD is the number of seconds to wait + * after we get a good time update before we feel + * like we should re-synchronize again with the + * time server. + */ +#define SNTP_WAITPERIOD 10 /* Wait period in seconds */ +#define SNTP_UPDATEPERIOD (30*60) /* Update period in seconds */ + +#endif /* CYKPKG_NET_SNTP_UNICAST */ + +#ifndef CYGNUM_SNTP_STACK_SIZE +/* Use a stack size of at least CYGNUM_SNTP_STACK_SIZE_MIN, but not less than + * CYGNUM_HAL_STACK_SIZE_TYPICAL. + */ +#define CYGNUM_SNTP_STACK_SIZE_MIN 4096 +#if (CYGNUM_HAL_STACK_SIZE_TYPICAL < CYGNUM_SNTP_STACK_SIZE_MIN) +#define CYGNUM_SNTP_STACK_SIZE CYGNUM_SNTP_STACK_SIZE_MIN +#else +#define CYGNUM_SNTP_STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL +#endif +#endif /* CYGNUM_SNTP_STACK_SIZE */ + +/* Is the new server better than the current one? If its the same as + the current, its always better. If the stratum is lower its better. + If we have not heard from the old server for more than 10 minutes, + the new server is better. */ + +static int is_better(struct sntp_srv_s *newer, struct sntp_srv_s *old) { + + time_t last_time, diff; + + if (!memcmp(&newer->addr, &old->addr, newer->addr.sa_len)) return 1; + if (newer->stratum < old->stratum) return 1; + + if (old->timestamp != 0xffffffff) { + last_time = TIME_NTP_TO_LOCAL(old->timestamp); + + diff = time(NULL) - last_time; + if (diff > 600) return 1; + + return 0; + } + return 1; +} + +const struct in6_addr in6addr_ntp_multicast = IN6ADDR_NTP_MULTICAST; + +static void sntp_fn(cyg_addrword_t data) +{ + int fd; + int ret; + struct sockaddr_in local; + struct servent *serv; + NTP_PACKET ntp_pkt; + struct sntp_srv_s new_srv; + struct sntp_srv_s best_srv; + int mode; + socklen_t len; + time_t new_time, current_time, diff; + fd_set readfds; + int n; +#ifdef CYGPKG_NET_INET6 + int fd6 = -1; + struct ipv6_mreq mreq; + struct sockaddr_in6 local6; +#endif +#ifdef CYGPKG_NET_SNTP_UNICAST + int i; + struct timeval timeout; +#endif /* CYGPKG_NET_SNTP_UNICAST */ + struct timeval *ptimeout = NULL; + + memset(&best_srv,0xff,sizeof(best_srv)); + + fd = socket(AF_INET,SOCK_DGRAM,0); + CYG_ASSERT(-1 != fd,"Failed to open socket"); + + serv = getservbyname("ntp","udp"); + CYG_ASSERT(serv,"getservbyname(sntp,udp)"); + + memset(&local,0,sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = serv->s_port; + local.sin_addr.s_addr = INADDR_ANY; + + ret=bind(fd,(struct sockaddr *)&local,sizeof(local)); + CYG_ASSERT(0 == ret, "Bind failed"); + + n = fd; + +#ifdef CYGPKG_NET_INET6 + fd6 = socket(AF_INET6, SOCK_DGRAM,0); + CYG_ASSERT(-1 != fd,"Failed to open socket"); + mreq.ipv6mr_multiaddr = in6addr_ntp_multicast; + mreq.ipv6mr_interface = 0; + + /* Join the well-known NTP multicast groups. We will + * try to join the link-local, site-local, and global + * unicast groups. + * + * Note that we skip the node-local group since it + * doesn't make any sense to join that group. If we + * had an NTP server running on the local node, we + * wouldn't need to have an NTP client get the time + * from it! + */ +#ifdef CYGHWR_NET_DRIVER_ETH0 + // Link-Local + mreq.ipv6mr_multiaddr.s6_addr[1]=0x02; + mreq.ipv6mr_interface = if_nametoindex("eth0"); + if (mreq.ipv6mr_interface != 0 ) { + ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Link-Local eth0"); + } +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + // Link-Local + mreq.ipv6mr_multiaddr.s6_addr[1]=0x02; + mreq.ipv6mr_interface = if_nametoindex("eth1"); + if (mreq.ipv6mr_interface != 0 ) { + ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Link-Local eth1"); + } +#endif + + // Site-Local + mreq.ipv6mr_multiaddr.s6_addr[1]=0x05; + ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Site-Local"); + + // Global + mreq.ipv6mr_multiaddr.s6_addr[1]=0x0e; + ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Global"); + + memset(&local6,0,sizeof(local6)); + local6.sin6_family = AF_INET6; + local6.sin6_len = sizeof(local6); + local6.sin6_port = serv->s_port; + local6.sin6_addr = in6addr_any; + + ret = bind(fd6, (struct sockaddr *)&local6,sizeof(local6)); + CYG_ASSERT(0 == ret, "Bind6 failed"); + + n = (n > fd6 ? n : fd6); +#endif + + while (1) { + FD_ZERO(&readfds); + FD_SET(fd,&readfds); +#ifdef CYGPKG_NET_INET6 + FD_SET(fd6,&readfds); +#endif + +#ifdef CYGPKG_NET_SNTP_UNICAST + /* By default, we will let select() wait + * for SNTP_WAITPERIOD to receive a packet. This + * allows us to periodically wake up and check + * if new servers have been configured. However, + * if we are waiting to send an update request, + * we will set ptimeout to something more + * reasonable below. + */ + timeout.tv_sec = SNTP_WAITPERIOD; + timeout.tv_usec = 0; + ptimeout = &timeout; + + /* If we've already set the time, then + * check to see if it's time to try and + * update it. + */ + if (NextTimeUpdate != 0) + { + current_time = time(NULL); + if (current_time < NextTimeUpdate) + { + /* Set the select() timeout to wake us + * up when it's time to send more + * requests. + */ + timeout.tv_sec = (SNTP_WAITPERIOD > (NextTimeUpdate - current_time)? + (NextTimeUpdate - current_time):SNTP_WAITPERIOD); + } else { + /* It's already time for us to update our time */ + NextTimeUpdate = 0; + } + } + + /* If we need to update our time and we have + * a list of NTP servers, then send out some + * time requests. + */ + if (NextTimeUpdate == 0 && (sntp_num_servers > 0)) + { + /* Send an NTP request to each NTP server + * in our server list. Use version 3 + * for v3 and v4 compatibility. + */ + memset(&ntp_pkt, 0, sizeof(ntp_pkt)); + ntp_pkt.Control = + NTP_LI_NOLEAP | + NTP_MODE_SET(NTP_MODE_CLIENT) | + NTP_VERSION_SET(3); + + /* Send a request packet to each of our + * configured servers. + */ + cyg_mutex_lock(&sntp_mutex); + for (i = 0; i < sntp_num_servers; i++) + { + /* Send the request packet using the + * appropriate protocol. + */ + ntp_pkt.TransmitTimestamp.Seconds = + htonl(TIME_LOCAL_TO_NTP(time(NULL))); + if (sntp_servers[i].sa_family == AF_INET) + { + sendto(fd, &ntp_pkt, sizeof(ntp_pkt), 0, + &sntp_servers[i], sntp_servers[i].sa_len); +#ifdef CYGPKG_NET_INET6 + } else if (sntp_servers[i].sa_family == AF_INET6) { + sendto(fd6, &ntp_pkt, sizeof(ntp_pkt), 0, + &sntp_servers[i], sntp_servers[i].sa_len); +#endif + } + } + cyg_mutex_unlock(&sntp_mutex); + + /* Set the NextTimeUpdate so that we don't + * send any more requests until the next + * poll period. And we've already configured + * the select() timeout above to wait for + * replies. + */ + NextTimeUpdate = time(NULL) + SNTP_WAITPERIOD; + } +#endif /* CYGPKG_NET_SNTP_UNICAST */ + + ret = select(n+1, &readfds, NULL, NULL, ptimeout); + CYG_ASSERT(-1 != ret, "Select"); + +#ifdef CYGPKG_NET_SNTP_UNICAST + /* If we timed out, then try resending requests */ + if (ret == 0) + continue; +#endif /* CYGPKG_NET_SNTP_UNICAST */ + + len = sizeof(new_srv.addr); + if (FD_ISSET(fd,&readfds)) { + ret=recvfrom(fd,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); + } +#ifdef CYGPKG_NET_INET6 + if (FD_ISSET(fd6,&readfds)) { + ret=recvfrom(fd6,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); + } +#endif + CYG_ASSERT(0 < ret,"recvfrom"); + + /* We expect at least enough bytes to fill the buffer */ + if (ret < NTP_PACKET_MINLEN) + continue; + + new_srv.version = NTP_VERSION_GET(&ntp_pkt); + new_srv.stratum = ntp_pkt.Stratum; + new_srv.timestamp = ntohl(ntp_pkt.TransmitTimestamp.Seconds); + mode = NTP_MODE_GET(&ntp_pkt); + + /* Only support protocol versions 3 or 4 */ + if (new_srv.version < 3 || new_srv.version > 4) { + CYG_TRACE1(1, "Unsupported version of NTP. Version %d",new_srv.version); + continue; + } + + /* Only process broadcast and server packets */ + if (mode != NTP_MODE_BROADCAST && mode != NTP_MODE_SERVER) + continue; + + /* Is the packet from a better server than our current one */ + if (is_better(&new_srv,&best_srv)) { + best_srv = new_srv; + + /* Work out the difference between server and our time. + * TODO: Implement RFC2030 recommendations for + * calculating propagation delay between the client + * and server. + */ + new_time = TIME_NTP_TO_LOCAL(best_srv.timestamp); + current_time = time(NULL); + diff = current_time - new_time; + + if (diff < 0) + diff = -diff; + + if (diff > 2) + cyg_libc_time_settime(new_time); + } +#ifdef CYGPKG_NET_SNTP_UNICAST + NextTimeUpdate = time(NULL) + SNTP_UPDATEPERIOD; +#endif + } +} + +/* Start the SNTP server */ +void cyg_sntp_start(void) { + + static char sntp_stack[CYGNUM_SNTP_STACK_SIZE]; + static cyg_thread sntp_thread_data; + static cyg_handle_t sntp_handle; + + /* Only initialize things once */ + if (sntp_initialized) + return; + sntp_initialized = 1; + +#ifdef CYGPKG_NET_SNTP_UNICAST + /* Initialize the SNTP mutex */ + cyg_mutex_init(&sntp_mutex); +#endif + + cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY+1, + sntp_fn, // entry + 0, // entry parameter + "SNTP Client", // Name + &sntp_stack, // stack + sizeof(sntp_stack), // stack size + &sntp_handle, // Handle + &sntp_thread_data); // Thread data structure + + cyg_thread_resume(sntp_handle); +} + +#ifdef CYGPKG_NET_SNTP_UNICAST +/* + * FUNCTION cyg_sntp_set_servers + * + * DESCRIPTION + * Sets the list of SNTP/NTP servers to use + * for SNTP unicast requests. The list is + * specified as a list of sockaddr structures + * and can contain both IPv4 and IPv6 + * addresses and UDP port numbers. + * + * The server_list array must be maintained + * by the caller and must not be modified after + * it is registered by this function. The + * array can be unregistered by calling this + * function again with different parameters. + * + * NOTE: If cyg_sntp_start() has not been called + * already, and this function is called with a + * list of 1 or more servers, then cyg_sntp_start() + * will be called by this function to start the client. + * + * PARAMETERS + * server_list - Array of IPv4 and/or IPv6 sockaddr's + * num_servers - Number of sockaddr's in array (0 to disable) + * + * RETURN VALUES + * None + */ +void cyg_sntp_set_servers(struct sockaddr *server_list, + cyg_uint32 num_servers) +{ + /* If we haven't already started the SNTP client, then + * start it now. + */ + if (!sntp_initialized) + { + /* If we haven't started already and we don't + * have a list of servers, then don't start + * anything up. + */ + if (num_servers == 0) + return; + cyg_sntp_start(); + } + + /* Get the server list mutex */ + cyg_mutex_lock(&sntp_mutex); + + /* Record the new server list */ + sntp_num_servers = num_servers; + if (num_servers == 0) { + server_list = NULL; + } else { + /* reset the waiting time to force a new update <= SNTP_WAITPERIOD*/ + NextTimeUpdate = 0; + } + sntp_servers = server_list; + + /* Free the mutex */ + cyg_mutex_unlock(&sntp_mutex); +} +#endif /* CYGPKG_NET_SNTP_UNICAST */ + + + + diff --git a/ecos/packages/net/sntp/current/tests/sntp1.c b/ecos/packages/net/sntp/current/tests/sntp1.c new file mode 100644 index 0000000..ebef692 --- /dev/null +++ b/ecos/packages/net/sntp/current/tests/sntp1.c @@ -0,0 +1,188 @@ +//================================================================= +// +// sntp1.c +// +// Simple Network Time Protocol test 1 +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Andrew Lunn +// Contributors: +// Date: 2003-02-11 +// Description: Tests the sntp client +//####DESCRIPTIONEND#### + +#include <pkgconf/isoinfra.h> +#include <cyg/infra/testcase.h> + +#if defined(CYGINT_ISO_STDIO_FORMATTED_IO) && defined(CYGINT_ISO_STRING_STRFUNCS) +#include <network.h> +#include <time.h> +#include <cyg/sntp/sntp.h> +#include <stdio.h> + +#define SECONDSPERMINUTE (cyg_uint32)60 +#define SECONDSPERHOUR (cyg_uint32)(SECONDSPERMINUTE * 60) +#define SECONDSPERDAY (cyg_uint32)(SECONDSPERHOUR * 24) +#define SECONDSPERYEAR (cyg_uint32)(SECONDSPERDAY * 365) + +void +net_test(cyg_addrword_t param) +{ + int seconds; + time_t now, build_time; + struct tm tm={ 0,0,0,0,0,0,0,0,0 }; + int i, loop, waittime; + char month[4]; + char months[12][4] = { "Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" }; + char time_info[32]; + + CYG_TEST_INIT(); + + CYG_TEST_INFO("sntp1 test build " __DATE__); + + init_all_network_interfaces(); + + cyg_sntp_start(); + + /* The SNTP client will try to obtain NTP time updates by + * listening for multicasts. It can also be configured + * to send unicast requests to specific NTP servers. By + * default, unicast NTP servers are obtained from DHCP. + * + * If unicast mode is enabled, the run the test loop twice. + * The first time, unicast requests will be sent. The + * second time, the unicast list will be unconfigured and + * the client will listen only for multicasts. + * + * Note that this test is somewhat bogus since multicast + * NTP packets will actually allow both test loops to + * pass. But it is the best we can do for the automated + * test, so consider this more of a usage example. + */ +#ifdef CYGPKG_NET_SNTP_UNICAST + loop = 2; +#else + loop = 1; +#endif + while (loop-- > 0) + { + if (loop == 1) { + CYG_TEST_INFO("Testing SNTP unicast mode."); + waittime=14; + } else { + CYG_TEST_INFO("Testing SNTP multicast mode."); + waittime=20; + } + for (seconds = waittime; seconds > 0; seconds--) { + now = time(NULL); + ctime_r(&now, time_info); + time_info[strlen(time_info)-1] = '\0'; // Strip \n + CYG_TEST_INFO(time_info); + cyg_thread_delay(100); + } + + now = time(NULL); + + if ( now < (5 * 60)) { + CYG_TEST_FAIL_FINISH("Nothing recieved from the SNTP server"); + } else { + + i=sscanf(__DATE__, "%s %d %d",month,&tm.tm_mday,&tm.tm_year); + CYG_ASSERT(3==i,"sscanf did not return enough results"); + for (i=0; i < 12; i++) { + if (!strcmp(month,months[i])) + break; + } + tm.tm_mon = i; + tm.tm_year -= 1900; + + build_time = mktime(&tm); + CYG_ASSERT(-1 != build_time,"mktime returned -1"); + + if (build_time > time(NULL)) { + CYG_TEST_FAIL_FINISH("Build time is ahead of SNTP time"); + } else { + if ((build_time + 60 * 60 * 24 * 90) < time(NULL)) { + CYG_TEST_FAIL_FINISH("Build time is more than 90 days old"); + } + } + } + +#ifdef CYGPKG_NET_SNTP_UNICAST + /* For the second pass of the test, we set the time + * back to epoch and unconfigure the list of SNTP + * unicast servers. This will test non-unicast mode. + */ + cyg_sntp_set_servers(NULL, 0); + cyg_libc_time_settime(0); +#endif + } + CYG_TEST_PASS_FINISH("sntp1 test is complete"); +} + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL*2) +static char thread_stack[STACK_SIZE]; +static cyg_thread thread_data; +static cyg_handle_t thread_handle; + +void +cyg_user_start(void) +{ + // Create a main thread, so we can run the scheduler and have time 'pass' + cyg_thread_create(10, // Priority - just a number + net_test, // entry + 0, // entry parameter + "Network test", // Name + thread_stack, // Stack + STACK_SIZE, // Size + &thread_handle, // Handle + &thread_data // Thread data structure + ); + cyg_thread_resume(thread_handle); // Start it +} + +#else //defined(CYGINT_ISO_STDIO_FORMATTED_IO) && defined(CYGINT_ISO_STRING_STRFUNCS) + +void cyg_user_start(void) +{ + CYG_TEST_NA("Not all the required packages are available"); +} + +#endif |