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
rtime_tli(char * host,struct timeval * timep,struct timeval * timeout)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