111963SAfshin.Ardakani@Sun.COM /* 211963SAfshin.Ardakani@Sun.COM * CDDL HEADER START 311963SAfshin.Ardakani@Sun.COM * 411963SAfshin.Ardakani@Sun.COM * The contents of this file are subject to the terms of the 511963SAfshin.Ardakani@Sun.COM * Common Development and Distribution License (the "License"). 611963SAfshin.Ardakani@Sun.COM * You may not use this file except in compliance with the License. 711963SAfshin.Ardakani@Sun.COM * 811963SAfshin.Ardakani@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 911963SAfshin.Ardakani@Sun.COM * or http://www.opensolaris.org/os/licensing. 1011963SAfshin.Ardakani@Sun.COM * See the License for the specific language governing permissions 1111963SAfshin.Ardakani@Sun.COM * and limitations under the License. 1211963SAfshin.Ardakani@Sun.COM * 1311963SAfshin.Ardakani@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1411963SAfshin.Ardakani@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1511963SAfshin.Ardakani@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1611963SAfshin.Ardakani@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1711963SAfshin.Ardakani@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1811963SAfshin.Ardakani@Sun.COM * 1911963SAfshin.Ardakani@Sun.COM * CDDL HEADER END 2011963SAfshin.Ardakani@Sun.COM */ 2111963SAfshin.Ardakani@Sun.COM /* 22*12065SKeyur.Desai@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2311963SAfshin.Ardakani@Sun.COM */ 2411963SAfshin.Ardakani@Sun.COM 2511963SAfshin.Ardakani@Sun.COM #include <sys/param.h> 2611963SAfshin.Ardakani@Sun.COM #include <sys/types.h> 2711963SAfshin.Ardakani@Sun.COM #include <sys/tzfile.h> 2811963SAfshin.Ardakani@Sun.COM #include <sys/atomic.h> 2911963SAfshin.Ardakani@Sun.COM #include <sys/kidmap.h> 3011963SAfshin.Ardakani@Sun.COM #include <sys/time.h> 3111963SAfshin.Ardakani@Sun.COM #include <sys/cpuvar.h> 3211963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h> 3311963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_fsops.h> 3411963SAfshin.Ardakani@Sun.COM #include <smbsrv/smbinfo.h> 3511963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_xdr.h> 3611963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_vops.h> 3711963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_idmap.h> 3811963SAfshin.Ardakani@Sun.COM 3911963SAfshin.Ardakani@Sun.COM #include <sys/sid.h> 4011963SAfshin.Ardakani@Sun.COM #include <sys/priv_names.h> 4111963SAfshin.Ardakani@Sun.COM 4211963SAfshin.Ardakani@Sun.COM static kmem_cache_t *smb_dtor_cache; 4311963SAfshin.Ardakani@Sun.COM static boolean_t smb_llist_initialized = B_FALSE; 4411963SAfshin.Ardakani@Sun.COM 4511963SAfshin.Ardakani@Sun.COM static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int); 4611963SAfshin.Ardakani@Sun.COM 4711963SAfshin.Ardakani@Sun.COM time_t tzh_leapcnt = 0; 4811963SAfshin.Ardakani@Sun.COM 4911963SAfshin.Ardakani@Sun.COM struct tm 5011963SAfshin.Ardakani@Sun.COM *smb_gmtime_r(time_t *clock, struct tm *result); 5111963SAfshin.Ardakani@Sun.COM 5211963SAfshin.Ardakani@Sun.COM time_t 5311963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm); 5411963SAfshin.Ardakani@Sun.COM 5511963SAfshin.Ardakani@Sun.COM struct tm { 5611963SAfshin.Ardakani@Sun.COM int tm_sec; 5711963SAfshin.Ardakani@Sun.COM int tm_min; 5811963SAfshin.Ardakani@Sun.COM int tm_hour; 5911963SAfshin.Ardakani@Sun.COM int tm_mday; 6011963SAfshin.Ardakani@Sun.COM int tm_mon; 6111963SAfshin.Ardakani@Sun.COM int tm_year; 6211963SAfshin.Ardakani@Sun.COM int tm_wday; 6311963SAfshin.Ardakani@Sun.COM int tm_yday; 6411963SAfshin.Ardakani@Sun.COM int tm_isdst; 6511963SAfshin.Ardakani@Sun.COM }; 6611963SAfshin.Ardakani@Sun.COM 6711963SAfshin.Ardakani@Sun.COM static int days_in_month[] = { 6811963SAfshin.Ardakani@Sun.COM 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 6911963SAfshin.Ardakani@Sun.COM }; 7011963SAfshin.Ardakani@Sun.COM 7111963SAfshin.Ardakani@Sun.COM int 7211963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str) 7311963SAfshin.Ardakani@Sun.COM { 7411963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 7511963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str)); 7611963SAfshin.Ardakani@Sun.COM return (strlen(str)); 7711963SAfshin.Ardakani@Sun.COM } 7811963SAfshin.Ardakani@Sun.COM 7911963SAfshin.Ardakani@Sun.COM int 8011963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str) 8111963SAfshin.Ardakani@Sun.COM { 8211963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 8311963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str) + 2); 8411963SAfshin.Ardakani@Sun.COM return (strlen(str) + 1); 8511963SAfshin.Ardakani@Sun.COM } 8611963SAfshin.Ardakani@Sun.COM 8711963SAfshin.Ardakani@Sun.COM int 8811963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_null_len(struct smb_request *sr) 8911963SAfshin.Ardakani@Sun.COM { 9011963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 9111963SAfshin.Ardakani@Sun.COM return (2); 9211963SAfshin.Ardakani@Sun.COM return (1); 9311963SAfshin.Ardakani@Sun.COM } 9411963SAfshin.Ardakani@Sun.COM 9511963SAfshin.Ardakani@Sun.COM /* 9611963SAfshin.Ardakani@Sun.COM * Return B_TRUE if pattern contains wildcards 9711963SAfshin.Ardakani@Sun.COM */ 9811963SAfshin.Ardakani@Sun.COM boolean_t 9911963SAfshin.Ardakani@Sun.COM smb_contains_wildcards(const char *pattern) 10011963SAfshin.Ardakani@Sun.COM { 10111963SAfshin.Ardakani@Sun.COM static const char *wildcards = "*?"; 10211963SAfshin.Ardakani@Sun.COM 10311963SAfshin.Ardakani@Sun.COM return (strpbrk(pattern, wildcards) != NULL); 10411963SAfshin.Ardakani@Sun.COM } 10511963SAfshin.Ardakani@Sun.COM 10611963SAfshin.Ardakani@Sun.COM /* 10711963SAfshin.Ardakani@Sun.COM * When converting wildcards a '.' in a name is treated as a base and 10811963SAfshin.Ardakani@Sun.COM * extension separator even if the name is longer than 8.3. 10911963SAfshin.Ardakani@Sun.COM * 11011963SAfshin.Ardakani@Sun.COM * The '*' character matches an entire part of the name. For example, 11111963SAfshin.Ardakani@Sun.COM * "*.abc" matches any name with an extension of "abc". 11211963SAfshin.Ardakani@Sun.COM * 11311963SAfshin.Ardakani@Sun.COM * The '?' character matches a single character. 11411963SAfshin.Ardakani@Sun.COM * If the base contains all ? (8 or more) then it is treated as *. 11511963SAfshin.Ardakani@Sun.COM * If the extension contains all ? (3 or more) then it is treated as *. 11611963SAfshin.Ardakani@Sun.COM * 11711963SAfshin.Ardakani@Sun.COM * Clients convert ASCII wildcards to Unicode wildcards as follows: 11811963SAfshin.Ardakani@Sun.COM * 11911963SAfshin.Ardakani@Sun.COM * ? is converted to > 12011963SAfshin.Ardakani@Sun.COM * . is converted to " if it is followed by ? or * 12111963SAfshin.Ardakani@Sun.COM * * is converted to < if it is followed by . 12211963SAfshin.Ardakani@Sun.COM * 12311963SAfshin.Ardakani@Sun.COM * Note that clients convert "*." to '< and drop the '.' but "*.txt" 12411963SAfshin.Ardakani@Sun.COM * is sent as "<.TXT", i.e. 12511963SAfshin.Ardakani@Sun.COM * 12611963SAfshin.Ardakani@Sun.COM * dir *. -> dir < 12711963SAfshin.Ardakani@Sun.COM * dir *.txt -> dir <.TXT 12811963SAfshin.Ardakani@Sun.COM * 12911963SAfshin.Ardakani@Sun.COM * Since " and < are illegal in Windows file names, we always convert 13011963SAfshin.Ardakani@Sun.COM * these Unicode wildcards without checking the following character. 13111963SAfshin.Ardakani@Sun.COM */ 13211963SAfshin.Ardakani@Sun.COM void 13311963SAfshin.Ardakani@Sun.COM smb_convert_wildcards(char *pattern) 13411963SAfshin.Ardakani@Sun.COM { 13511963SAfshin.Ardakani@Sun.COM static char *match_all[] = { 13611963SAfshin.Ardakani@Sun.COM "*.", 13711963SAfshin.Ardakani@Sun.COM "*.*" 13811963SAfshin.Ardakani@Sun.COM }; 13911963SAfshin.Ardakani@Sun.COM char *extension; 14011963SAfshin.Ardakani@Sun.COM char *p; 14111963SAfshin.Ardakani@Sun.COM int len; 14211963SAfshin.Ardakani@Sun.COM int i; 14311963SAfshin.Ardakani@Sun.COM 14411963SAfshin.Ardakani@Sun.COM /* 14511963SAfshin.Ardakani@Sun.COM * Special case "<" for "dir *.", and fast-track for "*". 14611963SAfshin.Ardakani@Sun.COM */ 14711963SAfshin.Ardakani@Sun.COM if ((*pattern == '<') || (*pattern == '*')) { 14811963SAfshin.Ardakani@Sun.COM if (*(pattern + 1) == '\0') { 14911963SAfshin.Ardakani@Sun.COM *pattern = '*'; 15011963SAfshin.Ardakani@Sun.COM return; 15111963SAfshin.Ardakani@Sun.COM } 15211963SAfshin.Ardakani@Sun.COM } 15311963SAfshin.Ardakani@Sun.COM 15411963SAfshin.Ardakani@Sun.COM for (p = pattern; *p != '\0'; ++p) { 15511963SAfshin.Ardakani@Sun.COM switch (*p) { 15611963SAfshin.Ardakani@Sun.COM case '<': 15711963SAfshin.Ardakani@Sun.COM *p = '*'; 15811963SAfshin.Ardakani@Sun.COM break; 15911963SAfshin.Ardakani@Sun.COM case '>': 16011963SAfshin.Ardakani@Sun.COM *p = '?'; 16111963SAfshin.Ardakani@Sun.COM break; 16211963SAfshin.Ardakani@Sun.COM case '\"': 16311963SAfshin.Ardakani@Sun.COM *p = '.'; 16411963SAfshin.Ardakani@Sun.COM break; 16511963SAfshin.Ardakani@Sun.COM default: 16611963SAfshin.Ardakani@Sun.COM break; 16711963SAfshin.Ardakani@Sun.COM } 16811963SAfshin.Ardakani@Sun.COM } 16911963SAfshin.Ardakani@Sun.COM 17011963SAfshin.Ardakani@Sun.COM /* 17111963SAfshin.Ardakani@Sun.COM * Replace "????????.ext" with "*.ext". 17211963SAfshin.Ardakani@Sun.COM */ 17311963SAfshin.Ardakani@Sun.COM p = pattern; 17411963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 17511963SAfshin.Ardakani@Sun.COM if (*p == '.') { 17611963SAfshin.Ardakani@Sun.COM *p = '\0'; 17711963SAfshin.Ardakani@Sun.COM len = strlen(pattern); 17811963SAfshin.Ardakani@Sun.COM *p = '.'; 17911963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_BASELEN) { 18011963SAfshin.Ardakani@Sun.COM *pattern = '*'; 18111963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern + 1, p, MAXPATHLEN - 1); 18211963SAfshin.Ardakani@Sun.COM } 18311963SAfshin.Ardakani@Sun.COM } 18411963SAfshin.Ardakani@Sun.COM 18511963SAfshin.Ardakani@Sun.COM /* 18611963SAfshin.Ardakani@Sun.COM * Replace "base.???" with 'base.*'. 18711963SAfshin.Ardakani@Sun.COM */ 18811963SAfshin.Ardakani@Sun.COM if ((extension = strrchr(pattern, '.')) != NULL) { 18911963SAfshin.Ardakani@Sun.COM p = ++extension; 19011963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 19111963SAfshin.Ardakani@Sun.COM if (*p == '\0') { 19211963SAfshin.Ardakani@Sun.COM len = strlen(extension); 19311963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_EXTLEN) { 19411963SAfshin.Ardakani@Sun.COM *extension = '\0'; 19511963SAfshin.Ardakani@Sun.COM (void) strlcat(pattern, "*", MAXPATHLEN); 19611963SAfshin.Ardakani@Sun.COM } 19711963SAfshin.Ardakani@Sun.COM } 19811963SAfshin.Ardakani@Sun.COM } 19911963SAfshin.Ardakani@Sun.COM 20011963SAfshin.Ardakani@Sun.COM /* 20111963SAfshin.Ardakani@Sun.COM * Replace anything that matches an entry in match_all with "*". 20211963SAfshin.Ardakani@Sun.COM */ 20311963SAfshin.Ardakani@Sun.COM for (i = 0; i < sizeof (match_all) / sizeof (match_all[0]); ++i) { 20411963SAfshin.Ardakani@Sun.COM if (strcmp(pattern, match_all[i]) == 0) { 20511963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern, "*", MAXPATHLEN); 20611963SAfshin.Ardakani@Sun.COM break; 20711963SAfshin.Ardakani@Sun.COM } 20811963SAfshin.Ardakani@Sun.COM } 20911963SAfshin.Ardakani@Sun.COM } 21011963SAfshin.Ardakani@Sun.COM 21111963SAfshin.Ardakani@Sun.COM /* 21211963SAfshin.Ardakani@Sun.COM * smb_sattr_check 21311963SAfshin.Ardakani@Sun.COM * 21411963SAfshin.Ardakani@Sun.COM * Check file attributes against a search attribute (sattr) mask. 21511963SAfshin.Ardakani@Sun.COM * 21611963SAfshin.Ardakani@Sun.COM * Normal files, which includes READONLY and ARCHIVE, always pass 21711963SAfshin.Ardakani@Sun.COM * this check. If the DIRECTORY, HIDDEN or SYSTEM special attributes 21811963SAfshin.Ardakani@Sun.COM * are set then they must appear in the search mask. The special 21911963SAfshin.Ardakani@Sun.COM * attributes are inclusive, i.e. all special attributes that appear 22011963SAfshin.Ardakani@Sun.COM * in sattr must also appear in the file attributes for the check to 22111963SAfshin.Ardakani@Sun.COM * pass. 22211963SAfshin.Ardakani@Sun.COM * 22311963SAfshin.Ardakani@Sun.COM * The following examples show how this works: 22411963SAfshin.Ardakani@Sun.COM * 22511963SAfshin.Ardakani@Sun.COM * fileA: READONLY 22611963SAfshin.Ardakani@Sun.COM * fileB: 0 (no attributes = normal file) 22711963SAfshin.Ardakani@Sun.COM * fileC: READONLY, ARCHIVE 22811963SAfshin.Ardakani@Sun.COM * fileD: HIDDEN 22911963SAfshin.Ardakani@Sun.COM * fileE: READONLY, HIDDEN, SYSTEM 23011963SAfshin.Ardakani@Sun.COM * dirA: DIRECTORY 23111963SAfshin.Ardakani@Sun.COM * 23211963SAfshin.Ardakani@Sun.COM * search attribute: 0 23311963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 23411963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN 23511963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and fileD. 23611963SAfshin.Ardakani@Sun.COM * search attribute: SYSTEM 23711963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 23811963SAfshin.Ardakani@Sun.COM * search attribute: DIRECTORY 23911963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and dirA. 24011963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN and SYSTEM 24111963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC, fileD and fileE. 24211963SAfshin.Ardakani@Sun.COM * 24311963SAfshin.Ardakani@Sun.COM * Returns true if the file and sattr match; otherwise, returns false. 24411963SAfshin.Ardakani@Sun.COM */ 24511963SAfshin.Ardakani@Sun.COM boolean_t 24611963SAfshin.Ardakani@Sun.COM smb_sattr_check(uint16_t dosattr, uint16_t sattr) 24711963SAfshin.Ardakani@Sun.COM { 24811963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) && 24911963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_DIRECTORY)) 25011963SAfshin.Ardakani@Sun.COM return (B_FALSE); 25111963SAfshin.Ardakani@Sun.COM 25211963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_HIDDEN) && 25311963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_HIDDEN)) 25411963SAfshin.Ardakani@Sun.COM return (B_FALSE); 25511963SAfshin.Ardakani@Sun.COM 25611963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_SYSTEM) && 25711963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_SYSTEM)) 25811963SAfshin.Ardakani@Sun.COM return (B_FALSE); 25911963SAfshin.Ardakani@Sun.COM 26011963SAfshin.Ardakani@Sun.COM return (B_TRUE); 26111963SAfshin.Ardakani@Sun.COM } 26211963SAfshin.Ardakani@Sun.COM 26311963SAfshin.Ardakani@Sun.COM int 26411963SAfshin.Ardakani@Sun.COM microtime(timestruc_t *tvp) 26511963SAfshin.Ardakani@Sun.COM { 26611963SAfshin.Ardakani@Sun.COM tvp->tv_sec = gethrestime_sec(); 26711963SAfshin.Ardakani@Sun.COM tvp->tv_nsec = 0; 26811963SAfshin.Ardakani@Sun.COM return (0); 26911963SAfshin.Ardakani@Sun.COM } 27011963SAfshin.Ardakani@Sun.COM 27111963SAfshin.Ardakani@Sun.COM int32_t 27211963SAfshin.Ardakani@Sun.COM clock_get_milli_uptime() 27311963SAfshin.Ardakani@Sun.COM { 27411963SAfshin.Ardakani@Sun.COM return (TICK_TO_MSEC(ddi_get_lbolt())); 27511963SAfshin.Ardakani@Sun.COM } 27611963SAfshin.Ardakani@Sun.COM 27711963SAfshin.Ardakani@Sun.COM int /*ARGSUSED*/ 27811963SAfshin.Ardakani@Sun.COM smb_noop(void *p, size_t size, int foo) 27911963SAfshin.Ardakani@Sun.COM { 28011963SAfshin.Ardakani@Sun.COM return (0); 28111963SAfshin.Ardakani@Sun.COM } 28211963SAfshin.Ardakani@Sun.COM 28311963SAfshin.Ardakani@Sun.COM /* 28411963SAfshin.Ardakani@Sun.COM * smb_idpool_increment 28511963SAfshin.Ardakani@Sun.COM * 28611963SAfshin.Ardakani@Sun.COM * This function increments the ID pool by doubling the current size. This 28711963SAfshin.Ardakani@Sun.COM * function assumes the caller entered the mutex of the pool. 28811963SAfshin.Ardakani@Sun.COM */ 28911963SAfshin.Ardakani@Sun.COM static int 29011963SAfshin.Ardakani@Sun.COM smb_idpool_increment( 29111963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 29211963SAfshin.Ardakani@Sun.COM { 29311963SAfshin.Ardakani@Sun.COM uint8_t *new_pool; 29411963SAfshin.Ardakani@Sun.COM uint32_t new_size; 29511963SAfshin.Ardakani@Sun.COM 29611963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 29711963SAfshin.Ardakani@Sun.COM 29811963SAfshin.Ardakani@Sun.COM new_size = pool->id_size * 2; 29911963SAfshin.Ardakani@Sun.COM if (new_size <= SMB_IDPOOL_MAX_SIZE) { 30011963SAfshin.Ardakani@Sun.COM new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP); 30111963SAfshin.Ardakani@Sun.COM if (new_pool) { 30211963SAfshin.Ardakani@Sun.COM bzero(new_pool, new_size / 8); 30311963SAfshin.Ardakani@Sun.COM bcopy(pool->id_pool, new_pool, pool->id_size / 8); 30411963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, pool->id_size / 8); 30511963SAfshin.Ardakani@Sun.COM pool->id_pool = new_pool; 30611963SAfshin.Ardakani@Sun.COM pool->id_free_counter += new_size - pool->id_size; 30711963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter += new_size - pool->id_size; 30811963SAfshin.Ardakani@Sun.COM pool->id_size = new_size; 30911963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (new_size / 8) - 1; 31011963SAfshin.Ardakani@Sun.COM if (new_size >= SMB_IDPOOL_MAX_SIZE) { 31111963SAfshin.Ardakani@Sun.COM /* id -1 made unavailable */ 31211963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx_msk] = 0x80; 31311963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 31411963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter--; 31511963SAfshin.Ardakani@Sun.COM } 31611963SAfshin.Ardakani@Sun.COM return (0); 31711963SAfshin.Ardakani@Sun.COM } 31811963SAfshin.Ardakani@Sun.COM } 31911963SAfshin.Ardakani@Sun.COM return (-1); 32011963SAfshin.Ardakani@Sun.COM } 32111963SAfshin.Ardakani@Sun.COM 32211963SAfshin.Ardakani@Sun.COM /* 32311963SAfshin.Ardakani@Sun.COM * smb_idpool_constructor 32411963SAfshin.Ardakani@Sun.COM * 32511963SAfshin.Ardakani@Sun.COM * This function initializes the pool structure provided. 32611963SAfshin.Ardakani@Sun.COM */ 32711963SAfshin.Ardakani@Sun.COM int 32811963SAfshin.Ardakani@Sun.COM smb_idpool_constructor( 32911963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 33011963SAfshin.Ardakani@Sun.COM { 33111963SAfshin.Ardakani@Sun.COM 33211963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC); 33311963SAfshin.Ardakani@Sun.COM 33411963SAfshin.Ardakani@Sun.COM pool->id_size = SMB_IDPOOL_MIN_SIZE; 33511963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1; 33611963SAfshin.Ardakani@Sun.COM pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 33711963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 33811963SAfshin.Ardakani@Sun.COM pool->id_bit = 0x02; 33911963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 1; 34011963SAfshin.Ardakani@Sun.COM pool->id_idx = 0; 34111963SAfshin.Ardakani@Sun.COM pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8), 34211963SAfshin.Ardakani@Sun.COM KM_SLEEP); 34311963SAfshin.Ardakani@Sun.COM bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8)); 34411963SAfshin.Ardakani@Sun.COM /* -1 id made unavailable */ 34511963SAfshin.Ardakani@Sun.COM pool->id_pool[0] = 0x01; /* id 0 made unavailable */ 34611963SAfshin.Ardakani@Sun.COM mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL); 34711963SAfshin.Ardakani@Sun.COM pool->id_magic = SMB_IDPOOL_MAGIC; 34811963SAfshin.Ardakani@Sun.COM return (0); 34911963SAfshin.Ardakani@Sun.COM } 35011963SAfshin.Ardakani@Sun.COM 35111963SAfshin.Ardakani@Sun.COM /* 35211963SAfshin.Ardakani@Sun.COM * smb_idpool_destructor 35311963SAfshin.Ardakani@Sun.COM * 35411963SAfshin.Ardakani@Sun.COM * This function tears down and frees the resources associated with the 35511963SAfshin.Ardakani@Sun.COM * pool provided. 35611963SAfshin.Ardakani@Sun.COM */ 35711963SAfshin.Ardakani@Sun.COM void 35811963SAfshin.Ardakani@Sun.COM smb_idpool_destructor( 35911963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 36011963SAfshin.Ardakani@Sun.COM { 36111963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 36211963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter == pool->id_max_free_counter); 36311963SAfshin.Ardakani@Sun.COM pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC; 36411963SAfshin.Ardakani@Sun.COM mutex_destroy(&pool->id_mutex); 36511963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, (size_t)(pool->id_size / 8)); 36611963SAfshin.Ardakani@Sun.COM } 36711963SAfshin.Ardakani@Sun.COM 36811963SAfshin.Ardakani@Sun.COM /* 36911963SAfshin.Ardakani@Sun.COM * smb_idpool_alloc 37011963SAfshin.Ardakani@Sun.COM * 37111963SAfshin.Ardakani@Sun.COM * This function allocates an ID from the pool provided. 37211963SAfshin.Ardakani@Sun.COM */ 37311963SAfshin.Ardakani@Sun.COM int 37411963SAfshin.Ardakani@Sun.COM smb_idpool_alloc( 37511963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 37611963SAfshin.Ardakani@Sun.COM uint16_t *id) 37711963SAfshin.Ardakani@Sun.COM { 37811963SAfshin.Ardakani@Sun.COM uint32_t i; 37911963SAfshin.Ardakani@Sun.COM uint8_t bit; 38011963SAfshin.Ardakani@Sun.COM uint8_t bit_idx; 38111963SAfshin.Ardakani@Sun.COM uint8_t byte; 38211963SAfshin.Ardakani@Sun.COM 38311963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 38411963SAfshin.Ardakani@Sun.COM 38511963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 38611963SAfshin.Ardakani@Sun.COM if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) { 38711963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 38811963SAfshin.Ardakani@Sun.COM return (-1); 38911963SAfshin.Ardakani@Sun.COM } 39011963SAfshin.Ardakani@Sun.COM 39111963SAfshin.Ardakani@Sun.COM i = pool->id_size; 39211963SAfshin.Ardakani@Sun.COM while (i) { 39311963SAfshin.Ardakani@Sun.COM bit = pool->id_bit; 39411963SAfshin.Ardakani@Sun.COM bit_idx = pool->id_bit_idx; 39511963SAfshin.Ardakani@Sun.COM byte = pool->id_pool[pool->id_idx]; 39611963SAfshin.Ardakani@Sun.COM while (bit) { 39711963SAfshin.Ardakani@Sun.COM if (byte & bit) { 39811963SAfshin.Ardakani@Sun.COM bit = bit << 1; 39911963SAfshin.Ardakani@Sun.COM bit_idx++; 40011963SAfshin.Ardakani@Sun.COM continue; 40111963SAfshin.Ardakani@Sun.COM } 40211963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx] |= bit; 40311963SAfshin.Ardakani@Sun.COM *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx); 40411963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 40511963SAfshin.Ardakani@Sun.COM pool->id_bit = bit; 40611963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = bit_idx; 40711963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 40811963SAfshin.Ardakani@Sun.COM return (0); 40911963SAfshin.Ardakani@Sun.COM } 41011963SAfshin.Ardakani@Sun.COM pool->id_bit = 1; 41111963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 0; 41211963SAfshin.Ardakani@Sun.COM pool->id_idx++; 41311963SAfshin.Ardakani@Sun.COM pool->id_idx &= pool->id_idx_msk; 41411963SAfshin.Ardakani@Sun.COM --i; 41511963SAfshin.Ardakani@Sun.COM } 41611963SAfshin.Ardakani@Sun.COM /* 41711963SAfshin.Ardakani@Sun.COM * This section of code shouldn't be reached. If there are IDs 41811963SAfshin.Ardakani@Sun.COM * available and none could be found there's a problem. 41911963SAfshin.Ardakani@Sun.COM */ 42011963SAfshin.Ardakani@Sun.COM ASSERT(0); 42111963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 42211963SAfshin.Ardakani@Sun.COM return (-1); 42311963SAfshin.Ardakani@Sun.COM } 42411963SAfshin.Ardakani@Sun.COM 42511963SAfshin.Ardakani@Sun.COM /* 42611963SAfshin.Ardakani@Sun.COM * smb_idpool_free 42711963SAfshin.Ardakani@Sun.COM * 42811963SAfshin.Ardakani@Sun.COM * This function frees the ID provided. 42911963SAfshin.Ardakani@Sun.COM */ 43011963SAfshin.Ardakani@Sun.COM void 43111963SAfshin.Ardakani@Sun.COM smb_idpool_free( 43211963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 43311963SAfshin.Ardakani@Sun.COM uint16_t id) 43411963SAfshin.Ardakani@Sun.COM { 43511963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 43611963SAfshin.Ardakani@Sun.COM ASSERT(id != 0); 43711963SAfshin.Ardakani@Sun.COM ASSERT(id != 0xFFFF); 43811963SAfshin.Ardakani@Sun.COM 43911963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 44011963SAfshin.Ardakani@Sun.COM if (pool->id_pool[id >> 3] & (1 << (id & 7))) { 44111963SAfshin.Ardakani@Sun.COM pool->id_pool[id >> 3] &= ~(1 << (id & 7)); 44211963SAfshin.Ardakani@Sun.COM pool->id_free_counter++; 44311963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter <= pool->id_max_free_counter); 44411963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 44511963SAfshin.Ardakani@Sun.COM return; 44611963SAfshin.Ardakani@Sun.COM } 44711963SAfshin.Ardakani@Sun.COM /* Freeing a free ID. */ 44811963SAfshin.Ardakani@Sun.COM ASSERT(0); 44911963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 45011963SAfshin.Ardakani@Sun.COM } 45111963SAfshin.Ardakani@Sun.COM 45211963SAfshin.Ardakani@Sun.COM /* 45311963SAfshin.Ardakani@Sun.COM * Initialize the llist delete queue object cache. 45411963SAfshin.Ardakani@Sun.COM */ 45511963SAfshin.Ardakani@Sun.COM void 45611963SAfshin.Ardakani@Sun.COM smb_llist_init(void) 45711963SAfshin.Ardakani@Sun.COM { 45811963SAfshin.Ardakani@Sun.COM if (smb_llist_initialized) 45911963SAfshin.Ardakani@Sun.COM return; 46011963SAfshin.Ardakani@Sun.COM 46111963SAfshin.Ardakani@Sun.COM smb_dtor_cache = kmem_cache_create("smb_dtor_cache", 46211963SAfshin.Ardakani@Sun.COM sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 46311963SAfshin.Ardakani@Sun.COM 46411963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_TRUE; 46511963SAfshin.Ardakani@Sun.COM } 46611963SAfshin.Ardakani@Sun.COM 46711963SAfshin.Ardakani@Sun.COM /* 46811963SAfshin.Ardakani@Sun.COM * Destroy the llist delete queue object cache. 46911963SAfshin.Ardakani@Sun.COM */ 47011963SAfshin.Ardakani@Sun.COM void 47111963SAfshin.Ardakani@Sun.COM smb_llist_fini(void) 47211963SAfshin.Ardakani@Sun.COM { 47311963SAfshin.Ardakani@Sun.COM if (!smb_llist_initialized) 47411963SAfshin.Ardakani@Sun.COM return; 47511963SAfshin.Ardakani@Sun.COM 47611963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(smb_dtor_cache); 47711963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_FALSE; 47811963SAfshin.Ardakani@Sun.COM } 47911963SAfshin.Ardakani@Sun.COM 48011963SAfshin.Ardakani@Sun.COM /* 48111963SAfshin.Ardakani@Sun.COM * smb_llist_constructor 48211963SAfshin.Ardakani@Sun.COM * 48311963SAfshin.Ardakani@Sun.COM * This function initializes a locked list. 48411963SAfshin.Ardakani@Sun.COM */ 48511963SAfshin.Ardakani@Sun.COM void 48611963SAfshin.Ardakani@Sun.COM smb_llist_constructor( 48711963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 48811963SAfshin.Ardakani@Sun.COM size_t size, 48911963SAfshin.Ardakani@Sun.COM size_t offset) 49011963SAfshin.Ardakani@Sun.COM { 49111963SAfshin.Ardakani@Sun.COM rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); 49211963SAfshin.Ardakani@Sun.COM mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); 49311963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_list, size, offset); 49411963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), 49511963SAfshin.Ardakani@Sun.COM offsetof(smb_dtor_t, dt_lnd)); 49611963SAfshin.Ardakani@Sun.COM ll->ll_count = 0; 49711963SAfshin.Ardakani@Sun.COM ll->ll_wrop = 0; 49811963SAfshin.Ardakani@Sun.COM ll->ll_deleteq_count = 0; 49911963SAfshin.Ardakani@Sun.COM } 50011963SAfshin.Ardakani@Sun.COM 50111963SAfshin.Ardakani@Sun.COM /* 50211963SAfshin.Ardakani@Sun.COM * Flush the delete queue and destroy a locked list. 50311963SAfshin.Ardakani@Sun.COM */ 50411963SAfshin.Ardakani@Sun.COM void 50511963SAfshin.Ardakani@Sun.COM smb_llist_destructor( 50611963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 50711963SAfshin.Ardakani@Sun.COM { 50811963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 50911963SAfshin.Ardakani@Sun.COM 51011963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_count == 0); 51111963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_deleteq_count == 0); 51211963SAfshin.Ardakani@Sun.COM 51311963SAfshin.Ardakani@Sun.COM rw_destroy(&ll->ll_lock); 51411963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_list); 51511963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_deleteq); 51611963SAfshin.Ardakani@Sun.COM mutex_destroy(&ll->ll_mutex); 51711963SAfshin.Ardakani@Sun.COM } 51811963SAfshin.Ardakani@Sun.COM 51911963SAfshin.Ardakani@Sun.COM /* 52011963SAfshin.Ardakani@Sun.COM * Post an object to the delete queue. The delete queue will be processed 52111963SAfshin.Ardakani@Sun.COM * during list exit or list destruction. Objects are often posted for 52211963SAfshin.Ardakani@Sun.COM * deletion during list iteration (while the list is locked) but that is 52311963SAfshin.Ardakani@Sun.COM * not required, and an object can be posted at any time. 52411963SAfshin.Ardakani@Sun.COM */ 52511963SAfshin.Ardakani@Sun.COM void 52611963SAfshin.Ardakani@Sun.COM smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc) 52711963SAfshin.Ardakani@Sun.COM { 52811963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 52911963SAfshin.Ardakani@Sun.COM 53011963SAfshin.Ardakani@Sun.COM ASSERT((object != NULL) && (dtorproc != NULL)); 53111963SAfshin.Ardakani@Sun.COM 53211963SAfshin.Ardakani@Sun.COM dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP); 53311963SAfshin.Ardakani@Sun.COM bzero(dtor, sizeof (smb_dtor_t)); 53411963SAfshin.Ardakani@Sun.COM dtor->dt_magic = SMB_DTOR_MAGIC; 53511963SAfshin.Ardakani@Sun.COM dtor->dt_object = object; 53611963SAfshin.Ardakani@Sun.COM dtor->dt_proc = dtorproc; 53711963SAfshin.Ardakani@Sun.COM 53811963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 53911963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_deleteq, dtor); 54011963SAfshin.Ardakani@Sun.COM ++ll->ll_deleteq_count; 54111963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 54211963SAfshin.Ardakani@Sun.COM } 54311963SAfshin.Ardakani@Sun.COM 54411963SAfshin.Ardakani@Sun.COM /* 54511963SAfshin.Ardakani@Sun.COM * Exit the list lock and process the delete queue. 54611963SAfshin.Ardakani@Sun.COM */ 54711963SAfshin.Ardakani@Sun.COM void 54811963SAfshin.Ardakani@Sun.COM smb_llist_exit(smb_llist_t *ll) 54911963SAfshin.Ardakani@Sun.COM { 55011963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 55111963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 55211963SAfshin.Ardakani@Sun.COM } 55311963SAfshin.Ardakani@Sun.COM 55411963SAfshin.Ardakani@Sun.COM /* 55511963SAfshin.Ardakani@Sun.COM * Flush the list delete queue. The mutex is dropped across the destructor 55611963SAfshin.Ardakani@Sun.COM * call in case this leads to additional objects being posted to the delete 55711963SAfshin.Ardakani@Sun.COM * queue. 55811963SAfshin.Ardakani@Sun.COM */ 559*12065SKeyur.Desai@Sun.COM void 56011963SAfshin.Ardakani@Sun.COM smb_llist_flush(smb_llist_t *ll) 56111963SAfshin.Ardakani@Sun.COM { 56211963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 56311963SAfshin.Ardakani@Sun.COM 56411963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 56511963SAfshin.Ardakani@Sun.COM 56611963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 56711963SAfshin.Ardakani@Sun.COM while (dtor != NULL) { 56811963SAfshin.Ardakani@Sun.COM SMB_DTOR_VALID(dtor); 56911963SAfshin.Ardakani@Sun.COM ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL)); 57011963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_deleteq, dtor); 57111963SAfshin.Ardakani@Sun.COM --ll->ll_deleteq_count; 57211963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 57311963SAfshin.Ardakani@Sun.COM 57411963SAfshin.Ardakani@Sun.COM dtor->dt_proc(dtor->dt_object); 57511963SAfshin.Ardakani@Sun.COM 57611963SAfshin.Ardakani@Sun.COM dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC; 57711963SAfshin.Ardakani@Sun.COM kmem_cache_free(smb_dtor_cache, dtor); 57811963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 57911963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 58011963SAfshin.Ardakani@Sun.COM } 58111963SAfshin.Ardakani@Sun.COM 58211963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 58311963SAfshin.Ardakani@Sun.COM } 58411963SAfshin.Ardakani@Sun.COM 58511963SAfshin.Ardakani@Sun.COM /* 58611963SAfshin.Ardakani@Sun.COM * smb_llist_upgrade 58711963SAfshin.Ardakani@Sun.COM * 58811963SAfshin.Ardakani@Sun.COM * This function tries to upgrade the lock of the locked list. It assumes the 58911963SAfshin.Ardakani@Sun.COM * locked has already been entered in RW_READER mode. It first tries using the 59011963SAfshin.Ardakani@Sun.COM * Solaris function rw_tryupgrade(). If that call fails the lock is released 59111963SAfshin.Ardakani@Sun.COM * and reentered in RW_WRITER mode. In that last case a window is opened during 59211963SAfshin.Ardakani@Sun.COM * which the contents of the list may have changed. The return code indicates 59311963SAfshin.Ardakani@Sun.COM * whether or not the list was modified when the lock was exited. 59411963SAfshin.Ardakani@Sun.COM */ 59511963SAfshin.Ardakani@Sun.COM int smb_llist_upgrade( 59611963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 59711963SAfshin.Ardakani@Sun.COM { 59811963SAfshin.Ardakani@Sun.COM uint64_t wrop; 59911963SAfshin.Ardakani@Sun.COM 60011963SAfshin.Ardakani@Sun.COM if (rw_tryupgrade(&ll->ll_lock) != 0) { 60111963SAfshin.Ardakani@Sun.COM return (0); 60211963SAfshin.Ardakani@Sun.COM } 60311963SAfshin.Ardakani@Sun.COM wrop = ll->ll_wrop; 60411963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 60511963SAfshin.Ardakani@Sun.COM rw_enter(&ll->ll_lock, RW_WRITER); 60611963SAfshin.Ardakani@Sun.COM return (wrop != ll->ll_wrop); 60711963SAfshin.Ardakani@Sun.COM } 60811963SAfshin.Ardakani@Sun.COM 60911963SAfshin.Ardakani@Sun.COM /* 61011963SAfshin.Ardakani@Sun.COM * smb_llist_insert_head 61111963SAfshin.Ardakani@Sun.COM * 61211963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. This 61311963SAfshin.Ardakani@Sun.COM * function assumes the lock of the list has already been entered. 61411963SAfshin.Ardakani@Sun.COM */ 61511963SAfshin.Ardakani@Sun.COM void 61611963SAfshin.Ardakani@Sun.COM smb_llist_insert_head( 61711963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 61811963SAfshin.Ardakani@Sun.COM void *obj) 61911963SAfshin.Ardakani@Sun.COM { 62011963SAfshin.Ardakani@Sun.COM list_insert_head(&ll->ll_list, obj); 62111963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 62211963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 62311963SAfshin.Ardakani@Sun.COM } 62411963SAfshin.Ardakani@Sun.COM 62511963SAfshin.Ardakani@Sun.COM /* 62611963SAfshin.Ardakani@Sun.COM * smb_llist_insert_tail 62711963SAfshin.Ardakani@Sun.COM * 62811963SAfshin.Ardakani@Sun.COM * This function appends to the object passed to the list. This function assumes 62911963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 63011963SAfshin.Ardakani@Sun.COM * 63111963SAfshin.Ardakani@Sun.COM */ 63211963SAfshin.Ardakani@Sun.COM void 63311963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail( 63411963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 63511963SAfshin.Ardakani@Sun.COM void *obj) 63611963SAfshin.Ardakani@Sun.COM { 63711963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_list, obj); 63811963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 63911963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 64011963SAfshin.Ardakani@Sun.COM } 64111963SAfshin.Ardakani@Sun.COM 64211963SAfshin.Ardakani@Sun.COM /* 64311963SAfshin.Ardakani@Sun.COM * smb_llist_remove 64411963SAfshin.Ardakani@Sun.COM * 64511963SAfshin.Ardakani@Sun.COM * This function removes the object passed from the list. This function assumes 64611963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 64711963SAfshin.Ardakani@Sun.COM */ 64811963SAfshin.Ardakani@Sun.COM void 64911963SAfshin.Ardakani@Sun.COM smb_llist_remove( 65011963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 65111963SAfshin.Ardakani@Sun.COM void *obj) 65211963SAfshin.Ardakani@Sun.COM { 65311963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_list, obj); 65411963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 65511963SAfshin.Ardakani@Sun.COM --ll->ll_count; 65611963SAfshin.Ardakani@Sun.COM } 65711963SAfshin.Ardakani@Sun.COM 65811963SAfshin.Ardakani@Sun.COM /* 65911963SAfshin.Ardakani@Sun.COM * smb_llist_get_count 66011963SAfshin.Ardakani@Sun.COM * 66111963SAfshin.Ardakani@Sun.COM * This function returns the number of elements in the specified list. 66211963SAfshin.Ardakani@Sun.COM */ 66311963SAfshin.Ardakani@Sun.COM uint32_t 66411963SAfshin.Ardakani@Sun.COM smb_llist_get_count( 66511963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 66611963SAfshin.Ardakani@Sun.COM { 66711963SAfshin.Ardakani@Sun.COM return (ll->ll_count); 66811963SAfshin.Ardakani@Sun.COM } 66911963SAfshin.Ardakani@Sun.COM 67011963SAfshin.Ardakani@Sun.COM /* 67111963SAfshin.Ardakani@Sun.COM * smb_slist_constructor 67211963SAfshin.Ardakani@Sun.COM * 67311963SAfshin.Ardakani@Sun.COM * Synchronized list constructor. 67411963SAfshin.Ardakani@Sun.COM */ 67511963SAfshin.Ardakani@Sun.COM void 67611963SAfshin.Ardakani@Sun.COM smb_slist_constructor( 67711963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 67811963SAfshin.Ardakani@Sun.COM size_t size, 67911963SAfshin.Ardakani@Sun.COM size_t offset) 68011963SAfshin.Ardakani@Sun.COM { 68111963SAfshin.Ardakani@Sun.COM mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL); 68211963SAfshin.Ardakani@Sun.COM cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL); 68311963SAfshin.Ardakani@Sun.COM list_create(&sl->sl_list, size, offset); 68411963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 68511963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 68611963SAfshin.Ardakani@Sun.COM } 68711963SAfshin.Ardakani@Sun.COM 68811963SAfshin.Ardakani@Sun.COM /* 68911963SAfshin.Ardakani@Sun.COM * smb_slist_destructor 69011963SAfshin.Ardakani@Sun.COM * 69111963SAfshin.Ardakani@Sun.COM * Synchronized list destructor. 69211963SAfshin.Ardakani@Sun.COM */ 69311963SAfshin.Ardakani@Sun.COM void 69411963SAfshin.Ardakani@Sun.COM smb_slist_destructor( 69511963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 69611963SAfshin.Ardakani@Sun.COM { 69711963SAfshin.Ardakani@Sun.COM ASSERT(sl->sl_count == 0); 69811963SAfshin.Ardakani@Sun.COM 69911963SAfshin.Ardakani@Sun.COM mutex_destroy(&sl->sl_mutex); 70011963SAfshin.Ardakani@Sun.COM cv_destroy(&sl->sl_cv); 70111963SAfshin.Ardakani@Sun.COM list_destroy(&sl->sl_list); 70211963SAfshin.Ardakani@Sun.COM } 70311963SAfshin.Ardakani@Sun.COM 70411963SAfshin.Ardakani@Sun.COM /* 70511963SAfshin.Ardakani@Sun.COM * smb_slist_insert_head 70611963SAfshin.Ardakani@Sun.COM * 70711963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. 70811963SAfshin.Ardakani@Sun.COM */ 70911963SAfshin.Ardakani@Sun.COM void 71011963SAfshin.Ardakani@Sun.COM smb_slist_insert_head( 71111963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 71211963SAfshin.Ardakani@Sun.COM void *obj) 71311963SAfshin.Ardakani@Sun.COM { 71411963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 71511963SAfshin.Ardakani@Sun.COM list_insert_head(&sl->sl_list, obj); 71611963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 71711963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 71811963SAfshin.Ardakani@Sun.COM } 71911963SAfshin.Ardakani@Sun.COM 72011963SAfshin.Ardakani@Sun.COM /* 72111963SAfshin.Ardakani@Sun.COM * smb_slist_insert_tail 72211963SAfshin.Ardakani@Sun.COM * 72311963SAfshin.Ardakani@Sun.COM * This function appends the object passed to the list. 72411963SAfshin.Ardakani@Sun.COM */ 72511963SAfshin.Ardakani@Sun.COM void 72611963SAfshin.Ardakani@Sun.COM smb_slist_insert_tail( 72711963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 72811963SAfshin.Ardakani@Sun.COM void *obj) 72911963SAfshin.Ardakani@Sun.COM { 73011963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 73111963SAfshin.Ardakani@Sun.COM list_insert_tail(&sl->sl_list, obj); 73211963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 73311963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 73411963SAfshin.Ardakani@Sun.COM } 73511963SAfshin.Ardakani@Sun.COM 73611963SAfshin.Ardakani@Sun.COM /* 73711963SAfshin.Ardakani@Sun.COM * smb_llist_remove 73811963SAfshin.Ardakani@Sun.COM * 73911963SAfshin.Ardakani@Sun.COM * This function removes the object passed by the caller from the list. 74011963SAfshin.Ardakani@Sun.COM */ 74111963SAfshin.Ardakani@Sun.COM void 74211963SAfshin.Ardakani@Sun.COM smb_slist_remove( 74311963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 74411963SAfshin.Ardakani@Sun.COM void *obj) 74511963SAfshin.Ardakani@Sun.COM { 74611963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 74711963SAfshin.Ardakani@Sun.COM list_remove(&sl->sl_list, obj); 74811963SAfshin.Ardakani@Sun.COM if ((--sl->sl_count == 0) && (sl->sl_waiting)) { 74911963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 75011963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 75111963SAfshin.Ardakani@Sun.COM } 75211963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 75311963SAfshin.Ardakani@Sun.COM } 75411963SAfshin.Ardakani@Sun.COM 75511963SAfshin.Ardakani@Sun.COM /* 75611963SAfshin.Ardakani@Sun.COM * smb_slist_move_tail 75711963SAfshin.Ardakani@Sun.COM * 75811963SAfshin.Ardakani@Sun.COM * This function transfers all the contents of the synchronized list to the 75911963SAfshin.Ardakani@Sun.COM * list_t provided. It returns the number of objects transferred. 76011963SAfshin.Ardakani@Sun.COM */ 76111963SAfshin.Ardakani@Sun.COM uint32_t 76211963SAfshin.Ardakani@Sun.COM smb_slist_move_tail( 76311963SAfshin.Ardakani@Sun.COM list_t *lst, 76411963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 76511963SAfshin.Ardakani@Sun.COM { 76611963SAfshin.Ardakani@Sun.COM uint32_t rv; 76711963SAfshin.Ardakani@Sun.COM 76811963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 76911963SAfshin.Ardakani@Sun.COM rv = sl->sl_count; 77011963SAfshin.Ardakani@Sun.COM if (sl->sl_count) { 77111963SAfshin.Ardakani@Sun.COM list_move_tail(lst, &sl->sl_list); 77211963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 77311963SAfshin.Ardakani@Sun.COM if (sl->sl_waiting) { 77411963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 77511963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 77611963SAfshin.Ardakani@Sun.COM } 77711963SAfshin.Ardakani@Sun.COM } 77811963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 77911963SAfshin.Ardakani@Sun.COM return (rv); 78011963SAfshin.Ardakani@Sun.COM } 78111963SAfshin.Ardakani@Sun.COM 78211963SAfshin.Ardakani@Sun.COM /* 78311963SAfshin.Ardakani@Sun.COM * smb_slist_obj_move 78411963SAfshin.Ardakani@Sun.COM * 78511963SAfshin.Ardakani@Sun.COM * This function moves an object from one list to the end of the other list. It 78611963SAfshin.Ardakani@Sun.COM * assumes the mutex of each list has been entered. 78711963SAfshin.Ardakani@Sun.COM */ 78811963SAfshin.Ardakani@Sun.COM void 78911963SAfshin.Ardakani@Sun.COM smb_slist_obj_move( 79011963SAfshin.Ardakani@Sun.COM smb_slist_t *dst, 79111963SAfshin.Ardakani@Sun.COM smb_slist_t *src, 79211963SAfshin.Ardakani@Sun.COM void *obj) 79311963SAfshin.Ardakani@Sun.COM { 79411963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset); 79511963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_size == src->sl_list.list_size); 79611963SAfshin.Ardakani@Sun.COM 79711963SAfshin.Ardakani@Sun.COM list_remove(&src->sl_list, obj); 79811963SAfshin.Ardakani@Sun.COM list_insert_tail(&dst->sl_list, obj); 79911963SAfshin.Ardakani@Sun.COM dst->sl_count++; 80011963SAfshin.Ardakani@Sun.COM src->sl_count--; 80111963SAfshin.Ardakani@Sun.COM if ((src->sl_count == 0) && (src->sl_waiting)) { 80211963SAfshin.Ardakani@Sun.COM src->sl_waiting = B_FALSE; 80311963SAfshin.Ardakani@Sun.COM cv_broadcast(&src->sl_cv); 80411963SAfshin.Ardakani@Sun.COM } 80511963SAfshin.Ardakani@Sun.COM } 80611963SAfshin.Ardakani@Sun.COM 80711963SAfshin.Ardakani@Sun.COM /* 80811963SAfshin.Ardakani@Sun.COM * smb_slist_wait_for_empty 80911963SAfshin.Ardakani@Sun.COM * 81011963SAfshin.Ardakani@Sun.COM * This function waits for a list to be emptied. 81111963SAfshin.Ardakani@Sun.COM */ 81211963SAfshin.Ardakani@Sun.COM void 81311963SAfshin.Ardakani@Sun.COM smb_slist_wait_for_empty( 81411963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 81511963SAfshin.Ardakani@Sun.COM { 81611963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 81711963SAfshin.Ardakani@Sun.COM while (sl->sl_count) { 81811963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_TRUE; 81911963SAfshin.Ardakani@Sun.COM cv_wait(&sl->sl_cv, &sl->sl_mutex); 82011963SAfshin.Ardakani@Sun.COM } 82111963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 82211963SAfshin.Ardakani@Sun.COM } 82311963SAfshin.Ardakani@Sun.COM 82411963SAfshin.Ardakani@Sun.COM /* 82511963SAfshin.Ardakani@Sun.COM * smb_slist_exit 82611963SAfshin.Ardakani@Sun.COM * 82711963SAfshin.Ardakani@Sun.COM * This function exits the muetx of the list and signal the condition variable 82811963SAfshin.Ardakani@Sun.COM * if the list is empty. 82911963SAfshin.Ardakani@Sun.COM */ 83011963SAfshin.Ardakani@Sun.COM void 83111963SAfshin.Ardakani@Sun.COM smb_slist_exit(smb_slist_t *sl) 83211963SAfshin.Ardakani@Sun.COM { 83311963SAfshin.Ardakani@Sun.COM if ((sl->sl_count == 0) && (sl->sl_waiting)) { 83411963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 83511963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 83611963SAfshin.Ardakani@Sun.COM } 83711963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 83811963SAfshin.Ardakani@Sun.COM } 83911963SAfshin.Ardakani@Sun.COM 84011963SAfshin.Ardakani@Sun.COM /* 84111963SAfshin.Ardakani@Sun.COM * smb_thread_entry_point 84211963SAfshin.Ardakani@Sun.COM * 84311963SAfshin.Ardakani@Sun.COM * Common entry point for all the threads created through smb_thread_start. 84411963SAfshin.Ardakani@Sun.COM * The state of the thread is set to "running" at the beginning and moved to 84511963SAfshin.Ardakani@Sun.COM * "exiting" just before calling thread_exit(). The condition variable is 84611963SAfshin.Ardakani@Sun.COM * also signaled. 84711963SAfshin.Ardakani@Sun.COM */ 84811963SAfshin.Ardakani@Sun.COM static void 84911963SAfshin.Ardakani@Sun.COM smb_thread_entry_point( 85011963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 85111963SAfshin.Ardakani@Sun.COM { 85211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 85311963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 85411963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING); 85511963SAfshin.Ardakani@Sun.COM thread->sth_th = curthread; 85611963SAfshin.Ardakani@Sun.COM thread->sth_did = thread->sth_th->t_did; 85711963SAfshin.Ardakani@Sun.COM 85811963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 85911963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_RUNNING; 86011963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 86111963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 86211963SAfshin.Ardakani@Sun.COM thread->sth_ep(thread, thread->sth_ep_arg); 86311963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 86411963SAfshin.Ardakani@Sun.COM } 86511963SAfshin.Ardakani@Sun.COM thread->sth_th = NULL; 86611963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITING; 86711963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 86811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 86911963SAfshin.Ardakani@Sun.COM thread_exit(); 87011963SAfshin.Ardakani@Sun.COM } 87111963SAfshin.Ardakani@Sun.COM 87211963SAfshin.Ardakani@Sun.COM /* 87311963SAfshin.Ardakani@Sun.COM * smb_thread_init 87411963SAfshin.Ardakani@Sun.COM */ 87511963SAfshin.Ardakani@Sun.COM void 87611963SAfshin.Ardakani@Sun.COM smb_thread_init( 87711963SAfshin.Ardakani@Sun.COM smb_thread_t *thread, 87811963SAfshin.Ardakani@Sun.COM char *name, 87911963SAfshin.Ardakani@Sun.COM smb_thread_ep_t ep, 88011963SAfshin.Ardakani@Sun.COM void *ep_arg, 88111963SAfshin.Ardakani@Sun.COM smb_thread_aw_t aw, 88211963SAfshin.Ardakani@Sun.COM void *aw_arg) 88311963SAfshin.Ardakani@Sun.COM { 88411963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic != SMB_THREAD_MAGIC); 88511963SAfshin.Ardakani@Sun.COM 88611963SAfshin.Ardakani@Sun.COM bzero(thread, sizeof (*thread)); 88711963SAfshin.Ardakani@Sun.COM 88811963SAfshin.Ardakani@Sun.COM (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name)); 88911963SAfshin.Ardakani@Sun.COM thread->sth_ep = ep; 89011963SAfshin.Ardakani@Sun.COM thread->sth_ep_arg = ep_arg; 89111963SAfshin.Ardakani@Sun.COM thread->sth_aw = aw; 89211963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = aw_arg; 89311963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 89411963SAfshin.Ardakani@Sun.COM mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL); 89511963SAfshin.Ardakani@Sun.COM cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL); 89611963SAfshin.Ardakani@Sun.COM thread->sth_magic = SMB_THREAD_MAGIC; 89711963SAfshin.Ardakani@Sun.COM } 89811963SAfshin.Ardakani@Sun.COM 89911963SAfshin.Ardakani@Sun.COM /* 90011963SAfshin.Ardakani@Sun.COM * smb_thread_destroy 90111963SAfshin.Ardakani@Sun.COM */ 90211963SAfshin.Ardakani@Sun.COM void 90311963SAfshin.Ardakani@Sun.COM smb_thread_destroy( 90411963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 90511963SAfshin.Ardakani@Sun.COM { 90611963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 90711963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED); 90811963SAfshin.Ardakani@Sun.COM thread->sth_magic = 0; 90911963SAfshin.Ardakani@Sun.COM mutex_destroy(&thread->sth_mtx); 91011963SAfshin.Ardakani@Sun.COM cv_destroy(&thread->sth_cv); 91111963SAfshin.Ardakani@Sun.COM } 91211963SAfshin.Ardakani@Sun.COM 91311963SAfshin.Ardakani@Sun.COM /* 91411963SAfshin.Ardakani@Sun.COM * smb_thread_start 91511963SAfshin.Ardakani@Sun.COM * 91611963SAfshin.Ardakani@Sun.COM * This function starts a thread with the parameters provided. It waits until 91711963SAfshin.Ardakani@Sun.COM * the state of the thread has been moved to running. 91811963SAfshin.Ardakani@Sun.COM */ 91911963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/ 92011963SAfshin.Ardakani@Sun.COM int 92111963SAfshin.Ardakani@Sun.COM smb_thread_start( 92211963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 92311963SAfshin.Ardakani@Sun.COM { 92411963SAfshin.Ardakani@Sun.COM int rc = 0; 92511963SAfshin.Ardakani@Sun.COM kthread_t *tmpthread; 92611963SAfshin.Ardakani@Sun.COM 92711963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 92811963SAfshin.Ardakani@Sun.COM 92911963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 93011963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 93111963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 93211963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_STARTING; 93311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 93411963SAfshin.Ardakani@Sun.COM tmpthread = thread_create(NULL, 0, smb_thread_entry_point, 93511963SAfshin.Ardakani@Sun.COM thread, 0, &p0, TS_RUN, minclsyspri); 93611963SAfshin.Ardakani@Sun.COM ASSERT(tmpthread != NULL); 93711963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 93811963SAfshin.Ardakani@Sun.COM while (thread->sth_state == SMB_THREAD_STATE_STARTING) 93911963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 94011963SAfshin.Ardakani@Sun.COM if (thread->sth_state != SMB_THREAD_STATE_RUNNING) 94111963SAfshin.Ardakani@Sun.COM rc = -1; 94211963SAfshin.Ardakani@Sun.COM break; 94311963SAfshin.Ardakani@Sun.COM default: 94411963SAfshin.Ardakani@Sun.COM ASSERT(0); 94511963SAfshin.Ardakani@Sun.COM rc = -1; 94611963SAfshin.Ardakani@Sun.COM break; 94711963SAfshin.Ardakani@Sun.COM } 94811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 94911963SAfshin.Ardakani@Sun.COM return (rc); 95011963SAfshin.Ardakani@Sun.COM } 95111963SAfshin.Ardakani@Sun.COM 95211963SAfshin.Ardakani@Sun.COM /* 95311963SAfshin.Ardakani@Sun.COM * smb_thread_stop 95411963SAfshin.Ardakani@Sun.COM * 95511963SAfshin.Ardakani@Sun.COM * This function signals a thread to kill itself and waits until the "exiting" 95611963SAfshin.Ardakani@Sun.COM * state has been reached. 95711963SAfshin.Ardakani@Sun.COM */ 95811963SAfshin.Ardakani@Sun.COM void 95911963SAfshin.Ardakani@Sun.COM smb_thread_stop( 96011963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 96111963SAfshin.Ardakani@Sun.COM { 96211963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 96311963SAfshin.Ardakani@Sun.COM 96411963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 96511963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 96611963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 96711963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_STARTING: 96811963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 96911963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_TRUE; 97011963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 97111963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 97211963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 97311963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITING) 97411963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 97511963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 97611963SAfshin.Ardakani@Sun.COM thread_join(thread->sth_did); 97711963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 97811963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 97911963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 98011963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_FALSE; 98111963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 98211963SAfshin.Ardakani@Sun.COM break; 98311963SAfshin.Ardakani@Sun.COM } 98411963SAfshin.Ardakani@Sun.COM /*FALLTHRU*/ 98511963SAfshin.Ardakani@Sun.COM 98611963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITING: 98711963SAfshin.Ardakani@Sun.COM if (thread->sth_kill) { 98811963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITED) 98911963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 99011963SAfshin.Ardakani@Sun.COM } else { 99111963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 99211963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 99311963SAfshin.Ardakani@Sun.COM } 99411963SAfshin.Ardakani@Sun.COM break; 99511963SAfshin.Ardakani@Sun.COM 99611963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 99711963SAfshin.Ardakani@Sun.COM break; 99811963SAfshin.Ardakani@Sun.COM 99911963SAfshin.Ardakani@Sun.COM default: 100011963SAfshin.Ardakani@Sun.COM ASSERT(0); 100111963SAfshin.Ardakani@Sun.COM break; 100211963SAfshin.Ardakani@Sun.COM } 100311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 100411963SAfshin.Ardakani@Sun.COM } 100511963SAfshin.Ardakani@Sun.COM 100611963SAfshin.Ardakani@Sun.COM /* 100711963SAfshin.Ardakani@Sun.COM * smb_thread_signal 100811963SAfshin.Ardakani@Sun.COM * 100911963SAfshin.Ardakani@Sun.COM * This function signals a thread. 101011963SAfshin.Ardakani@Sun.COM */ 101111963SAfshin.Ardakani@Sun.COM void 101211963SAfshin.Ardakani@Sun.COM smb_thread_signal( 101311963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 101411963SAfshin.Ardakani@Sun.COM { 101511963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 101611963SAfshin.Ardakani@Sun.COM 101711963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 101811963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 101911963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 102011963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 102111963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 102211963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 102311963SAfshin.Ardakani@Sun.COM break; 102411963SAfshin.Ardakani@Sun.COM 102511963SAfshin.Ardakani@Sun.COM default: 102611963SAfshin.Ardakani@Sun.COM break; 102711963SAfshin.Ardakani@Sun.COM } 102811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 102911963SAfshin.Ardakani@Sun.COM } 103011963SAfshin.Ardakani@Sun.COM 103111963SAfshin.Ardakani@Sun.COM boolean_t 103211963SAfshin.Ardakani@Sun.COM smb_thread_continue(smb_thread_t *thread) 103311963SAfshin.Ardakani@Sun.COM { 103411963SAfshin.Ardakani@Sun.COM boolean_t result; 103511963SAfshin.Ardakani@Sun.COM 103611963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 103711963SAfshin.Ardakani@Sun.COM 103811963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 103911963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 0); 104011963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 104111963SAfshin.Ardakani@Sun.COM 104211963SAfshin.Ardakani@Sun.COM return (result); 104311963SAfshin.Ardakani@Sun.COM } 104411963SAfshin.Ardakani@Sun.COM 104511963SAfshin.Ardakani@Sun.COM boolean_t 104611963SAfshin.Ardakani@Sun.COM smb_thread_continue_nowait(smb_thread_t *thread) 104711963SAfshin.Ardakani@Sun.COM { 104811963SAfshin.Ardakani@Sun.COM boolean_t result; 104911963SAfshin.Ardakani@Sun.COM 105011963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 105111963SAfshin.Ardakani@Sun.COM 105211963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 105311963SAfshin.Ardakani@Sun.COM /* 105411963SAfshin.Ardakani@Sun.COM * Setting ticks=-1 requests a non-blocking check. We will 105511963SAfshin.Ardakani@Sun.COM * still block if the thread is in "suspend" state. 105611963SAfshin.Ardakani@Sun.COM */ 105711963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, -1); 105811963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 105911963SAfshin.Ardakani@Sun.COM 106011963SAfshin.Ardakani@Sun.COM return (result); 106111963SAfshin.Ardakani@Sun.COM } 106211963SAfshin.Ardakani@Sun.COM 106311963SAfshin.Ardakani@Sun.COM boolean_t 106411963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait(smb_thread_t *thread, int seconds) 106511963SAfshin.Ardakani@Sun.COM { 106611963SAfshin.Ardakani@Sun.COM boolean_t result; 106711963SAfshin.Ardakani@Sun.COM 106811963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 106911963SAfshin.Ardakani@Sun.COM 107011963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 107111963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 107211963SAfshin.Ardakani@Sun.COM SEC_TO_TICK(seconds)); 107311963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 107411963SAfshin.Ardakani@Sun.COM 107511963SAfshin.Ardakani@Sun.COM return (result); 107611963SAfshin.Ardakani@Sun.COM } 107711963SAfshin.Ardakani@Sun.COM 107811963SAfshin.Ardakani@Sun.COM /* 107911963SAfshin.Ardakani@Sun.COM * smb_thread_continue_timedwait_locked 108011963SAfshin.Ardakani@Sun.COM * 108111963SAfshin.Ardakani@Sun.COM * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait 108211963SAfshin.Ardakani@Sun.COM * indefinitely 108311963SAfshin.Ardakani@Sun.COM */ 108411963SAfshin.Ardakani@Sun.COM static boolean_t 108511963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks) 108611963SAfshin.Ardakani@Sun.COM { 108711963SAfshin.Ardakani@Sun.COM boolean_t result; 108811963SAfshin.Ardakani@Sun.COM 108911963SAfshin.Ardakani@Sun.COM /* -1 means don't block */ 109011963SAfshin.Ardakani@Sun.COM if (ticks != -1 && !thread->sth_kill) { 109111963SAfshin.Ardakani@Sun.COM if (ticks == 0) { 109211963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 109311963SAfshin.Ardakani@Sun.COM } else { 109411963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&thread->sth_cv, 109511963SAfshin.Ardakani@Sun.COM &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK); 109611963SAfshin.Ardakani@Sun.COM } 109711963SAfshin.Ardakani@Sun.COM } 109811963SAfshin.Ardakani@Sun.COM result = (thread->sth_kill == 0); 109911963SAfshin.Ardakani@Sun.COM 110011963SAfshin.Ardakani@Sun.COM return (result); 110111963SAfshin.Ardakani@Sun.COM } 110211963SAfshin.Ardakani@Sun.COM 110311963SAfshin.Ardakani@Sun.COM void 110411963SAfshin.Ardakani@Sun.COM smb_thread_set_awaken(smb_thread_t *thread, smb_thread_aw_t new_aw_fn, 110511963SAfshin.Ardakani@Sun.COM void *new_aw_arg) 110611963SAfshin.Ardakani@Sun.COM { 110711963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 110811963SAfshin.Ardakani@Sun.COM 110911963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 111011963SAfshin.Ardakani@Sun.COM thread->sth_aw = new_aw_fn; 111111963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = new_aw_arg; 111211963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 111311963SAfshin.Ardakani@Sun.COM } 111411963SAfshin.Ardakani@Sun.COM 111511963SAfshin.Ardakani@Sun.COM /* 111611963SAfshin.Ardakani@Sun.COM * smb_rwx_init 111711963SAfshin.Ardakani@Sun.COM */ 111811963SAfshin.Ardakani@Sun.COM void 111911963SAfshin.Ardakani@Sun.COM smb_rwx_init( 112011963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 112111963SAfshin.Ardakani@Sun.COM { 112211963SAfshin.Ardakani@Sun.COM bzero(rwx, sizeof (smb_rwx_t)); 112311963SAfshin.Ardakani@Sun.COM cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL); 112411963SAfshin.Ardakani@Sun.COM mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL); 112511963SAfshin.Ardakani@Sun.COM rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL); 112611963SAfshin.Ardakani@Sun.COM } 112711963SAfshin.Ardakani@Sun.COM 112811963SAfshin.Ardakani@Sun.COM /* 112911963SAfshin.Ardakani@Sun.COM * smb_rwx_destroy 113011963SAfshin.Ardakani@Sun.COM */ 113111963SAfshin.Ardakani@Sun.COM void 113211963SAfshin.Ardakani@Sun.COM smb_rwx_destroy( 113311963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 113411963SAfshin.Ardakani@Sun.COM { 113511963SAfshin.Ardakani@Sun.COM mutex_destroy(&rwx->rwx_mutex); 113611963SAfshin.Ardakani@Sun.COM cv_destroy(&rwx->rwx_cv); 113711963SAfshin.Ardakani@Sun.COM rw_destroy(&rwx->rwx_lock); 113811963SAfshin.Ardakani@Sun.COM } 113911963SAfshin.Ardakani@Sun.COM 114011963SAfshin.Ardakani@Sun.COM /* 114111963SAfshin.Ardakani@Sun.COM * smb_rwx_rwexit 114211963SAfshin.Ardakani@Sun.COM */ 114311963SAfshin.Ardakani@Sun.COM void 114411963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit( 114511963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 114611963SAfshin.Ardakani@Sun.COM { 114711963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 114811963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 114911963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 115011963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 115111963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 115211963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 115311963SAfshin.Ardakani@Sun.COM } 115411963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 115511963SAfshin.Ardakani@Sun.COM } 115611963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 115711963SAfshin.Ardakani@Sun.COM } 115811963SAfshin.Ardakani@Sun.COM 115911963SAfshin.Ardakani@Sun.COM /* 116011963SAfshin.Ardakani@Sun.COM * smb_rwx_rwupgrade 116111963SAfshin.Ardakani@Sun.COM */ 116211963SAfshin.Ardakani@Sun.COM krw_t 116311963SAfshin.Ardakani@Sun.COM smb_rwx_rwupgrade( 116411963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 116511963SAfshin.Ardakani@Sun.COM { 116611963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 116711963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 116811963SAfshin.Ardakani@Sun.COM return (RW_WRITER); 116911963SAfshin.Ardakani@Sun.COM } 117011963SAfshin.Ardakani@Sun.COM if (!rw_tryupgrade(&rwx->rwx_lock)) { 117111963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 117211963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, RW_WRITER); 117311963SAfshin.Ardakani@Sun.COM } 117411963SAfshin.Ardakani@Sun.COM return (RW_READER); 117511963SAfshin.Ardakani@Sun.COM } 117611963SAfshin.Ardakani@Sun.COM 117711963SAfshin.Ardakani@Sun.COM /* 117811963SAfshin.Ardakani@Sun.COM * smb_rwx_rwrestore 117911963SAfshin.Ardakani@Sun.COM */ 118011963SAfshin.Ardakani@Sun.COM void 118111963SAfshin.Ardakani@Sun.COM smb_rwx_rwdowngrade( 118211963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 118311963SAfshin.Ardakani@Sun.COM krw_t mode) 118411963SAfshin.Ardakani@Sun.COM { 118511963SAfshin.Ardakani@Sun.COM ASSERT(rw_write_held(&rwx->rwx_lock)); 118611963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 118711963SAfshin.Ardakani@Sun.COM 118811963SAfshin.Ardakani@Sun.COM if (mode == RW_WRITER) { 118911963SAfshin.Ardakani@Sun.COM return; 119011963SAfshin.Ardakani@Sun.COM } 119111963SAfshin.Ardakani@Sun.COM ASSERT(mode == RW_READER); 119211963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 119311963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 119411963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 119511963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 119611963SAfshin.Ardakani@Sun.COM } 119711963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 119811963SAfshin.Ardakani@Sun.COM rw_downgrade(&rwx->rwx_lock); 119911963SAfshin.Ardakani@Sun.COM } 120011963SAfshin.Ardakani@Sun.COM 120111963SAfshin.Ardakani@Sun.COM /* 120211963SAfshin.Ardakani@Sun.COM * smb_rwx_wait 120311963SAfshin.Ardakani@Sun.COM * 120411963SAfshin.Ardakani@Sun.COM * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER 120511963SAfshin.Ardakani@Sun.COM * mode. It will: 120611963SAfshin.Ardakani@Sun.COM * 120711963SAfshin.Ardakani@Sun.COM * 1) release the lock and save its current mode. 120811963SAfshin.Ardakani@Sun.COM * 2) wait until the condition variable is signaled. This can happen for 120911963SAfshin.Ardakani@Sun.COM * 2 reasons: When a writer releases the lock or when the time out (if 121011963SAfshin.Ardakani@Sun.COM * provided) expires. 121111963SAfshin.Ardakani@Sun.COM * 3) re-acquire the lock in the mode saved in (1). 121211963SAfshin.Ardakani@Sun.COM */ 121311963SAfshin.Ardakani@Sun.COM int 121411963SAfshin.Ardakani@Sun.COM smb_rwx_rwwait( 121511963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 121611963SAfshin.Ardakani@Sun.COM clock_t timeout) 121711963SAfshin.Ardakani@Sun.COM { 121811963SAfshin.Ardakani@Sun.COM int rc; 121911963SAfshin.Ardakani@Sun.COM krw_t mode; 122011963SAfshin.Ardakani@Sun.COM 122111963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 122211963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_TRUE; 122311963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 122411963SAfshin.Ardakani@Sun.COM 122511963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 122611963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 122711963SAfshin.Ardakani@Sun.COM mode = RW_WRITER; 122811963SAfshin.Ardakani@Sun.COM } else { 122911963SAfshin.Ardakani@Sun.COM ASSERT(rw_read_held(&rwx->rwx_lock)); 123011963SAfshin.Ardakani@Sun.COM mode = RW_READER; 123111963SAfshin.Ardakani@Sun.COM } 123211963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 123311963SAfshin.Ardakani@Sun.COM 123411963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 123511963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 123611963SAfshin.Ardakani@Sun.COM if (timeout == -1) { 123711963SAfshin.Ardakani@Sun.COM rc = 1; 123811963SAfshin.Ardakani@Sun.COM cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex); 123911963SAfshin.Ardakani@Sun.COM } else { 124011963SAfshin.Ardakani@Sun.COM rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex, 124111963SAfshin.Ardakani@Sun.COM timeout, TR_CLOCK_TICK); 124211963SAfshin.Ardakani@Sun.COM } 124311963SAfshin.Ardakani@Sun.COM } 124411963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 124511963SAfshin.Ardakani@Sun.COM 124611963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, mode); 124711963SAfshin.Ardakani@Sun.COM return (rc); 124811963SAfshin.Ardakani@Sun.COM } 124911963SAfshin.Ardakani@Sun.COM 125011963SAfshin.Ardakani@Sun.COM /* 125111963SAfshin.Ardakani@Sun.COM * SMB ID mapping 125211963SAfshin.Ardakani@Sun.COM * 125311963SAfshin.Ardakani@Sun.COM * Solaris ID mapping service (aka Winchester) works with domain SIDs 125411963SAfshin.Ardakani@Sun.COM * and RIDs where domain SIDs are in string format. CIFS service works 125511963SAfshin.Ardakani@Sun.COM * with binary SIDs understandable by CIFS clients. A layer of SMB ID 125611963SAfshin.Ardakani@Sun.COM * mapping functions are implemeted to hide the SID conversion details 125711963SAfshin.Ardakani@Sun.COM * and also hide the handling of array of batch mapping requests. 125811963SAfshin.Ardakani@Sun.COM * 125911963SAfshin.Ardakani@Sun.COM * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server 126011963SAfshin.Ardakani@Sun.COM * currently only runs in the global zone the global zone is specified. 126111963SAfshin.Ardakani@Sun.COM * This needs to be fixed when the CIFS server supports zones. 126211963SAfshin.Ardakani@Sun.COM */ 126311963SAfshin.Ardakani@Sun.COM 126411963SAfshin.Ardakani@Sun.COM static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); 126511963SAfshin.Ardakani@Sun.COM 126611963SAfshin.Ardakani@Sun.COM /* 126711963SAfshin.Ardakani@Sun.COM * smb_idmap_getid 126811963SAfshin.Ardakani@Sun.COM * 126911963SAfshin.Ardakani@Sun.COM * Maps the given Windows SID to a Solaris ID using the 127011963SAfshin.Ardakani@Sun.COM * simple mapping API. 127111963SAfshin.Ardakani@Sun.COM */ 127211963SAfshin.Ardakani@Sun.COM idmap_stat 127311963SAfshin.Ardakani@Sun.COM smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype) 127411963SAfshin.Ardakani@Sun.COM { 127511963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 127611963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ]; 127711963SAfshin.Ardakani@Sun.COM 127811963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, sidstr); 127911963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0) 128011963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 128111963SAfshin.Ardakani@Sun.COM sim.sim_domsid = sidstr; 128211963SAfshin.Ardakani@Sun.COM sim.sim_id = id; 128311963SAfshin.Ardakani@Sun.COM 128411963SAfshin.Ardakani@Sun.COM switch (*idtype) { 128511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 128611963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid, 128711963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 128811963SAfshin.Ardakani@Sun.COM break; 128911963SAfshin.Ardakani@Sun.COM 129011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 129111963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid, 129211963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 129311963SAfshin.Ardakani@Sun.COM break; 129411963SAfshin.Ardakani@Sun.COM 129511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 129611963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid, 129711963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id, &sim.sim_idtype); 129811963SAfshin.Ardakani@Sun.COM break; 129911963SAfshin.Ardakani@Sun.COM 130011963SAfshin.Ardakani@Sun.COM default: 130111963SAfshin.Ardakani@Sun.COM ASSERT(0); 130211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 130311963SAfshin.Ardakani@Sun.COM } 130411963SAfshin.Ardakani@Sun.COM 130511963SAfshin.Ardakani@Sun.COM *idtype = sim.sim_idtype; 130611963SAfshin.Ardakani@Sun.COM 130711963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 130811963SAfshin.Ardakani@Sun.COM } 130911963SAfshin.Ardakani@Sun.COM 131011963SAfshin.Ardakani@Sun.COM /* 131111963SAfshin.Ardakani@Sun.COM * smb_idmap_getsid 131211963SAfshin.Ardakani@Sun.COM * 131311963SAfshin.Ardakani@Sun.COM * Maps the given Solaris ID to a Windows SID using the 131411963SAfshin.Ardakani@Sun.COM * simple mapping API. 131511963SAfshin.Ardakani@Sun.COM */ 131611963SAfshin.Ardakani@Sun.COM idmap_stat 131711963SAfshin.Ardakani@Sun.COM smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid) 131811963SAfshin.Ardakani@Sun.COM { 131911963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 132011963SAfshin.Ardakani@Sun.COM 132111963SAfshin.Ardakani@Sun.COM switch (idtype) { 132211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 132311963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbyuid(global_zone, id, 132411963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 132511963SAfshin.Ardakani@Sun.COM break; 132611963SAfshin.Ardakani@Sun.COM 132711963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 132811963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbygid(global_zone, id, 132911963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 133011963SAfshin.Ardakani@Sun.COM break; 133111963SAfshin.Ardakani@Sun.COM 133211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 133311963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 133411963SAfshin.Ardakani@Sun.COM sim.sim_domsid = "S-1-1"; 133511963SAfshin.Ardakani@Sun.COM sim.sim_rid = 0; 133611963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_SUCCESS; 133711963SAfshin.Ardakani@Sun.COM break; 133811963SAfshin.Ardakani@Sun.COM 133911963SAfshin.Ardakani@Sun.COM default: 134011963SAfshin.Ardakani@Sun.COM ASSERT(0); 134111963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 134211963SAfshin.Ardakani@Sun.COM } 134311963SAfshin.Ardakani@Sun.COM 134411963SAfshin.Ardakani@Sun.COM if (sim.sim_stat != IDMAP_SUCCESS) 134511963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 134611963SAfshin.Ardakani@Sun.COM 134711963SAfshin.Ardakani@Sun.COM if (sim.sim_domsid == NULL) 134811963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOMAPPING); 134911963SAfshin.Ardakani@Sun.COM 135011963SAfshin.Ardakani@Sun.COM sim.sim_sid = smb_sid_fromstr(sim.sim_domsid); 135111963SAfshin.Ardakani@Sun.COM if (sim.sim_sid == NULL) 135211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_INTERNAL); 135311963SAfshin.Ardakani@Sun.COM 135411963SAfshin.Ardakani@Sun.COM *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid); 135511963SAfshin.Ardakani@Sun.COM smb_sid_free(sim.sim_sid); 135611963SAfshin.Ardakani@Sun.COM if (*sid == NULL) 135711963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_ERR_INTERNAL; 135811963SAfshin.Ardakani@Sun.COM 135911963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 136011963SAfshin.Ardakani@Sun.COM } 136111963SAfshin.Ardakani@Sun.COM 136211963SAfshin.Ardakani@Sun.COM /* 136311963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_create 136411963SAfshin.Ardakani@Sun.COM * 136511963SAfshin.Ardakani@Sun.COM * Creates and initializes the context for batch ID mapping. 136611963SAfshin.Ardakani@Sun.COM */ 136711963SAfshin.Ardakani@Sun.COM idmap_stat 136811963SAfshin.Ardakani@Sun.COM smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 136911963SAfshin.Ardakani@Sun.COM { 137011963SAfshin.Ardakani@Sun.COM ASSERT(sib); 137111963SAfshin.Ardakani@Sun.COM 137211963SAfshin.Ardakani@Sun.COM bzero(sib, sizeof (smb_idmap_batch_t)); 137311963SAfshin.Ardakani@Sun.COM 137411963SAfshin.Ardakani@Sun.COM sib->sib_idmaph = kidmap_get_create(global_zone); 137511963SAfshin.Ardakani@Sun.COM 137611963SAfshin.Ardakani@Sun.COM sib->sib_flags = flags; 137711963SAfshin.Ardakani@Sun.COM sib->sib_nmap = nmap; 137811963SAfshin.Ardakani@Sun.COM sib->sib_size = nmap * sizeof (smb_idmap_t); 137911963SAfshin.Ardakani@Sun.COM sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP); 138011963SAfshin.Ardakani@Sun.COM 138111963SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 138211963SAfshin.Ardakani@Sun.COM } 138311963SAfshin.Ardakani@Sun.COM 138411963SAfshin.Ardakani@Sun.COM /* 138511963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_destroy 138611963SAfshin.Ardakani@Sun.COM * 138711963SAfshin.Ardakani@Sun.COM * Frees the batch ID mapping context. 138811963SAfshin.Ardakani@Sun.COM * If ID mapping is Solaris -> Windows it frees memories 138911963SAfshin.Ardakani@Sun.COM * allocated for binary SIDs. 139011963SAfshin.Ardakani@Sun.COM */ 139111963SAfshin.Ardakani@Sun.COM void 139211963SAfshin.Ardakani@Sun.COM smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 139311963SAfshin.Ardakani@Sun.COM { 139411963SAfshin.Ardakani@Sun.COM char *domsid; 139511963SAfshin.Ardakani@Sun.COM int i; 139611963SAfshin.Ardakani@Sun.COM 139711963SAfshin.Ardakani@Sun.COM ASSERT(sib); 139811963SAfshin.Ardakani@Sun.COM ASSERT(sib->sib_maps); 139911963SAfshin.Ardakani@Sun.COM 140011963SAfshin.Ardakani@Sun.COM if (sib->sib_idmaph) 140111963SAfshin.Ardakani@Sun.COM kidmap_get_destroy(sib->sib_idmaph); 140211963SAfshin.Ardakani@Sun.COM 140311963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_ID2SID) { 140411963SAfshin.Ardakani@Sun.COM /* 140511963SAfshin.Ardakani@Sun.COM * SIDs are allocated only when mapping 140611963SAfshin.Ardakani@Sun.COM * UID/GID to SIDs 140711963SAfshin.Ardakani@Sun.COM */ 140811963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) 140911963SAfshin.Ardakani@Sun.COM smb_sid_free(sib->sib_maps[i].sim_sid); 141011963SAfshin.Ardakani@Sun.COM } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { 141111963SAfshin.Ardakani@Sun.COM /* 141211963SAfshin.Ardakani@Sun.COM * SID prefixes are allocated only when mapping 141311963SAfshin.Ardakani@Sun.COM * SIDs to UID/GID 141411963SAfshin.Ardakani@Sun.COM */ 141511963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 141611963SAfshin.Ardakani@Sun.COM domsid = sib->sib_maps[i].sim_domsid; 141711963SAfshin.Ardakani@Sun.COM if (domsid) 141811963SAfshin.Ardakani@Sun.COM smb_mem_free(domsid); 141911963SAfshin.Ardakani@Sun.COM } 142011963SAfshin.Ardakani@Sun.COM } 142111963SAfshin.Ardakani@Sun.COM 142211963SAfshin.Ardakani@Sun.COM if (sib->sib_size && sib->sib_maps) 142311963SAfshin.Ardakani@Sun.COM kmem_free(sib->sib_maps, sib->sib_size); 142411963SAfshin.Ardakani@Sun.COM } 142511963SAfshin.Ardakani@Sun.COM 142611963SAfshin.Ardakani@Sun.COM /* 142711963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getid 142811963SAfshin.Ardakani@Sun.COM * 142911963SAfshin.Ardakani@Sun.COM * Queue a request to map the given SID to a UID or GID. 143011963SAfshin.Ardakani@Sun.COM * 143111963SAfshin.Ardakani@Sun.COM * sim->sim_id should point to variable that's supposed to 143211963SAfshin.Ardakani@Sun.COM * hold the returned UID/GID. This needs to be setup by caller 143311963SAfshin.Ardakani@Sun.COM * of this function. 143411963SAfshin.Ardakani@Sun.COM * 143511963SAfshin.Ardakani@Sun.COM * If requested ID type is known, it's passed as 'idtype', 143611963SAfshin.Ardakani@Sun.COM * if it's unknown it'll be returned in sim->sim_idtype. 143711963SAfshin.Ardakani@Sun.COM */ 143811963SAfshin.Ardakani@Sun.COM idmap_stat 143911963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 144011963SAfshin.Ardakani@Sun.COM smb_sid_t *sid, int idtype) 144111963SAfshin.Ardakani@Sun.COM { 144211963SAfshin.Ardakani@Sun.COM char strsid[SMB_SID_STRSZ]; 144311963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 144411963SAfshin.Ardakani@Sun.COM 144511963SAfshin.Ardakani@Sun.COM ASSERT(idmaph); 144611963SAfshin.Ardakani@Sun.COM ASSERT(sim); 144711963SAfshin.Ardakani@Sun.COM ASSERT(sid); 144811963SAfshin.Ardakani@Sun.COM 144911963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, strsid); 145011963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0) 145111963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 145211963SAfshin.Ardakani@Sun.COM sim->sim_domsid = smb_mem_strdup(strsid); 145311963SAfshin.Ardakani@Sun.COM 145411963SAfshin.Ardakani@Sun.COM switch (idtype) { 145511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 145611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid, 145711963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 145811963SAfshin.Ardakani@Sun.COM break; 145911963SAfshin.Ardakani@Sun.COM 146011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 146111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid, 146211963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 146311963SAfshin.Ardakani@Sun.COM break; 146411963SAfshin.Ardakani@Sun.COM 146511963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 146611963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid, 146711963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_idtype, 146811963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 146911963SAfshin.Ardakani@Sun.COM break; 147011963SAfshin.Ardakani@Sun.COM 147111963SAfshin.Ardakani@Sun.COM default: 147211963SAfshin.Ardakani@Sun.COM ASSERT(0); 147311963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 147411963SAfshin.Ardakani@Sun.COM } 147511963SAfshin.Ardakani@Sun.COM 147611963SAfshin.Ardakani@Sun.COM return (idm_stat); 147711963SAfshin.Ardakani@Sun.COM } 147811963SAfshin.Ardakani@Sun.COM 147911963SAfshin.Ardakani@Sun.COM /* 148011963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getsid 148111963SAfshin.Ardakani@Sun.COM * 148211963SAfshin.Ardakani@Sun.COM * Queue a request to map the given UID/GID to a SID. 148311963SAfshin.Ardakani@Sun.COM * 148411963SAfshin.Ardakani@Sun.COM * sim->sim_domsid and sim->sim_rid will contain the mapping 148511963SAfshin.Ardakani@Sun.COM * result upon successful process of the batched request. 148611963SAfshin.Ardakani@Sun.COM */ 148711963SAfshin.Ardakani@Sun.COM idmap_stat 148811963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 148911963SAfshin.Ardakani@Sun.COM uid_t id, int idtype) 149011963SAfshin.Ardakani@Sun.COM { 149111963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 149211963SAfshin.Ardakani@Sun.COM 149311963SAfshin.Ardakani@Sun.COM switch (idtype) { 149411963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 149511963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbyuid(idmaph, id, 149611963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 149711963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 149811963SAfshin.Ardakani@Sun.COM break; 149911963SAfshin.Ardakani@Sun.COM 150011963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 150111963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbygid(idmaph, id, 150211963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 150311963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 150411963SAfshin.Ardakani@Sun.COM break; 150511963SAfshin.Ardakani@Sun.COM 150611963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_OWNERAT: 150711963SAfshin.Ardakani@Sun.COM /* Current Owner S-1-5-32-766 */ 150811963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 150911963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_OWNER_RID; 151011963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 151111963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 151211963SAfshin.Ardakani@Sun.COM break; 151311963SAfshin.Ardakani@Sun.COM 151411963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUPAT: 151511963SAfshin.Ardakani@Sun.COM /* Current Group S-1-5-32-767 */ 151611963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 151711963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_GROUP_RID; 151811963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 151911963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 152011963SAfshin.Ardakani@Sun.COM break; 152111963SAfshin.Ardakani@Sun.COM 152211963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 152311963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 152411963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_WORLD_AUTH_SIDSTR; 152511963SAfshin.Ardakani@Sun.COM sim->sim_rid = 0; 152611963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 152711963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 152811963SAfshin.Ardakani@Sun.COM break; 152911963SAfshin.Ardakani@Sun.COM 153011963SAfshin.Ardakani@Sun.COM default: 153111963SAfshin.Ardakani@Sun.COM ASSERT(0); 153211963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 153311963SAfshin.Ardakani@Sun.COM } 153411963SAfshin.Ardakani@Sun.COM 153511963SAfshin.Ardakani@Sun.COM return (idm_stat); 153611963SAfshin.Ardakani@Sun.COM } 153711963SAfshin.Ardakani@Sun.COM 153811963SAfshin.Ardakani@Sun.COM /* 153911963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_binsid 154011963SAfshin.Ardakani@Sun.COM * 154111963SAfshin.Ardakani@Sun.COM * Convert sidrids to binary sids 154211963SAfshin.Ardakani@Sun.COM * 154311963SAfshin.Ardakani@Sun.COM * Returns 0 if successful and non-zero upon failure. 154411963SAfshin.Ardakani@Sun.COM */ 154511963SAfshin.Ardakani@Sun.COM static int 154611963SAfshin.Ardakani@Sun.COM smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 154711963SAfshin.Ardakani@Sun.COM { 154811963SAfshin.Ardakani@Sun.COM smb_sid_t *sid; 154911963SAfshin.Ardakani@Sun.COM smb_idmap_t *sim; 155011963SAfshin.Ardakani@Sun.COM int i; 155111963SAfshin.Ardakani@Sun.COM 155211963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_SID2ID) 155311963SAfshin.Ardakani@Sun.COM /* This operation is not required */ 155411963SAfshin.Ardakani@Sun.COM return (0); 155511963SAfshin.Ardakani@Sun.COM 155611963SAfshin.Ardakani@Sun.COM sim = sib->sib_maps; 155711963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; sim++, i++) { 155811963SAfshin.Ardakani@Sun.COM ASSERT(sim->sim_domsid); 155911963SAfshin.Ardakani@Sun.COM if (sim->sim_domsid == NULL) 156011963SAfshin.Ardakani@Sun.COM return (1); 156111963SAfshin.Ardakani@Sun.COM 156211963SAfshin.Ardakani@Sun.COM if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL) 156311963SAfshin.Ardakani@Sun.COM return (1); 156411963SAfshin.Ardakani@Sun.COM 156511963SAfshin.Ardakani@Sun.COM sim->sim_sid = smb_sid_splice(sid, sim->sim_rid); 156611963SAfshin.Ardakani@Sun.COM smb_sid_free(sid); 156711963SAfshin.Ardakani@Sun.COM } 156811963SAfshin.Ardakani@Sun.COM 156911963SAfshin.Ardakani@Sun.COM return (0); 157011963SAfshin.Ardakani@Sun.COM } 157111963SAfshin.Ardakani@Sun.COM 157211963SAfshin.Ardakani@Sun.COM /* 157311963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getmappings 157411963SAfshin.Ardakani@Sun.COM * 157511963SAfshin.Ardakani@Sun.COM * trigger ID mapping service to get the mappings for queued 157611963SAfshin.Ardakani@Sun.COM * requests. 157711963SAfshin.Ardakani@Sun.COM * 157811963SAfshin.Ardakani@Sun.COM * Checks the result of all the queued requests. 157911963SAfshin.Ardakani@Sun.COM * If this is a Solaris -> Windows mapping it generates 158011963SAfshin.Ardakani@Sun.COM * binary SIDs from returned (domsid, rid) pairs. 158111963SAfshin.Ardakani@Sun.COM */ 158211963SAfshin.Ardakani@Sun.COM idmap_stat 158311963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 158411963SAfshin.Ardakani@Sun.COM { 158511963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat = IDMAP_SUCCESS; 158611963SAfshin.Ardakani@Sun.COM int i; 158711963SAfshin.Ardakani@Sun.COM 158811963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_get_mappings(sib->sib_idmaph); 158911963SAfshin.Ardakani@Sun.COM if (idm_stat != IDMAP_SUCCESS) 159011963SAfshin.Ardakani@Sun.COM return (idm_stat); 159111963SAfshin.Ardakani@Sun.COM 159211963SAfshin.Ardakani@Sun.COM /* 159311963SAfshin.Ardakani@Sun.COM * Check the status for all the queued requests 159411963SAfshin.Ardakani@Sun.COM */ 159511963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 159611963SAfshin.Ardakani@Sun.COM if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) 159711963SAfshin.Ardakani@Sun.COM return (sib->sib_maps[i].sim_stat); 159811963SAfshin.Ardakani@Sun.COM } 159911963SAfshin.Ardakani@Sun.COM 160011963SAfshin.Ardakani@Sun.COM if (smb_idmap_batch_binsid(sib) != 0) 160111963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_ERR_OTHER; 160211963SAfshin.Ardakani@Sun.COM 160311963SAfshin.Ardakani@Sun.COM return (idm_stat); 160411963SAfshin.Ardakani@Sun.COM } 160511963SAfshin.Ardakani@Sun.COM 160611963SAfshin.Ardakani@Sun.COM uint64_t 160711963SAfshin.Ardakani@Sun.COM smb_time_unix_to_nt(timestruc_t *unix_time) 160811963SAfshin.Ardakani@Sun.COM { 160911963SAfshin.Ardakani@Sun.COM uint64_t nt_time; 161011963SAfshin.Ardakani@Sun.COM 161111963SAfshin.Ardakani@Sun.COM if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) 161211963SAfshin.Ardakani@Sun.COM return (0); 161311963SAfshin.Ardakani@Sun.COM 161411963SAfshin.Ardakani@Sun.COM nt_time = unix_time->tv_sec; 161511963SAfshin.Ardakani@Sun.COM nt_time *= 10000000; /* seconds to 100ns */ 161611963SAfshin.Ardakani@Sun.COM nt_time += unix_time->tv_nsec / 100; 161711963SAfshin.Ardakani@Sun.COM return (nt_time + NT_TIME_BIAS); 161811963SAfshin.Ardakani@Sun.COM } 161911963SAfshin.Ardakani@Sun.COM 162011963SAfshin.Ardakani@Sun.COM void 162111963SAfshin.Ardakani@Sun.COM smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) 162211963SAfshin.Ardakani@Sun.COM { 162311963SAfshin.Ardakani@Sun.COM uint32_t seconds; 162411963SAfshin.Ardakani@Sun.COM 162511963SAfshin.Ardakani@Sun.COM ASSERT(unix_time); 162611963SAfshin.Ardakani@Sun.COM 162711963SAfshin.Ardakani@Sun.COM if ((nt_time == 0) || (nt_time == -1)) { 162811963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = 0; 162911963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = 0; 163011963SAfshin.Ardakani@Sun.COM return; 163111963SAfshin.Ardakani@Sun.COM } 163211963SAfshin.Ardakani@Sun.COM 163311963SAfshin.Ardakani@Sun.COM nt_time -= NT_TIME_BIAS; 163411963SAfshin.Ardakani@Sun.COM seconds = nt_time / 10000000; 163511963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = seconds; 163611963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = (nt_time % 10000000) * 100; 163711963SAfshin.Ardakani@Sun.COM } 163811963SAfshin.Ardakani@Sun.COM 163911963SAfshin.Ardakani@Sun.COM /* 164011963SAfshin.Ardakani@Sun.COM * smb_time_gmt_to_local, smb_time_local_to_gmt 164111963SAfshin.Ardakani@Sun.COM * 164211963SAfshin.Ardakani@Sun.COM * Apply the gmt offset to convert between local time and gmt 164311963SAfshin.Ardakani@Sun.COM */ 164411963SAfshin.Ardakani@Sun.COM int32_t 164511963SAfshin.Ardakani@Sun.COM smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt) 164611963SAfshin.Ardakani@Sun.COM { 164711963SAfshin.Ardakani@Sun.COM if ((gmt == 0) || (gmt == -1)) 164811963SAfshin.Ardakani@Sun.COM return (0); 164911963SAfshin.Ardakani@Sun.COM 165011963SAfshin.Ardakani@Sun.COM return (gmt - sr->sr_gmtoff); 165111963SAfshin.Ardakani@Sun.COM } 165211963SAfshin.Ardakani@Sun.COM 165311963SAfshin.Ardakani@Sun.COM int32_t 165411963SAfshin.Ardakani@Sun.COM smb_time_local_to_gmt(smb_request_t *sr, int32_t local) 165511963SAfshin.Ardakani@Sun.COM { 165611963SAfshin.Ardakani@Sun.COM if ((local == 0) || (local == -1)) 165711963SAfshin.Ardakani@Sun.COM return (0); 165811963SAfshin.Ardakani@Sun.COM 165911963SAfshin.Ardakani@Sun.COM return (local + sr->sr_gmtoff); 166011963SAfshin.Ardakani@Sun.COM } 166111963SAfshin.Ardakani@Sun.COM 166211963SAfshin.Ardakani@Sun.COM 166311963SAfshin.Ardakani@Sun.COM /* 166411963SAfshin.Ardakani@Sun.COM * smb_time_dos_to_unix 166511963SAfshin.Ardakani@Sun.COM * 166611963SAfshin.Ardakani@Sun.COM * Convert SMB_DATE & SMB_TIME values to a unix timestamp. 166711963SAfshin.Ardakani@Sun.COM * 166811963SAfshin.Ardakani@Sun.COM * A date/time field of 0 means that that server file system 166911963SAfshin.Ardakani@Sun.COM * assigned value need not be changed. The behaviour when the 167011963SAfshin.Ardakani@Sun.COM * date/time field is set to -1 is not documented but is 167111963SAfshin.Ardakani@Sun.COM * generally treated like 0. 167211963SAfshin.Ardakani@Sun.COM * If date or time is 0 or -1 the unix time is returned as 0 167311963SAfshin.Ardakani@Sun.COM * so that the caller can identify and handle this special case. 167411963SAfshin.Ardakani@Sun.COM */ 167511963SAfshin.Ardakani@Sun.COM int32_t 167611963SAfshin.Ardakani@Sun.COM smb_time_dos_to_unix(int16_t date, int16_t time) 167711963SAfshin.Ardakani@Sun.COM { 167811963SAfshin.Ardakani@Sun.COM struct tm atm; 167911963SAfshin.Ardakani@Sun.COM 168011963SAfshin.Ardakani@Sun.COM if (((date == 0) || (time == 0)) || 168111963SAfshin.Ardakani@Sun.COM ((date == -1) || (time == -1))) { 168211963SAfshin.Ardakani@Sun.COM return (0); 168311963SAfshin.Ardakani@Sun.COM } 168411963SAfshin.Ardakani@Sun.COM 168511963SAfshin.Ardakani@Sun.COM atm.tm_year = ((date >> 9) & 0x3F) + 80; 168611963SAfshin.Ardakani@Sun.COM atm.tm_mon = ((date >> 5) & 0x0F) - 1; 168711963SAfshin.Ardakani@Sun.COM atm.tm_mday = ((date >> 0) & 0x1F); 168811963SAfshin.Ardakani@Sun.COM atm.tm_hour = ((time >> 11) & 0x1F); 168911963SAfshin.Ardakani@Sun.COM atm.tm_min = ((time >> 5) & 0x3F); 169011963SAfshin.Ardakani@Sun.COM atm.tm_sec = ((time >> 0) & 0x1F) << 1; 169111963SAfshin.Ardakani@Sun.COM 169211963SAfshin.Ardakani@Sun.COM return (smb_timegm(&atm)); 169311963SAfshin.Ardakani@Sun.COM } 169411963SAfshin.Ardakani@Sun.COM 169511963SAfshin.Ardakani@Sun.COM void 169611963SAfshin.Ardakani@Sun.COM smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) 169711963SAfshin.Ardakani@Sun.COM { 169811963SAfshin.Ardakani@Sun.COM struct tm atm; 169911963SAfshin.Ardakani@Sun.COM int i; 170011963SAfshin.Ardakani@Sun.COM time_t tmp_time; 170111963SAfshin.Ardakani@Sun.COM 170211963SAfshin.Ardakani@Sun.COM if (ux_time == 0) { 170311963SAfshin.Ardakani@Sun.COM *date_p = 0; 170411963SAfshin.Ardakani@Sun.COM *time_p = 0; 170511963SAfshin.Ardakani@Sun.COM return; 170611963SAfshin.Ardakani@Sun.COM } 170711963SAfshin.Ardakani@Sun.COM 170811963SAfshin.Ardakani@Sun.COM tmp_time = (time_t)ux_time; 170911963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tmp_time, &atm); 171011963SAfshin.Ardakani@Sun.COM 171111963SAfshin.Ardakani@Sun.COM if (date_p) { 171211963SAfshin.Ardakani@Sun.COM i = 0; 171311963SAfshin.Ardakani@Sun.COM i += atm.tm_year - 80; 171411963SAfshin.Ardakani@Sun.COM i <<= 4; 171511963SAfshin.Ardakani@Sun.COM i += atm.tm_mon + 1; 171611963SAfshin.Ardakani@Sun.COM i <<= 5; 171711963SAfshin.Ardakani@Sun.COM i += atm.tm_mday; 171811963SAfshin.Ardakani@Sun.COM 171911963SAfshin.Ardakani@Sun.COM *date_p = (short)i; 172011963SAfshin.Ardakani@Sun.COM } 172111963SAfshin.Ardakani@Sun.COM if (time_p) { 172211963SAfshin.Ardakani@Sun.COM i = 0; 172311963SAfshin.Ardakani@Sun.COM i += atm.tm_hour; 172411963SAfshin.Ardakani@Sun.COM i <<= 6; 172511963SAfshin.Ardakani@Sun.COM i += atm.tm_min; 172611963SAfshin.Ardakani@Sun.COM i <<= 5; 172711963SAfshin.Ardakani@Sun.COM i += atm.tm_sec >> 1; 172811963SAfshin.Ardakani@Sun.COM 172911963SAfshin.Ardakani@Sun.COM *time_p = (short)i; 173011963SAfshin.Ardakani@Sun.COM } 173111963SAfshin.Ardakani@Sun.COM } 173211963SAfshin.Ardakani@Sun.COM 173311963SAfshin.Ardakani@Sun.COM 173411963SAfshin.Ardakani@Sun.COM /* 173511963SAfshin.Ardakani@Sun.COM * smb_gmtime_r 173611963SAfshin.Ardakani@Sun.COM * 173711963SAfshin.Ardakani@Sun.COM * Thread-safe version of smb_gmtime. Returns a null pointer if either 173811963SAfshin.Ardakani@Sun.COM * input parameter is a null pointer. Otherwise returns a pointer 173911963SAfshin.Ardakani@Sun.COM * to result. 174011963SAfshin.Ardakani@Sun.COM * 174111963SAfshin.Ardakani@Sun.COM * Day of the week calculation: the Epoch was a thursday. 174211963SAfshin.Ardakani@Sun.COM * 174311963SAfshin.Ardakani@Sun.COM * There are no timezone corrections so tm_isdst and tm_gmtoff are 174411963SAfshin.Ardakani@Sun.COM * always zero, and the zone is always WET. 174511963SAfshin.Ardakani@Sun.COM */ 174611963SAfshin.Ardakani@Sun.COM struct tm * 174711963SAfshin.Ardakani@Sun.COM smb_gmtime_r(time_t *clock, struct tm *result) 174811963SAfshin.Ardakani@Sun.COM { 174911963SAfshin.Ardakani@Sun.COM time_t tsec; 175011963SAfshin.Ardakani@Sun.COM int year; 175111963SAfshin.Ardakani@Sun.COM int month; 175211963SAfshin.Ardakani@Sun.COM int sec_per_month; 175311963SAfshin.Ardakani@Sun.COM 175411963SAfshin.Ardakani@Sun.COM if (clock == 0 || result == 0) 175511963SAfshin.Ardakani@Sun.COM return (0); 175611963SAfshin.Ardakani@Sun.COM 175711963SAfshin.Ardakani@Sun.COM bzero(result, sizeof (struct tm)); 175811963SAfshin.Ardakani@Sun.COM tsec = *clock; 175911963SAfshin.Ardakani@Sun.COM tsec -= tzh_leapcnt; 176011963SAfshin.Ardakani@Sun.COM 176111963SAfshin.Ardakani@Sun.COM result->tm_wday = tsec / SECSPERDAY; 176211963SAfshin.Ardakani@Sun.COM result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; 176311963SAfshin.Ardakani@Sun.COM 176411963SAfshin.Ardakani@Sun.COM year = EPOCH_YEAR; 176511963SAfshin.Ardakani@Sun.COM while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : 176611963SAfshin.Ardakani@Sun.COM (SECSPERDAY * DAYSPERNYEAR))) { 176711963SAfshin.Ardakani@Sun.COM if (isleap(year)) 176811963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERLYEAR; 176911963SAfshin.Ardakani@Sun.COM else 177011963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERNYEAR; 177111963SAfshin.Ardakani@Sun.COM 177211963SAfshin.Ardakani@Sun.COM ++year; 177311963SAfshin.Ardakani@Sun.COM } 177411963SAfshin.Ardakani@Sun.COM 177511963SAfshin.Ardakani@Sun.COM result->tm_year = year - TM_YEAR_BASE; 177611963SAfshin.Ardakani@Sun.COM result->tm_yday = tsec / SECSPERDAY; 177711963SAfshin.Ardakani@Sun.COM 177811963SAfshin.Ardakani@Sun.COM for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { 177911963SAfshin.Ardakani@Sun.COM sec_per_month = days_in_month[month] * SECSPERDAY; 178011963SAfshin.Ardakani@Sun.COM 178111963SAfshin.Ardakani@Sun.COM if (month == TM_FEBRUARY && isleap(year)) 178211963SAfshin.Ardakani@Sun.COM sec_per_month += SECSPERDAY; 178311963SAfshin.Ardakani@Sun.COM 178411963SAfshin.Ardakani@Sun.COM if (tsec < sec_per_month) 178511963SAfshin.Ardakani@Sun.COM break; 178611963SAfshin.Ardakani@Sun.COM 178711963SAfshin.Ardakani@Sun.COM tsec -= sec_per_month; 178811963SAfshin.Ardakani@Sun.COM } 178911963SAfshin.Ardakani@Sun.COM 179011963SAfshin.Ardakani@Sun.COM result->tm_mon = month; 179111963SAfshin.Ardakani@Sun.COM result->tm_mday = (tsec / SECSPERDAY) + 1; 179211963SAfshin.Ardakani@Sun.COM tsec %= SECSPERDAY; 179311963SAfshin.Ardakani@Sun.COM result->tm_sec = tsec % 60; 179411963SAfshin.Ardakani@Sun.COM tsec /= 60; 179511963SAfshin.Ardakani@Sun.COM result->tm_min = tsec % 60; 179611963SAfshin.Ardakani@Sun.COM tsec /= 60; 179711963SAfshin.Ardakani@Sun.COM result->tm_hour = (int)tsec; 179811963SAfshin.Ardakani@Sun.COM 179911963SAfshin.Ardakani@Sun.COM return (result); 180011963SAfshin.Ardakani@Sun.COM } 180111963SAfshin.Ardakani@Sun.COM 180211963SAfshin.Ardakani@Sun.COM 180311963SAfshin.Ardakani@Sun.COM /* 180411963SAfshin.Ardakani@Sun.COM * smb_timegm 180511963SAfshin.Ardakani@Sun.COM * 180611963SAfshin.Ardakani@Sun.COM * Converts the broken-down time in tm to a time value, i.e. the number 180711963SAfshin.Ardakani@Sun.COM * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is 180811963SAfshin.Ardakani@Sun.COM * not a POSIX or ANSI function. Per the man page, the input values of 180911963SAfshin.Ardakani@Sun.COM * tm_wday and tm_yday are ignored and, as the input data is assumed to 181011963SAfshin.Ardakani@Sun.COM * represent GMT, we force tm_isdst and tm_gmtoff to 0. 181111963SAfshin.Ardakani@Sun.COM * 181211963SAfshin.Ardakani@Sun.COM * Before returning the clock time, we use smb_gmtime_r to set up tm_wday 181311963SAfshin.Ardakani@Sun.COM * and tm_yday, and bring the other fields within normal range. I don't 181411963SAfshin.Ardakani@Sun.COM * think this is really how it should be done but it's convenient for 181511963SAfshin.Ardakani@Sun.COM * now. 181611963SAfshin.Ardakani@Sun.COM */ 181711963SAfshin.Ardakani@Sun.COM time_t 181811963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm) 181911963SAfshin.Ardakani@Sun.COM { 182011963SAfshin.Ardakani@Sun.COM time_t tsec; 182111963SAfshin.Ardakani@Sun.COM int dd; 182211963SAfshin.Ardakani@Sun.COM int mm; 182311963SAfshin.Ardakani@Sun.COM int yy; 182411963SAfshin.Ardakani@Sun.COM int year; 182511963SAfshin.Ardakani@Sun.COM 182611963SAfshin.Ardakani@Sun.COM if (tm == 0) 182711963SAfshin.Ardakani@Sun.COM return (-1); 182811963SAfshin.Ardakani@Sun.COM 182911963SAfshin.Ardakani@Sun.COM year = tm->tm_year + TM_YEAR_BASE; 183011963SAfshin.Ardakani@Sun.COM tsec = tzh_leapcnt; 183111963SAfshin.Ardakani@Sun.COM 183211963SAfshin.Ardakani@Sun.COM for (yy = EPOCH_YEAR; yy < year; ++yy) { 183311963SAfshin.Ardakani@Sun.COM if (isleap(yy)) 183411963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERLYEAR; 183511963SAfshin.Ardakani@Sun.COM else 183611963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERNYEAR; 183711963SAfshin.Ardakani@Sun.COM } 183811963SAfshin.Ardakani@Sun.COM 183911963SAfshin.Ardakani@Sun.COM for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { 184011963SAfshin.Ardakani@Sun.COM dd = days_in_month[mm] * SECSPERDAY; 184111963SAfshin.Ardakani@Sun.COM 184211963SAfshin.Ardakani@Sun.COM if (mm == TM_FEBRUARY && isleap(year)) 184311963SAfshin.Ardakani@Sun.COM dd += SECSPERDAY; 184411963SAfshin.Ardakani@Sun.COM 184511963SAfshin.Ardakani@Sun.COM tsec += dd; 184611963SAfshin.Ardakani@Sun.COM } 184711963SAfshin.Ardakani@Sun.COM 184811963SAfshin.Ardakani@Sun.COM tsec += (tm->tm_mday - 1) * SECSPERDAY; 184911963SAfshin.Ardakani@Sun.COM tsec += tm->tm_sec; 185011963SAfshin.Ardakani@Sun.COM tsec += tm->tm_min * SECSPERMIN; 185111963SAfshin.Ardakani@Sun.COM tsec += tm->tm_hour * SECSPERHOUR; 185211963SAfshin.Ardakani@Sun.COM 185311963SAfshin.Ardakani@Sun.COM tm->tm_isdst = 0; 185411963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tsec, tm); 185511963SAfshin.Ardakani@Sun.COM return (tsec); 185611963SAfshin.Ardakani@Sun.COM } 185711963SAfshin.Ardakani@Sun.COM 185811963SAfshin.Ardakani@Sun.COM /* 185911963SAfshin.Ardakani@Sun.COM * smb_cred_set_sid 186011963SAfshin.Ardakani@Sun.COM * 186111963SAfshin.Ardakani@Sun.COM * Initialize the ksid based on the given smb_id_t. 186211963SAfshin.Ardakani@Sun.COM */ 186311963SAfshin.Ardakani@Sun.COM static void 186411963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 186511963SAfshin.Ardakani@Sun.COM { 186611963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ]; 186711963SAfshin.Ardakani@Sun.COM int rc; 186811963SAfshin.Ardakani@Sun.COM 186911963SAfshin.Ardakani@Sun.COM ASSERT(id); 187011963SAfshin.Ardakani@Sun.COM ASSERT(id->i_sid); 187111963SAfshin.Ardakani@Sun.COM 187211963SAfshin.Ardakani@Sun.COM ksid->ks_id = id->i_id; 187311963SAfshin.Ardakani@Sun.COM smb_sid_tostr(id->i_sid, sidstr); 187411963SAfshin.Ardakani@Sun.COM rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 187511963SAfshin.Ardakani@Sun.COM ASSERT(rc == 0); 187611963SAfshin.Ardakani@Sun.COM 187711963SAfshin.Ardakani@Sun.COM ksid->ks_attr = id->i_attrs; 187811963SAfshin.Ardakani@Sun.COM ksid->ks_domain = ksid_lookupdomain(sidstr); 187911963SAfshin.Ardakani@Sun.COM } 188011963SAfshin.Ardakani@Sun.COM 188111963SAfshin.Ardakani@Sun.COM /* 188211963SAfshin.Ardakani@Sun.COM * smb_cred_set_sidlist 188311963SAfshin.Ardakani@Sun.COM * 188411963SAfshin.Ardakani@Sun.COM * Allocate and initialize the ksidlist based on the Windows group list of the 188511963SAfshin.Ardakani@Sun.COM * access token. 188611963SAfshin.Ardakani@Sun.COM */ 188711963SAfshin.Ardakani@Sun.COM static ksidlist_t * 188811963SAfshin.Ardakani@Sun.COM smb_cred_set_sidlist(smb_ids_t *token_grps) 188911963SAfshin.Ardakani@Sun.COM { 189011963SAfshin.Ardakani@Sun.COM int i; 189111963SAfshin.Ardakani@Sun.COM ksidlist_t *lp; 189211963SAfshin.Ardakani@Sun.COM 189311963SAfshin.Ardakani@Sun.COM lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 189411963SAfshin.Ardakani@Sun.COM lp->ksl_ref = 1; 189511963SAfshin.Ardakani@Sun.COM lp->ksl_nsid = token_grps->i_cnt; 189611963SAfshin.Ardakani@Sun.COM lp->ksl_neid = 0; 189711963SAfshin.Ardakani@Sun.COM 189811963SAfshin.Ardakani@Sun.COM for (i = 0; i < lp->ksl_nsid; i++) { 189911963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 190011963SAfshin.Ardakani@Sun.COM if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 190111963SAfshin.Ardakani@Sun.COM lp->ksl_neid++; 190211963SAfshin.Ardakani@Sun.COM } 190311963SAfshin.Ardakani@Sun.COM 190411963SAfshin.Ardakani@Sun.COM return (lp); 190511963SAfshin.Ardakani@Sun.COM } 190611963SAfshin.Ardakani@Sun.COM 190711963SAfshin.Ardakani@Sun.COM /* 190811963SAfshin.Ardakani@Sun.COM * A Solaris credential (cred_t structure) will be allocated and 190911963SAfshin.Ardakani@Sun.COM * initialized based on the given Windows style user access token. 191011963SAfshin.Ardakani@Sun.COM * 191111963SAfshin.Ardakani@Sun.COM * cred's gid is set to the primary group of the mapped Solaris user. 191211963SAfshin.Ardakani@Sun.COM * When there is no such mapped user (i.e. the mapped UID is ephemeral) 191311963SAfshin.Ardakani@Sun.COM * or his/her primary group could not be obtained, cred's gid is set to 191411963SAfshin.Ardakani@Sun.COM * the mapped Solaris group of token's primary group. 191511963SAfshin.Ardakani@Sun.COM */ 191611963SAfshin.Ardakani@Sun.COM cred_t * 191711963SAfshin.Ardakani@Sun.COM smb_cred_create(smb_token_t *token, uint32_t *privileges) 191811963SAfshin.Ardakani@Sun.COM { 191911963SAfshin.Ardakani@Sun.COM ksid_t ksid; 192011963SAfshin.Ardakani@Sun.COM ksidlist_t *ksidlist = NULL; 192111963SAfshin.Ardakani@Sun.COM smb_posix_grps_t *posix_grps; 192211963SAfshin.Ardakani@Sun.COM cred_t *cr; 192311963SAfshin.Ardakani@Sun.COM gid_t gid; 192411963SAfshin.Ardakani@Sun.COM 192511963SAfshin.Ardakani@Sun.COM ASSERT(token); 192611963SAfshin.Ardakani@Sun.COM ASSERT(token->tkn_posix_grps); 192711963SAfshin.Ardakani@Sun.COM posix_grps = token->tkn_posix_grps; 192811963SAfshin.Ardakani@Sun.COM 192911963SAfshin.Ardakani@Sun.COM ASSERT(privileges); 193011963SAfshin.Ardakani@Sun.COM 193111963SAfshin.Ardakani@Sun.COM cr = crget(); 193211963SAfshin.Ardakani@Sun.COM ASSERT(cr != NULL); 193311963SAfshin.Ardakani@Sun.COM 193411963SAfshin.Ardakani@Sun.COM if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 193511963SAfshin.Ardakani@Sun.COM (posix_grps->pg_ngrps != 0)) { 193611963SAfshin.Ardakani@Sun.COM gid = posix_grps->pg_grps[0]; 193711963SAfshin.Ardakani@Sun.COM } else { 193811963SAfshin.Ardakani@Sun.COM gid = token->tkn_primary_grp.i_id; 193911963SAfshin.Ardakani@Sun.COM } 194011963SAfshin.Ardakani@Sun.COM 194111963SAfshin.Ardakani@Sun.COM if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 194211963SAfshin.Ardakani@Sun.COM crfree(cr); 194311963SAfshin.Ardakani@Sun.COM return (NULL); 194411963SAfshin.Ardakani@Sun.COM } 194511963SAfshin.Ardakani@Sun.COM 194611963SAfshin.Ardakani@Sun.COM if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 194711963SAfshin.Ardakani@Sun.COM crfree(cr); 194811963SAfshin.Ardakani@Sun.COM return (NULL); 194911963SAfshin.Ardakani@Sun.COM } 195011963SAfshin.Ardakani@Sun.COM 195111963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_user, &ksid); 195211963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_USER); 195311963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 195411963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_GROUP); 195511963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_owner, &ksid); 195611963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_OWNER); 195711963SAfshin.Ardakani@Sun.COM ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 195811963SAfshin.Ardakani@Sun.COM crsetsidlist(cr, ksidlist); 195911963SAfshin.Ardakani@Sun.COM 196011963SAfshin.Ardakani@Sun.COM *privileges = 0; 196111963SAfshin.Ardakani@Sun.COM 196211963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 196311963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_BACKUP; 196411963SAfshin.Ardakani@Sun.COM 196511963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 196611963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_RESTORE; 196711963SAfshin.Ardakani@Sun.COM 196811963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) { 196911963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 197011963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL); 197111963SAfshin.Ardakani@Sun.COM } 197211963SAfshin.Ardakani@Sun.COM 197311963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 197411963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_SECURITY; 197511963SAfshin.Ardakani@Sun.COM 197611963SAfshin.Ardakani@Sun.COM return (cr); 197711963SAfshin.Ardakani@Sun.COM } 197811963SAfshin.Ardakani@Sun.COM 197911963SAfshin.Ardakani@Sun.COM /* 198011963SAfshin.Ardakani@Sun.COM * smb_cred_rele 198111963SAfshin.Ardakani@Sun.COM * 198211963SAfshin.Ardakani@Sun.COM * The reference count of the user's credential will get decremented if it 198311963SAfshin.Ardakani@Sun.COM * is non-zero. Otherwise, the credential will be freed. 198411963SAfshin.Ardakani@Sun.COM */ 198511963SAfshin.Ardakani@Sun.COM void 198611963SAfshin.Ardakani@Sun.COM smb_cred_rele(cred_t *cr) 198711963SAfshin.Ardakani@Sun.COM { 198811963SAfshin.Ardakani@Sun.COM ASSERT(cr); 198911963SAfshin.Ardakani@Sun.COM crfree(cr); 199011963SAfshin.Ardakani@Sun.COM } 199111963SAfshin.Ardakani@Sun.COM 199211963SAfshin.Ardakani@Sun.COM /* 199311963SAfshin.Ardakani@Sun.COM * smb_cred_is_member 199411963SAfshin.Ardakani@Sun.COM * 199511963SAfshin.Ardakani@Sun.COM * Same as smb_token_is_member. The only difference is that 199611963SAfshin.Ardakani@Sun.COM * we compare the given SID against user SID and the ksidlist 199711963SAfshin.Ardakani@Sun.COM * of the user's cred. 199811963SAfshin.Ardakani@Sun.COM */ 199911963SAfshin.Ardakani@Sun.COM int 200011963SAfshin.Ardakani@Sun.COM smb_cred_is_member(cred_t *cr, smb_sid_t *sid) 200111963SAfshin.Ardakani@Sun.COM { 200211963SAfshin.Ardakani@Sun.COM ksidlist_t *ksidlist; 200311963SAfshin.Ardakani@Sun.COM ksid_t ksid1, *ksid2; 200411963SAfshin.Ardakani@Sun.COM smb_id_t id; 200511963SAfshin.Ardakani@Sun.COM int i, rc = 0; 200611963SAfshin.Ardakani@Sun.COM 200711963SAfshin.Ardakani@Sun.COM ASSERT(cr); 200811963SAfshin.Ardakani@Sun.COM 200911963SAfshin.Ardakani@Sun.COM bzero(&id, sizeof (smb_id_t)); 201011963SAfshin.Ardakani@Sun.COM id.i_sid = sid; 201111963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&id, &ksid1); 201211963SAfshin.Ardakani@Sun.COM 201311963SAfshin.Ardakani@Sun.COM ksidlist = crgetsidlist(cr); 201411963SAfshin.Ardakani@Sun.COM ASSERT(ksidlist); 201511963SAfshin.Ardakani@Sun.COM ASSERT(ksid1.ks_domain); 201611963SAfshin.Ardakani@Sun.COM ASSERT(ksid1.ks_domain->kd_name); 201711963SAfshin.Ardakani@Sun.COM 201811963SAfshin.Ardakani@Sun.COM i = 0; 201911963SAfshin.Ardakani@Sun.COM ksid2 = crgetsid(cr, KSID_USER); 202011963SAfshin.Ardakani@Sun.COM do { 202111963SAfshin.Ardakani@Sun.COM ASSERT(ksid2->ks_domain); 202211963SAfshin.Ardakani@Sun.COM ASSERT(ksid2->ks_domain->kd_name); 202311963SAfshin.Ardakani@Sun.COM 202411963SAfshin.Ardakani@Sun.COM if (strcmp(ksid1.ks_domain->kd_name, 202511963SAfshin.Ardakani@Sun.COM ksid2->ks_domain->kd_name) == 0 && 202611963SAfshin.Ardakani@Sun.COM ksid1.ks_rid == ksid2->ks_rid) { 202711963SAfshin.Ardakani@Sun.COM rc = 1; 202811963SAfshin.Ardakani@Sun.COM break; 202911963SAfshin.Ardakani@Sun.COM } 203011963SAfshin.Ardakani@Sun.COM 203111963SAfshin.Ardakani@Sun.COM ksid2 = &ksidlist->ksl_sids[i]; 203211963SAfshin.Ardakani@Sun.COM } while (i++ < ksidlist->ksl_nsid); 203311963SAfshin.Ardakani@Sun.COM 203411963SAfshin.Ardakani@Sun.COM ksid_rele(&ksid1); 203511963SAfshin.Ardakani@Sun.COM return (rc); 203611963SAfshin.Ardakani@Sun.COM } 203711963SAfshin.Ardakani@Sun.COM 203811963SAfshin.Ardakani@Sun.COM /* 203911963SAfshin.Ardakani@Sun.COM * smb_cred_create_privs 204011963SAfshin.Ardakani@Sun.COM * 204111963SAfshin.Ardakani@Sun.COM * Creates a duplicate credential that contains system privileges for 204211963SAfshin.Ardakani@Sun.COM * certain SMB privileges: Backup and Restore. 204311963SAfshin.Ardakani@Sun.COM * 204411963SAfshin.Ardakani@Sun.COM */ 204511963SAfshin.Ardakani@Sun.COM cred_t * 204611963SAfshin.Ardakani@Sun.COM smb_cred_create_privs(cred_t *user_cr, uint32_t privileges) 204711963SAfshin.Ardakani@Sun.COM { 204811963SAfshin.Ardakani@Sun.COM cred_t *cr = NULL; 204911963SAfshin.Ardakani@Sun.COM 205011963SAfshin.Ardakani@Sun.COM ASSERT(user_cr != NULL); 205111963SAfshin.Ardakani@Sun.COM 205211963SAfshin.Ardakani@Sun.COM if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE)) 205311963SAfshin.Ardakani@Sun.COM cr = crdup(user_cr); 205411963SAfshin.Ardakani@Sun.COM 205511963SAfshin.Ardakani@Sun.COM if (cr == NULL) 205611963SAfshin.Ardakani@Sun.COM return (NULL); 205711963SAfshin.Ardakani@Sun.COM 205811963SAfshin.Ardakani@Sun.COM if (privileges & SMB_USER_PRIV_BACKUP) { 205911963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_DAC_READ, 206011963SAfshin.Ardakani@Sun.COM PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL); 206111963SAfshin.Ardakani@Sun.COM } 206211963SAfshin.Ardakani@Sun.COM 206311963SAfshin.Ardakani@Sun.COM if (privileges & SMB_USER_PRIV_RESTORE) { 206411963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_DAC_WRITE, 206511963SAfshin.Ardakani@Sun.COM PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF, 206611963SAfshin.Ardakani@Sun.COM PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY, 206711963SAfshin.Ardakani@Sun.COM PRIV_FILE_OWNER, PRIV_FILE_SETID, PRIV_SYS_LINKDIR, 206811963SAfshin.Ardakani@Sun.COM PRIV_SYS_MOUNT, NULL); 206911963SAfshin.Ardakani@Sun.COM } 207011963SAfshin.Ardakani@Sun.COM 207111963SAfshin.Ardakani@Sun.COM return (cr); 207211963SAfshin.Ardakani@Sun.COM } 207311963SAfshin.Ardakani@Sun.COM 207411963SAfshin.Ardakani@Sun.COM /* 207511963SAfshin.Ardakani@Sun.COM * smb_pad_align 207611963SAfshin.Ardakani@Sun.COM * 207711963SAfshin.Ardakani@Sun.COM * Returns the number of bytes required to pad an offset to the 207811963SAfshin.Ardakani@Sun.COM * specified alignment. 207911963SAfshin.Ardakani@Sun.COM */ 208011963SAfshin.Ardakani@Sun.COM uint32_t 208111963SAfshin.Ardakani@Sun.COM smb_pad_align(uint32_t offset, uint32_t align) 208211963SAfshin.Ardakani@Sun.COM { 208311963SAfshin.Ardakani@Sun.COM uint32_t pad = offset % align; 208411963SAfshin.Ardakani@Sun.COM 208511963SAfshin.Ardakani@Sun.COM if (pad != 0) 208611963SAfshin.Ardakani@Sun.COM pad = align - pad; 208711963SAfshin.Ardakani@Sun.COM 208811963SAfshin.Ardakani@Sun.COM return (pad); 208911963SAfshin.Ardakani@Sun.COM } 209011963SAfshin.Ardakani@Sun.COM 209111963SAfshin.Ardakani@Sun.COM /* 209211963SAfshin.Ardakani@Sun.COM * smb_panic 209311963SAfshin.Ardakani@Sun.COM * 209411963SAfshin.Ardakani@Sun.COM * Logs the file name, function name and line number passed in and panics the 209511963SAfshin.Ardakani@Sun.COM * system. 209611963SAfshin.Ardakani@Sun.COM */ 209711963SAfshin.Ardakani@Sun.COM void 209811963SAfshin.Ardakani@Sun.COM smb_panic(char *file, const char *func, int line) 209911963SAfshin.Ardakani@Sun.COM { 210011963SAfshin.Ardakani@Sun.COM cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line); 210111963SAfshin.Ardakani@Sun.COM } 2102