1 /* $NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)netdate.c 8.2 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $");
41 #include <sys/param.h>
43 #include <sys/socket.h>
45 #include <netinet/in.h>
48 #include <protocols/timed.h>
59 #define WAITACK 2000 /* milliseconds */
60 #define WAITDATEACK 5000 /* milliseconds */
63 tsp_type_to_string(const struct tsp
*msg
)
68 return i
< TSPTYPENUMBER
? tsptype
[i
] : "unknown";
72 * Set the date in the machines controlled by timedaemons by communicating the
73 * new date to the local timedaemon. If the timedaemon is in the master state,
74 * it performs the correction on all slaves. If it is in the slave state, it
75 * notifies the master that a correction is needed.
76 * Returns 0 on success. Returns > 0 on failure.
79 netsettime(time_t tval
)
81 struct sockaddr_in dest
;
83 char hostname
[MAXHOSTNAMELEN
];
86 int found
, s
, timed_ack
, waittime
;
88 if ((sp
= getservbyname("timed", "udp")) == NULL
) {
89 warnx("udp/timed: unknown service");
93 (void)memset(&dest
, 0, sizeof(dest
));
95 dest
.sin_len
= sizeof(dest
);
97 dest
.sin_family
= AF_INET
;
98 dest
.sin_port
= sp
->s_port
;
99 dest
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
100 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
102 if (errno
!= EAFNOSUPPORT
)
109 static const int on
= IP_PORTRANGE_LOW
;
111 if (setsockopt(s
, IPPROTO_IP
, IP_PORTRANGE
, &on
,
119 msg
.tsp_type
= TSP_SETDATE
;
120 msg
.tsp_vers
= TSPVERSION
;
121 if (gethostname(hostname
, sizeof(hostname
)) == -1) {
125 (void)strlcpy(msg
.tsp_name
, hostname
, sizeof(msg
.tsp_name
));
126 msg
.tsp_seq
= htons((in_port_t
)0);
127 msg
.tsp_time
.tv_sec
= htonl((in_addr_t
)tval
); /* XXX: y2038 */
128 msg
.tsp_time
.tv_usec
= htonl((in_addr_t
)0);
129 if (connect(s
, (const void *)&dest
, sizeof(dest
)) == -1) {
133 if (send(s
, &msg
, sizeof(msg
), 0) == -1) {
134 if (errno
!= ECONNREFUSED
)
142 ready
.events
= POLLIN
;
144 found
= poll(&ready
, 1, waittime
);
151 if (getsockopt(s
, SOL_SOCKET
, SO_ERROR
, &error
, &len
) == -1) {
156 if (error
!= ECONNREFUSED
) {
158 warn("send (delayed error)");
164 if (found
> 0 && ready
.revents
& POLLIN
) {
167 if ((ret
= recv(s
, &msg
, sizeof(msg
), 0)) == -1) {
168 if (errno
!= ECONNREFUSED
)
171 } else if ((size_t)ret
< sizeof(msg
)) {
172 warnx("recv: incomplete packet");
176 msg
.tsp_seq
= ntohs(msg
.tsp_seq
);
177 msg
.tsp_time
.tv_sec
= ntohl(msg
.tsp_time
.tv_sec
);
178 msg
.tsp_time
.tv_usec
= ntohl(msg
.tsp_time
.tv_usec
);
179 switch (msg
.tsp_type
) {
182 waittime
= WAITDATEACK
;
188 warnx("wrong ack received from timed: %s",
189 tsp_type_to_string(&msg
));
195 warnx("can't reach time daemon, time set locally");