1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21148c5f43SAlan Wright
22da6c28aaSamw /*
23148c5f43SAlan Wright * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24b3700b07SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25da6c28aaSamw */
26da6c28aaSamw
27da6c28aaSamw /*
28da6c28aaSamw * Server Service (srvsvc) client side RPC library interface. The
29da6c28aaSamw * srvsvc interface allows a client to query a server for information
30da6c28aaSamw * on shares, sessions, connections and files on the server. Some
31da6c28aaSamw * functions are available via anonymous IPC while others require
32da6c28aaSamw * administrator privilege. Also, some functions return NT status
33da6c28aaSamw * values while others return Win32 errors codes.
34da6c28aaSamw */
35da6c28aaSamw
36da6c28aaSamw #include <sys/errno.h>
37*3299f39fSGordon Ross #include <sys/tzfile.h>
38da6c28aaSamw #include <stdio.h>
39da6c28aaSamw #include <time.h>
40da6c28aaSamw #include <strings.h>
41*3299f39fSGordon Ross #include <unistd.h>
42da6c28aaSamw
43da6c28aaSamw #include <smbsrv/libsmb.h>
448d7e4166Sjose borrego #include <smbsrv/libmlsvc.h>
45da6c28aaSamw #include <smbsrv/smbinfo.h>
46da6c28aaSamw #include <smbsrv/ndl/srvsvc.ndl>
47da6c28aaSamw
48da6c28aaSamw /*
49da6c28aaSamw * Information level for NetShareGetInfo.
50da6c28aaSamw */
51da6c28aaSamw DWORD srvsvc_info_level = 1;
52da6c28aaSamw
53da6c28aaSamw /*
548d7e4166Sjose borrego * Bind to the the SRVSVC.
55da6c28aaSamw *
5655bf511dSas * If username argument is NULL, an anonymous connection will be established.
5755bf511dSas * Otherwise, an authenticated connection will be established.
58da6c28aaSamw */
5955bf511dSas static int
srvsvc_open(char * server,char * domain,char * username,mlsvc_handle_t * handle)608d7e4166Sjose borrego srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle)
61da6c28aaSamw {
62a0aa776eSAlan Wright smb_domainex_t di;
63da6c28aaSamw
64da6c28aaSamw if (server == NULL || domain == NULL) {
658d7e4166Sjose borrego if (!smb_domain_getinfo(&di))
6655bf511dSas return (-1);
67da6c28aaSamw
68b3700b07SGordon Ross server = di.d_dci.dc_name;
69a0aa776eSAlan Wright domain = di.d_primary.di_nbname;
7055bf511dSas }
71da6c28aaSamw
7255bf511dSas if (username == NULL)
7355bf511dSas username = MLSVC_ANON_USER;
74da6c28aaSamw
75b3700b07SGordon Ross if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") != 0)
76da6c28aaSamw return (-1);
77da6c28aaSamw
788d7e4166Sjose borrego return (0);
79da6c28aaSamw }
80da6c28aaSamw
81da6c28aaSamw /*
828d7e4166Sjose borrego * Unbind the SRVSVC connection.
83da6c28aaSamw */
848d7e4166Sjose borrego static void
srvsvc_close(mlsvc_handle_t * handle)858d7e4166Sjose borrego srvsvc_close(mlsvc_handle_t *handle)
86da6c28aaSamw {
878d7e4166Sjose borrego ndr_rpc_unbind(handle);
88da6c28aaSamw }
89da6c28aaSamw
90da6c28aaSamw /*
91da6c28aaSamw * This is a client side routine for NetShareGetInfo.
92da6c28aaSamw * Levels 0 and 1 work with an anonymous connection but
93da6c28aaSamw * level 2 requires administrator access.
94da6c28aaSamw */
95da6c28aaSamw int
srvsvc_net_share_get_info(char * server,char * domain,char * netname)96da6c28aaSamw srvsvc_net_share_get_info(char *server, char *domain, char *netname)
97da6c28aaSamw {
98da6c28aaSamw struct mlsm_NetShareGetInfo arg;
99da6c28aaSamw mlsvc_handle_t handle;
100da6c28aaSamw int rc;
101da6c28aaSamw int opnum;
102eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_0 *info0;
103eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_1 *info1;
104eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_2 *info2;
105da6c28aaSamw int len;
106a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
107da6c28aaSamw
108da6c28aaSamw if (netname == NULL)
109da6c28aaSamw return (-1);
110da6c28aaSamw
111da6c28aaSamw if (srvsvc_info_level == 2)
112a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
113da6c28aaSamw
1148d7e4166Sjose borrego if (srvsvc_open(server, domain, user, &handle) != 0)
115da6c28aaSamw return (-1);
116da6c28aaSamw
117da6c28aaSamw opnum = SRVSVC_OPNUM_NetShareGetInfo;
118da6c28aaSamw bzero(&arg, sizeof (struct mlsm_NetShareGetInfo));
119da6c28aaSamw
120da6c28aaSamw len = strlen(server) + 4;
1218d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len);
122da6c28aaSamw if (arg.servername == NULL) {
1238d7e4166Sjose borrego srvsvc_close(&handle);
124da6c28aaSamw return (-1);
125da6c28aaSamw }
126da6c28aaSamw
127da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
128da6c28aaSamw arg.netname = (LPTSTR)netname;
129da6c28aaSamw arg.level = srvsvc_info_level; /* share information level */
130da6c28aaSamw
1318d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg);
132da6c28aaSamw if ((rc != 0) || (arg.status != 0)) {
1338d7e4166Sjose borrego srvsvc_close(&handle);
134da6c28aaSamw return (-1);
135da6c28aaSamw }
136da6c28aaSamw
137da6c28aaSamw switch (arg.result.switch_value) {
138da6c28aaSamw case 0:
139da6c28aaSamw info0 = arg.result.ru.info0;
140da6c28aaSamw smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname);
141da6c28aaSamw break;
142da6c28aaSamw
143da6c28aaSamw case 1:
144da6c28aaSamw info1 = arg.result.ru.info1;
145da6c28aaSamw smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname);
146da6c28aaSamw smb_tracef("srvsvc shi1_type=%u", info1->shi1_type);
147da6c28aaSamw
148da6c28aaSamw if (info1->shi1_comment)
149da6c28aaSamw smb_tracef("srvsvc shi1_comment=%s",
150da6c28aaSamw info1->shi1_comment);
151da6c28aaSamw break;
152da6c28aaSamw
153da6c28aaSamw case 2:
154da6c28aaSamw info2 = arg.result.ru.info2;
155da6c28aaSamw smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname);
156da6c28aaSamw smb_tracef("srvsvc shi2_type=%u", info2->shi2_type);
157da6c28aaSamw
158da6c28aaSamw if (info2->shi2_comment)
159da6c28aaSamw smb_tracef("srvsvc shi2_comment=%s",
160da6c28aaSamw info2->shi2_comment);
161da6c28aaSamw
162da6c28aaSamw smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions);
163da6c28aaSamw smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses);
164da6c28aaSamw smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses);
165da6c28aaSamw
166da6c28aaSamw if (info2->shi2_path)
167da6c28aaSamw smb_tracef("srvsvc shi2_path=%s", info2->shi2_path);
168da6c28aaSamw
169da6c28aaSamw if (info2->shi2_passwd)
170da6c28aaSamw smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd);
171da6c28aaSamw break;
172da6c28aaSamw
173da6c28aaSamw default:
174da6c28aaSamw smb_tracef("srvsvc: unknown level");
175da6c28aaSamw break;
176da6c28aaSamw }
177da6c28aaSamw
1788d7e4166Sjose borrego srvsvc_close(&handle);
179da6c28aaSamw return (0);
180da6c28aaSamw }
181da6c28aaSamw
182da6c28aaSamw /*
183da6c28aaSamw * This is a client side routine for NetSessionEnum.
184da6c28aaSamw * NetSessionEnum requires administrator rights.
185da6c28aaSamw */
186da6c28aaSamw int
srvsvc_net_session_enum(char * server,char * domain,char * netname)187da6c28aaSamw srvsvc_net_session_enum(char *server, char *domain, char *netname)
188da6c28aaSamw {
189da6c28aaSamw struct mslm_NetSessionEnum arg;
190da6c28aaSamw mlsvc_handle_t handle;
191da6c28aaSamw int rc;
192da6c28aaSamw int opnum;
193da6c28aaSamw struct mslm_infonres infonres;
194da6c28aaSamw struct mslm_SESSION_INFO_1 *nsi1;
195da6c28aaSamw int len;
196a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
197da6c28aaSamw
198da6c28aaSamw if (netname == NULL)
199da6c28aaSamw return (-1);
200da6c28aaSamw
201a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
202a0aa776eSAlan Wright
2038d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle);
204da6c28aaSamw if (rc != 0)
205da6c28aaSamw return (-1);
206da6c28aaSamw
207da6c28aaSamw opnum = SRVSVC_OPNUM_NetSessionEnum;
208da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetSessionEnum));
209da6c28aaSamw
210da6c28aaSamw len = strlen(server) + 4;
2118d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len);
212da6c28aaSamw if (arg.servername == NULL) {
2138d7e4166Sjose borrego srvsvc_close(&handle);
214da6c28aaSamw return (-1);
215da6c28aaSamw }
216da6c28aaSamw
217da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
218da6c28aaSamw infonres.entriesread = 0;
219da6c28aaSamw infonres.entries = 0;
220da6c28aaSamw arg.level = 1;
221da6c28aaSamw arg.result.level = 1;
222da6c28aaSamw arg.result.bufptr.p = &infonres;
223da6c28aaSamw arg.resume_handle = 0;
224da6c28aaSamw arg.pref_max_len = 0xFFFFFFFF;
225da6c28aaSamw
2268d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg);
227da6c28aaSamw if ((rc != 0) || (arg.status != 0)) {
2288d7e4166Sjose borrego srvsvc_close(&handle);
229da6c28aaSamw return (-1);
230da6c28aaSamw }
231da6c28aaSamw
232da6c28aaSamw /* Only the first session info is dereferenced. */
233da6c28aaSamw nsi1 = ((struct mslm_infonres *)arg.result.bufptr.p)->entries;
234da6c28aaSamw
235da6c28aaSamw smb_tracef("srvsvc switch_value=%d", arg.level);
236da6c28aaSamw smb_tracef("srvsvc sesi1_cname=%s", nsi1->sesi1_cname);
237da6c28aaSamw smb_tracef("srvsvc sesi1_uname=%s", nsi1->sesi1_uname);
238da6c28aaSamw smb_tracef("srvsvc sesi1_nopens=%u", nsi1->sesi1_nopens);
239da6c28aaSamw smb_tracef("srvsvc sesi1_time=%u", nsi1->sesi1_time);
240da6c28aaSamw smb_tracef("srvsvc sesi1_itime=%u", nsi1->sesi1_itime);
241da6c28aaSamw smb_tracef("srvsvc sesi1_uflags=%u", nsi1->sesi1_uflags);
242da6c28aaSamw
2438d7e4166Sjose borrego srvsvc_close(&handle);
244da6c28aaSamw return (0);
245da6c28aaSamw }
246da6c28aaSamw
247da6c28aaSamw /*
248da6c28aaSamw * This is a client side routine for NetConnectEnum.
249da6c28aaSamw * NetConnectEnum requires administrator rights.
250da6c28aaSamw * Level 0 and level 1 requests are supported.
251da6c28aaSamw */
252da6c28aaSamw int
srvsvc_net_connect_enum(char * server,char * domain,char * netname,int level)253da6c28aaSamw srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level)
254da6c28aaSamw {
255da6c28aaSamw struct mslm_NetConnectEnum arg;
256da6c28aaSamw mlsvc_handle_t handle;
257da6c28aaSamw int rc;
258da6c28aaSamw int opnum;
259da6c28aaSamw struct mslm_NetConnectInfo1 info1;
260da6c28aaSamw struct mslm_NetConnectInfo0 info0;
261da6c28aaSamw struct mslm_NetConnectInfoBuf1 *cib1;
262da6c28aaSamw int len;
263a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
264da6c28aaSamw
265da6c28aaSamw if (netname == NULL)
266da6c28aaSamw return (-1);
267da6c28aaSamw
268a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
269a0aa776eSAlan Wright
2708d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle);
271da6c28aaSamw if (rc != 0)
272da6c28aaSamw return (-1);
273da6c28aaSamw
274da6c28aaSamw opnum = SRVSVC_OPNUM_NetConnectEnum;
275da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetConnectEnum));
276da6c28aaSamw
277da6c28aaSamw len = strlen(server) + 4;
2788d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len);
279da6c28aaSamw if (arg.servername == NULL) {
2808d7e4166Sjose borrego srvsvc_close(&handle);
281da6c28aaSamw return (-1);
282da6c28aaSamw }
283da6c28aaSamw
284da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
285da6c28aaSamw arg.qualifier = (LPTSTR)netname;
286da6c28aaSamw
287da6c28aaSamw switch (level) {
288da6c28aaSamw case 0:
289da6c28aaSamw arg.info.level = 0;
290da6c28aaSamw arg.info.switch_value = 0;
291da6c28aaSamw arg.info.ru.info0 = &info0;
292da6c28aaSamw info0.entries_read = 0;
293da6c28aaSamw info0.ci0 = 0;
294da6c28aaSamw break;
295da6c28aaSamw case 1:
296da6c28aaSamw arg.info.level = 1;
297da6c28aaSamw arg.info.switch_value = 1;
298da6c28aaSamw arg.info.ru.info1 = &info1;
299da6c28aaSamw info1.entries_read = 0;
300da6c28aaSamw info1.ci1 = 0;
301da6c28aaSamw break;
302da6c28aaSamw default:
3038d7e4166Sjose borrego srvsvc_close(&handle);
304da6c28aaSamw return (-1);
305da6c28aaSamw }
306da6c28aaSamw
307da6c28aaSamw arg.resume_handle = 0;
308da6c28aaSamw arg.pref_max_len = 0xFFFFFFFF;
309da6c28aaSamw
3108d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg);
311da6c28aaSamw if ((rc != 0) || (arg.status != 0)) {
3128d7e4166Sjose borrego srvsvc_close(&handle);
313da6c28aaSamw return (-1);
314da6c28aaSamw }
315da6c28aaSamw
316da6c28aaSamw smb_tracef("srvsvc switch_value=%d", arg.info.switch_value);
317da6c28aaSamw
318da6c28aaSamw switch (level) {
319da6c28aaSamw case 0:
320da6c28aaSamw if (arg.info.ru.info0 && arg.info.ru.info0->ci0) {
321da6c28aaSamw smb_tracef("srvsvc coni0_id=%x",
322da6c28aaSamw arg.info.ru.info0->ci0->coni0_id);
323da6c28aaSamw }
324da6c28aaSamw break;
325da6c28aaSamw case 1:
326da6c28aaSamw if (arg.info.ru.info1 && arg.info.ru.info1->ci1) {
327da6c28aaSamw cib1 = arg.info.ru.info1->ci1;
328da6c28aaSamw
329da6c28aaSamw smb_tracef("srvsvc coni_uname=%s",
330da6c28aaSamw cib1->coni1_username ?
331da6c28aaSamw (char *)cib1->coni1_username : "(null)");
332da6c28aaSamw smb_tracef("srvsvc coni1_netname=%s",
333da6c28aaSamw cib1->coni1_netname ?
334da6c28aaSamw (char *)cib1->coni1_netname : "(null)");
335da6c28aaSamw smb_tracef("srvsvc coni1_nopens=%u",
336da6c28aaSamw cib1->coni1_num_opens);
337da6c28aaSamw smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time);
338da6c28aaSamw smb_tracef("srvsvc coni1_num_users=%u",
339da6c28aaSamw cib1->coni1_num_users);
340da6c28aaSamw }
341da6c28aaSamw break;
342da6c28aaSamw
343da6c28aaSamw default:
344da6c28aaSamw smb_tracef("srvsvc: unknown level");
345da6c28aaSamw break;
346da6c28aaSamw }
347da6c28aaSamw
3488d7e4166Sjose borrego srvsvc_close(&handle);
349da6c28aaSamw return (0);
350da6c28aaSamw }
351da6c28aaSamw
352a0aa776eSAlan Wright /*
353*3299f39fSGordon Ross * Compare the time here with the remote time on the server
354*3299f39fSGordon Ross * and report clock skew.
355a0aa776eSAlan Wright */
356*3299f39fSGordon Ross void
srvsvc_timecheck(char * server,char * domain)357*3299f39fSGordon Ross srvsvc_timecheck(char *server, char *domain)
3581fcced4cSJordan Brown {
359*3299f39fSGordon Ross char hostname[MAXHOSTNAMELEN];
360*3299f39fSGordon Ross struct timeval dc_tv;
361*3299f39fSGordon Ross struct tm dc_tm;
362*3299f39fSGordon Ross struct tm *tm;
363*3299f39fSGordon Ross time_t tnow;
364*3299f39fSGordon Ross time_t tdiff;
365*3299f39fSGordon Ross int priority;
366*3299f39fSGordon Ross
367*3299f39fSGordon Ross if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) {
368*3299f39fSGordon Ross syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed");
369*3299f39fSGordon Ross return;
370*3299f39fSGordon Ross }
371a0aa776eSAlan Wright
372*3299f39fSGordon Ross tnow = time(NULL);
3731fcced4cSJordan Brown
374*3299f39fSGordon Ross if (tnow > dc_tv.tv_sec)
375*3299f39fSGordon Ross tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN;
376*3299f39fSGordon Ross else
377*3299f39fSGordon Ross tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN;
3781fcced4cSJordan Brown
379*3299f39fSGordon Ross if (tdiff != 0) {
380*3299f39fSGordon Ross (void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN);
381*3299f39fSGordon Ross (void) gethostname(hostname, MAXHOSTNAMELEN);
3821fcced4cSJordan Brown
383*3299f39fSGordon Ross priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG;
384*3299f39fSGordon Ross syslog(priority, "DC [%s] clock skew detected: %u minutes",
385*3299f39fSGordon Ross server, tdiff);
3861fcced4cSJordan Brown
387*3299f39fSGordon Ross tm = gmtime(&dc_tv.tv_sec);
388*3299f39fSGordon Ross syslog(priority, "%-8s UTC: %s", server, asctime(tm));
389*3299f39fSGordon Ross tm = gmtime(&tnow);
390*3299f39fSGordon Ross syslog(priority, "%-8s UTC: %s", hostname, asctime(tm));
3911fcced4cSJordan Brown }
3921fcced4cSJordan Brown }
3931fcced4cSJordan Brown
394da6c28aaSamw /*
395da6c28aaSamw * Synchronize the local system clock with the domain controller.
396da6c28aaSamw */
397da6c28aaSamw void
srvsvc_timesync(void)398da6c28aaSamw srvsvc_timesync(void)
399da6c28aaSamw {
400a0aa776eSAlan Wright smb_domainex_t di;
401da6c28aaSamw struct timeval tv;
402da6c28aaSamw struct tm tm;
403da6c28aaSamw time_t tsecs;
404da6c28aaSamw
4058d7e4166Sjose borrego if (!smb_domain_getinfo(&di))
406da6c28aaSamw return;
407da6c28aaSamw
408b3700b07SGordon Ross if (srvsvc_net_remote_tod(di.d_dci.dc_name, di.d_primary.di_nbname,
409b3700b07SGordon Ross &tv, &tm) != 0)
410da6c28aaSamw return;
411da6c28aaSamw
412da6c28aaSamw if (settimeofday(&tv, 0))
413da6c28aaSamw smb_tracef("unable to set system time");
414da6c28aaSamw
415da6c28aaSamw tsecs = time(0);
416da6c28aaSamw (void) localtime_r(&tsecs, &tm);
417da6c28aaSamw smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec));
418da6c28aaSamw }
419da6c28aaSamw
420da6c28aaSamw /*
421da6c28aaSamw * NetRemoteTOD to get the current GMT time from a Windows NT server.
422da6c28aaSamw */
423da6c28aaSamw int
srvsvc_gettime(unsigned long * t)424da6c28aaSamw srvsvc_gettime(unsigned long *t)
425da6c28aaSamw {
426a0aa776eSAlan Wright smb_domainex_t di;
427da6c28aaSamw struct timeval tv;
428da6c28aaSamw struct tm tm;
429da6c28aaSamw
4308d7e4166Sjose borrego if (!smb_domain_getinfo(&di))
431da6c28aaSamw return (-1);
432da6c28aaSamw
433b3700b07SGordon Ross if (srvsvc_net_remote_tod(di.d_dci.dc_name, di.d_primary.di_nbname,
434b3700b07SGordon Ross &tv, &tm) != 0)
435da6c28aaSamw return (-1);
436da6c28aaSamw
437da6c28aaSamw *t = tv.tv_sec;
438da6c28aaSamw return (0);
439da6c28aaSamw }
440da6c28aaSamw
441da6c28aaSamw /*
442da6c28aaSamw * This is a client side routine for NetRemoteTOD, which gets the time
443da6c28aaSamw * and date from a remote system. The time information is returned in
444da6c28aaSamw * the timeval and tm.
445da6c28aaSamw *
446da6c28aaSamw * typedef struct _TIME_OF_DAY_INFO {
447da6c28aaSamw * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT
448da6c28aaSamw * DWORD tod_msecs; // arbitrary milliseconds (since reset)
449da6c28aaSamw * DWORD tod_hours; // current hour [0-23]
450da6c28aaSamw * DWORD tod_mins; // current minute [0-59]
451da6c28aaSamw * DWORD tod_secs; // current second [0-59]
452da6c28aaSamw * DWORD tod_hunds; // current hundredth (0.01) second [0-99]
453da6c28aaSamw * LONG tod_timezone; // time zone of the server
454da6c28aaSamw * DWORD tod_tinterval; // clock tick time interval
455da6c28aaSamw * DWORD tod_day; // day of the month [1-31]
456da6c28aaSamw * DWORD tod_month; // month of the year [1-12]
457da6c28aaSamw * DWORD tod_year; // current year
458da6c28aaSamw * DWORD tod_weekday; // day of the week since sunday [0-6]
459da6c28aaSamw * } TIME_OF_DAY_INFO;
460da6c28aaSamw *
461da6c28aaSamw * The time zone of the server is calculated in minutes from Greenwich
462da6c28aaSamw * Mean Time (GMT). For time zones west of Greenwich, the value is
463da6c28aaSamw * positive; for time zones east of Greenwich, the value is negative.
464da6c28aaSamw * A value of -1 indicates that the time zone is undefined.
465da6c28aaSamw *
466da6c28aaSamw * The clock tick value represents a resolution of one ten-thousandth
467da6c28aaSamw * (0.0001) second.
468da6c28aaSamw */
469da6c28aaSamw int
srvsvc_net_remote_tod(char * server,char * domain,struct timeval * tv,struct tm * tm)470da6c28aaSamw srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv,
471da6c28aaSamw struct tm *tm)
472da6c28aaSamw {
4739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetRemoteTOD arg;
4749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_TIME_OF_DAY_INFO *tod;
4759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mlsvc_handle_t handle;
4769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc;
4779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int opnum;
4789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int len;
4799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char user[SMB_USERNAME_MAXLEN];
480a0aa776eSAlan Wright
481a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
482da6c28aaSamw
4838d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle);
484da6c28aaSamw if (rc != 0)
485da6c28aaSamw return (-1);
486da6c28aaSamw
487da6c28aaSamw opnum = SRVSVC_OPNUM_NetRemoteTOD;
488da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetRemoteTOD));
489da6c28aaSamw
490da6c28aaSamw len = strlen(server) + 4;
4918d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len);
492da6c28aaSamw if (arg.servername == NULL) {
4938d7e4166Sjose borrego srvsvc_close(&handle);
494da6c28aaSamw return (-1);
495da6c28aaSamw }
496da6c28aaSamw
497da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
498da6c28aaSamw
4998d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg);
500da6c28aaSamw if ((rc != 0) || (arg.status != 0)) {
5018d7e4166Sjose borrego srvsvc_close(&handle);
502da6c28aaSamw return (-1);
503da6c28aaSamw }
504da6c28aaSamw
505da6c28aaSamw /*
506da6c28aaSamw * We're assigning milliseconds to microseconds
507da6c28aaSamw * here but the value's not really relevant.
508da6c28aaSamw */
509da6c28aaSamw tod = arg.bufptr;
510da6c28aaSamw
511da6c28aaSamw if (tv) {
512da6c28aaSamw tv->tv_sec = tod->tod_elapsedt;
513da6c28aaSamw tv->tv_usec = tod->tod_msecs;
514da6c28aaSamw }
515da6c28aaSamw
516da6c28aaSamw if (tm) {
517da6c28aaSamw tm->tm_sec = tod->tod_secs;
518da6c28aaSamw tm->tm_min = tod->tod_mins;
519da6c28aaSamw tm->tm_hour = tod->tod_hours;
520da6c28aaSamw tm->tm_mday = tod->tod_day;
521da6c28aaSamw tm->tm_mon = tod->tod_month - 1;
522da6c28aaSamw tm->tm_year = tod->tod_year - 1900;
523da6c28aaSamw tm->tm_wday = tod->tod_weekday;
524da6c28aaSamw }
525da6c28aaSamw
5268d7e4166Sjose borrego srvsvc_close(&handle);
527da6c28aaSamw return (0);
528da6c28aaSamw }
529