Index: packages/net/sntp/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/sntp/current/ChangeLog,v retrieving revision 1.6 diff -r1.6 ChangeLog 0a1,6 > 2003-09-29 Dan Jakubiec > > * 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. > Index: packages/net/sntp/current/cdl/sntp.cdl =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/sntp/current/cdl/sntp.cdl,v retrieving revision 1.2 diff -r1.2 sntp.cdl 69a70,80 > cdl_option 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." > } > Index: packages/net/sntp/current/include/sntp.h =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/sntp/current/include/sntp.h,v retrieving revision 1.4 diff -r1.4 sntp.h 52a53 > #include 54a56,58 > /* General Definitions */ > #define NTP_UDP_PORT 123 > 62a67,70 > > #ifdef CYGPKG_NET_SNTP_UNICAST > __externC void cyg_sntp_set_servers(struct sockaddr *server_list, cyg_uint32 num_servers); > #endif Index: packages/net/sntp/current/src/sntp.c =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/sntp/current/src/sntp.c,v retrieving revision 1.4 diff -r1.4 sntp.c 50a51,52 > #include > #include 58,63c60,121 < #define VERSION_MASK 0x38000000 < #define VERSION_SHIFT 27 < #define MODE_MASK 0x07000000 < #define MODE_SHIFT 24 < #define STRATUM_MASK 0x00ff0000 < #define STRATUM_SHIFT 16 --- > /* 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) 65d122 < #define MODE_BROADCAST 5 72a130 > static int sntp_initialized = 0; 74,87c132,170 < #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)); < } --- > > #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; > > /* 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 */ 102c185 < last_time = timestamp2time(old->timestamp); --- > last_time = TIME_NTP_TO_LOCAL(old->timestamp); 114c197,198 < static void sntp_fn(cyg_addrword_t data) { --- > static void sntp_fn(cyg_addrword_t data) > { 119c203 < cyg_uint32 buf[12]; --- > NTP_PACKET ntp_pkt; 131a216,221 > #ifdef CYGPKG_NET_SNTP_UNICAST > int i; > struct timeval timeout; > time_t NextTimeUpdate = 0; > #endif /* CYGPKG_NET_SNTP_UNICAST */ > struct timeval *ptimeout = NULL; 158,161c248,257 < // Node-Local < ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); < CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Node-Local"); < --- > /* 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! > */ 210c306,389 < ret = select(n+1, &readfds,NULL,NULL,NULL); --- > #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 = NextTimeUpdate - current_time; > } 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); 212a392,397 > #ifdef CYGPKG_NET_SNTP_UNICAST > /* If we timed out, then try resending requests */ > if (ret == 0) > continue; > #endif /* CYGPKG_NET_SNTP_UNICAST */ > 215c400 < ret=recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&new_srv.addr,&len); --- > ret=recvfrom(fd,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); 219c404 < ret=recvfrom(fd6,buf,sizeof(buf),0,(struct sockaddr *)&new_srv.addr,&len); --- > ret=recvfrom(fd6,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); 223,226c408,410 < < /* 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)) --- > > /* We expect at least enough bytes to fill the buffer */ > if (ret < NTP_PACKET_MINLEN) 229,232c413,416 < 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; --- > 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); 240,241c424,425 < /* Only process broadcast packet */ < if (mode != MODE_BROADCAST) --- > /* Only process broadcast and server packets */ > if (mode != NTP_MODE_BROADCAST && mode != NTP_MODE_SERVER) 248,249c432,437 < /* Work out the difference between server and our time */ < new_time = timestamp2time(best_srv.timestamp); --- > /* 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); 254c442 < diff = -diff; --- > diff = -diff; 257c445 < cyg_libc_time_settime(new_time); --- > cyg_libc_time_settime(new_time); 258a447,449 > #ifdef CYGPKG_NET_SNTP_UNICAST > NextTimeUpdate = time(NULL) + SNTP_UPDATEPERIOD; > #endif 265c456 < static char sntp_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; --- > static char sntp_stack[CYGNUM_SNTP_STACK_SIZE]; 268a460,469 > /* 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 > 272c473 < "sntp", // Name --- > "SNTP Client", // Name 279a481,528 > > #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: This function must be called AFTER > * cyg_sntp_start(). > * > * 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) > { > /* Get the server list mutex */ > if (!sntp_initialized) > return; > cyg_mutex_lock(&sntp_mutex); > > /* Record the new server list */ > sntp_num_servers = num_servers; > if (num_servers == 0) > server_list = NULL; > sntp_servers = server_list; > > /* Free the mutex */ > cyg_mutex_unlock(&sntp_mutex); > } > #endif /* CYGPKG_NET_SNTP_UNICAST */ >