/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley * 4.3 BSD under license from the Regents of the University of * California. */ /* * get time from remote machine * * gets time, obtaining value from host * on the (udp, tcp)/time tli connection. Since timeserver returns * with time of day in seconds since Jan 1, 1900, must * subtract seconds before Jan 1, 1970 to get * what unix uses. */ #include "mt.h" #include #include #include #include #include #include extern int __rpc_timeval_to_msec(); #ifdef DEBUG #define debug(msg) t_error(msg) #else #define debug(msg) #endif #define NYEARS (1970 - 1900) #define TOFFSET ((uint_t)60*60*24*(365*NYEARS + (NYEARS/4))) /* * This is based upon the internet time server, but it contacts it by * using TLI instead of socket. */ int rtime_tli(char *host, struct timeval *timep, struct timeval *timeout) { uint32_t thetime; int flag; struct nd_addrlist *nlist = NULL; struct nd_hostserv rpcbind_hs; struct netconfig *nconf = NULL; int foundit = 0; int fd = -1; nconf = __rpc_getconfip(timeout == NULL ? "tcp" : "udp"); if (nconf == NULL) goto error; if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) { debug("open"); goto error; } if (t_bind(fd, NULL, NULL) < 0) { debug("bind"); goto error; } /* Get the address of the rpcbind */ rpcbind_hs.h_host = host; rpcbind_hs.h_serv = "time"; /* Basically get the address of the remote machine on IP */ if (netdir_getbyname(nconf, &rpcbind_hs, &nlist)) goto error; if (nconf->nc_semantics == NC_TPI_CLTS) { struct t_unitdata tu_data; struct pollfd pfd; int res; int msec; tu_data.addr = *nlist->n_addrs; tu_data.udata.buf = (char *)&thetime; tu_data.udata.len = (uint_t)sizeof (thetime); tu_data.udata.maxlen = tu_data.udata.len; tu_data.opt.len = 0; tu_data.opt.maxlen = 0; if (t_sndudata(fd, &tu_data) == -1) { debug("udp"); goto error; } pfd.fd = fd; pfd.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; msec = __rpc_timeval_to_msec(timeout); do { res = poll(&pfd, 1, msec); } while (res < 0); if ((res <= 0) || (pfd.revents & POLLNVAL)) goto error; if (t_rcvudata(fd, &tu_data, &flag) < 0) { debug("udp"); goto error; } foundit = 1; } else { struct t_call sndcall; sndcall.addr = *nlist->n_addrs; sndcall.opt.len = sndcall.opt.maxlen = 0; sndcall.udata.len = sndcall.udata.maxlen = 0; if (t_connect(fd, &sndcall, NULL) == -1) { debug("tcp"); goto error; } if (t_rcv(fd, (char *)&thetime, (uint_t)sizeof (thetime), &flag) != (uint_t)sizeof (thetime)) { debug("tcp"); goto error; } foundit = 1; } thetime = ntohl(thetime); timep->tv_sec = thetime - TOFFSET; timep->tv_usec = 0; error: if (nconf) { (void) freenetconfigent(nconf); if (fd != -1) { (void) t_close(fd); if (nlist) netdir_free((char *)nlist, ND_ADDRLIST); } } return (foundit); }