source: rtems/cpukit/libnetworking/lib/rtems_bsdnet_ntp.c @ 9b4422a2

4.11
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on May 3, 2012 at 3:09:24 PM

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Synchronize with an NTP server
3 *
4 * This program may be distributed and used for any purpose.
5 * I ask only that you:
6 *      1. Leave this author information intact.
7 *      2. Document any changes you make.
8 *
9 * W. Eric Norum
10 * Canadian Light Source
11 * University of Saskatchewan
12 * Saskatoon, Saskatchewan, CANADA
13 * eric@cls.usask.ca
14 */
15
16#ifdef HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <unistd.h> /* close */
21#include <stdio.h>
22#include <string.h>
23#include <errno.h>
24#include <time.h>
25#include <limits.h>
26#include <rtems.h>
27#include <rtems/rtems_bsdnet.h>
28#include <rtems/error.h>
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32
33#include <rtems/bsdnet/servers.h>
34
35/*
36 * RTEMS base: 1988, January 1
37 *  UNIX base: 1970, January 1
38 *   NTP base: 1900, January 1
39 */
40#define UNIX_BASE_TO_NTP_BASE (uint32_t)(((70UL*365UL)+17UL) * (24UL*60UL*60UL))
41
42struct ntpPacket {
43        struct ntpPacketSmall   ntp;
44        char                    authenticator[96];
45};
46
47static int
48processPacket (struct ntpPacketSmall *p, int state, void *unused)
49{
50        time_t tbuf;
51        struct tm *lt;
52        rtems_time_of_day rt;
53        rtems_interval ticks_per_second;
54
55        if ( state )
56                return 0;
57
58        ticks_per_second = rtems_clock_get_ticks_per_second();
59        tbuf = ntohl (p->transmit_timestamp.integer) - UNIX_BASE_TO_NTP_BASE - rtems_bsdnet_timeoffset;
60        lt = gmtime (&tbuf);
61        rt.year = lt->tm_year + 1900;
62        rt.month = lt->tm_mon + 1;
63        rt.day = lt->tm_mday;
64        rt.hour = lt->tm_hour;
65        rt.minute = lt->tm_min;
66        rt.second = lt->tm_sec;
67        rt.ticks = ntohl (p->transmit_timestamp.fraction) / (ULONG_MAX / ticks_per_second);
68        if (rt.ticks >= ticks_per_second)
69                rt.ticks = ticks_per_second - 1;
70        rtems_clock_set (&rt);
71        return 0;
72}
73
74static int
75getServerTimespec(struct ntpPacketSmall *p, int state, void *usr_data)
76{
77struct timespec *ts = usr_data;
78unsigned long long tmp;
79
80        if ( 0 == state ) {
81                ts->tv_sec  = ntohl( p->transmit_timestamp.integer );
82                ts->tv_sec -= rtems_bsdnet_timeoffset + UNIX_BASE_TO_NTP_BASE;
83
84                tmp  = 1000000000 * (unsigned long long)ntohl(p->transmit_timestamp.fraction);
85
86                ts->tv_nsec = (unsigned long) (tmp>>32);
87        }
88        return 0;
89}
90
91int rtems_bsdnet_ntp_retry_count  = 5;
92int rtems_bsdnet_ntp_timeout_secs = 5;
93int rtems_bsdnet_ntp_bcast_timeout_secs = 80;
94
95static int
96tryServer (int i, int s, rtems_bsdnet_ntp_callback_t callback, void *usr_data)
97{
98        int l = 0;
99        struct timeval tv;
100        socklen_t farlen;
101        struct sockaddr_in farAddr;
102        struct ntpPacketSmall packet;
103
104        if (i < 0)
105                tv.tv_sec = rtems_bsdnet_ntp_bcast_timeout_secs;
106        else
107                tv.tv_sec = rtems_bsdnet_ntp_timeout_secs;
108        tv.tv_usec = 0;
109        if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
110                fprintf (stderr, "rtems_bsdnet_get_ntp() Can't set socket receive timeout: %s\n", strerror (errno));
111                close (s);
112                return -1;
113        }
114        if (i >= 0) {
115                memset (&farAddr, 0, sizeof farAddr);
116                farAddr.sin_family = AF_INET;
117                farAddr.sin_port = htons (123);
118                farAddr.sin_addr = rtems_bsdnet_ntpserver[i];
119                memset (&packet, 0, sizeof packet);
120                packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */
121                if ( callback( &packet, 1, usr_data ) )
122                        return -1;
123                l = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr);
124                if (l != sizeof packet) {
125                        fprintf (stderr, "rtems_bsdnet_get_ntp() Can't send: %s\n", strerror (errno));
126                        return -1;
127                }
128        } else {
129                if ( callback( &packet, -1, usr_data ) )
130                        return -1;
131        }
132        farlen = sizeof farAddr;
133        i = recvfrom (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, &farlen);
134        if (i == 0)
135                fprintf (stderr, "rtems_bsdnet_get_ntp() Unexpected EOF");
136        if (i < 0) {
137                if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
138                        return -1;
139                fprintf (stderr, "rtems_bsdnet_get_ntp() Can't receive: %s\n", strerror (errno));
140        }
141
142        if ( i >= sizeof packet &&
143                ((packet.li_vn_mode & (0x7 << 3)) == (3 << 3)) &&
144            ((packet.transmit_timestamp.integer != 0) || (packet.transmit_timestamp.fraction != 0)) &&
145                0 == callback( &packet, 0 , usr_data) )
146                return 0;
147
148        return -1;
149}
150
151int rtems_bsdnet_get_ntp(int sock, rtems_bsdnet_ntp_callback_t callback, void *usr_data)
152{
153int s = -1;
154int i;
155int retry;
156struct sockaddr_in myAddr;
157int reuseFlag;
158int ret;
159
160        if ( !callback )
161                callback = getServerTimespec;
162
163        if ( sock < 0 ) {
164        s = socket (AF_INET, SOCK_DGRAM, 0);
165        if (s < 0) {
166                fprintf (stderr, "rtems_bsdnet_get_ntp() Can't create socket: %s\n", strerror (errno));
167                return -1;
168        }
169        reuseFlag = 1;
170        if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
171                fprintf (stderr, "rtems_bsdnet_get_ntp() Can't set socket reuse: %s\n", strerror (errno));
172                close (s);
173                return -1;
174        }
175        memset (&myAddr, 0, sizeof myAddr);
176        myAddr.sin_family = AF_INET;
177        myAddr.sin_port = htons (0);
178        myAddr.sin_addr.s_addr = htonl (INADDR_ANY);
179        if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) {
180                fprintf (stderr, "rtems_bsdnet_get_ntp() Can't bind socket: %s\n", strerror (errno));
181                close (s);
182                return -1;
183        }
184        sock = s;
185        }
186        ret = -1;
187        for (retry = 0 ; (ret == -1) && (retry < rtems_bsdnet_ntp_retry_count) ; retry++) {
188                /*
189                 * If there's no server we just have to wait
190                 * and hope that there's an NTP broadcast
191                 * server out there somewhere.
192                 */
193                if (rtems_bsdnet_ntpserver_count < 0) {
194                        ret = tryServer (-1, sock, callback, usr_data);
195                }
196                else {
197                        for (i = 0 ; (ret == -1) && (i < rtems_bsdnet_ntpserver_count) ; i++) {
198                                ret = tryServer (i, sock, callback, usr_data);
199                        }
200                }
201        }
202        if ( s >= 0 )
203                close (s);
204        return ret;
205}
206
207int
208rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority)
209{
210        if (interval != 0) {
211                fprintf (stderr, "Daemon-mode note yet supported.\n");
212                errno = EINVAL;
213                return -1;
214        }
215        return rtems_bsdnet_get_ntp( -1, processPacket, 0);
216}
Note: See TracBrowser for help on using the repository browser.