OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libnetworking/] [lib/] [rtems_bsdnet_ntp.c] - Blame information for rev 1026

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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
 *  rtems_bsdnet_ntp.c,v 1.5 2001/04/24 21:02:03 joel Exp
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
 
37
struct timestamp {
38
        rtems_unsigned32        integer;
39
        rtems_unsigned32        fraction;
40
};
41
 
42
struct 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
 
56
struct ntpPacket {
57
        struct ntpPacketSmall   ntp;
58
        char                    authenticator[96];
59
};
60
 
61
static int
62
processPacket (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
 
88
static int
89
tryServer (int i, int s)
90
{
91
        int l;
92
        struct timeval tv;
93
        int farlen;
94
        struct sockaddr_in farAddr;
95
        struct ntpPacketSmall packet;
96
 
97
        if (i < 0)
98
                tv.tv_sec = 80;
99
        else
100
                tv.tv_sec = 5;
101
        tv.tv_usec = 0;
102
        if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
103
                printf ("Can't set socket receive timeout: %s\n", strerror (errno));
104
                close (s);
105
                return -1;
106
        }
107
        if (i >= 0) {
108
                memset (&farAddr, 0, sizeof farAddr);
109
                farAddr.sin_family = AF_INET;
110
                farAddr.sin_port = htons (123);
111
                farAddr.sin_addr = rtems_bsdnet_ntpserver[i];
112
                memset (&packet, 0, sizeof packet);
113
                packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */
114
                l = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr);
115
                if (l != sizeof packet) {
116
                        printf ("Can't send: %s\n", strerror (errno));
117
                        return -1;
118
                }
119
        }
120
        farlen = sizeof farAddr;
121
        i = recvfrom (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, &farlen);
122
        if (i == 0)
123
                printf ("Unexpected EOF");
124
        if (i < 0) {
125
                if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
126
                        return -1;
127
                printf ("Can't receive: %s\n", strerror (errno));
128
        }
129
        if ((i >= sizeof packet) && processPacket (&packet))
130
                return 0;
131
        return -1;
132
}
133
 
134
int
135
rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority)
136
{
137
        int s;
138
        int i;
139
        int retry;
140
        struct sockaddr_in myAddr;
141
        int reuseFlag;
142
        int ret;
143
 
144
        if (interval != 0) {
145
                printf ("Daemon-mode note yet supported.\n");
146
                errno = EINVAL;
147
                return -1;
148
        }
149
        s = socket (AF_INET, SOCK_DGRAM, 0);
150
        if (s < 0) {
151
                printf ("Can't create socket: %s\n", strerror (errno));
152
                return -1;
153
        }
154
        reuseFlag = 1;
155
        if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
156
                printf ("Can't set socket reuse: %s\n", strerror (errno));
157
                close (s);
158
                return -1;
159
        }
160
        memset (&myAddr, 0, sizeof myAddr);
161
        myAddr.sin_family = AF_INET;
162
        myAddr.sin_port = htons (123);
163
        myAddr.sin_addr.s_addr = htonl (INADDR_ANY);
164
        if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) {
165
                printf ("Can't bind socket: %s\n", strerror (errno));
166
                close (s);
167
                return -1;
168
        }
169
        ret = -1;
170
        for (retry = 0 ; (ret == -1) && (retry < 5) ; retry++) {
171
                /*
172
                 * If there's no server we just have to wait
173
                 * and hope that there's an NTP broadcast
174
                 * server out there somewhere.
175
                 */
176
                if (rtems_bsdnet_ntpserver_count < 0) {
177
                        ret = tryServer (-1, s);
178
                }
179
                else {
180
                        for (i = 0 ; (ret == -1) && (i < rtems_bsdnet_ntpserver_count) ; i++) {
181
                                ret = tryServer (i, s);
182
                        }
183
                }
184
        }
185
        close (s);
186
        return ret;
187
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.