srvsvc_clnt.c revision 10717:fe0545fc3cdd
12742Swollman/*
22742Swollman * CDDL HEADER START
32742Swollman *
42742Swollman * The contents of this file are subject to the terms of the
52742Swollman * Common Development and Distribution License (the "License").
62742Swollman * You may not use this file except in compliance with the License.
72742Swollman *
82742Swollman * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92742Swollman * or http://www.opensolaris.org/os/licensing.
102742Swollman * See the License for the specific language governing permissions
112742Swollman * and limitations under the License.
122742Swollman *
132742Swollman * When distributing Covered Code, include this CDDL HEADER in each
142742Swollman * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152742Swollman * If applicable, add the following below this CDDL HEADER, with the
162742Swollman * fields enclosed by brackets "[]" replaced with your own identifying
172742Swollman * information: Portions Copyright [yyyy] [name of copyright owner]
182742Swollman *
192742Swollman * CDDL HEADER END
202742Swollman */
212742Swollman/*
222742Swollman * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
232742Swollman * Use is subject to license terms.
242742Swollman */
252742Swollman
262742Swollman/*
272742Swollman * Server Service (srvsvc) client side RPC library interface. The
282742Swollman * srvsvc interface allows a client to query a server for information
292742Swollman * on shares, sessions, connections and files on the server. Some
302742Swollman * functions are available via anonymous IPC while others require
312742Swollman * administrator privilege. Also, some functions return NT status
322742Swollman * values while others return Win32 errors codes.
332742Swollman */
342742Swollman
352742Swollman#include <sys/errno.h>
362742Swollman#include <stdio.h>
372742Swollman#include <time.h>
382742Swollman#include <strings.h>
392742Swollman#include <time.h>
402742Swollman
412742Swollman#include <smbsrv/libsmb.h>
422742Swollman#include <smbsrv/libmlsvc.h>
432742Swollman#include <smbsrv/smbinfo.h>
442742Swollman#include <smbsrv/ntstatus.h>
452742Swollman#include <smbsrv/ndl/srvsvc.ndl>
462742Swollman
472742Swollman/*
482742Swollman * Information level for NetShareGetInfo.
492742Swollman */
502742SwollmanDWORD srvsvc_info_level = 1;
512742Swollman
522742Swollmanstatic int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *);
532742Swollman
542742Swollman/*
552742Swollman * Bind to the the SRVSVC.
562742Swollman *
572742Swollman * If username argument is NULL, an anonymous connection will be established.
582742Swollman * Otherwise, an authenticated connection will be established.
592742Swollman */
602742Swollmanstatic int
612742Swollmansrvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle)
622742Swollman{
632742Swollman	smb_domainex_t di;
642742Swollman
652742Swollman	if (server == NULL || domain == NULL) {
662742Swollman		if (!smb_domain_getinfo(&di))
672742Swollman			return (-1);
682742Swollman
692742Swollman		server = di.d_dc;
702742Swollman		domain = di.d_primary.di_nbname;
712742Swollman	}
722742Swollman
732742Swollman	if (username == NULL)
742742Swollman		username = MLSVC_ANON_USER;
752742Swollman
762742Swollman	if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") < 0)
772742Swollman		return (-1);
782742Swollman
792742Swollman	return (0);
802742Swollman}
812742Swollman
822742Swollman/*
832742Swollman * Unbind the SRVSVC connection.
842742Swollman */
852742Swollmanstatic void
862742Swollmansrvsvc_close(mlsvc_handle_t *handle)
872742Swollman{
882742Swollman	ndr_rpc_unbind(handle);
892742Swollman}
902742Swollman
912742Swollman/*
922742Swollman * This is a client side routine for NetShareGetInfo.
932742Swollman * Levels 0 and 1 work with an anonymous connection but
942742Swollman * level 2 requires administrator access.
952742Swollman */
962742Swollmanint
972742Swollmansrvsvc_net_share_get_info(char *server, char *domain, char *netname)
982742Swollman{
992742Swollman	struct mlsm_NetShareGetInfo arg;
1002742Swollman	mlsvc_handle_t handle;
1012742Swollman	int rc;
1022742Swollman	int opnum;
1032742Swollman	struct mslm_NetShareInfo_0 *info0;
1042742Swollman	struct mslm_NetShareInfo_1 *info1;
1052742Swollman	struct mslm_NetShareInfo_2 *info2;
1062742Swollman	int len;
1078029Swollman	char user[SMB_USERNAME_MAXLEN];
1088029Swollman
1092742Swollman	if (netname == NULL)
1102742Swollman		return (-1);
1112742Swollman
1122742Swollman	if (srvsvc_info_level == 2)
1132742Swollman		smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
1142742Swollman
1158029Swollman	if (srvsvc_open(server, domain, user, &handle) != 0)
1168029Swollman		return (-1);
1172742Swollman
1182742Swollman	opnum = SRVSVC_OPNUM_NetShareGetInfo;
1192742Swollman	bzero(&arg, sizeof (struct mlsm_NetShareGetInfo));
1202742Swollman
1212742Swollman	len = strlen(server) + 4;
1222742Swollman	arg.servername = ndr_rpc_malloc(&handle, len);
1232742Swollman	if (arg.servername == NULL) {
1248029Swollman		srvsvc_close(&handle);
1258029Swollman		return (-1);
1262742Swollman	}
1272742Swollman
1282742Swollman	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
1292742Swollman	arg.netname = (LPTSTR)netname;
1302742Swollman	arg.level = srvsvc_info_level; /* share information level */
1312742Swollman
1322742Swollman	rc = ndr_rpc_call(&handle, opnum, &arg);
1338029Swollman	if ((rc != 0) || (arg.status != 0)) {
1348029Swollman		srvsvc_close(&handle);
1352742Swollman		return (-1);
1362742Swollman	}
1372742Swollman
1382742Swollman	switch (arg.result.switch_value) {
1392742Swollman	case 0:
1408029Swollman		info0 = arg.result.ru.info0;
1418029Swollman		smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname);
1422742Swollman		break;
1432742Swollman
1442742Swollman	case 1:
1452742Swollman		info1 = arg.result.ru.info1;
1462742Swollman		smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname);
1478029Swollman		smb_tracef("srvsvc shi1_type=%u", info1->shi1_type);
1488029Swollman
1492742Swollman		if (info1->shi1_comment)
1502742Swollman			smb_tracef("srvsvc shi1_comment=%s",
1512742Swollman			    info1->shi1_comment);
1522742Swollman		break;
1532742Swollman
1542742Swollman	case 2:
1558029Swollman		info2 = arg.result.ru.info2;
1568029Swollman		smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname);
1572742Swollman		smb_tracef("srvsvc shi2_type=%u", info2->shi2_type);
1582742Swollman
1592742Swollman		if (info2->shi2_comment)
1602742Swollman			smb_tracef("srvsvc shi2_comment=%s",
1612742Swollman			    info2->shi2_comment);
1622742Swollman
1632742Swollman		smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions);
1642742Swollman		smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses);
1658029Swollman		smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses);
1668029Swollman
1672742Swollman		if (info2->shi2_path)
1682742Swollman			smb_tracef("srvsvc shi2_path=%s", info2->shi2_path);
1692742Swollman
1702742Swollman		if (info2->shi2_passwd)
1712742Swollman			smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd);
1728029Swollman		break;
1738029Swollman
1742742Swollman	default:
1752742Swollman		smb_tracef("srvsvc: unknown level");
1762742Swollman		break;
1772742Swollman	}
1782742Swollman
1792742Swollman	srvsvc_close(&handle);
1802742Swollman	return (0);
1818029Swollman}
1828029Swollman
1832742Swollman/*
1842742Swollman * This is a client side routine for NetSessionEnum.
1852742Swollman * NetSessionEnum requires administrator rights.
1862742Swollman */
1872742Swollmanint
1888029Swollmansrvsvc_net_session_enum(char *server, char *domain, char *netname)
1898029Swollman{
1902742Swollman	struct mslm_NetSessionEnum arg;
1912742Swollman	mlsvc_handle_t handle;
1922742Swollman	int rc;
1932742Swollman	int opnum;
1942742Swollman	struct mslm_infonres infonres;
1958029Swollman	struct mslm_SESSION_INFO_1 *nsi1;
1968029Swollman	int len;
1972742Swollman	char user[SMB_USERNAME_MAXLEN];
1982742Swollman
1992742Swollman	if (netname == NULL)
2002742Swollman		return (-1);
2012742Swollman
2028029Swollman	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2038029Swollman
2042742Swollman	rc = srvsvc_open(server, domain, user, &handle);
2052742Swollman	if (rc != 0)
2062742Swollman		return (-1);
2072742Swollman
2082742Swollman	opnum = SRVSVC_OPNUM_NetSessionEnum;
2098029Swollman	bzero(&arg, sizeof (struct mslm_NetSessionEnum));
2108029Swollman
2112742Swollman	len = strlen(server) + 4;
2122742Swollman	arg.servername = ndr_rpc_malloc(&handle, len);
2132742Swollman	if (arg.servername == NULL) {
2142742Swollman		srvsvc_close(&handle);
2152742Swollman		return (-1);
2162742Swollman	}
2172742Swollman
2182742Swollman	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
2192742Swollman	infonres.entriesread = 0;
2202742Swollman	infonres.entries = 0;
2212742Swollman	arg.level = 1;
2222742Swollman	arg.result.level = 1;
2232742Swollman	arg.result.bufptr.p = &infonres;
2242742Swollman	arg.resume_handle = 0;
2252742Swollman	arg.pref_max_len = 0xFFFFFFFF;
2262742Swollman
2272742Swollman	rc = ndr_rpc_call(&handle, opnum, &arg);
2282742Swollman	if ((rc != 0) || (arg.status != 0)) {
2292742Swollman		srvsvc_close(&handle);
2302742Swollman		return (-1);
2312742Swollman	}
2322742Swollman
2332742Swollman	/* Only the first session info is dereferenced. */
2342742Swollman	nsi1 = ((struct mslm_infonres *)arg.result.bufptr.p)->entries;
2352742Swollman
2362742Swollman	smb_tracef("srvsvc switch_value=%d", arg.level);
2372742Swollman	smb_tracef("srvsvc sesi1_cname=%s", nsi1->sesi1_cname);
2382742Swollman	smb_tracef("srvsvc sesi1_uname=%s", nsi1->sesi1_uname);
2392742Swollman	smb_tracef("srvsvc sesi1_nopens=%u", nsi1->sesi1_nopens);
2402742Swollman	smb_tracef("srvsvc sesi1_time=%u", nsi1->sesi1_time);
2412742Swollman	smb_tracef("srvsvc sesi1_itime=%u", nsi1->sesi1_itime);
2422742Swollman	smb_tracef("srvsvc sesi1_uflags=%u", nsi1->sesi1_uflags);
2432742Swollman
2442742Swollman	srvsvc_close(&handle);
2452742Swollman	return (0);
2462742Swollman}
2472742Swollman
2482742Swollman/*
2492742Swollman * This is a client side routine for NetConnectEnum.
2502742Swollman * NetConnectEnum requires administrator rights.
2512742Swollman * Level 0 and level 1 requests are supported.
2528029Swollman */
2538029Swollmanint
2542742Swollmansrvsvc_net_connect_enum(char *server, char *domain, char *netname, int level)
2552742Swollman{
2562742Swollman	struct mslm_NetConnectEnum arg;
2572742Swollman	mlsvc_handle_t handle;
2582742Swollman	int rc;
2592742Swollman	int opnum;
2608029Swollman	struct mslm_NetConnectInfo1 info1;
2618029Swollman	struct mslm_NetConnectInfo0 info0;
2622742Swollman	struct mslm_NetConnectInfoBuf1 *cib1;
2632742Swollman	int len;
2642742Swollman	char user[SMB_USERNAME_MAXLEN];
2652742Swollman
2662742Swollman	if (netname == NULL)
2672742Swollman		return (-1);
2682742Swollman
2698029Swollman	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2708029Swollman
2712742Swollman	rc = srvsvc_open(server, domain, user, &handle);
2722742Swollman	if (rc != 0)
2732742Swollman		return (-1);
2742742Swollman
2752742Swollman	opnum = SRVSVC_OPNUM_NetConnectEnum;
2762742Swollman	bzero(&arg, sizeof (struct mslm_NetConnectEnum));
2778029Swollman
2788029Swollman	len = strlen(server) + 4;
2792742Swollman	arg.servername = ndr_rpc_malloc(&handle, len);
2802742Swollman	if (arg.servername == NULL) {
2812742Swollman		srvsvc_close(&handle);
2822742Swollman		return (-1);
2832742Swollman	}
2848029Swollman
2858029Swollman	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
2862742Swollman	arg.qualifier = (LPTSTR)netname;
2872742Swollman
2882742Swollman	switch (level) {
2892742Swollman	case 0:
2902742Swollman		arg.info.level = 0;
2912742Swollman		arg.info.switch_value = 0;
2922742Swollman		arg.info.ru.info0 = &info0;
2938029Swollman		info0.entries_read = 0;
2948029Swollman		info0.ci0 = 0;
2952742Swollman		break;
2962742Swollman	case 1:
2972742Swollman		arg.info.level = 1;
2982742Swollman		arg.info.switch_value = 1;
2992742Swollman		arg.info.ru.info1 = &info1;
3002742Swollman		info1.entries_read = 0;
3012742Swollman		info1.ci1 = 0;
3022742Swollman		break;
3032742Swollman	default:
3042742Swollman		srvsvc_close(&handle);
3052742Swollman		return (-1);
3062742Swollman	}
3072742Swollman
3088029Swollman	arg.resume_handle = 0;
3098029Swollman	arg.pref_max_len = 0xFFFFFFFF;
3102742Swollman
3112742Swollman	rc = ndr_rpc_call(&handle, opnum, &arg);
3122742Swollman	if ((rc != 0) || (arg.status != 0)) {
3132742Swollman		srvsvc_close(&handle);
3142742Swollman		return (-1);
3152742Swollman	}
3162742Swollman
3178029Swollman	smb_tracef("srvsvc switch_value=%d", arg.info.switch_value);
3188029Swollman
3192742Swollman	switch (level) {
3202742Swollman	case 0:
3212742Swollman		if (arg.info.ru.info0 && arg.info.ru.info0->ci0) {
3222742Swollman			smb_tracef("srvsvc coni0_id=%x",
3232742Swollman			    arg.info.ru.info0->ci0->coni0_id);
3242742Swollman		}
3258029Swollman		break;
3268029Swollman	case 1:
3272742Swollman		if (arg.info.ru.info1 && arg.info.ru.info1->ci1) {
3282742Swollman			cib1 = arg.info.ru.info1->ci1;
3292742Swollman
3302742Swollman			smb_tracef("srvsvc coni_uname=%s",
3312742Swollman			    cib1->coni1_username ?
3322742Swollman			    (char *)cib1->coni1_username : "(null)");
3332742Swollman			smb_tracef("srvsvc coni1_netname=%s",
3342742Swollman			    cib1->coni1_netname ?
3352742Swollman			    (char *)cib1->coni1_netname : "(null)");
3362742Swollman			smb_tracef("srvsvc coni1_nopens=%u",
3378029Swollman			    cib1->coni1_num_opens);
3388029Swollman			smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time);
3392742Swollman			smb_tracef("srvsvc coni1_num_users=%u",
3402742Swollman			    cib1->coni1_num_users);
3412742Swollman		}
3422742Swollman		break;
3432742Swollman
3442742Swollman	default:
3452742Swollman		smb_tracef("srvsvc: unknown level");
3468029Swollman		break;
3478029Swollman	}
3482742Swollman
3492742Swollman	srvsvc_close(&handle);
3502742Swollman	return (0);
3512742Swollman}
3522742Swollman
3532742Swollman/*
3542742Swollman * Windows 95+ and Windows NT4.0 both report the version as 4.0.
3552742Swollman * Windows 2000+ reports the version as 5.x.
3562742Swollman */
3572742Swollmanint
3582742Swollmansrvsvc_net_server_getinfo(char *server, char *domain,
3592742Swollman    srvsvc_server_info_t *svinfo)
3602742Swollman{
3612742Swollman	mlsvc_handle_t handle;
3622742Swollman	struct mslm_NetServerGetInfo arg;
3638029Swollman	struct mslm_SERVER_INFO_101 *sv101;
3648029Swollman	int len, opnum, rc;
3652742Swollman	char user[SMB_USERNAME_MAXLEN];
3662742Swollman
3672742Swollman	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
3682742Swollman
3692742Swollman	if (srvsvc_open(server, domain, user, &handle) != 0)
3702742Swollman		return (-1);
3712742Swollman
3722742Swollman	opnum = SRVSVC_OPNUM_NetServerGetInfo;
3732742Swollman	bzero(&arg, sizeof (arg));
3742742Swollman
3752742Swollman	len = strlen(server) + 4;
3762742Swollman	arg.servername = ndr_rpc_malloc(&handle, len);
3772742Swollman	if (arg.servername == NULL)
3782742Swollman		return (-1);
3792742Swollman
3802742Swollman	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
3812742Swollman	arg.level = 101;
3822742Swollman
3832742Swollman	rc = ndr_rpc_call(&handle, opnum, &arg);
3842742Swollman	if ((rc != 0) || (arg.status != 0)) {
3852742Swollman		srvsvc_close(&handle);
3862742Swollman		return (-1);
3872742Swollman	}
3882742Swollman
3892742Swollman	sv101 = arg.result.bufptr.bufptr101;
3902742Swollman
3912742Swollman	bzero(svinfo, sizeof (srvsvc_server_info_t));
3922742Swollman	svinfo->sv_platform_id = sv101->sv101_platform_id;
3932742Swollman	svinfo->sv_version_major = sv101->sv101_version_major;
3942742Swollman	svinfo->sv_version_minor = sv101->sv101_version_minor;
3952742Swollman	svinfo->sv_type = sv101->sv101_type;
3962742Swollman	if (sv101->sv101_name)
3972742Swollman		svinfo->sv_name = strdup((char *)sv101->sv101_name);
3982742Swollman	if (sv101->sv101_comment)
3992742Swollman		svinfo->sv_comment = strdup((char *)sv101->sv101_comment);
4002742Swollman
4012742Swollman	if (svinfo->sv_type & SV_TYPE_WFW)
4022742Swollman		svinfo->sv_os = NATIVE_OS_WIN95;
4032742Swollman	if (svinfo->sv_type & SV_TYPE_WINDOWS)
4048029Swollman		svinfo->sv_os = NATIVE_OS_WIN95;
4058029Swollman	if ((svinfo->sv_type & SV_TYPE_NT) ||
4062742Swollman	    (svinfo->sv_type & SV_TYPE_SERVER_NT))
4072742Swollman		svinfo->sv_os = NATIVE_OS_WINNT;
4082742Swollman	if (svinfo->sv_version_major > 4)
4092742Swollman		svinfo->sv_os = NATIVE_OS_WIN2000;
4102742Swollman
4112742Swollman	srvsvc_close(&handle);
4122742Swollman	return (0);
4138029Swollman}
4148029Swollman
4152742Swollman/*
4162742Swollman * Synchronize the local system clock with the domain controller.
4172742Swollman */
4182742Swollmanvoid
4192742Swollmansrvsvc_timesync(void)
4208029Swollman{
4218029Swollman	smb_domainex_t di;
4222742Swollman	struct timeval tv;
4232742Swollman	struct tm tm;
4242742Swollman	time_t tsecs;
4252742Swollman
4262742Swollman	if (!smb_domain_getinfo(&di))
4272742Swollman		return;
4288029Swollman
4298029Swollman	if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm)
4308029Swollman	    != 0)
4312742Swollman		return;
4322742Swollman
4332742Swollman	if (settimeofday(&tv, 0))
4342742Swollman		smb_tracef("unable to set system time");
4352742Swollman
4362742Swollman	tsecs = time(0);
4372742Swollman	(void) localtime_r(&tsecs, &tm);
4382742Swollman	smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec));
4392742Swollman}
4402742Swollman
4418029Swollman/*
4422742Swollman * NetRemoteTOD to get the current GMT time from a Windows NT server.
4432742Swollman */
4442742Swollmanint
4452742Swollmansrvsvc_gettime(unsigned long *t)
4462742Swollman{
4472742Swollman	smb_domainex_t di;
4482742Swollman	struct timeval tv;
4492742Swollman	struct tm tm;
4508029Swollman
4518029Swollman	if (!smb_domain_getinfo(&di))
4522742Swollman		return (-1);
4532742Swollman
4542742Swollman	if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm)
4552742Swollman	    != 0)
4562742Swollman		return (-1);
4578029Swollman
4588029Swollman	*t = tv.tv_sec;
4592742Swollman	return (0);
4602742Swollman}
4612742Swollman
4622742Swollman/*
4632742Swollman * This is a client side routine for NetRemoteTOD, which gets the time
4642742Swollman * and date from a remote system. The time information is returned in
4652742Swollman * the timeval and tm.
4662742Swollman *
4672742Swollman * typedef struct _TIME_OF_DAY_INFO {
4682742Swollman *	DWORD tod_elapsedt;  // seconds since 00:00:00 January 1 1970 GMT
4692742Swollman *	DWORD tod_msecs;     // arbitrary milliseconds (since reset)
4702742Swollman *	DWORD tod_hours;     // current hour [0-23]
4712742Swollman *	DWORD tod_mins;      // current minute [0-59]
4722742Swollman *	DWORD tod_secs;      // current second [0-59]
4732742Swollman *	DWORD tod_hunds;     // current hundredth (0.01) second [0-99]
4742742Swollman *	LONG tod_timezone;   // time zone of the server
4752742Swollman *	DWORD tod_tinterval; // clock tick time interval
4762742Swollman *	DWORD tod_day;       // day of the month [1-31]
4772742Swollman *	DWORD tod_month;     // month of the year [1-12]
4782742Swollman *	DWORD tod_year;      // current year
4792742Swollman *	DWORD tod_weekday;   // day of the week since sunday [0-6]
4802742Swollman * } TIME_OF_DAY_INFO;
4812742Swollman *
4828029Swollman * The time zone of the server is calculated in minutes from Greenwich
4838029Swollman * Mean Time (GMT). For time zones west of Greenwich, the value is
4848029Swollman * positive; for time zones east of Greenwich, the value is negative.
4852742Swollman * A value of -1 indicates that the time zone is undefined.
4862742Swollman *
4872742Swollman * The clock tick value represents a resolution of one ten-thousandth
4882742Swollman * (0.0001) second.
4892742Swollman */
4902742Swollmanint
4912742Swollmansrvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv,
4922742Swollman    struct tm *tm)
4938029Swollman{
4948029Swollman	char timebuf[64];
4952742Swollman	struct mslm_NetRemoteTOD arg;
4962742Swollman	struct mslm_TIME_OF_DAY_INFO *tod;
4972742Swollman	mlsvc_handle_t handle;
4982742Swollman	int rc;
4992742Swollman	int opnum;
5002742Swollman	int len;
5012742Swollman	char user[SMB_USERNAME_MAXLEN];
5022742Swollman
5038029Swollman	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
5048029Swollman
5052742Swollman	rc = srvsvc_open(server, domain, user, &handle);
5062742Swollman	if (rc != 0)
5072742Swollman		return (-1);
5082742Swollman
5092742Swollman	opnum = SRVSVC_OPNUM_NetRemoteTOD;
5102742Swollman	bzero(&arg, sizeof (struct mslm_NetRemoteTOD));
5112742Swollman
5128029Swollman	len = strlen(server) + 4;
5138029Swollman	arg.servername = ndr_rpc_malloc(&handle, len);
5142742Swollman	if (arg.servername == NULL) {
5152742Swollman		srvsvc_close(&handle);
5162742Swollman		return (-1);
5172742Swollman	}
5182742Swollman
5198029Swollman	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
5208029Swollman
5212742Swollman	rc = ndr_rpc_call(&handle, opnum, &arg);
5222742Swollman	if ((rc != 0) || (arg.status != 0)) {
5232742Swollman		srvsvc_close(&handle);
5242742Swollman		return (-1);
5252742Swollman	}
5268029Swollman
5278029Swollman	/*
5282742Swollman	 * We're assigning milliseconds to microseconds
5292742Swollman	 * here but the value's not really relevant.
5302742Swollman	 */
5312742Swollman	tod = arg.bufptr;
5322742Swollman
5338029Swollman	if (tv) {
5348029Swollman		tv->tv_sec = tod->tod_elapsedt;
5352742Swollman		tv->tv_usec = tod->tod_msecs;
5362742Swollman		smb_tracef("RemoteTime from %s: %s", server,
5372742Swollman		    ctime(&tv->tv_sec));
5382742Swollman	}
5392742Swollman
5402742Swollman	if (tm) {
5412742Swollman		tm->tm_sec = tod->tod_secs;
5422742Swollman		tm->tm_min = tod->tod_mins;
5432742Swollman		tm->tm_hour = tod->tod_hours;
5442742Swollman		tm->tm_mday = tod->tod_day;
5458029Swollman		tm->tm_mon = tod->tod_month - 1;
5468029Swollman		tm->tm_year = tod->tod_year - 1900;
5472742Swollman		tm->tm_wday = tod->tod_weekday;
5482742Swollman
5492742Swollman		(void) strftime(timebuf, sizeof (timebuf),
5502742Swollman		    "NetRemoteTOD: %D %T", tm);
5512742Swollman		smb_tracef("NetRemoteTOD from %s: %s", server, timebuf);
5522742Swollman	}
5538029Swollman
5548029Swollman	srvsvc_close(&handle);
5552742Swollman	return (0);
5562742Swollman}
5572742Swollman
5582742Swollmanvoid
5592742Swollmansrvsvc_net_test(char *server, char *domain, char *netname)
5602742Swollman{
5618029Swollman	smb_domainex_t di;
5628029Swollman	srvsvc_server_info_t svinfo;
5632742Swollman
5642742Swollman	(void) smb_tracef("%s %s %s", server, domain, netname);
5652742Swollman
5662742Swollman	if (smb_domain_getinfo(&di)) {
5672742Swollman		server = di.d_dc;
5688029Swollman		domain = di.d_primary.di_nbname;
5698029Swollman	}
5702742Swollman
5712742Swollman	if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) {
5722742Swollman		smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x",
5732742Swollman		    svinfo.sv_name ? svinfo.sv_name : "NULL",
5742742Swollman		    svinfo.sv_comment ? svinfo.sv_comment : "NULL",
5752742Swollman		    svinfo.sv_version_major, svinfo.sv_version_minor,
5762742Swollman		    svinfo.sv_platform_id, svinfo.sv_type);
5772742Swollman
5782742Swollman		free(svinfo.sv_name);
5792742Swollman		free(svinfo.sv_comment);
5802742Swollman	}
5812742Swollman
5822742Swollman	(void) srvsvc_net_share_get_info(server, domain, netname);
5832742Swollman#if 0
5848029Swollman	/*
5858029Swollman	 * The NetSessionEnum server-side definition was updated.
5862742Swollman	 * Disabled until the client-side has been updated.
5872742Swollman	 */
5882742Swollman	(void) srvsvc_net_session_enum(server, domain, netname);
5892742Swollman#endif
5902742Swollman	(void) srvsvc_net_connect_enum(server, domain, netname, 0);
5912742Swollman	(void) srvsvc_net_connect_enum(server, domain, netname, 1);
5922742Swollman}
5932742Swollman