# HG changeset patch # User asl # Date 1046184141 0 # Node ID d21da3c914748e1371e30a79d865314e12316dc8 # Parent 95c190a63a7e7a9967b2d2b59cf408a92ddc4b28 First import of the Simple Network Time Protocol client. diff --git a/packages/net/sntp/current/ChangeLog b/packages/net/sntp/current/ChangeLog new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/ChangeLog @@ -0,0 +1,42 @@ +2003-02-16 Andrew Lunn + + * 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 + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Andrew Lunn +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/packages/net/sntp/current/cdl/sntp.cdl b/packages/net/sntp/current/cdl/sntp.cdl new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/cdl/sntp.cdl @@ -0,0 +1,103 @@ +# ==================================================================== +# +# sntp.cdl +# +# Simple Network Time Protocol +# +# ==================================================================== +######ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2003 Andrew Lunn +## +## 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., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-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 an SNTP client which will recieve + SNTP broadcasts and set the system clock to the correct + time." + doc ref/net-sntp.html + include_dir cyg/sntp + + requires CYGPKG_NET + requires CYGPKG_ISO_TIME + + compile sntp.c + + 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 { "tests/sntp1.c" } + } +} + +# ==================================================================== +# EOF sntp.cdl diff --git a/packages/net/sntp/current/doc/sntp.sgml b/packages/net/sntp/current/doc/sntp.sgml new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/doc/sntp.sgml @@ -0,0 +1,100 @@ + +Simple Network Time Protocol Client + + +The SNTP package provides implementation of a client for RFC 2030, the +Simple Network Time Protocol (SNTP). The client listens for broadcasts +from an NTP server and uses the information received to set the system +clock. + + + +The SNTP Client + +Starting the SNTP client + +The sntp client is implemented as a thread which listens for NTP +broadcasts. This thread is not automatically start by the +system. Instead it must be started by the user application. The header +file cyg/sntp/sntp.h declares the function to be +called. The thread is then started by calling the function: + + +void cyg_sntp_start(void); + + + +Once started, the thread will run forever. + + + +What it does + +The SNTP client listens for NTP broadcasts from any NTP servers. Such +broadcasts 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 broadcast 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 minute and another server is broadcasting, the client will +change server. + + +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. + + + + +Warning: timestamp wrap around + +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 +broadcast is received. + + +YOU HAVE BEEN WARNED! + + + +The SNTP test program + +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 a broadcast packet has been received, +at is accurate to within a few days. + + +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 a broadcast 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 broadcast messages have +been received. Check that the server is actually broadcasting, using +the correct port (123), 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. + + +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 10 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. + + + + \ No newline at end of file diff --git a/packages/net/sntp/current/include/sntp.h b/packages/net/sntp/current/include/sntp.h new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/include/sntp.h @@ -0,0 +1,56 @@ +#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 Andrew Lunn +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): andrew.lunn +// Contributors: +// Date: 2003-02-11 +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +/* Call this function to start the SNTP Client */ +void cyg_sntp_start(void); + +#endif diff --git a/packages/net/sntp/current/src/sntp.c b/packages/net/sntp/current/src/sntp.c new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/src/sntp.c @@ -0,0 +1,197 @@ +//============================================================================= +// +// sntp.c +// +// Simple Network Time Protocol +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Andrew Lunn +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): andrew.lunn +// Contributors: +// Date: 2003-02-12 +// Description: Provides a Simple Network Time Protocol Client +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include +#include +#include + +#define VERSION_MASK 0x38000000 +#define VERSION_SHIFT 27 +#define MODE_MASK 0x07000000 +#define MODE_SHIFT 24 +#define STRATUM_MASK 0x00ff0000 +#define STRATUM_SHIFT 16 + +#define MODE_BROADCAST 5 + +struct sntp_srv_s { + struct sockaddr_in addr; + int stratum; + int version; + cyg_uint32 timestamp; +}; + +#define SECONDSPERMINUTE (cyg_uint32)60 +#define SECONDSPERHOUR (cyg_uint32)(SECONDSPERMINUTE * 60) +#define SECONDSPERDAY (cyg_uint32)(SECONDSPERHOUR * 24) +#define SECONDSPERYEAR (cyg_uint32)(SECONDSPERDAY * 365) + +/* Convert a SNTP timestamp to a time_t. timestamps are seconds from + 1/1/1900. time_t is 1/1/1970. That equates to 70 years, or which + 17 were leap years.*/ +static time_t timestamp2time(cyg_uint32 timestamp) { + + return timestamp - + (SECONDSPERYEAR * (cyg_uint32)(70)) - + (SECONDSPERDAY * (cyg_uint32)(17)); +} + +/* 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 (newer->addr.sin_addr.s_addr == old->addr.sin_addr.s_addr) return 1; + if (newer->stratum < old->stratum) return 1; + + if (old->timestamp != 0xffffffff) { + last_time = timestamp2time(old->timestamp); + + diff = time(NULL) - last_time; + if (diff > 600) return 1; + + return 0; + } + return 1; +} + +static void sntp_fn(cyg_addrword_t data) { + int fd; + int ret; + struct sockaddr_in local; + struct servent *serv; + cyg_uint32 buf[12]; + struct sntp_srv_s new_srv; + struct sntp_srv_s best_srv; + int mode; + int len; + time_t new_time, current_time, diff; + + 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_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"); + + while (1) { + len = sizeof(new_srv.addr); + ret=recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&new_srv.addr,&len); + CYG_ASSERT(0 < ret,"recvfrom"); + + /* We expect at least enough bytes to fill the buffer. There could + be more if there is a digest, but we ignore that. */ + if (ret < sizeof(buf)) + continue; + + new_srv.version = (htonl(buf[0]) & VERSION_MASK) >> VERSION_SHIFT; + new_srv.stratum = (htonl(buf[0]) & STRATUM_MASK) >> STRATUM_SHIFT; + new_srv.timestamp = htonl(buf[10]); + mode = (htonl(buf[0]) & MODE_MASK) >> MODE_SHIFT; + + /* Only support protocol versions 3 or 4 */ + if (new_srv.version < 3 || new_srv.version > 4) + continue; + + /* Only process broadcast packet */ + if (mode != MODE_BROADCAST) + 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 */ + new_time = timestamp2time(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); + } + } +} + +/* Start the SNTP server */ +void cyg_sntp_start(void) { + + static char sntp_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; + static cyg_thread sntp_thread_data; + static cyg_handle_t sntp_handle; + + cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY+1, + sntp_fn, // entry + 0, // entry parameter + "sntp", // Name + &sntp_stack, // stack + sizeof(sntp_stack), // stack size + &sntp_handle, // Handle + &sntp_thread_data); // Thread data structure + + cyg_thread_resume(sntp_handle); +} diff --git a/packages/net/sntp/current/tests/sntp1.c b/packages/net/sntp/current/tests/sntp1.c new file mode 100644 --- /dev/null +++ b/packages/net/sntp/current/tests/sntp1.c @@ -0,0 +1,135 @@ +//================================================================= +// +// sntp1.c +// +// Simple Network Time Protocol test 1 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2003 Andrew Lunn +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Andrew Lunn +// Contributors: +// Date: 2003-02-11 +// Description: Tests the sntp client +//####DESCRIPTIONEND#### + +#include +#include +#include +#include +#include + +#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; + char month[4]; + char months[12][4] = { "Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" }; + + CYG_TEST_INIT(); + + CYG_TEST_INFO("sntp1 test build " __DATE__); + + init_all_network_interfaces(); + + cyg_sntp_start(); + + for (seconds = 120; seconds > 0; seconds--) { + now = time(NULL); + CYG_TEST_INFO(ctime(&now)); + 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_mday++; + + 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 * 10) > time(NULL)) { + CYG_TEST_FAIL_FINISH("Build time is more than 10 days old"); + } + } + } + CYG_TEST_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 +}