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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [lib/] [rtems_bsdnet_ntp.c] - Blame information for rev 373

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

Line No. Rev Author Line
1 30 unneback
/*
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: rtems_bsdnet_ntp.c,v 1.2 2001-09-27 12:01:52 chris 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
int
89
rtems_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
}

powered by: WebSVN 2.1.0

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