summaryrefslogtreecommitdiff
path: root/net/sntp.c
blob: d5d5671933180a942278912a8e9cd6e3018c2d78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * SNTP support driver
 *
 * Masami Komiya <mkomiya@sonare.it> 2005
 *
 */

#include <common.h>
#include <command.h>
#include <dm.h>
#include <log.h>
#include <net.h>
#include <rtc.h>

#include <net/sntp.h>

#define SNTP_TIMEOUT 10000UL

static int sntp_our_port;

/* NTP server IP address */
struct in_addr	net_ntp_server;
/* offset time from UTC */
int		net_ntp_time_offset;

static void sntp_send(void)
{
	struct sntp_pkt_t pkt;
	int pktlen = SNTP_PACKET_LEN;
	int sport;

	debug("%s\n", __func__);

	memset(&pkt, 0, sizeof(pkt));

	pkt.li = NTP_LI_NOLEAP;
	pkt.vn = NTP_VERSION;
	pkt.mode = NTP_MODE_CLIENT;

	memcpy((char *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE,
	       (char *)&pkt, pktlen);

	sntp_our_port = 10000 + (get_timer(0) % 4096);
	sport = NTP_SERVICE_PORT;

	net_send_udp_packet(net_server_ethaddr, net_ntp_server, sport,
			    sntp_our_port, pktlen);
}

static void sntp_timeout_handler(void)
{
	puts("Timeout\n");
	net_set_state(NETLOOP_FAIL);
	return;
}

static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
			 unsigned src, unsigned len)
{
#ifdef CONFIG_TIMESTAMP
	struct sntp_pkt_t *rpktp = (struct sntp_pkt_t *)pkt;
	struct rtc_time tm;
	ulong seconds;
#endif

	debug("%s\n", __func__);

	if (dest != sntp_our_port)
		return;

#ifdef CONFIG_TIMESTAMP
	/*
	 * As the RTC's used in U-Boot support second resolution only
	 * we simply ignore the sub-second field.
	 */
	memcpy(&seconds, &rpktp->transmit_timestamp, sizeof(ulong));

	rtc_to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm);
#if defined(CONFIG_CMD_DATE)
#  ifdef CONFIG_DM_RTC
	struct udevice *dev;
	int ret;

	ret = uclass_get_device(UCLASS_RTC, 0, &dev);
	if (ret)
		printf("SNTP: cannot find RTC: err=%d\n", ret);
	else
		dm_rtc_set(dev, &tm);
#  else
	rtc_set(&tm);
#  endif
#endif
	printf("Date: %4d-%02d-%02d Time: %2d:%02d:%02d\n",
	       tm.tm_year, tm.tm_mon, tm.tm_mday,
	       tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif

	net_set_state(NETLOOP_SUCCESS);
}

/*
 * SNTP:
 *
 *	Prerequisites:	- own ethernet address
 *			- own IP address
 *	We want:	- network time
 *	Next step:	none
 */
int sntp_prereq(void *data)
{
	if (net_ntp_server.s_addr == 0) {
		puts("*** ERROR: NTP server address not given\n");
		return 1;
	}

	return 0;
}

int sntp_start(void *data)
{
	debug("%s\n", __func__);

	net_set_timeout_handler(SNTP_TIMEOUT, sntp_timeout_handler);
	net_set_udp_handler(sntp_handler);
	memset(net_server_ethaddr, 0, sizeof(net_server_ethaddr));

	sntp_send();

	return 0;
}