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
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.
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]
23 * Copyright 2014 Gary Mills
24 * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright (c) 2018, Joyent, Inc.
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
33 * Portions of this source code were derived from Berkeley 4.3 BSD
34 * under license from the Regents of the University of California.
38 * Miscellaneous support routines for kernel implentation of AUTH_DES
42 * rtime - get time from remote machine
44 * sets time, obtaining value from host
45 * on the udp/time socket. Since timeserver returns
46 * with time of day in seconds since Jan 1, 1900, must
47 * subtract 86400(365*70 + 17) to get time
48 * since Jan 1, 1970, which is what get/settimeofday
51 #include <sys/param.h>
52 #include <sys/types.h>
54 #include <sys/systm.h>
55 #include <sys/errno.h>
58 #include <sys/socket.h>
59 #include <sys/sysmacros.h>
60 #include <netinet/in.h>
62 #include <sys/stream.h>
63 #include <sys/strsubr.h>
65 #include <sys/utsname.h>
66 #include <sys/vnode.h>
69 #include <sys/systeminfo.h>
70 #include <rpc/rpcb_prot.h>
71 #include <sys/cmn_err.h>
73 #define TOFFSET ((uint32_t)86400 * (365 * 70 + (70 / 4)))
74 #define WRITTEN ((uint32_t)86400 * (365 * 86 + (86 / 4)))
76 #define NC_INET "inet" /* XXX */
79 rtime(struct knetconfig
*synconfig
, struct netbuf
*addrp
, int calltype
,
80 struct timeval
*timep
, struct timeval
*wait
)
87 struct t_kunitdata
*unitdata
;
88 struct t_call
*server
;
100 RPCLOG0(8, "rtime: using old method\n");
101 if ((error
= t_kopen(NULL
, synconfig
->knc_rdev
,
102 FREAD
|FWRITE
, &tiptr
, CRED())) != 0) {
103 RPCLOG(1, "rtime: t_kopen %d\n", error
);
107 if ((error
= t_kbind(tiptr
, NULL
, NULL
)) != 0) {
108 (void) t_kclose(tiptr
, 1);
109 RPCLOG(1, "rtime: t_kbind %d\n", error
);
113 if (synconfig
->knc_semantics
== NC_TPI_CLTS
) {
114 if ((error
= t_kalloc(tiptr
, T_UNITDATA
,
115 T_UDATA
|T_ADDR
, (char **)&unitdata
)) != 0) {
116 RPCLOG(1, "rtime: t_kalloc %d\n", error
);
117 (void) t_kclose(tiptr
, 1);
121 unitdata
->addr
.len
= addrp
->len
;
122 bcopy(addrp
->buf
, unitdata
->addr
.buf
,
126 unitdata
->udata
.buf
= (caddr_t
)&dummy
;
127 unitdata
->udata
.len
= sizeof (dummy
);
129 if ((error
= t_ksndudata(tiptr
, unitdata
, NULL
)) !=
131 RPCLOG(1, "rtime: t_ksndudata %d\n", error
);
132 (void) t_kfree(tiptr
, (char *)unitdata
,
134 (void) t_kclose(tiptr
, 1);
138 timo
= TIMEVAL_TO_TICK(wait
);
140 RPCLOG(8, "rtime: timo %x\n", timo
);
141 if ((error
= t_kspoll(tiptr
, timo
, READWAIT
,
143 RPCLOG(1, "rtime: t_kspoll %d\n", error
);
144 (void) t_kfree(tiptr
, (char *)unitdata
,
146 (void) t_kclose(tiptr
, 1);
151 RPCLOG0(1, "rtime: t_kspoll timed out\n");
152 (void) t_kfree(tiptr
, (char *)unitdata
,
154 (void) t_kclose(tiptr
, 1);
158 error
= t_krcvudata(tiptr
, unitdata
, &type
, &uderr
);
160 RPCLOG(1, "rtime: t_krcvudata %d\n", error
);
161 (void) t_kfree(tiptr
, (char *)unitdata
,
163 (void) t_kclose(tiptr
, 1);
164 if (error
== EBADMSG
&& retries
-- > 0)
169 if (type
== T_UDERR
) {
170 if (bcmp(addrp
->buf
, unitdata
->addr
.buf
,
171 unitdata
->addr
.len
) != 0) {
173 * Response comes from some other
175 * ignore it since it's not related to the
176 * request we just sent out.
178 (void) t_kfree(tiptr
, (char *)unitdata
,
180 (void) t_kclose(tiptr
, 1);
185 if (type
!= T_DATA
) {
187 "rtime: t_krcvudata returned type %d\n",
189 (void) t_kfree(tiptr
, (char *)unitdata
,
191 (void) t_kclose(tiptr
, 1);
197 if (unitdata
->udata
.len
< sizeof (uint32_t)) {
198 RPCLOG(1, "rtime: bad rcvd length %d\n",
199 unitdata
->udata
.len
);
200 (void) t_kfree(tiptr
, (char *)unitdata
,
202 (void) t_kclose(tiptr
, 1);
208 thetime
= (time_t)ntohl(
209 /* LINTED pointer alignment */
210 *(uint32_t *)unitdata
->udata
.buf
);
211 (void) t_kfree(tiptr
, (char *)unitdata
, T_UNITDATA
);
215 if ((error
= t_kalloc(tiptr
, T_CALL
, T_ADDR
,
216 (char **)&server
)) != 0) {
217 RPCLOG(1, "rtime: t_kalloc %d\n", error
);
218 (void) t_kclose(tiptr
, 1);
222 server
->addr
.len
= addrp
->len
;
223 bcopy(addrp
->buf
, server
->addr
.buf
, server
->addr
.len
);
225 if ((error
= t_kconnect(tiptr
, server
, NULL
)) != 0) {
226 RPCLOG(1, "rtime: t_kconnect %d\n", error
);
227 (void) t_kfree(tiptr
, (char *)server
, T_CALL
);
228 (void) t_kclose(tiptr
, 1);
231 (void) t_kfree(tiptr
, (char *)server
, T_CALL
);
233 timo
= TIMEVAL_TO_TICK(wait
);
235 RPCLOG(8, "rtime: timo %x\n", timo
);
240 /* now read up to 4 bytes from the TIME server */
241 while (i
< sizeof (dummy
)) {
243 error
= t_kspoll(tiptr
, timo
, READWAIT
, &type
);
245 RPCLOG(1, "rtime: t_kspoll %d\n",
247 (void) t_kclose(tiptr
, 1);
253 "rtime: t_kspoll timed out\n");
254 (void) t_kclose(tiptr
, 1);
258 error
= tli_recv(tiptr
, &mp
,
261 RPCLOG(1, "rtime: tli_recv %d\n",
263 (void) t_kclose(tiptr
, 1);
267 if (mp
->b_datap
->db_type
!= M_DATA
) {
268 RPCLOG(1, "rtime: wrong msg type %d\n",
269 mp
->b_datap
->db_type
);
271 "rtime: wrong msg type: read %d"
273 (void) t_kclose(tiptr
, 1);
281 * The outer loop iterates until we reach the
282 * end of the mblk chain.
284 while (mp2
!= NULL
) {
287 * The inner loop iterates until
288 * we've gotten 4 bytes or until
289 * the mblk is exhausted.
291 while (i
< sizeof (dummy
) &&
292 mp2
->b_rptr
< mp2
->b_wptr
) {
297 * We avoid big-endian/little-endian
298 * issues by serializing the result
299 * one byte at a time.
302 dummy
+= ((*mp2
->b_rptr
) &
314 thetime
= (time_t)dummy
;
317 (void) t_kclose(tiptr
, 1);
321 struct timeval timout
;
323 RPCLOG0(8, "rtime: using new method\n");
327 * We talk to rpcbind.
329 error
= clnt_tli_kcreate(synconfig
, addrp
, (rpcprog_t
)RPCBPROG
,
330 (rpcvers_t
)RPCBVERS
, 0, retries
, CRED(), &client
);
334 "rtime: clnt_tli_kcreate returned %d\n", error
);
339 error
= clnt_call(client
, RPCBPROC_GETTIME
, (xdrproc_t
)xdr_void
,
340 NULL
, (xdrproc_t
)xdr_u_int
,
341 (caddr_t
)&srvtime
, timout
);
343 auth_destroy(client
->cl_auth
);
344 clnt_destroy(client
);
345 if (error
== RPC_UDERROR
) {
349 if (error
!= RPC_SUCCESS
) {
350 RPCLOG(1, "rtime: time sync clnt_call returned %d\n",
360 RPCLOG(8, "rtime: thetime = %lx\n", thetime
);
362 if (thetime
< WRITTEN
) {
363 RPCLOG(1, "rtime: time returned is too far in past %lx",
365 RPCLOG(1, "rtime: WRITTEN %x", WRITTEN
);
370 timep
->tv_sec
= thetime
;
371 RPCLOG(8, "rtime: timep->tv_sec = %lx\n", timep
->tv_sec
);
372 RPCLOG(8, "rtime: machine time = %lx\n", gethrestime_sec());
374 RPCLOG0(8, "rtime: returning success\n");
379 * What is my network name?
380 * WARNING: this gets the network name in sun unix format.
381 * Other operating systems (non-unix) are free to put something else
384 * Return 0 on success
385 * Return RPC errors (non-zero values) if failed.
388 kgetnetname(char *netname
)
390 return (key_getnetname(netname
, CRED()));