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 /* 37 * get time from remote machine 38 * 39 * gets time, obtaining value from host 40 * on the (udp, tcp)/time tli connection. Since timeserver returns 41 * with time of day in seconds since Jan 1, 1900, must 42 * subtract seconds before Jan 1, 1970 to get 43 * what unix uses. 44 */ 45 #include "mt.h" 46 #include <rpc/rpc.h> 47 #include <errno.h> 48 #include <sys/poll.h> 49 #include <rpc/nettype.h> 50 #include <netdir.h> 51 #include <stdio.h> 52 53 extern int __rpc_timeval_to_msec(); 54 55 #ifdef DEBUG 56 #define debug(msg) t_error(msg) 57 #else 58 #define debug(msg) 59 #endif 60 61 #define NYEARS (1970 - 1900) 62 #define TOFFSET ((uint_t)60*60*24*(365*NYEARS + (NYEARS/4))) 63 64 /* 65 * This is based upon the internet time server, but it contacts it by 66 * using TLI instead of socket. 67 */ 68 int 69 rtime_tli(char *host, struct timeval *timep, struct timeval *timeout) 70 { 71 uint32_t thetime; 72 int flag; 73 struct nd_addrlist *nlist = NULL; 74 struct nd_hostserv rpcbind_hs; 75 struct netconfig *nconf = NULL; 76 int foundit = 0; 77 int fd = -1; 78 79 nconf = __rpc_getconfip(timeout == NULL ? "tcp" : "udp"); 80 if (nconf == NULL) 81 goto error; 82 83 if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) == -1) { 84 debug("open"); 85 goto error; 86 } 87 if (t_bind(fd, NULL, NULL) < 0) { 88 debug("bind"); 89 goto error; 90 } 91 92 /* Get the address of the rpcbind */ 93 rpcbind_hs.h_host = host; 94 rpcbind_hs.h_serv = "time"; 95 /* Basically get the address of the remote machine on IP */ 96 if (netdir_getbyname(nconf, &rpcbind_hs, &nlist)) 97 goto error; 98 99 if (nconf->nc_semantics == NC_TPI_CLTS) { 100 struct t_unitdata tu_data; 101 struct pollfd pfd; 102 int res; 103 int msec; 104 105 tu_data.addr = *nlist->n_addrs; 106 tu_data.udata.buf = (char *)&thetime; 107 tu_data.udata.len = (uint_t)sizeof (thetime); 108 tu_data.udata.maxlen = tu_data.udata.len; 109 tu_data.opt.len = 0; 110 tu_data.opt.maxlen = 0; 111 if (t_sndudata(fd, &tu_data) == -1) { 112 debug("udp"); 113 goto error; 114 } 115 pfd.fd = fd; 116 pfd.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; 117 118 msec = __rpc_timeval_to_msec(timeout); 119 do { 120 res = poll(&pfd, 1, msec); 121 } while (res < 0); 122 if ((res <= 0) || (pfd.revents & POLLNVAL)) 123 goto error; 124 if (t_rcvudata(fd, &tu_data, &flag) < 0) { 125 debug("udp"); 126 goto error; 127 } 128 foundit = 1; 129 } else { 130 struct t_call sndcall; 131 132 sndcall.addr = *nlist->n_addrs; 133 sndcall.opt.len = sndcall.opt.maxlen = 0; 134 sndcall.udata.len = sndcall.udata.maxlen = 0; 135 136 if (t_connect(fd, &sndcall, NULL) == -1) { 137 debug("tcp"); 138 goto error; 139 } 140 if (t_rcv(fd, (char *)&thetime, (uint_t)sizeof (thetime), &flag) 141 != (uint_t)sizeof (thetime)) { 142 debug("tcp"); 143 goto error; 144 } 145 foundit = 1; 146 } 147 148 thetime = ntohl(thetime); 149 timep->tv_sec = thetime - TOFFSET; 150 timep->tv_usec = 0; 151 152 error: 153 if (nconf) { 154 (void) freenetconfigent(nconf); 155 if (fd != -1) { 156 (void) t_close(fd); 157 if (nlist) 158 netdir_free((char *)nlist, ND_ADDRLIST); 159 } 160 } 161 return (foundit); 162 } 163