source: rtems/cpukit/libnetworking/lib/rtems_bsdnet_ntp.c @ df49c60

4.104.114.84.9
Last change on this file since df49c60 was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 2000 at 3:00:15 PM

Merged from 4.5.0-beta3a

  • Property mode set to 100644
File size: 4.0 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 *  $Id$
16 */
17
18#include <stdio.h>
19#include <string.h>
20#include <errno.h>
21#include <time.h>
22#include <limits.h>
23#include <rtems.h>
24#include <rtems/rtems_bsdnet.h>
25#include <rtems/error.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <netinet/in.h>
29
30/*
31 * RTEMS base: 1988, January 1
32 *  UNIX base: 1970, January 1
33 *   NTP base: 1900, January 1
34 */
35#define UNIX_BASE_TO_NTP_BASE (((70UL*365UL)+17UL) * (24*60*60))
36
37struct timestamp {
38        rtems_unsigned32        integer;
39        rtems_unsigned32        fraction;
40};
41
42struct ntpPacketSmall {
43        rtems_unsigned8         li_vn_mode;
44        rtems_unsigned8         stratum;
45        rtems_signed8           poll_interval;
46        rtems_signed8           precision;
47        rtems_signed32          root_delay;
48        rtems_signed32          root_dispersion;
49        char                    reference_identifier[4];
50        struct timestamp        reference_timestamp;
51        struct timestamp        originate_timestamp;
52        struct timestamp        receive_timestamp;
53        struct timestamp        transmit_timestamp;
54};
55
56struct ntpPacket {
57        struct ntpPacketSmall   ntp;
58        char                    authenticator[96];
59};
60
61static int
62processPacket (struct ntpPacketSmall *p)
63{
64        time_t tbuf;
65        struct tm *lt;
66        rtems_time_of_day rt;
67        rtems_interval ticks_per_second;
68
69        if (((p->li_vn_mode & (0x7 << 3)) != (3 << 3))
70         || ((p->transmit_timestamp.integer == 0) && (p->transmit_timestamp.fraction == 0)))
71                return 0;
72        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
73        tbuf = ntohl (p->transmit_timestamp.integer) - UNIX_BASE_TO_NTP_BASE - rtems_bsdnet_timeoffset;
74        lt = gmtime (&tbuf);
75        rt.year = lt->tm_year + 1900;
76        rt.month = lt->tm_mon + 1;
77        rt.day = lt->tm_mday;
78        rt.hour = lt->tm_hour;
79        rt.minute = lt->tm_min;
80        rt.second = lt->tm_sec;
81        rt.ticks = ntohl (p->transmit_timestamp.fraction) / (ULONG_MAX / ticks_per_second);
82        if (rt.ticks >= ticks_per_second)
83                rt.ticks = ticks_per_second - 1;
84        rtems_clock_set (&rt);
85        return 1;
86}
87
88int
89rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority)
90{
91        int s;
92        int i;
93        static struct sockaddr_in myAddr, farAddr;
94        int fromlen;
95        struct ntpPacketSmall packet;
96        struct timeval tv;
97
98        if (interval != 0) {
99                printf ("Daemon-mode note yet supported.\n");
100                errno = EINVAL;
101                return -1;
102        }
103        s = socket (AF_INET, SOCK_DGRAM, 0);
104        if (s < 0) {
105                printf ("Can't create socket: %s\n", strerror (errno));
106                return -1;
107        }
108        tv.tv_sec = 5;
109        tv.tv_usec = 0;
110        if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
111                printf ("Can't set socket receive timeout: %s", strerror (errno));
112                return -1;
113        }
114        memset (&myAddr, 0, sizeof myAddr);
115        myAddr.sin_family = AF_INET;
116        myAddr.sin_port = htons (123);
117        myAddr.sin_addr.s_addr = htonl (INADDR_ANY);
118        if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) {
119                printf ("Can't bind socket: %s\n", strerror (errno));
120                return -1;
121        }
122        for (;;) {
123                /*
124                 * If there's no server we just have to wait
125                 * and hope that there's an NTP broadcast
126                 * server out there somewhere.
127                 */
128                if (rtems_bsdnet_ntpserver_count > 0) {
129                        memset (&farAddr, 0, sizeof farAddr);
130                        farAddr.sin_family = AF_INET;
131                        farAddr.sin_port = htons (123);
132                        /*
133                         * For now, try only the first server.
134                         */
135                        farAddr.sin_addr = rtems_bsdnet_ntpserver[0];
136                        memset (&packet, 0, sizeof packet);
137                        packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */
138                        i = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr);
139                        if (i != sizeof packet) {
140                                printf ("Can't send: %s\n", strerror (errno));
141                                return -1;
142                        }
143                }
144                fromlen = sizeof farAddr;
145                i = recvfrom (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, &fromlen);
146                if (i == 0)
147                        rtems_panic ("EOF");
148                if (i < 0) {
149                        if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
150                                continue;
151                        rtems_panic ("Can't receive: %s", strerror (errno));
152                }
153                if (i >= sizeof packet) {
154                        if (processPacket (&packet))
155                                return 0;
156                }
157        }
158}
Note: See TracBrowser for help on using the repository browser.