1 /* $NetBSD: netdate.c,v 1.26 2007/02/04 22:21:53 cbiere 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.26 2007/02/04 22:21:53 cbiere 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 */
65 tsp_type_to_string(const struct tsp
*msg
)
70 return i
< TSPTYPENUMBER
? tsptype
[i
] : "unknown";
74 * Set the date in the machines controlled by timedaemons by communicating the
75 * new date to the local timedaemon. If the timedaemon is in the master state,
76 * it performs the correction on all slaves. If it is in the slave state, it
77 * notifies the master that a correction is needed.
78 * Returns 0 on success. Returns > 0 on failure, setting retval to 2;
81 netsettime(time_t tval
)
83 struct sockaddr_in dest
;
85 char hostname
[MAXHOSTNAMELEN
];
88 int found
, s
, timed_ack
, waittime
;
90 if ((sp
= getservbyname("timed", "udp")) == NULL
) {
91 warnx("udp/timed: unknown service");
95 (void)memset(&dest
, 0, sizeof(dest
));
97 dest
.sin_len
= sizeof(dest
);
99 dest
.sin_family
= AF_INET
;
100 dest
.sin_port
= sp
->s_port
;
101 dest
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
102 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
104 if (errno
!= EAFNOSUPPORT
)
111 static const int on
= IP_PORTRANGE_LOW
;
113 if (setsockopt(s
, IPPROTO_IP
, IP_PORTRANGE
,
114 &on
, sizeof(on
)) < 0) {
121 msg
.tsp_type
= TSP_SETDATE
;
122 msg
.tsp_vers
= TSPVERSION
;
123 if (gethostname(hostname
, sizeof(hostname
))) {
127 strncpy(msg
.tsp_name
, hostname
, sizeof(msg
.tsp_name
));
128 msg
.tsp_name
[sizeof(msg
.tsp_name
) - 1] = '\0';
129 msg
.tsp_seq
= htons((uint16_t)0);
130 msg
.tsp_time
.tv_sec
= htonl((uint32_t)tval
); /* XXX: y2038 */
131 msg
.tsp_time
.tv_usec
= htonl((uint32_t)0);
132 if (connect(s
, (const struct sockaddr
*)&dest
, sizeof(dest
)) < 0) {
136 if (send(s
, &msg
, sizeof(msg
), 0) < 0) {
137 if (errno
!= ECONNREFUSED
)
145 ready
.events
= POLLIN
;
147 found
= poll(&ready
, 1, waittime
);
153 length
= sizeof(error
);
154 if (!getsockopt(s
, SOL_SOCKET
, SO_ERROR
, &error
, &length
)
156 if (error
!= ECONNREFUSED
)
157 warn("send (delayed error)");
162 if (found
> 0 && ready
.revents
& POLLIN
) {
165 ret
= recv(s
, &msg
, sizeof(msg
), 0);
167 if (errno
!= ECONNREFUSED
)
170 } else if ((size_t)ret
< sizeof(msg
)) {
171 warnx("recv: incomplete packet");
175 msg
.tsp_seq
= ntohs(msg
.tsp_seq
);
176 msg
.tsp_time
.tv_sec
= ntohl(msg
.tsp_time
.tv_sec
);
177 msg
.tsp_time
.tv_usec
= ntohl(msg
.tsp_time
.tv_usec
);
178 switch (msg
.tsp_type
) {
181 waittime
= WAITDATEACK
;
187 warnx("wrong ack received from timed: %s",
188 tsp_type_to_string(&msg
));
194 warnx("can't reach time daemon, time set locally");