1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28*0Sstevel@tonic-gate /* All Rights Reserved */
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate /*
31*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
32*0Sstevel@tonic-gate * under license from the Regents of the University of California.
33*0Sstevel@tonic-gate */
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
36*0Sstevel@tonic-gate
37*0Sstevel@tonic-gate /*
38*0Sstevel@tonic-gate * Miscellaneous support routines for kernel implentation of AUTH_DES
39*0Sstevel@tonic-gate */
40*0Sstevel@tonic-gate
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate * rtime - get time from remote machine
43*0Sstevel@tonic-gate *
44*0Sstevel@tonic-gate * sets time, obtaining value from host
45*0Sstevel@tonic-gate * on the udp/time socket. Since timeserver returns
46*0Sstevel@tonic-gate * with time of day in seconds since Jan 1, 1900, must
47*0Sstevel@tonic-gate * subtract 86400(365*70 + 17) to get time
48*0Sstevel@tonic-gate * since Jan 1, 1970, which is what get/settimeofday
49*0Sstevel@tonic-gate * uses.
50*0Sstevel@tonic-gate */
51*0Sstevel@tonic-gate #include <sys/param.h>
52*0Sstevel@tonic-gate #include <sys/types.h>
53*0Sstevel@tonic-gate #include <sys/time.h>
54*0Sstevel@tonic-gate #include <sys/systm.h>
55*0Sstevel@tonic-gate #include <sys/errno.h>
56*0Sstevel@tonic-gate #include <sys/proc.h>
57*0Sstevel@tonic-gate #include <sys/user.h>
58*0Sstevel@tonic-gate #include <sys/socket.h>
59*0Sstevel@tonic-gate #include <sys/sysmacros.h>
60*0Sstevel@tonic-gate #include <netinet/in.h>
61*0Sstevel@tonic-gate #include <rpc/rpc.h>
62*0Sstevel@tonic-gate #include <sys/stream.h>
63*0Sstevel@tonic-gate #include <sys/strsubr.h>
64*0Sstevel@tonic-gate #include <sys/cred.h>
65*0Sstevel@tonic-gate #include <sys/utsname.h>
66*0Sstevel@tonic-gate #include <sys/vnode.h>
67*0Sstevel@tonic-gate #include <sys/file.h>
68*0Sstevel@tonic-gate #include <sys/uio.h>
69*0Sstevel@tonic-gate #include <sys/systeminfo.h>
70*0Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
71*0Sstevel@tonic-gate #include <sys/cmn_err.h>
72*0Sstevel@tonic-gate
73*0Sstevel@tonic-gate #define TOFFSET ((uint32_t)86400 * (365 * 70 + (70 / 4)))
74*0Sstevel@tonic-gate #define WRITTEN ((uint32_t)86400 * (365 * 86 + (86 / 4)))
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate #define NC_INET "inet" /* XXX */
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gate int
rtime(struct knetconfig * synconfig,struct netbuf * addrp,int calltype,struct timeval * timep,struct timeval * wait)79*0Sstevel@tonic-gate rtime(struct knetconfig *synconfig, struct netbuf *addrp, int calltype,
80*0Sstevel@tonic-gate struct timeval *timep, struct timeval *wait)
81*0Sstevel@tonic-gate {
82*0Sstevel@tonic-gate int error;
83*0Sstevel@tonic-gate int timo;
84*0Sstevel@tonic-gate time_t thetime;
85*0Sstevel@tonic-gate int32_t srvtime;
86*0Sstevel@tonic-gate uint32_t dummy;
87*0Sstevel@tonic-gate struct t_kunitdata *unitdata;
88*0Sstevel@tonic-gate struct t_call *server;
89*0Sstevel@tonic-gate TIUSER *tiptr;
90*0Sstevel@tonic-gate int type;
91*0Sstevel@tonic-gate int uderr;
92*0Sstevel@tonic-gate int i;
93*0Sstevel@tonic-gate int retries;
94*0Sstevel@tonic-gate mblk_t *mp;
95*0Sstevel@tonic-gate mblk_t *mp2;
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate retries = 5;
98*0Sstevel@tonic-gate if (calltype == 0) {
99*0Sstevel@tonic-gate again:
100*0Sstevel@tonic-gate RPCLOG0(8, "rtime: using old method\n");
101*0Sstevel@tonic-gate if ((error = t_kopen(NULL, synconfig->knc_rdev,
102*0Sstevel@tonic-gate FREAD|FWRITE, &tiptr, CRED())) != 0) {
103*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kopen %d\n", error);
104*0Sstevel@tonic-gate return (-1);
105*0Sstevel@tonic-gate }
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate if ((error = t_kbind(tiptr, NULL, NULL)) != 0) {
108*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
109*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kbind %d\n", error);
110*0Sstevel@tonic-gate return (-1);
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gate if (synconfig->knc_semantics == NC_TPI_CLTS) {
114*0Sstevel@tonic-gate if ((error = t_kalloc(tiptr, T_UNITDATA, T_UDATA|T_ADDR,
115*0Sstevel@tonic-gate (char **)&unitdata)) != 0) {
116*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kalloc %d\n", error);
117*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
118*0Sstevel@tonic-gate return (-1);
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate
121*0Sstevel@tonic-gate unitdata->addr.len = addrp->len;
122*0Sstevel@tonic-gate bcopy(addrp->buf, unitdata->addr.buf, unitdata->addr.len);
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gate dummy = 0;
125*0Sstevel@tonic-gate unitdata->udata.buf = (caddr_t)&dummy;
126*0Sstevel@tonic-gate unitdata->udata.len = sizeof (dummy);
127*0Sstevel@tonic-gate
128*0Sstevel@tonic-gate if ((error = t_ksndudata(tiptr, unitdata, NULL)) != 0) {
129*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_ksndudata %d\n", error);
130*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
131*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
132*0Sstevel@tonic-gate return (-1);
133*0Sstevel@tonic-gate }
134*0Sstevel@tonic-gate
135*0Sstevel@tonic-gate timo = TIMEVAL_TO_TICK(wait);
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate RPCLOG(8, "rtime: timo %x\n", timo);
138*0Sstevel@tonic-gate if ((error = t_kspoll(tiptr, timo, READWAIT, &type)) != 0) {
139*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kspoll %d\n", error);
140*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
141*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
142*0Sstevel@tonic-gate return (-1);
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate if (type == 0) {
146*0Sstevel@tonic-gate RPCLOG0(1, "rtime: t_kspoll timed out\n");
147*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
148*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
149*0Sstevel@tonic-gate return (-1);
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gate error = t_krcvudata(tiptr, unitdata, &type, &uderr);
153*0Sstevel@tonic-gate if (error != 0) {
154*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_krcvudata %d\n", error);
155*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
156*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
157*0Sstevel@tonic-gate return (-1);
158*0Sstevel@tonic-gate }
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate if (type == T_UDERR) {
161*0Sstevel@tonic-gate if (bcmp(addrp->buf, unitdata->addr.buf,
162*0Sstevel@tonic-gate unitdata->addr.len) != 0) {
163*0Sstevel@tonic-gate /*
164*0Sstevel@tonic-gate * Response comes from some other
165*0Sstevel@tonic-gate * destination:
166*0Sstevel@tonic-gate * ignore it since it's not related to the
167*0Sstevel@tonic-gate * request we just sent out.
168*0Sstevel@tonic-gate */
169*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata,
170*0Sstevel@tonic-gate T_UNITDATA);
171*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
172*0Sstevel@tonic-gate goto again;
173*0Sstevel@tonic-gate }
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate
176*0Sstevel@tonic-gate if (type != T_DATA) {
177*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_krcvudata returned type %d\n",
178*0Sstevel@tonic-gate type);
179*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
180*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
181*0Sstevel@tonic-gate if (retries-- == 0)
182*0Sstevel@tonic-gate return (-1);
183*0Sstevel@tonic-gate goto again;
184*0Sstevel@tonic-gate }
185*0Sstevel@tonic-gate
186*0Sstevel@tonic-gate if (unitdata->udata.len < sizeof (uint32_t)) {
187*0Sstevel@tonic-gate RPCLOG(1, "rtime: bad rcvd length %d\n",
188*0Sstevel@tonic-gate unitdata->udata.len);
189*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
190*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
191*0Sstevel@tonic-gate if (retries-- == 0)
192*0Sstevel@tonic-gate return (-1);
193*0Sstevel@tonic-gate goto again;
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate
196*0Sstevel@tonic-gate /* LINTED pointer alignment */
197*0Sstevel@tonic-gate thetime = (time_t)ntohl(*(uint32_t *)unitdata->udata.buf);
198*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate } else {
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gate if ((error = t_kalloc(tiptr, T_CALL, T_ADDR,
203*0Sstevel@tonic-gate (char **)&server)) != 0) {
204*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kalloc %d\n", error);
205*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
206*0Sstevel@tonic-gate return (-1);
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate server->addr.len = addrp->len;
210*0Sstevel@tonic-gate bcopy(addrp->buf, server->addr.buf, server->addr.len);
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate if ((error = t_kconnect(tiptr, server, NULL)) != 0) {
213*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kconnect %d\n", error);
214*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)server, T_CALL);
215*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
216*0Sstevel@tonic-gate return (-1);
217*0Sstevel@tonic-gate }
218*0Sstevel@tonic-gate (void) t_kfree(tiptr, (char *)server, T_CALL);
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gate timo = TIMEVAL_TO_TICK(wait);
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gate RPCLOG(8, "rtime: timo %x\n", timo);
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate i = 0;
225*0Sstevel@tonic-gate dummy = 0;
226*0Sstevel@tonic-gate
227*0Sstevel@tonic-gate /* now read up to 4 bytes from the TIME server */
228*0Sstevel@tonic-gate while (i < sizeof (dummy)) {
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate error = t_kspoll(tiptr, timo, READWAIT, &type);
231*0Sstevel@tonic-gate if (error != 0) {
232*0Sstevel@tonic-gate RPCLOG(1, "rtime: t_kspoll %d\n", error);
233*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
234*0Sstevel@tonic-gate return (-1);
235*0Sstevel@tonic-gate }
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gate if (type == 0) {
238*0Sstevel@tonic-gate RPCLOG0(1, "rtime: t_kspoll timed out\n");
239*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
240*0Sstevel@tonic-gate return (-1);
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gate error = tli_recv(tiptr, &mp, tiptr->fp->f_flag);
244*0Sstevel@tonic-gate if (error != 0) {
245*0Sstevel@tonic-gate RPCLOG(1, "rtime: tli_recv %d\n", error);
246*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
247*0Sstevel@tonic-gate return (-1);
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate if (mp->b_datap->db_type != M_DATA) {
251*0Sstevel@tonic-gate RPCLOG(1, "rtime: wrong msg type %d\n",
252*0Sstevel@tonic-gate mp->b_datap->db_type);
253*0Sstevel@tonic-gate RPCLOG(1, "rtime: wrong msg type: read %d"
254*0Sstevel@tonic-gate " bytes\n", i);
255*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
256*0Sstevel@tonic-gate freemsg(mp);
257*0Sstevel@tonic-gate return (-1);
258*0Sstevel@tonic-gate }
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate mp2 = mp;
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate /*
263*0Sstevel@tonic-gate * The outer loop iterates until we reach the end of
264*0Sstevel@tonic-gate * the mblk chain.
265*0Sstevel@tonic-gate */
266*0Sstevel@tonic-gate while (mp2 != NULL) {
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gate /*
269*0Sstevel@tonic-gate * The inner loop iterates until we've gotten
270*0Sstevel@tonic-gate * 4 bytes or until the mblk is exhausted.
271*0Sstevel@tonic-gate */
272*0Sstevel@tonic-gate while (i < sizeof (dummy) &&
273*0Sstevel@tonic-gate mp2->b_rptr < mp2->b_wptr) {
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate i++;
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gate /*
278*0Sstevel@tonic-gate * We avoid big-endian/little-endian
279*0Sstevel@tonic-gate * issues by serializing the result
280*0Sstevel@tonic-gate * one byte at a time.
281*0Sstevel@tonic-gate */
282*0Sstevel@tonic-gate dummy <<= 8;
283*0Sstevel@tonic-gate dummy += ((*mp2->b_rptr) & 0xFF);
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate mp2->b_rptr++;
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate
288*0Sstevel@tonic-gate mp2 = mp2->b_cont;
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate freemsg(mp);
292*0Sstevel@tonic-gate }
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate thetime = (time_t)dummy;
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gate (void) t_kclose(tiptr, 1);
298*0Sstevel@tonic-gate
299*0Sstevel@tonic-gate } else {
300*0Sstevel@tonic-gate CLIENT *client;
301*0Sstevel@tonic-gate struct timeval timout;
302*0Sstevel@tonic-gate
303*0Sstevel@tonic-gate RPCLOG0(8, "rtime: using new method\n");
304*0Sstevel@tonic-gate
305*0Sstevel@tonic-gate new_again:
306*0Sstevel@tonic-gate /*
307*0Sstevel@tonic-gate * We talk to rpcbind.
308*0Sstevel@tonic-gate */
309*0Sstevel@tonic-gate error = clnt_tli_kcreate(synconfig, addrp, (rpcprog_t)RPCBPROG,
310*0Sstevel@tonic-gate (rpcvers_t)RPCBVERS, 0, retries, CRED(), &client);
311*0Sstevel@tonic-gate
312*0Sstevel@tonic-gate if (error != 0) {
313*0Sstevel@tonic-gate RPCLOG(1,
314*0Sstevel@tonic-gate "rtime: clnt_tli_kcreate returned %d\n", error);
315*0Sstevel@tonic-gate return (-1);
316*0Sstevel@tonic-gate }
317*0Sstevel@tonic-gate timout.tv_sec = 60;
318*0Sstevel@tonic-gate timout.tv_usec = 0;
319*0Sstevel@tonic-gate error = clnt_call(client, RPCBPROC_GETTIME, (xdrproc_t)xdr_void,
320*0Sstevel@tonic-gate NULL, (xdrproc_t)xdr_u_int,
321*0Sstevel@tonic-gate (caddr_t)&srvtime, timout);
322*0Sstevel@tonic-gate thetime = srvtime;
323*0Sstevel@tonic-gate auth_destroy(client->cl_auth);
324*0Sstevel@tonic-gate clnt_destroy(client);
325*0Sstevel@tonic-gate if (error == RPC_UDERROR) {
326*0Sstevel@tonic-gate if (retries-- > 0)
327*0Sstevel@tonic-gate goto new_again;
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate if (error != RPC_SUCCESS) {
330*0Sstevel@tonic-gate RPCLOG(1, "rtime: time sync clnt_call returned %d\n",
331*0Sstevel@tonic-gate error);
332*0Sstevel@tonic-gate error = EIO;
333*0Sstevel@tonic-gate return (-1);
334*0Sstevel@tonic-gate }
335*0Sstevel@tonic-gate }
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gate if (calltype != 0)
338*0Sstevel@tonic-gate thetime += TOFFSET;
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate RPCLOG(8, "rtime: thetime = %lx\n", thetime);
341*0Sstevel@tonic-gate
342*0Sstevel@tonic-gate if (thetime < WRITTEN) {
343*0Sstevel@tonic-gate RPCLOG(1, "rtime: time returned is too far in past %lx",
344*0Sstevel@tonic-gate thetime);
345*0Sstevel@tonic-gate RPCLOG(1, "rtime: WRITTEN %x", WRITTEN);
346*0Sstevel@tonic-gate return (-1);
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate thetime -= TOFFSET;
349*0Sstevel@tonic-gate
350*0Sstevel@tonic-gate timep->tv_sec = thetime;
351*0Sstevel@tonic-gate RPCLOG(8, "rtime: timep->tv_sec = %lx\n", timep->tv_sec);
352*0Sstevel@tonic-gate RPCLOG(8, "rtime: machine time = %lx\n", gethrestime_sec());
353*0Sstevel@tonic-gate timep->tv_usec = 0;
354*0Sstevel@tonic-gate RPCLOG0(8, "rtime: returning success\n");
355*0Sstevel@tonic-gate return (0);
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate
358*0Sstevel@tonic-gate /*
359*0Sstevel@tonic-gate * What is my network name?
360*0Sstevel@tonic-gate * WARNING: this gets the network name in sun unix format.
361*0Sstevel@tonic-gate * Other operating systems (non-unix) are free to put something else
362*0Sstevel@tonic-gate * here.
363*0Sstevel@tonic-gate *
364*0Sstevel@tonic-gate * Return 0 on success
365*0Sstevel@tonic-gate * Return RPC errors (non-zero values) if failed.
366*0Sstevel@tonic-gate */
367*0Sstevel@tonic-gate enum clnt_stat
kgetnetname(char * netname)368*0Sstevel@tonic-gate kgetnetname(char *netname)
369*0Sstevel@tonic-gate {
370*0Sstevel@tonic-gate return (key_getnetname(netname, CRED()));
371*0Sstevel@tonic-gate }
372