xref: /openbsd-src/usr.sbin/rdate/rfc868time.c (revision 893695cea05286a86be12c6215f6501df588dceb)
1*893695ceSjsg /*	$OpenBSD: rfc868time.c,v 1.13 2023/01/04 13:00:11 jsg Exp $	*/
24142bea0Sjakob /*	$NetBSD: rdate.c,v 1.4 1996/03/16 12:37:45 pk Exp $	*/
34142bea0Sjakob 
44142bea0Sjakob /*
54142bea0Sjakob  * Copyright (c) 1994 Christos Zoulas
64142bea0Sjakob  * All rights reserved.
74142bea0Sjakob  *
84142bea0Sjakob  * Redistribution and use in source and binary forms, with or without
94142bea0Sjakob  * modification, are permitted provided that the following conditions
104142bea0Sjakob  * are met:
114142bea0Sjakob  * 1. Redistributions of source code must retain the above copyright
124142bea0Sjakob  *    notice, this list of conditions and the following disclaimer.
134142bea0Sjakob  * 2. Redistributions in binary form must reproduce the above copyright
144142bea0Sjakob  *    notice, this list of conditions and the following disclaimer in the
154142bea0Sjakob  *    documentation and/or other materials provided with the distribution.
164142bea0Sjakob  *
174142bea0Sjakob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
184142bea0Sjakob  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
194142bea0Sjakob  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
204142bea0Sjakob  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
214142bea0Sjakob  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
224142bea0Sjakob  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234142bea0Sjakob  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244142bea0Sjakob  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254142bea0Sjakob  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
264142bea0Sjakob  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274142bea0Sjakob  */
284142bea0Sjakob 
294142bea0Sjakob /*
304142bea0Sjakob  * rdate.c: Set the date from the specified host
314142bea0Sjakob  *
32246969aeSjakob  *	Uses the rfc868 time protocol at socket 37 (tcp).
334142bea0Sjakob  *	Time is returned as the number of seconds since
344142bea0Sjakob  *	midnight January 1st 1900.
354142bea0Sjakob  */
36246969aeSjakob 
37b9ce4fd1Sjakob #include <sys/socket.h>
38b9ce4fd1Sjakob #include <sys/time.h>
39b9ce4fd1Sjakob #include <netinet/in.h>
40b9ce4fd1Sjakob 
414142bea0Sjakob #include <stdio.h>
424142bea0Sjakob #include <ctype.h>
434142bea0Sjakob #include <err.h>
444142bea0Sjakob #include <string.h>
454142bea0Sjakob #include <netdb.h>
464142bea0Sjakob #include <unistd.h>
474142bea0Sjakob #include <time.h>
484142bea0Sjakob 
49246969aeSjakob /* Obviously it is not just for SNTP clients... */
50246969aeSjakob #include "ntpleaps.h"
51246969aeSjakob 
524142bea0Sjakob /* seconds from midnight Jan 1900 - 1970 */
534142bea0Sjakob #define DIFFERENCE 2208988800UL
544142bea0Sjakob 
55d2c62849Sderaadt void
56d2c62849Sderaadt rfc868time_client(const char *hostname, int family, struct timeval *new,
57d2c62849Sderaadt     struct timeval *adjust, int leapflag);
58d2c62849Sderaadt 
594142bea0Sjakob 
604142bea0Sjakob void
rfc868time_client(const char * hostname,int family,struct timeval * new,struct timeval * adjust,int leapflag)6122d417c3Sjakob rfc868time_client(const char *hostname, int family, struct timeval *new,
62246969aeSjakob     struct timeval *adjust, int leapflag)
634142bea0Sjakob {
642e2f3e6dSjakob 	struct addrinfo hints, *res0, *res;
654142bea0Sjakob 	struct timeval old;
66246969aeSjakob 	u_int32_t tim;	/* RFC 868 states clearly this is an uint32 */
67eea542eaSderaadt 	int s;
682e2f3e6dSjakob 	int error;
69246969aeSjakob 	u_int64_t td;
704142bea0Sjakob 
712e2f3e6dSjakob 	memset(&hints, 0, sizeof(hints));
7222d417c3Sjakob 	hints.ai_family = family;
732e2f3e6dSjakob 	hints.ai_socktype = SOCK_STREAM;
742e2f3e6dSjakob 	error = getaddrinfo(hostname, "time", &hints, &res0);
752e2f3e6dSjakob 	if (error) {
762e2f3e6dSjakob 		errx(1, "%s: %s", hostname, gai_strerror(error));
772e2f3e6dSjakob 		/*NOTREACHED*/
784142bea0Sjakob 	}
792e2f3e6dSjakob 
804a5cc25cSmestre 	if (pledge("stdio inet", NULL) == -1)
814a5cc25cSmestre 		err(1, "pledge");
824a5cc25cSmestre 
832e2f3e6dSjakob 	s = -1;
842e2f3e6dSjakob 	for (res = res0; res; res = res->ai_next) {
852e2f3e6dSjakob 		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
86df69c215Sderaadt 		if (s == -1)
872e2f3e6dSjakob 			continue;
882e2f3e6dSjakob 
89df69c215Sderaadt 		if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
902e2f3e6dSjakob 			close(s);
912e2f3e6dSjakob 			s = -1;
922e2f3e6dSjakob 			continue;
934142bea0Sjakob 		}
944142bea0Sjakob 
952e2f3e6dSjakob 		break;
962e2f3e6dSjakob 	}
97df69c215Sderaadt 	if (s == -1)
984142bea0Sjakob 		err(1, "Could not connect socket");
992e2f3e6dSjakob 	freeaddrinfo(res0);
1004142bea0Sjakob 
101246969aeSjakob 	if (read(s, &tim, sizeof(tim)) != sizeof(tim))
1024142bea0Sjakob 		err(1, "Could not read data");
1034142bea0Sjakob 
1044142bea0Sjakob 	(void) close(s);
1054142bea0Sjakob 	tim = ntohl(tim) - DIFFERENCE;
1064142bea0Sjakob 
1074142bea0Sjakob 	if (gettimeofday(&old, NULL) == -1)
1084142bea0Sjakob 		err(1, "Could not get local time of day");
1094142bea0Sjakob 
110246969aeSjakob 	td = SEC_TO_TAI64(old.tv_sec);
111246969aeSjakob 	if (leapflag)
112246969aeSjakob 		ntpleaps_sub(&td);
113246969aeSjakob 
114246969aeSjakob 	adjust->tv_sec = tim - TAI64_TO_SEC(td);
1154142bea0Sjakob 	adjust->tv_usec = 0;
1164142bea0Sjakob 
117246969aeSjakob 	new->tv_sec = old.tv_sec + adjust->tv_sec;
1184142bea0Sjakob 	new->tv_usec = 0;
1194142bea0Sjakob }
120