1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 /* 31 * Portions of this source code were derived from Berkeley 32 * 4.3 BSD under license from the Regents of the University of 33 * California. 34 */ 35 36 #pragma ident "%Z%%M% %I% %E% SMI" 37 38 /* 39 * get time from remote machine 40 * 41 * gets time, obtaining value from host 42 * on the (udp, tcp)/time tli connection. Since timeserver returns 43 * with time of day in seconds since Jan 1, 1900, must 44 * subtract seconds before Jan 1, 1970 to get 45 * what unix uses. 46 */ 47 #include "mt.h" 48 #include <rpc/rpc.h> 49 #include <errno.h> 50 #include <sys/poll.h> 51 #include <rpc/nettype.h> 52 #include <netdir.h> 53 #include <stdio.h> 54 55 extern int __rpc_timeval_to_msec(); 56 57 #ifdef DEBUG 58 #define debug(msg) t_error(msg) 59 #else 60 #define debug(msg) 61 #endif 62 63 #define NYEARS (1970 - 1900) 64 #define TOFFSET ((uint_t)60*60*24*(365*NYEARS + (NYEARS/4))) 65 66 /* 67 * This is based upon the internet time server, but it contacts it by 68 * using TLI instead of socket. 69 */ 70 int 71 rtime_tli(char *host, struct timeval *timep, struct timeval *timeout) 72 { 73 uint32_t thetime; 74 int flag; 75 struct nd_addrlist *nlist = NULL; 76 struct nd_hostserv rpcbind_hs; 77 struct netconfig *nconf = NULL; 78 int foundit = 0; 79 int fd = -1; 80 81 nconf = __rpc_getconfip(timeout == NULL ? "tcp" : "udp"); 82 if (nconf == NULL) 83 goto error; 84 85 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) { 86 debug("open"); 87 goto error; 88 } 89 if (t_bind(fd, NULL, NULL) < 0) { 90 debug("bind"); 91 goto error; 92 } 93 94 /* Get the address of the rpcbind */ 95 rpcbind_hs.h_host = host; 96 rpcbind_hs.h_serv = "time"; 97 /* Basically get the address of the remote machine on IP */ 98 if (netdir_getbyname(nconf, &rpcbind_hs, &nlist)) 99 goto error; 100 101 if (nconf->nc_semantics == NC_TPI_CLTS) { 102 struct t_unitdata tu_data; 103 struct pollfd pfd; 104 int res; 105 int msec; 106 107 tu_data.addr = *nlist->n_addrs; 108 tu_data.udata.buf = (char *)&thetime; 109 tu_data.udata.len = (uint_t)sizeof (thetime); 110 tu_data.udata.maxlen = tu_data.udata.len; 111 tu_data.opt.len = 0; 112 tu_data.opt.maxlen = 0; 113 if (t_sndudata(fd, &tu_data) == -1) { 114 debug("udp"); 115 goto error; 116 } 117 pfd.fd = fd; 118 pfd.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; 119 120 msec = __rpc_timeval_to_msec(timeout); 121 do { 122 res = poll(&pfd, 1, msec); 123 } while (res < 0); 124 if ((res <= 0) || (pfd.revents & POLLNVAL)) 125 goto error; 126 if (t_rcvudata(fd, &tu_data, &flag) < 0) { 127 debug("udp"); 128 goto error; 129 } 130 foundit = 1; 131 } else { 132 struct t_call sndcall; 133 134 sndcall.addr = *nlist->n_addrs; 135 sndcall.opt.len = sndcall.opt.maxlen = 0; 136 sndcall.udata.len = sndcall.udata.maxlen = 0; 137 138 if (t_connect(fd, &sndcall, NULL) == -1) { 139 debug("tcp"); 140 goto error; 141 } 142 if (t_rcv(fd, (char *)&thetime, (uint_t)sizeof (thetime), &flag) 143 != (uint_t)sizeof (thetime)) { 144 debug("tcp"); 145 goto error; 146 } 147 foundit = 1; 148 } 149 150 thetime = ntohl(thetime); 151 timep->tv_sec = thetime - TOFFSET; 152 timep->tv_usec = 0; 153 154 error: 155 if (nconf) { 156 (void) freenetconfigent(nconf); 157 if (fd != -1) { 158 (void) t_close(fd); 159 if (nlist) 160 netdir_free((char *)nlist, ND_ADDRLIST); 161 } 162 } 163 return (foundit); 164 } 165