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 */ 21da6c28aaSamw /* 2289dc44ceSjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * Server Service (srvsvc) client side RPC library interface. The 28da6c28aaSamw * srvsvc interface allows a client to query a server for information 29da6c28aaSamw * on shares, sessions, connections and files on the server. Some 30da6c28aaSamw * functions are available via anonymous IPC while others require 31da6c28aaSamw * administrator privilege. Also, some functions return NT status 32da6c28aaSamw * values while others return Win32 errors codes. 33da6c28aaSamw */ 34da6c28aaSamw 35da6c28aaSamw #include <sys/errno.h> 36da6c28aaSamw #include <stdio.h> 37da6c28aaSamw #include <time.h> 38da6c28aaSamw #include <strings.h> 39da6c28aaSamw #include <time.h> 40da6c28aaSamw 41da6c28aaSamw #include <smbsrv/libsmb.h> 42da6c28aaSamw #include <smbsrv/libsmbrdr.h> 438d7e4166Sjose borrego #include <smbsrv/libmlsvc.h> 44da6c28aaSamw #include <smbsrv/smbinfo.h> 45da6c28aaSamw #include <smbsrv/ntstatus.h> 46da6c28aaSamw #include <smbsrv/ndl/srvsvc.ndl> 47da6c28aaSamw 48da6c28aaSamw /* 49da6c28aaSamw * Information level for NetShareGetInfo. 50da6c28aaSamw */ 51da6c28aaSamw DWORD srvsvc_info_level = 1; 52da6c28aaSamw 53da6c28aaSamw static int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); 54da6c28aaSamw 55da6c28aaSamw /* 568d7e4166Sjose borrego * Bind to the the SRVSVC. 57da6c28aaSamw * 5855bf511dSas * If username argument is NULL, an anonymous connection will be established. 5955bf511dSas * Otherwise, an authenticated connection will be established. 60da6c28aaSamw */ 6155bf511dSas static int 628d7e4166Sjose borrego srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle) 63da6c28aaSamw { 648d7e4166Sjose borrego smb_domain_t di; 65da6c28aaSamw 66da6c28aaSamw if (server == NULL || domain == NULL) { 678d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 6855bf511dSas return (-1); 69da6c28aaSamw 708d7e4166Sjose borrego server = di.d_dc; 7129bd2886SAlan Wright domain = di.d_info.di_nbname; 7255bf511dSas } 73da6c28aaSamw 7455bf511dSas if (username == NULL) 7555bf511dSas username = MLSVC_ANON_USER; 76da6c28aaSamw 778d7e4166Sjose borrego if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") < 0) 78da6c28aaSamw return (-1); 79da6c28aaSamw 808d7e4166Sjose borrego return (0); 81da6c28aaSamw } 82da6c28aaSamw 83da6c28aaSamw /* 848d7e4166Sjose borrego * Unbind the SRVSVC connection. 85da6c28aaSamw */ 868d7e4166Sjose borrego static void 878d7e4166Sjose borrego srvsvc_close(mlsvc_handle_t *handle) 88da6c28aaSamw { 898d7e4166Sjose borrego ndr_rpc_unbind(handle); 90da6c28aaSamw } 91da6c28aaSamw 92da6c28aaSamw /* 93da6c28aaSamw * This is a client side routine for NetShareGetInfo. 94da6c28aaSamw * Levels 0 and 1 work with an anonymous connection but 95da6c28aaSamw * level 2 requires administrator access. 96da6c28aaSamw */ 97da6c28aaSamw int 98da6c28aaSamw srvsvc_net_share_get_info(char *server, char *domain, char *netname) 99da6c28aaSamw { 100da6c28aaSamw struct mlsm_NetShareGetInfo arg; 101da6c28aaSamw mlsvc_handle_t handle; 102da6c28aaSamw int rc; 103da6c28aaSamw int opnum; 104eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_0 *info0; 105eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_1 *info1; 106eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_2 *info2; 107da6c28aaSamw int len; 10855bf511dSas char *user = NULL; 109da6c28aaSamw 110da6c28aaSamw if (netname == NULL) 111da6c28aaSamw return (-1); 112da6c28aaSamw 113da6c28aaSamw if (srvsvc_info_level == 2) 11455bf511dSas user = smbrdr_ipc_get_user(); 115da6c28aaSamw 1168d7e4166Sjose borrego if (srvsvc_open(server, domain, user, &handle) != 0) 117da6c28aaSamw return (-1); 118da6c28aaSamw 119da6c28aaSamw opnum = SRVSVC_OPNUM_NetShareGetInfo; 120da6c28aaSamw bzero(&arg, sizeof (struct mlsm_NetShareGetInfo)); 121da6c28aaSamw 122da6c28aaSamw len = strlen(server) + 4; 1238d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 124da6c28aaSamw if (arg.servername == NULL) { 1258d7e4166Sjose borrego srvsvc_close(&handle); 126da6c28aaSamw return (-1); 127da6c28aaSamw } 128da6c28aaSamw 129da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 130da6c28aaSamw arg.netname = (LPTSTR)netname; 131da6c28aaSamw arg.level = srvsvc_info_level; /* share information level */ 132da6c28aaSamw 1338d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 134da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 1358d7e4166Sjose borrego srvsvc_close(&handle); 136da6c28aaSamw return (-1); 137da6c28aaSamw } 138da6c28aaSamw 139da6c28aaSamw switch (arg.result.switch_value) { 140da6c28aaSamw case 0: 141da6c28aaSamw info0 = arg.result.ru.info0; 142da6c28aaSamw smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname); 143da6c28aaSamw break; 144da6c28aaSamw 145da6c28aaSamw case 1: 146da6c28aaSamw info1 = arg.result.ru.info1; 147da6c28aaSamw smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname); 148da6c28aaSamw smb_tracef("srvsvc shi1_type=%u", info1->shi1_type); 149da6c28aaSamw 150da6c28aaSamw if (info1->shi1_comment) 151da6c28aaSamw smb_tracef("srvsvc shi1_comment=%s", 152da6c28aaSamw info1->shi1_comment); 153da6c28aaSamw break; 154da6c28aaSamw 155da6c28aaSamw case 2: 156da6c28aaSamw info2 = arg.result.ru.info2; 157da6c28aaSamw smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname); 158da6c28aaSamw smb_tracef("srvsvc shi2_type=%u", info2->shi2_type); 159da6c28aaSamw 160da6c28aaSamw if (info2->shi2_comment) 161da6c28aaSamw smb_tracef("srvsvc shi2_comment=%s", 162da6c28aaSamw info2->shi2_comment); 163da6c28aaSamw 164da6c28aaSamw smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions); 165da6c28aaSamw smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses); 166da6c28aaSamw smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses); 167da6c28aaSamw 168da6c28aaSamw if (info2->shi2_path) 169da6c28aaSamw smb_tracef("srvsvc shi2_path=%s", info2->shi2_path); 170da6c28aaSamw 171da6c28aaSamw if (info2->shi2_passwd) 172da6c28aaSamw smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd); 173da6c28aaSamw break; 174da6c28aaSamw 175da6c28aaSamw default: 176da6c28aaSamw smb_tracef("srvsvc: unknown level"); 177da6c28aaSamw break; 178da6c28aaSamw } 179da6c28aaSamw 1808d7e4166Sjose borrego srvsvc_close(&handle); 181da6c28aaSamw return (0); 182da6c28aaSamw } 183da6c28aaSamw 184da6c28aaSamw /* 185da6c28aaSamw * This is a client side routine for NetSessionEnum. 186da6c28aaSamw * NetSessionEnum requires administrator rights. 187da6c28aaSamw */ 188da6c28aaSamw int 189da6c28aaSamw srvsvc_net_session_enum(char *server, char *domain, char *netname) 190da6c28aaSamw { 191da6c28aaSamw struct mslm_NetSessionEnum arg; 192da6c28aaSamw mlsvc_handle_t handle; 193da6c28aaSamw int rc; 194da6c28aaSamw int opnum; 195da6c28aaSamw struct mslm_infonres infonres; 196da6c28aaSamw struct mslm_SESSION_INFO_1 *nsi1; 197da6c28aaSamw int len; 19855bf511dSas char *user = smbrdr_ipc_get_user(); 199da6c28aaSamw 200da6c28aaSamw if (netname == NULL) 201da6c28aaSamw return (-1); 202da6c28aaSamw 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 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; 26355bf511dSas char *user = smbrdr_ipc_get_user(); 264da6c28aaSamw 265da6c28aaSamw if (netname == NULL) 266da6c28aaSamw return (-1); 267da6c28aaSamw 2688d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle); 269da6c28aaSamw if (rc != 0) 270da6c28aaSamw return (-1); 271da6c28aaSamw 272da6c28aaSamw opnum = SRVSVC_OPNUM_NetConnectEnum; 273da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetConnectEnum)); 274da6c28aaSamw 275da6c28aaSamw len = strlen(server) + 4; 2768d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 277da6c28aaSamw if (arg.servername == NULL) { 2788d7e4166Sjose borrego srvsvc_close(&handle); 279da6c28aaSamw return (-1); 280da6c28aaSamw } 281da6c28aaSamw 282da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 283da6c28aaSamw arg.qualifier = (LPTSTR)netname; 284da6c28aaSamw 285da6c28aaSamw switch (level) { 286da6c28aaSamw case 0: 287da6c28aaSamw arg.info.level = 0; 288da6c28aaSamw arg.info.switch_value = 0; 289da6c28aaSamw arg.info.ru.info0 = &info0; 290da6c28aaSamw info0.entries_read = 0; 291da6c28aaSamw info0.ci0 = 0; 292da6c28aaSamw break; 293da6c28aaSamw case 1: 294da6c28aaSamw arg.info.level = 1; 295da6c28aaSamw arg.info.switch_value = 1; 296da6c28aaSamw arg.info.ru.info1 = &info1; 297da6c28aaSamw info1.entries_read = 0; 298da6c28aaSamw info1.ci1 = 0; 299da6c28aaSamw break; 300da6c28aaSamw default: 3018d7e4166Sjose borrego srvsvc_close(&handle); 302da6c28aaSamw return (-1); 303da6c28aaSamw } 304da6c28aaSamw 305da6c28aaSamw arg.resume_handle = 0; 306da6c28aaSamw arg.pref_max_len = 0xFFFFFFFF; 307da6c28aaSamw 3088d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 309da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 3108d7e4166Sjose borrego srvsvc_close(&handle); 311da6c28aaSamw return (-1); 312da6c28aaSamw } 313da6c28aaSamw 314da6c28aaSamw smb_tracef("srvsvc switch_value=%d", arg.info.switch_value); 315da6c28aaSamw 316da6c28aaSamw switch (level) { 317da6c28aaSamw case 0: 318da6c28aaSamw if (arg.info.ru.info0 && arg.info.ru.info0->ci0) { 319da6c28aaSamw smb_tracef("srvsvc coni0_id=%x", 320da6c28aaSamw arg.info.ru.info0->ci0->coni0_id); 321da6c28aaSamw } 322da6c28aaSamw break; 323da6c28aaSamw case 1: 324da6c28aaSamw if (arg.info.ru.info1 && arg.info.ru.info1->ci1) { 325da6c28aaSamw cib1 = arg.info.ru.info1->ci1; 326da6c28aaSamw 327da6c28aaSamw smb_tracef("srvsvc coni_uname=%s", 328da6c28aaSamw cib1->coni1_username ? 329da6c28aaSamw (char *)cib1->coni1_username : "(null)"); 330da6c28aaSamw smb_tracef("srvsvc coni1_netname=%s", 331da6c28aaSamw cib1->coni1_netname ? 332da6c28aaSamw (char *)cib1->coni1_netname : "(null)"); 333da6c28aaSamw smb_tracef("srvsvc coni1_nopens=%u", 334da6c28aaSamw cib1->coni1_num_opens); 335da6c28aaSamw smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time); 336da6c28aaSamw smb_tracef("srvsvc coni1_num_users=%u", 337da6c28aaSamw cib1->coni1_num_users); 338da6c28aaSamw } 339da6c28aaSamw break; 340da6c28aaSamw 341da6c28aaSamw default: 342da6c28aaSamw smb_tracef("srvsvc: unknown level"); 343da6c28aaSamw break; 344da6c28aaSamw } 345da6c28aaSamw 3468d7e4166Sjose borrego srvsvc_close(&handle); 347da6c28aaSamw return (0); 348da6c28aaSamw } 349da6c28aaSamw 350*1fcced4cSJordan Brown int 351*1fcced4cSJordan Brown srvsvc_net_server_getinfo(char *server, char *domain, 352*1fcced4cSJordan Brown srvsvc_server_info_t *svinfo) 353*1fcced4cSJordan Brown { 354*1fcced4cSJordan Brown mlsvc_handle_t handle; 355*1fcced4cSJordan Brown struct mslm_NetServerGetInfo arg; 356*1fcced4cSJordan Brown struct mslm_SERVER_INFO_101 *sv101; 357*1fcced4cSJordan Brown int len, opnum, rc; 358*1fcced4cSJordan Brown char *user = smbrdr_ipc_get_user(); 359*1fcced4cSJordan Brown 360*1fcced4cSJordan Brown if (srvsvc_open(server, domain, user, &handle) != 0) 361*1fcced4cSJordan Brown return (-1); 362*1fcced4cSJordan Brown 363*1fcced4cSJordan Brown opnum = SRVSVC_OPNUM_NetServerGetInfo; 364*1fcced4cSJordan Brown bzero(&arg, sizeof (arg)); 365*1fcced4cSJordan Brown 366*1fcced4cSJordan Brown len = strlen(server) + 4; 367*1fcced4cSJordan Brown arg.servername = ndr_rpc_malloc(&handle, len); 368*1fcced4cSJordan Brown if (arg.servername == NULL) 369*1fcced4cSJordan Brown return (-1); 370*1fcced4cSJordan Brown 371*1fcced4cSJordan Brown (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 372*1fcced4cSJordan Brown arg.level = 101; 373*1fcced4cSJordan Brown 374*1fcced4cSJordan Brown rc = ndr_rpc_call(&handle, opnum, &arg); 375*1fcced4cSJordan Brown if ((rc != 0) || (arg.status != 0)) { 376*1fcced4cSJordan Brown srvsvc_close(&handle); 377*1fcced4cSJordan Brown return (-1); 378*1fcced4cSJordan Brown } 379*1fcced4cSJordan Brown 380*1fcced4cSJordan Brown sv101 = arg.result.bufptr.bufptr101; 381*1fcced4cSJordan Brown 382*1fcced4cSJordan Brown bzero(svinfo, sizeof (srvsvc_server_info_t)); 383*1fcced4cSJordan Brown svinfo->sv_platform_id = sv101->sv101_platform_id; 384*1fcced4cSJordan Brown svinfo->sv_version_major = sv101->sv101_version_major; 385*1fcced4cSJordan Brown svinfo->sv_version_minor = sv101->sv101_version_minor; 386*1fcced4cSJordan Brown svinfo->sv_type = sv101->sv101_type; 387*1fcced4cSJordan Brown if (sv101->sv101_name) 388*1fcced4cSJordan Brown svinfo->sv_name = strdup((char *)sv101->sv101_name); 389*1fcced4cSJordan Brown if (sv101->sv101_comment) 390*1fcced4cSJordan Brown svinfo->sv_comment = strdup((char *)sv101->sv101_comment); 391*1fcced4cSJordan Brown 392*1fcced4cSJordan Brown srvsvc_close(&handle); 393*1fcced4cSJordan Brown return (0); 394*1fcced4cSJordan Brown } 395*1fcced4cSJordan Brown 396da6c28aaSamw /* 397da6c28aaSamw * Synchronize the local system clock with the domain controller. 398da6c28aaSamw */ 399da6c28aaSamw void 400da6c28aaSamw srvsvc_timesync(void) 401da6c28aaSamw { 4028d7e4166Sjose borrego smb_domain_t di; 403da6c28aaSamw struct timeval tv; 404da6c28aaSamw struct tm tm; 405da6c28aaSamw time_t tsecs; 406da6c28aaSamw 4078d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 408da6c28aaSamw return; 409da6c28aaSamw 41029bd2886SAlan Wright if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &tv, &tm) != 0) 411da6c28aaSamw return; 412da6c28aaSamw 413da6c28aaSamw if (settimeofday(&tv, 0)) 414da6c28aaSamw smb_tracef("unable to set system time"); 415da6c28aaSamw 416da6c28aaSamw tsecs = time(0); 417da6c28aaSamw (void) localtime_r(&tsecs, &tm); 418da6c28aaSamw smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec)); 419da6c28aaSamw } 420da6c28aaSamw 421da6c28aaSamw /* 422da6c28aaSamw * NetRemoteTOD to get the current GMT time from a Windows NT server. 423da6c28aaSamw */ 424da6c28aaSamw int 425da6c28aaSamw srvsvc_gettime(unsigned long *t) 426da6c28aaSamw { 4278d7e4166Sjose borrego smb_domain_t di; 428da6c28aaSamw struct timeval tv; 429da6c28aaSamw struct tm tm; 430da6c28aaSamw 4318d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 432da6c28aaSamw return (-1); 433da6c28aaSamw 43429bd2886SAlan Wright if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &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 470da6c28aaSamw srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv, 471da6c28aaSamw struct tm *tm) 472da6c28aaSamw { 473da6c28aaSamw char timebuf[64]; 474da6c28aaSamw struct mslm_NetRemoteTOD arg; 475da6c28aaSamw struct mslm_TIME_OF_DAY_INFO *tod; 476da6c28aaSamw mlsvc_handle_t handle; 477da6c28aaSamw int rc; 478da6c28aaSamw int opnum; 479da6c28aaSamw int len; 48055bf511dSas char *user = smbrdr_ipc_get_user(); 481da6c28aaSamw 4828d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle); 483da6c28aaSamw if (rc != 0) 484da6c28aaSamw return (-1); 485da6c28aaSamw 486da6c28aaSamw opnum = SRVSVC_OPNUM_NetRemoteTOD; 487da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetRemoteTOD)); 488da6c28aaSamw 489da6c28aaSamw len = strlen(server) + 4; 4908d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 491da6c28aaSamw if (arg.servername == NULL) { 4928d7e4166Sjose borrego srvsvc_close(&handle); 493da6c28aaSamw return (-1); 494da6c28aaSamw } 495da6c28aaSamw 496da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 497da6c28aaSamw 4988d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 499da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 5008d7e4166Sjose borrego srvsvc_close(&handle); 501da6c28aaSamw return (-1); 502da6c28aaSamw } 503da6c28aaSamw 504da6c28aaSamw /* 505da6c28aaSamw * We're assigning milliseconds to microseconds 506da6c28aaSamw * here but the value's not really relevant. 507da6c28aaSamw */ 508da6c28aaSamw tod = arg.bufptr; 509da6c28aaSamw 510da6c28aaSamw if (tv) { 511da6c28aaSamw tv->tv_sec = tod->tod_elapsedt; 512da6c28aaSamw tv->tv_usec = tod->tod_msecs; 513c8ec8eeaSjose borrego smb_tracef("RemoteTime from %s: %s", server, 514c8ec8eeaSjose borrego ctime(&tv->tv_sec)); 515da6c28aaSamw } 516da6c28aaSamw 517da6c28aaSamw if (tm) { 518da6c28aaSamw tm->tm_sec = tod->tod_secs; 519da6c28aaSamw tm->tm_min = tod->tod_mins; 520da6c28aaSamw tm->tm_hour = tod->tod_hours; 521da6c28aaSamw tm->tm_mday = tod->tod_day; 522da6c28aaSamw tm->tm_mon = tod->tod_month - 1; 523da6c28aaSamw tm->tm_year = tod->tod_year - 1900; 524da6c28aaSamw tm->tm_wday = tod->tod_weekday; 525da6c28aaSamw 526da6c28aaSamw (void) strftime(timebuf, sizeof (timebuf), 527da6c28aaSamw "NetRemoteTOD: %D %T", tm); 528c8ec8eeaSjose borrego smb_tracef("NetRemoteTOD from %s: %s", server, timebuf); 529da6c28aaSamw } 530da6c28aaSamw 5318d7e4166Sjose borrego srvsvc_close(&handle); 532da6c28aaSamw return (0); 533da6c28aaSamw } 534da6c28aaSamw 535da6c28aaSamw void 536da6c28aaSamw srvsvc_net_test(char *server, char *domain, char *netname) 537da6c28aaSamw { 5388d7e4166Sjose borrego smb_domain_t di; 539*1fcced4cSJordan Brown srvsvc_server_info_t svinfo; 540da6c28aaSamw 541da6c28aaSamw (void) smb_tracef("%s %s %s", server, domain, netname); 542da6c28aaSamw 5438d7e4166Sjose borrego if (smb_domain_getinfo(&di)) { 5448d7e4166Sjose borrego server = di.d_dc; 54529bd2886SAlan Wright domain = di.d_info.di_nbname; 546da6c28aaSamw } 547da6c28aaSamw 548*1fcced4cSJordan Brown if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) { 549*1fcced4cSJordan Brown smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x", 550*1fcced4cSJordan Brown svinfo.sv_name ? svinfo.sv_name : "NULL", 551*1fcced4cSJordan Brown svinfo.sv_comment ? svinfo.sv_comment : "NULL", 552*1fcced4cSJordan Brown svinfo.sv_version_major, svinfo.sv_version_minor, 553*1fcced4cSJordan Brown svinfo.sv_platform_id, svinfo.sv_type); 554*1fcced4cSJordan Brown 555*1fcced4cSJordan Brown free(svinfo.sv_name); 556*1fcced4cSJordan Brown free(svinfo.sv_comment); 557*1fcced4cSJordan Brown } 558*1fcced4cSJordan Brown 559da6c28aaSamw (void) srvsvc_net_share_get_info(server, domain, netname); 560da6c28aaSamw #if 0 561da6c28aaSamw /* 562da6c28aaSamw * The NetSessionEnum server-side definition was updated. 563da6c28aaSamw * Disabled until the client-side has been updated. 564da6c28aaSamw */ 565da6c28aaSamw (void) srvsvc_net_session_enum(server, domain, netname); 566da6c28aaSamw #endif 567da6c28aaSamw (void) srvsvc_net_connect_enum(server, domain, netname, 0); 568da6c28aaSamw (void) srvsvc_net_connect_enum(server, domain, netname, 1); 569da6c28aaSamw } 570