xref: /onnv-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c (revision 11332:ed3411181494)
16007Sthurlow /*
26007Sthurlow  * Copyright (c) 2000-2001 Boris Popov
36007Sthurlow  * All rights reserved.
46007Sthurlow  *
56007Sthurlow  * Redistribution and use in source and binary forms, with or without
66007Sthurlow  * modification, are permitted provided that the following conditions
76007Sthurlow  * are met:
86007Sthurlow  * 1. Redistributions of source code must retain the above copyright
96007Sthurlow  *    notice, this list of conditions and the following disclaimer.
106007Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow  *    notice, this list of conditions and the following disclaimer in the
126007Sthurlow  *    documentation and/or other materials provided with the distribution.
136007Sthurlow  * 3. All advertising materials mentioning features or use of this software
146007Sthurlow  *    must display the following acknowledgement:
156007Sthurlow  *    This product includes software developed by Boris Popov.
166007Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow  *    may be used to endorse or promote products derived from this software
186007Sthurlow  *    without specific prior written permission.
196007Sthurlow  *
206007Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow  * SUCH DAMAGE.
316007Sthurlow  *
326007Sthurlow  * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
336007Sthurlow  */
347431SGordon.Ross@Sun.COM /*
3510023SGordon.Ross@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
367431SGordon.Ross@Sun.COM  * Use is subject to license terms.
377431SGordon.Ross@Sun.COM  */
386007Sthurlow 
396007Sthurlow /*
406007Sthurlow  * Connection engine.
416007Sthurlow  */
426007Sthurlow 
436007Sthurlow #include <sys/param.h>
446007Sthurlow #include <sys/systm.h>
456007Sthurlow #include <sys/kmem.h>
466007Sthurlow #include <sys/proc.h>
476007Sthurlow #include <sys/lock.h>
486007Sthurlow #include <sys/vnode.h>
496007Sthurlow #include <sys/stream.h>
506007Sthurlow #include <sys/stropts.h>
516007Sthurlow #include <sys/socketvar.h>
526007Sthurlow #include <sys/cred.h>
536007Sthurlow #include <netinet/in.h>
546007Sthurlow #include <inet/ip.h>
556007Sthurlow #include <inet/ip6.h>
566007Sthurlow #include <sys/cmn_err.h>
576007Sthurlow #include <sys/thread.h>
586007Sthurlow #include <sys/atomic.h>
5910023SGordon.Ross@Sun.COM #include <sys/u8_textprep.h>
606007Sthurlow 
616007Sthurlow #include <netsmb/smb_osdep.h>
626007Sthurlow 
636007Sthurlow #include <netsmb/smb.h>
646007Sthurlow #include <netsmb/smb_conn.h>
656007Sthurlow #include <netsmb/smb_subr.h>
666007Sthurlow #include <netsmb/smb_tran.h>
676007Sthurlow #include <netsmb/smb_pass.h>
686007Sthurlow 
696007Sthurlow static struct smb_connobj smb_vclist;
706007Sthurlow 
716007Sthurlow void smb_co_init(struct smb_connobj *cp, int level, char *objname);
726007Sthurlow void smb_co_done(struct smb_connobj *cp);
736007Sthurlow void smb_co_hold(struct smb_connobj *cp);
746007Sthurlow void smb_co_rele(struct smb_connobj *cp);
756007Sthurlow void smb_co_kill(struct smb_connobj *cp);
766007Sthurlow 
776007Sthurlow static void smb_vc_free(struct smb_connobj *cp);
786007Sthurlow static void smb_vc_gone(struct smb_connobj *cp);
796007Sthurlow 
806007Sthurlow static void smb_share_free(struct smb_connobj *cp);
816007Sthurlow static void smb_share_gone(struct smb_connobj *cp);
826007Sthurlow 
836007Sthurlow int
smb_sm_init(void)846007Sthurlow smb_sm_init(void)
856007Sthurlow {
866007Sthurlow 	smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
876007Sthurlow 	return (0);
886007Sthurlow }
896007Sthurlow 
906007Sthurlow int
smb_sm_idle(void)916007Sthurlow smb_sm_idle(void)
926007Sthurlow {
936007Sthurlow 	int error = 0;
946007Sthurlow 	SMB_CO_LOCK(&smb_vclist);
956007Sthurlow 	if (smb_vclist.co_usecount > 1) {
966007Sthurlow 		SMBSDEBUG("%d connections still active\n",
976007Sthurlow 		    smb_vclist.co_usecount - 1);
986007Sthurlow 		error = EBUSY;
996007Sthurlow 	}
1006007Sthurlow 	SMB_CO_UNLOCK(&smb_vclist);
1016007Sthurlow 	return (error);
1026007Sthurlow }
1036007Sthurlow 
1046007Sthurlow void
smb_sm_done(void)1056007Sthurlow smb_sm_done(void)
1066007Sthurlow {
1076007Sthurlow 	/*
1086007Sthurlow 	 * XXX Q4BP why are we not iterating on smb_vclist here?
1096007Sthurlow 	 * Because the caller has just called smb_sm_idle() to
1106007Sthurlow 	 * make sure we have no VCs before calling this.
1116007Sthurlow 	 */
1126007Sthurlow 	smb_co_done(&smb_vclist);
1136007Sthurlow }
1146007Sthurlow 
1156007Sthurlow 
1166007Sthurlow 
1176007Sthurlow /*
1186007Sthurlow  * Common code for connection object
1196007Sthurlow  */
1206007Sthurlow /*ARGSUSED*/
1216007Sthurlow void
smb_co_init(struct smb_connobj * cp,int level,char * objname)1226007Sthurlow smb_co_init(struct smb_connobj *cp, int level, char *objname)
1236007Sthurlow {
1246007Sthurlow 
1256007Sthurlow 	mutex_init(&cp->co_lock, objname,  MUTEX_DRIVER, NULL);
1266007Sthurlow 
1276007Sthurlow 	cp->co_level = level;
1286007Sthurlow 	cp->co_usecount = 1;
1296007Sthurlow 	SLIST_INIT(&cp->co_children);
1306007Sthurlow }
1316007Sthurlow 
1326007Sthurlow /*
1336007Sthurlow  * Called just before free of an object
1346007Sthurlow  * of which smb_connobj is a part, i.e.
1356007Sthurlow  * _vc_free, _share_free, also sm_done.
1366007Sthurlow  */
1376007Sthurlow void
smb_co_done(struct smb_connobj * cp)1386007Sthurlow smb_co_done(struct smb_connobj *cp)
1396007Sthurlow {
1406007Sthurlow 	ASSERT(SLIST_EMPTY(&cp->co_children));
1416007Sthurlow 	mutex_destroy(&cp->co_lock);
1426007Sthurlow }
1436007Sthurlow 
1446007Sthurlow static void
smb_co_addchild(struct smb_connobj * parent,struct smb_connobj * child)1456007Sthurlow smb_co_addchild(
1466007Sthurlow 	struct smb_connobj *parent,
1476007Sthurlow 	struct smb_connobj *child)
1486007Sthurlow {
1496007Sthurlow 
1506007Sthurlow 	/*
1516007Sthurlow 	 * Set the child's pointer to the parent.
1526007Sthurlow 	 * No references yet, so no need to lock.
1536007Sthurlow 	 */
1546007Sthurlow 	ASSERT(child->co_usecount == 1);
1556007Sthurlow 	child->co_parent = parent;
1566007Sthurlow 
1576007Sthurlow 	/*
1586007Sthurlow 	 * Add the child to the parent's list of
1596007Sthurlow 	 * children, and in-line smb_co_hold
1606007Sthurlow 	 */
1616007Sthurlow 	ASSERT(MUTEX_HELD(&parent->co_lock));
1626007Sthurlow 	parent->co_usecount++;
1636007Sthurlow 	SLIST_INSERT_HEAD(&parent->co_children, child, co_next);
1646007Sthurlow }
1656007Sthurlow 
1666007Sthurlow void
smb_co_hold(struct smb_connobj * cp)1676007Sthurlow smb_co_hold(struct smb_connobj *cp)
1686007Sthurlow {
1696007Sthurlow 	SMB_CO_LOCK(cp);
1706007Sthurlow 	cp->co_usecount++;
1716007Sthurlow 	SMB_CO_UNLOCK(cp);
1726007Sthurlow }
1736007Sthurlow 
1746007Sthurlow /*
1756007Sthurlow  * Called via smb_vc_rele, smb_share_rele
1766007Sthurlow  */
1776007Sthurlow void
smb_co_rele(struct smb_connobj * co)1786007Sthurlow smb_co_rele(struct smb_connobj *co)
1796007Sthurlow {
1806007Sthurlow 	struct smb_connobj *parent;
1816007Sthurlow 	int old_flags;
1826007Sthurlow 
1836007Sthurlow 	SMB_CO_LOCK(co);
1846007Sthurlow 	if (co->co_usecount > 1) {
1856007Sthurlow 		co->co_usecount--;
1866007Sthurlow 		SMB_CO_UNLOCK(co);
1876007Sthurlow 		return;
1886007Sthurlow 	}
1896007Sthurlow 	ASSERT(co->co_usecount == 1);
1906007Sthurlow 	co->co_usecount = 0;
1916007Sthurlow 
1926007Sthurlow 	/*
1936007Sthurlow 	 * This list of children should be empty now.
1946007Sthurlow 	 * Check this while we're still linked, so
1956007Sthurlow 	 * we have a better chance of debugging.
1966007Sthurlow 	 */
1976007Sthurlow 	ASSERT(SLIST_EMPTY(&co->co_children));
1986007Sthurlow 
1996007Sthurlow 	/*
2006007Sthurlow 	 * OK, this element is going away.
2016007Sthurlow 	 *
2026007Sthurlow 	 * We need to drop the lock on this CO so we can take the
2036007Sthurlow 	 * parent CO lock. The _GONE flag prevents this CO from
2046007Sthurlow 	 * getting new references before we can unlink it from the
2056007Sthurlow 	 * parent list.
2066007Sthurlow 	 *
2076007Sthurlow 	 * The _GONE flag is also used to ensure that the co_gone
2086007Sthurlow 	 * function is called only once.  Note that smb_co_kill may
2096007Sthurlow 	 * do this before we get here.  If we find that the _GONE
2106007Sthurlow 	 * flag was not already set, then call the co_gone hook
2116007Sthurlow 	 * (smb_share_gone, smb_vc_gone) which will disconnect
2126007Sthurlow 	 * the share or the VC, respectively.
2136007Sthurlow 	 *
2146007Sthurlow 	 * Note the old: smb_co_gone(co, scred);
2156007Sthurlow 	 * is now in-line here.
2166007Sthurlow 	 */
2176007Sthurlow 	old_flags = co->co_flags;
2186007Sthurlow 	co->co_flags |= SMBO_GONE;
2196007Sthurlow 	SMB_CO_UNLOCK(co);
2206007Sthurlow 
2216007Sthurlow 	if ((old_flags & SMBO_GONE) == 0 && co->co_gone)
2226007Sthurlow 		co->co_gone(co);
2236007Sthurlow 
2246007Sthurlow 	/*
2256007Sthurlow 	 * If we have a parent (only smb_vclist does not)
2266007Sthurlow 	 * then unlink from parent's list of children.
2276007Sthurlow 	 * We have the only reference to the child.
2286007Sthurlow 	 */
2296007Sthurlow 	parent = co->co_parent;
2306007Sthurlow 	if (parent) {
2316007Sthurlow 		SMB_CO_LOCK(parent);
2326007Sthurlow 		ASSERT(SLIST_FIRST(&parent->co_children));
2336007Sthurlow 		if (SLIST_FIRST(&parent->co_children)) {
2346007Sthurlow 			SLIST_REMOVE(&parent->co_children, co,
2356007Sthurlow 			    smb_connobj, co_next);
2366007Sthurlow 		}
2376007Sthurlow 		SMB_CO_UNLOCK(parent);
2386007Sthurlow 	}
2396007Sthurlow 
2406007Sthurlow 	/*
2416007Sthurlow 	 * Now it's safe to free the CO
2426007Sthurlow 	 */
2436007Sthurlow 	if (co->co_free) {
2446007Sthurlow 		co->co_free(co);
2456007Sthurlow 	}
2466007Sthurlow 
2476007Sthurlow 	/*
2486007Sthurlow 	 * Finally, if the CO had a parent, decrement
2496007Sthurlow 	 * the parent's hold count for the lost child.
2506007Sthurlow 	 */
2516007Sthurlow 	if (parent) {
2526007Sthurlow 		/*
2536007Sthurlow 		 * Recursive call here (easier for debugging).
2546007Sthurlow 		 * Can only go two levels.
2556007Sthurlow 		 */
2566007Sthurlow 		smb_co_rele(parent);
2576007Sthurlow 	}
2586007Sthurlow }
2596007Sthurlow 
2606007Sthurlow /*
2616007Sthurlow  * Do just the first part of what co_gone does,
2626007Sthurlow  * i.e. tree disconnect, or disconnect a VC.
2636007Sthurlow  * This is used to forcibly close things.
2646007Sthurlow  */
2656007Sthurlow void
smb_co_kill(struct smb_connobj * co)2666007Sthurlow smb_co_kill(struct smb_connobj *co)
2676007Sthurlow {
2686007Sthurlow 	int old_flags;
2696007Sthurlow 
2706007Sthurlow 	SMB_CO_LOCK(co);
2716007Sthurlow 	old_flags = co->co_flags;
2726007Sthurlow 	co->co_flags |= SMBO_GONE;
2736007Sthurlow 	SMB_CO_UNLOCK(co);
2746007Sthurlow 
2756007Sthurlow 	/*
2766007Sthurlow 	 * Do the same "call only once" logic here as in
2776007Sthurlow 	 * smb_co_rele, though it's probably not possible
2786007Sthurlow 	 * for this to be called after smb_co_rele.
2796007Sthurlow 	 */
2806007Sthurlow 	if ((old_flags & SMBO_GONE) == 0 && co->co_gone)
2816007Sthurlow 		co->co_gone(co);
2826007Sthurlow 
2836007Sthurlow 	/* XXX: Walk list of children and kill those too? */
2846007Sthurlow }
2856007Sthurlow 
2866007Sthurlow 
2876007Sthurlow /*
28810023SGordon.Ross@Sun.COM  * Session objects, which are referred to as "VC" for
28910023SGordon.Ross@Sun.COM  * "virtual cirtuit". This has nothing to do with the
29010023SGordon.Ross@Sun.COM  * CIFS notion of a "virtual cirtuit".  See smb_conn.h
2916007Sthurlow  */
2926007Sthurlow 
2936007Sthurlow void
smb_vc_hold(struct smb_vc * vcp)2946007Sthurlow smb_vc_hold(struct smb_vc *vcp)
2956007Sthurlow {
2966007Sthurlow 	smb_co_hold(VCTOCP(vcp));
2976007Sthurlow }
2986007Sthurlow 
2996007Sthurlow void
smb_vc_rele(struct smb_vc * vcp)3006007Sthurlow smb_vc_rele(struct smb_vc *vcp)
3016007Sthurlow {
3026007Sthurlow 	smb_co_rele(VCTOCP(vcp));
3036007Sthurlow }
3046007Sthurlow 
3056007Sthurlow void
smb_vc_kill(struct smb_vc * vcp)3066007Sthurlow smb_vc_kill(struct smb_vc *vcp)
3076007Sthurlow {
3086007Sthurlow 	smb_co_kill(VCTOCP(vcp));
3096007Sthurlow }
3106007Sthurlow 
3116007Sthurlow /*
3126007Sthurlow  * Normally called via smb_vc_rele()
3136007Sthurlow  * after co_usecount drops to zero.
3146007Sthurlow  * Also called via: smb_vc_kill()
3156007Sthurlow  *
3166007Sthurlow  * Shutdown the VC to this server,
3176007Sthurlow  * invalidate shares linked with it.
3186007Sthurlow  */
3196007Sthurlow /*ARGSUSED*/
3206007Sthurlow static void
smb_vc_gone(struct smb_connobj * cp)3216007Sthurlow smb_vc_gone(struct smb_connobj *cp)
3226007Sthurlow {
3236007Sthurlow 	struct smb_vc *vcp = CPTOVC(cp);
3246007Sthurlow 
3256007Sthurlow 	/*
3266007Sthurlow 	 * Was smb_vc_disconnect(vcp);
3276007Sthurlow 	 */
3286007Sthurlow 	smb_iod_disconnect(vcp);
3296007Sthurlow }
3306007Sthurlow 
33110023SGordon.Ross@Sun.COM /*
33210023SGordon.Ross@Sun.COM  * The VC has no more references.  Free it.
33310023SGordon.Ross@Sun.COM  * No locks needed here.
33410023SGordon.Ross@Sun.COM  */
3356007Sthurlow static void
smb_vc_free(struct smb_connobj * cp)3366007Sthurlow smb_vc_free(struct smb_connobj *cp)
3376007Sthurlow {
3386007Sthurlow 	struct smb_vc *vcp = CPTOVC(cp);
3396007Sthurlow 
3406007Sthurlow 	/*
34110023SGordon.Ross@Sun.COM 	 * The _gone call should have emptied the request list,
34210023SGordon.Ross@Sun.COM 	 * but let's make sure, as requests may have references
34310023SGordon.Ross@Sun.COM 	 * to this VC without taking a hold.  (The hold is the
34410023SGordon.Ross@Sun.COM 	 * responsibility of threads placing requests.)
3456007Sthurlow 	 */
34610023SGordon.Ross@Sun.COM 	ASSERT(vcp->iod_rqlist.tqh_first == NULL);
3476007Sthurlow 
3486007Sthurlow 	if (vcp->vc_tdata)
34910023SGordon.Ross@Sun.COM 		SMB_TRAN_DONE(vcp);
3506007Sthurlow 
3516007Sthurlow /*
3526007Sthurlow  * We are not using the iconv routines here. So commenting them for now.
3536007Sthurlow  * REVISIT.
3546007Sthurlow  */
3556007Sthurlow #ifdef NOTYETDEFINED
3566007Sthurlow 	if (vcp->vc_tolower)
3576007Sthurlow 		iconv_close(vcp->vc_tolower);
3586007Sthurlow 	if (vcp->vc_toupper)
3596007Sthurlow 		iconv_close(vcp->vc_toupper);
3606007Sthurlow 	if (vcp->vc_tolocal)
3616007Sthurlow 		iconv_close(vcp->vc_tolocal);
3626007Sthurlow 	if (vcp->vc_toserver)
3636007Sthurlow 		iconv_close(vcp->vc_toserver);
3646007Sthurlow #endif
3656007Sthurlow 
3668271SGordon.Ross@Sun.COM 	if (vcp->vc_mackey != NULL)
3678271SGordon.Ross@Sun.COM 		kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
3688271SGordon.Ross@Sun.COM 
36910023SGordon.Ross@Sun.COM 	cv_destroy(&vcp->iod_idle);
3706007Sthurlow 	rw_destroy(&vcp->iod_rqlock);
3716007Sthurlow 	sema_destroy(&vcp->vc_sendlock);
3726007Sthurlow 	cv_destroy(&vcp->vc_statechg);
3736007Sthurlow 	smb_co_done(VCTOCP(vcp));
3746007Sthurlow 	kmem_free(vcp, sizeof (*vcp));
3756007Sthurlow }
3766007Sthurlow 
37710023SGordon.Ross@Sun.COM /*ARGSUSED*/
37810023SGordon.Ross@Sun.COM int
smb_vc_create(smbioc_ossn_t * ossn,smb_cred_t * scred,smb_vc_t ** vcpp)37910023SGordon.Ross@Sun.COM smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
38010023SGordon.Ross@Sun.COM {
38110023SGordon.Ross@Sun.COM 	static char objtype[] = "smb_vc";
38210023SGordon.Ross@Sun.COM 	cred_t *cr = scred->scr_cred;
38310023SGordon.Ross@Sun.COM 	struct smb_vc *vcp;
38410023SGordon.Ross@Sun.COM 	int error = 0;
38510023SGordon.Ross@Sun.COM 
38610023SGordon.Ross@Sun.COM 	ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
38710023SGordon.Ross@Sun.COM 
38810023SGordon.Ross@Sun.COM 	vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
38910023SGordon.Ross@Sun.COM 
39010023SGordon.Ross@Sun.COM 	smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
39110023SGordon.Ross@Sun.COM 	vcp->vc_co.co_free = smb_vc_free;
39210023SGordon.Ross@Sun.COM 	vcp->vc_co.co_gone = smb_vc_gone;
39310023SGordon.Ross@Sun.COM 
39410023SGordon.Ross@Sun.COM 	cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
39510023SGordon.Ross@Sun.COM 	sema_init(&vcp->vc_sendlock, 1, objtype, SEMA_DRIVER, NULL);
39610023SGordon.Ross@Sun.COM 	rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
39710023SGordon.Ross@Sun.COM 	cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
39810023SGordon.Ross@Sun.COM 
39910023SGordon.Ross@Sun.COM 	/* Expanded TAILQ_HEAD_INITIALIZER */
40010023SGordon.Ross@Sun.COM 	vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
40110023SGordon.Ross@Sun.COM 
40210023SGordon.Ross@Sun.COM 	vcp->vc_state = SMBIOD_ST_IDLE;
40310023SGordon.Ross@Sun.COM 
40410023SGordon.Ross@Sun.COM 	/*
40510023SGordon.Ross@Sun.COM 	 * These identify the connection.
40610023SGordon.Ross@Sun.COM 	 */
40710023SGordon.Ross@Sun.COM 	vcp->vc_zoneid = getzoneid();
40810023SGordon.Ross@Sun.COM 	bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
40910023SGordon.Ross@Sun.COM 
41010023SGordon.Ross@Sun.COM 	/* This fills in vcp->vc_tdata */
41110023SGordon.Ross@Sun.COM 	vcp->vc_tdesc = &smb_tran_nbtcp_desc;
41210023SGordon.Ross@Sun.COM 	if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
41310023SGordon.Ross@Sun.COM 		goto errout;
41410023SGordon.Ross@Sun.COM 
41510023SGordon.Ross@Sun.COM 	/* Success! */
41610023SGordon.Ross@Sun.COM 	smb_co_addchild(&smb_vclist, VCTOCP(vcp));
41710023SGordon.Ross@Sun.COM 	*vcpp = vcp;
41810023SGordon.Ross@Sun.COM 	return (0);
41910023SGordon.Ross@Sun.COM 
42010023SGordon.Ross@Sun.COM errout:
42110023SGordon.Ross@Sun.COM 	/*
42210023SGordon.Ross@Sun.COM 	 * This will destroy the new vc.
42310023SGordon.Ross@Sun.COM 	 * See: smb_vc_free
42410023SGordon.Ross@Sun.COM 	 */
42510023SGordon.Ross@Sun.COM 	smb_vc_rele(vcp);
42610023SGordon.Ross@Sun.COM 	return (error);
42710023SGordon.Ross@Sun.COM }
4286007Sthurlow 
4296007Sthurlow /*
43010023SGordon.Ross@Sun.COM  * Find or create a VC identified by the info in ossn
43110023SGordon.Ross@Sun.COM  * and return it with a "hold", but not locked.
4326007Sthurlow  */
4336007Sthurlow /*ARGSUSED*/
4346007Sthurlow int
smb_vc_findcreate(smbioc_ossn_t * ossn,smb_cred_t * scred,smb_vc_t ** vcpp)43510023SGordon.Ross@Sun.COM smb_vc_findcreate(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
4366007Sthurlow {
4376007Sthurlow 	struct smb_connobj *co;
43810023SGordon.Ross@Sun.COM 	struct smb_vc *vcp;
43910023SGordon.Ross@Sun.COM 	smbioc_ssn_ident_t *vc_id;
44010023SGordon.Ross@Sun.COM 	int error;
44110023SGordon.Ross@Sun.COM 	zoneid_t zoneid = getzoneid();
4426007Sthurlow 
44310023SGordon.Ross@Sun.COM 	*vcpp = vcp = NULL;
4446007Sthurlow 
44510023SGordon.Ross@Sun.COM 	SMB_CO_LOCK(&smb_vclist);
4466007Sthurlow 
4476007Sthurlow 	/* var, head, next_field */
44810023SGordon.Ross@Sun.COM 	SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
44910023SGordon.Ross@Sun.COM 		vcp = CPTOVC(co);
45010023SGordon.Ross@Sun.COM 
45110023SGordon.Ross@Sun.COM 		/*
45210023SGordon.Ross@Sun.COM 		 * Some things we can check without
45310023SGordon.Ross@Sun.COM 		 * holding the lock (those that are
45410023SGordon.Ross@Sun.COM 		 * set at creation and never change).
45510023SGordon.Ross@Sun.COM 		 */
45610023SGordon.Ross@Sun.COM 
45710023SGordon.Ross@Sun.COM 		/* VCs in other zones are invisibile. */
45810023SGordon.Ross@Sun.COM 		if (vcp->vc_zoneid != zoneid)
45910023SGordon.Ross@Sun.COM 			continue;
4606007Sthurlow 
46110023SGordon.Ross@Sun.COM 		/* Also segregate by Unix owner. */
46210023SGordon.Ross@Sun.COM 		if (vcp->vc_owner != ossn->ssn_owner)
46310023SGordon.Ross@Sun.COM 			continue;
46410023SGordon.Ross@Sun.COM 
46510023SGordon.Ross@Sun.COM 		/*
46610023SGordon.Ross@Sun.COM 		 * Compare identifying info:
46710023SGordon.Ross@Sun.COM 		 * server address, user, domain
46810023SGordon.Ross@Sun.COM 		 * names are case-insensitive
46910023SGordon.Ross@Sun.COM 		 */
47010023SGordon.Ross@Sun.COM 		vc_id = &vcp->vc_ssn.ssn_id;
47110023SGordon.Ross@Sun.COM 		if (bcmp(&vc_id->id_srvaddr,
47210023SGordon.Ross@Sun.COM 		    &ossn->ssn_id.id_srvaddr,
47310023SGordon.Ross@Sun.COM 		    sizeof (vc_id->id_srvaddr)))
47410023SGordon.Ross@Sun.COM 			continue;
47510023SGordon.Ross@Sun.COM 		if (u8_strcmp(vc_id->id_user, ossn->ssn_id.id_user, 0,
47610023SGordon.Ross@Sun.COM 		    U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
47710023SGordon.Ross@Sun.COM 			continue;
47810023SGordon.Ross@Sun.COM 		if (u8_strcmp(vc_id->id_domain, ossn->ssn_id.id_domain, 0,
47910023SGordon.Ross@Sun.COM 		    U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
4806007Sthurlow 			continue;
4816007Sthurlow 
48210023SGordon.Ross@Sun.COM 		/*
48310023SGordon.Ross@Sun.COM 		 * We have a match, but still have to check
48410023SGordon.Ross@Sun.COM 		 * the _GONE flag, and do that with a lock.
48510023SGordon.Ross@Sun.COM 		 * No new references when _GONE is set.
48610023SGordon.Ross@Sun.COM 		 *
48710023SGordon.Ross@Sun.COM 		 * Also clear SMBVOPT_CREATE which the caller
48810023SGordon.Ross@Sun.COM 		 * may check to find out if we did create.
48910023SGordon.Ross@Sun.COM 		 */
49010023SGordon.Ross@Sun.COM 		SMB_VC_LOCK(vcp);
49110023SGordon.Ross@Sun.COM 		if ((vcp->vc_flags & SMBV_GONE) == 0) {
49210023SGordon.Ross@Sun.COM 			ossn->ssn_vopt &= ~SMBVOPT_CREATE;
49310023SGordon.Ross@Sun.COM 			/*
49410023SGordon.Ross@Sun.COM 			 * Return it held, unlocked.
49510023SGordon.Ross@Sun.COM 			 * In-line smb_vc_hold here.
49610023SGordon.Ross@Sun.COM 			 */
49710023SGordon.Ross@Sun.COM 			co->co_usecount++;
49810023SGordon.Ross@Sun.COM 			SMB_VC_UNLOCK(vcp);
49910023SGordon.Ross@Sun.COM 			*vcpp = vcp;
50010023SGordon.Ross@Sun.COM 			error = 0;
50110023SGordon.Ross@Sun.COM 			goto out;
50210023SGordon.Ross@Sun.COM 		}
50310023SGordon.Ross@Sun.COM 		SMB_VC_UNLOCK(vcp);
50410023SGordon.Ross@Sun.COM 		/* keep looking. */
5056007Sthurlow 	}
50610023SGordon.Ross@Sun.COM 	vcp = NULL;
5076007Sthurlow 
50810023SGordon.Ross@Sun.COM 	/* Note: smb_vclist is still locked. */
50910023SGordon.Ross@Sun.COM 
51010023SGordon.Ross@Sun.COM 	if (ossn->ssn_vopt & SMBVOPT_CREATE) {
51110023SGordon.Ross@Sun.COM 		/*
51210023SGordon.Ross@Sun.COM 		 * Create a new VC.  It starts out with
51310023SGordon.Ross@Sun.COM 		 * hold count = 1, so don't incr. here.
51410023SGordon.Ross@Sun.COM 		 */
51510023SGordon.Ross@Sun.COM 		error = smb_vc_create(ossn, scred, &vcp);
51610023SGordon.Ross@Sun.COM 		if (error == 0)
51710023SGordon.Ross@Sun.COM 			*vcpp = vcp;
51810023SGordon.Ross@Sun.COM 	} else
51910023SGordon.Ross@Sun.COM 		error = ENOENT;
52010023SGordon.Ross@Sun.COM 
52110023SGordon.Ross@Sun.COM out:
52210023SGordon.Ross@Sun.COM 	SMB_CO_UNLOCK(&smb_vclist);
52310023SGordon.Ross@Sun.COM 	return (error);
5246007Sthurlow }
5256007Sthurlow 
5266007Sthurlow 
52710023SGordon.Ross@Sun.COM /*
52810023SGordon.Ross@Sun.COM  * Helper functions that operate on VCs
52910023SGordon.Ross@Sun.COM  */
5306007Sthurlow 
5316007Sthurlow /*
5326007Sthurlow  * Get a pointer to the IP address suitable for passing to Trusted
5336007Sthurlow  * Extensions find_tpc() routine.  Used by smbfs_mount_label_policy().
5346007Sthurlow  * Compare this code to nfs_mount_label_policy() if problems arise.
5356007Sthurlow  */
5366007Sthurlow void *
smb_vc_getipaddr(struct smb_vc * vcp,int * ipvers)5376007Sthurlow smb_vc_getipaddr(struct smb_vc *vcp, int *ipvers)
5386007Sthurlow {
53910023SGordon.Ross@Sun.COM 	smbioc_ssn_ident_t *id = &vcp->vc_ssn.ssn_id;
54010023SGordon.Ross@Sun.COM 	void *ret;
5416007Sthurlow 
54210023SGordon.Ross@Sun.COM 	switch (id->id_srvaddr.sa.sa_family) {
54310023SGordon.Ross@Sun.COM 	case AF_INET:
5446007Sthurlow 		*ipvers = IPV4_VERSION;
54510023SGordon.Ross@Sun.COM 		ret = &id->id_srvaddr.sin.sin_addr;
54610023SGordon.Ross@Sun.COM 		break;
5476007Sthurlow 
54810023SGordon.Ross@Sun.COM 	case AF_INET6:
5496007Sthurlow 		*ipvers = IPV6_VERSION;
55010023SGordon.Ross@Sun.COM 		ret = &id->id_srvaddr.sin6.sin6_addr;
55110023SGordon.Ross@Sun.COM 		break;
5526007Sthurlow 	default:
5536007Sthurlow 		SMBSDEBUG("invalid address family %d\n",
55410023SGordon.Ross@Sun.COM 		    id->id_srvaddr.sa.sa_family);
5556007Sthurlow 		*ipvers = 0;
55610023SGordon.Ross@Sun.COM 		ret = NULL;
55710023SGordon.Ross@Sun.COM 		break;
5586007Sthurlow 	}
55910023SGordon.Ross@Sun.COM 	return (ret);
5606007Sthurlow }
5616007Sthurlow 
56210023SGordon.Ross@Sun.COM void
smb_vc_walkshares(struct smb_vc * vcp,walk_share_func_t func)56310023SGordon.Ross@Sun.COM smb_vc_walkshares(struct smb_vc *vcp,
56410023SGordon.Ross@Sun.COM 	walk_share_func_t func)
56510023SGordon.Ross@Sun.COM {
56610023SGordon.Ross@Sun.COM 	smb_connobj_t *co;
56710023SGordon.Ross@Sun.COM 	smb_share_t *ssp;
56810023SGordon.Ross@Sun.COM 
56910023SGordon.Ross@Sun.COM 	/*
57010023SGordon.Ross@Sun.COM 	 * Walk the share list calling func(ssp, arg)
57110023SGordon.Ross@Sun.COM 	 */
57210023SGordon.Ross@Sun.COM 	SMB_VC_LOCK(vcp);
57310023SGordon.Ross@Sun.COM 	SLIST_FOREACH(co, &(VCTOCP(vcp)->co_children), co_next) {
57410023SGordon.Ross@Sun.COM 		ssp = CPTOSS(co);
57510023SGordon.Ross@Sun.COM 		SMB_SS_LOCK(ssp);
57610023SGordon.Ross@Sun.COM 		func(ssp);
57710023SGordon.Ross@Sun.COM 		SMB_SS_UNLOCK(ssp);
57810023SGordon.Ross@Sun.COM 	}
57910023SGordon.Ross@Sun.COM 	SMB_VC_UNLOCK(vcp);
58010023SGordon.Ross@Sun.COM }
58110023SGordon.Ross@Sun.COM 
58210023SGordon.Ross@Sun.COM 
5836007Sthurlow /*
5846007Sthurlow  * Share implementation
5856007Sthurlow  */
5866007Sthurlow 
5876007Sthurlow void
smb_share_hold(struct smb_share * ssp)5886007Sthurlow smb_share_hold(struct smb_share *ssp)
5896007Sthurlow {
5906007Sthurlow 	smb_co_hold(SSTOCP(ssp));
5916007Sthurlow }
5926007Sthurlow 
5936007Sthurlow void
smb_share_rele(struct smb_share * ssp)5946007Sthurlow smb_share_rele(struct smb_share *ssp)
5956007Sthurlow {
5966007Sthurlow 	smb_co_rele(SSTOCP(ssp));
5976007Sthurlow }
5986007Sthurlow 
5996007Sthurlow void
smb_share_kill(struct smb_share * ssp)6006007Sthurlow smb_share_kill(struct smb_share *ssp)
6016007Sthurlow {
6026007Sthurlow 	smb_co_kill(SSTOCP(ssp));
6036007Sthurlow }
6046007Sthurlow 
60510023SGordon.Ross@Sun.COM /*
60610023SGordon.Ross@Sun.COM  * Normally called via smb_share_rele()
60710023SGordon.Ross@Sun.COM  * after co_usecount drops to zero.
60810023SGordon.Ross@Sun.COM  * Also called via: smb_share_kill()
60910023SGordon.Ross@Sun.COM  */
61010023SGordon.Ross@Sun.COM static void
smb_share_gone(struct smb_connobj * cp)61110023SGordon.Ross@Sun.COM smb_share_gone(struct smb_connobj *cp)
61210023SGordon.Ross@Sun.COM {
61310023SGordon.Ross@Sun.COM 	struct smb_cred scred;
61410023SGordon.Ross@Sun.COM 	struct smb_share *ssp = CPTOSS(cp);
6156007Sthurlow 
61610023SGordon.Ross@Sun.COM 	smb_credinit(&scred, NULL);
61710023SGordon.Ross@Sun.COM 	smb_iod_shutdown_share(ssp);
618*11332SGordon.Ross@Sun.COM 	(void) smb_smb_treedisconnect(ssp, &scred);
61910023SGordon.Ross@Sun.COM 	smb_credrele(&scred);
62010023SGordon.Ross@Sun.COM }
62110023SGordon.Ross@Sun.COM 
62210023SGordon.Ross@Sun.COM /*
62310023SGordon.Ross@Sun.COM  * Normally called via smb_share_rele()
62410023SGordon.Ross@Sun.COM  * after co_usecount drops to zero.
62510023SGordon.Ross@Sun.COM  */
62610023SGordon.Ross@Sun.COM static void
smb_share_free(struct smb_connobj * cp)62710023SGordon.Ross@Sun.COM smb_share_free(struct smb_connobj *cp)
6286007Sthurlow {
62910023SGordon.Ross@Sun.COM 	struct smb_share *ssp = CPTOSS(cp);
63010023SGordon.Ross@Sun.COM 
63110023SGordon.Ross@Sun.COM 	cv_destroy(&ssp->ss_conn_done);
63210023SGordon.Ross@Sun.COM 	smb_co_done(SSTOCP(ssp));
63310023SGordon.Ross@Sun.COM 	kmem_free(ssp, sizeof (*ssp));
63410023SGordon.Ross@Sun.COM }
63510023SGordon.Ross@Sun.COM 
63610023SGordon.Ross@Sun.COM /*
63710023SGordon.Ross@Sun.COM  * Allocate share structure and attach it to the given VC
63810023SGordon.Ross@Sun.COM  * Connection expected to be locked on entry. Share will be returned
63910023SGordon.Ross@Sun.COM  * in locked state.
64010023SGordon.Ross@Sun.COM  */
64110023SGordon.Ross@Sun.COM /*ARGSUSED*/
64210023SGordon.Ross@Sun.COM int
smb_share_create(smbioc_tcon_t * tcon,struct smb_vc * vcp,struct smb_share ** sspp,struct smb_cred * scred)64310023SGordon.Ross@Sun.COM smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
64410023SGordon.Ross@Sun.COM 	struct smb_share **sspp, struct smb_cred *scred)
64510023SGordon.Ross@Sun.COM {
64610023SGordon.Ross@Sun.COM 	static char objtype[] = "smb_ss";
64710023SGordon.Ross@Sun.COM 	struct smb_share *ssp;
64810023SGordon.Ross@Sun.COM 
64910023SGordon.Ross@Sun.COM 	ASSERT(MUTEX_HELD(&vcp->vc_lock));
65010023SGordon.Ross@Sun.COM 
65110023SGordon.Ross@Sun.COM 	ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
65210023SGordon.Ross@Sun.COM 	smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
65310023SGordon.Ross@Sun.COM 	ssp->ss_co.co_free = smb_share_free;
65410023SGordon.Ross@Sun.COM 	ssp->ss_co.co_gone = smb_share_gone;
65510023SGordon.Ross@Sun.COM 
65610023SGordon.Ross@Sun.COM 	cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
6576007Sthurlow 	ssp->ss_tid = SMB_TID_UNKNOWN;
65810023SGordon.Ross@Sun.COM 
65910023SGordon.Ross@Sun.COM 	bcopy(&tcon->tc_sh, &ssp->ss_ioc,
66010023SGordon.Ross@Sun.COM 	    sizeof (smbioc_oshare_t));
66110023SGordon.Ross@Sun.COM 
66210023SGordon.Ross@Sun.COM 	smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
66310023SGordon.Ross@Sun.COM 	*sspp = ssp;
66410023SGordon.Ross@Sun.COM 
66510023SGordon.Ross@Sun.COM 	return (0);
6666007Sthurlow }
6676007Sthurlow 
6686007Sthurlow /*
66910023SGordon.Ross@Sun.COM  * Find or create a share under the given VC
67010023SGordon.Ross@Sun.COM  * and return it with a "hold", but not locked.
6716007Sthurlow  */
67210023SGordon.Ross@Sun.COM 
6736007Sthurlow int
smb_share_findcreate(smbioc_tcon_t * tcon,struct smb_vc * vcp,struct smb_share ** sspp,struct smb_cred * scred)67410023SGordon.Ross@Sun.COM smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
67510023SGordon.Ross@Sun.COM 	struct smb_share **sspp, struct smb_cred *scred)
6766007Sthurlow {
67710023SGordon.Ross@Sun.COM 	struct smb_connobj *co;
67810023SGordon.Ross@Sun.COM 	struct smb_share *ssp = NULL;
67910023SGordon.Ross@Sun.COM 	int error = 0;
68010023SGordon.Ross@Sun.COM 
68110023SGordon.Ross@Sun.COM 	*sspp = NULL;
68210023SGordon.Ross@Sun.COM 
68310023SGordon.Ross@Sun.COM 	SMB_VC_LOCK(vcp);
68410023SGordon.Ross@Sun.COM 
68510023SGordon.Ross@Sun.COM 	/* var, head, next_field */
68610023SGordon.Ross@Sun.COM 	SLIST_FOREACH(co, &(VCTOCP(vcp)->co_children), co_next) {
68710023SGordon.Ross@Sun.COM 		ssp = CPTOSS(co);
68810023SGordon.Ross@Sun.COM 
68910023SGordon.Ross@Sun.COM 		/* Share name */
69010023SGordon.Ross@Sun.COM 		if (u8_strcmp(ssp->ss_name, tcon->tc_sh.sh_name, 0,
69110023SGordon.Ross@Sun.COM 		    U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
69210023SGordon.Ross@Sun.COM 			continue;
69310023SGordon.Ross@Sun.COM 
69410023SGordon.Ross@Sun.COM 		/*
69510023SGordon.Ross@Sun.COM 		 * We have a match, but still have to check
69610023SGordon.Ross@Sun.COM 		 * the _GONE flag, and do that with a lock.
69710023SGordon.Ross@Sun.COM 		 * No new references when _GONE is set.
69810023SGordon.Ross@Sun.COM 		 *
69910023SGordon.Ross@Sun.COM 		 * Also clear SMBSOPT_CREATE which the caller
70010023SGordon.Ross@Sun.COM 		 * may check to find out if we did create.
70110023SGordon.Ross@Sun.COM 		 */
70210023SGordon.Ross@Sun.COM 		SMB_SS_LOCK(ssp);
70310023SGordon.Ross@Sun.COM 		if ((ssp->ss_flags & SMBS_GONE) == 0) {
70410023SGordon.Ross@Sun.COM 			tcon->tc_opt &= ~SMBSOPT_CREATE;
70510023SGordon.Ross@Sun.COM 			/*
70610023SGordon.Ross@Sun.COM 			 * Return it held, unlocked.
70710023SGordon.Ross@Sun.COM 			 * In-line smb_share_hold here.
70810023SGordon.Ross@Sun.COM 			 */
70910023SGordon.Ross@Sun.COM 			co->co_usecount++;
71010023SGordon.Ross@Sun.COM 			SMB_SS_UNLOCK(ssp);
71110023SGordon.Ross@Sun.COM 			*sspp = ssp;
71210023SGordon.Ross@Sun.COM 			error = 0;
71310023SGordon.Ross@Sun.COM 			goto out;
71410023SGordon.Ross@Sun.COM 		}
71510023SGordon.Ross@Sun.COM 		SMB_SS_UNLOCK(ssp);
71610023SGordon.Ross@Sun.COM 		/* keep looking. */
71710023SGordon.Ross@Sun.COM 	}
71810023SGordon.Ross@Sun.COM 	ssp = NULL;
71910023SGordon.Ross@Sun.COM 
72010023SGordon.Ross@Sun.COM 	/* Note: vcp (list of shares) is still locked. */
72110023SGordon.Ross@Sun.COM 
72210023SGordon.Ross@Sun.COM 	if (tcon->tc_opt & SMBSOPT_CREATE) {
72310023SGordon.Ross@Sun.COM 		/*
72410023SGordon.Ross@Sun.COM 		 * Create a new share.  It starts out with
72510023SGordon.Ross@Sun.COM 		 * hold count = 1, so don't incr. here.
72610023SGordon.Ross@Sun.COM 		 */
72710023SGordon.Ross@Sun.COM 		error = smb_share_create(tcon, vcp, &ssp, scred);
72810023SGordon.Ross@Sun.COM 		if (error == 0)
72910023SGordon.Ross@Sun.COM 			*sspp = ssp;
73010023SGordon.Ross@Sun.COM 	} else
73110023SGordon.Ross@Sun.COM 		error = ENOENT;
73210023SGordon.Ross@Sun.COM 
73310023SGordon.Ross@Sun.COM out:
73410023SGordon.Ross@Sun.COM 	SMB_VC_UNLOCK(vcp);
73510023SGordon.Ross@Sun.COM 	return (error);
73610023SGordon.Ross@Sun.COM }
73710023SGordon.Ross@Sun.COM 
73810023SGordon.Ross@Sun.COM 
73910023SGordon.Ross@Sun.COM /*
74010023SGordon.Ross@Sun.COM  * Helper functions that operate on shares
74110023SGordon.Ross@Sun.COM  */
74210023SGordon.Ross@Sun.COM 
74310023SGordon.Ross@Sun.COM /*
74410023SGordon.Ross@Sun.COM  * Mark this share as invalid, so consumers will know
74510023SGordon.Ross@Sun.COM  * their file handles have become invalid.
74610023SGordon.Ross@Sun.COM  *
74710023SGordon.Ross@Sun.COM  * Most share consumers store a copy of ss_vcgenid when
74810023SGordon.Ross@Sun.COM  * opening a file handle and compare that with what's in
74910023SGordon.Ross@Sun.COM  * the share before using a file handle.  If the genid
75010023SGordon.Ross@Sun.COM  * doesn't match, the file handle has become "stale"
75110023SGordon.Ross@Sun.COM  * due to disconnect.  Therefore, zap ss_vcgenid here.
75210023SGordon.Ross@Sun.COM  */
75310023SGordon.Ross@Sun.COM void
smb_share_invalidate(struct smb_share * ssp)75410023SGordon.Ross@Sun.COM smb_share_invalidate(struct smb_share *ssp)
75510023SGordon.Ross@Sun.COM {
7566007Sthurlow 
7576007Sthurlow 	ASSERT(MUTEX_HELD(&ssp->ss_lock));
7586007Sthurlow 
75910023SGordon.Ross@Sun.COM 	ssp->ss_flags &= ~SMBS_CONNECTED;
76010023SGordon.Ross@Sun.COM 	ssp->ss_tid = SMB_TID_UNKNOWN;
76110023SGordon.Ross@Sun.COM 	ssp->ss_vcgenid = 0;
7626007Sthurlow }
7636007Sthurlow 
7646007Sthurlow /*
7656007Sthurlow  * Connect (or reconnect) a share object.
76610023SGordon.Ross@Sun.COM  *
76710023SGordon.Ross@Sun.COM  * Called by smb_usr_get_tree() for new connections,
76810023SGordon.Ross@Sun.COM  * and called by smb_rq_enqueue() for reconnect.
7696007Sthurlow  */
7706007Sthurlow int
smb_share_tcon(smb_share_t * ssp,smb_cred_t * scred)77110023SGordon.Ross@Sun.COM smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
7726007Sthurlow {
7736007Sthurlow 	clock_t tmo;
7746007Sthurlow 	int error;
7756007Sthurlow 
77610023SGordon.Ross@Sun.COM 	SMB_SS_LOCK(ssp);
7776007Sthurlow 
7786007Sthurlow 	if (ssp->ss_flags & SMBS_CONNECTED) {
7796007Sthurlow 		SMBIODEBUG("alread connected?");
78010023SGordon.Ross@Sun.COM 		error = 0;
78110023SGordon.Ross@Sun.COM 		goto out;
7826007Sthurlow 	}
7836007Sthurlow 
7846007Sthurlow 	/*
7856007Sthurlow 	 * Wait for completion of any state changes
7866007Sthurlow 	 * that might be underway.
7876007Sthurlow 	 */
7886007Sthurlow 	while (ssp->ss_flags & SMBS_RECONNECTING) {
7896007Sthurlow 		ssp->ss_conn_waiters++;
7906007Sthurlow 		tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
7916007Sthurlow 		ssp->ss_conn_waiters--;
7926007Sthurlow 		if (tmo == 0) {
7936007Sthurlow 			/* Interrupt! */
79410023SGordon.Ross@Sun.COM 			error = EINTR;
79510023SGordon.Ross@Sun.COM 			goto out;
7966007Sthurlow 		}
7976007Sthurlow 	}
7986007Sthurlow 
7996007Sthurlow 	/* Did someone else do it for us? */
80010023SGordon.Ross@Sun.COM 	if (ssp->ss_flags & SMBS_CONNECTED) {
80110023SGordon.Ross@Sun.COM 		error = 0;
80210023SGordon.Ross@Sun.COM 		goto out;
80310023SGordon.Ross@Sun.COM 	}
8046007Sthurlow 
8056007Sthurlow 	/*
8066007Sthurlow 	 * OK, we'll do the work.
8076007Sthurlow 	 */
8086007Sthurlow 	ssp->ss_flags |= SMBS_RECONNECTING;
8096007Sthurlow 
81010023SGordon.Ross@Sun.COM 	/*
81110023SGordon.Ross@Sun.COM 	 * Drop the lock while doing the TCON.
81210023SGordon.Ross@Sun.COM 	 * On success, sets ss_tid, ss_vcgenid,
81310023SGordon.Ross@Sun.COM 	 * and ss_flags |= SMBS_CONNECTED;
81410023SGordon.Ross@Sun.COM 	 */
8156007Sthurlow 	SMB_SS_UNLOCK(ssp);
81610023SGordon.Ross@Sun.COM 	error = smb_smb_treeconnect(ssp, scred);
8176007Sthurlow 	SMB_SS_LOCK(ssp);
8186007Sthurlow 
8196007Sthurlow 	ssp->ss_flags &= ~SMBS_RECONNECTING;
8206007Sthurlow 
8216007Sthurlow 	/* They can all go ahead! */
8226007Sthurlow 	if (ssp->ss_conn_waiters)
8236007Sthurlow 		cv_broadcast(&ssp->ss_conn_done);
8246007Sthurlow 
82510023SGordon.Ross@Sun.COM out:
82610023SGordon.Ross@Sun.COM 	SMB_SS_UNLOCK(ssp);
8276007Sthurlow 
82810023SGordon.Ross@Sun.COM 	return (error);
8296007Sthurlow }
8306007Sthurlow 
8316007Sthurlow /*
8326007Sthurlow  * Solaris zones support
8336007Sthurlow  */
8346007Sthurlow /*ARGSUSED*/
8356007Sthurlow void
lingering_vc(struct smb_vc * vc)8366007Sthurlow lingering_vc(struct smb_vc *vc)
8376007Sthurlow {
8386007Sthurlow 	/* good place for a breakpoint */
8396007Sthurlow 	DEBUG_ENTER("lingering VC");
8406007Sthurlow }
8416007Sthurlow 
8426007Sthurlow /*
8436007Sthurlow  * On zone shutdown, kill any IOD threads still running in this zone.
8446007Sthurlow  */
8456007Sthurlow /* ARGSUSED */
8466007Sthurlow void
nsmb_zone_shutdown(zoneid_t zoneid,void * data)8476007Sthurlow nsmb_zone_shutdown(zoneid_t zoneid, void *data)
8486007Sthurlow {
8496007Sthurlow 	struct smb_connobj *co;
8506007Sthurlow 	struct smb_vc *vcp;
8516007Sthurlow 
8526007Sthurlow 	SMB_CO_LOCK(&smb_vclist);
8536007Sthurlow 	SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
8546007Sthurlow 		vcp = CPTOVC(co);
8556007Sthurlow 
8566007Sthurlow 		if (vcp->vc_zoneid != zoneid)
8576007Sthurlow 			continue;
8586007Sthurlow 
8596007Sthurlow 		/*
8606007Sthurlow 		 * This will close the connection, and
8616007Sthurlow 		 * cause the IOD thread to terminate.
8626007Sthurlow 		 */
8636007Sthurlow 		smb_vc_kill(vcp);
8646007Sthurlow 	}
8656007Sthurlow 	SMB_CO_UNLOCK(&smb_vclist);
8666007Sthurlow }
8676007Sthurlow 
8686007Sthurlow /*
8696007Sthurlow  * On zone destroy, kill any IOD threads and free all resources they used.
8706007Sthurlow  */
8716007Sthurlow /* ARGSUSED */
8726007Sthurlow void
nsmb_zone_destroy(zoneid_t zoneid,void * data)8736007Sthurlow nsmb_zone_destroy(zoneid_t zoneid, void *data)
8746007Sthurlow {
8756007Sthurlow 	struct smb_connobj *co;
8766007Sthurlow 	struct smb_vc *vcp;
8776007Sthurlow 
8786007Sthurlow 	/*
8796007Sthurlow 	 * We will repeat what should have already happened
8806007Sthurlow 	 * in zone_shutdown to make things go away.
8816007Sthurlow 	 *
8826007Sthurlow 	 * There should have been an smb_vc_rele call
8836007Sthurlow 	 * by now for all VCs in the zone.  If not,
8846007Sthurlow 	 * there's probably more we needed to do in
8856007Sthurlow 	 * the shutdown call.
8866007Sthurlow 	 */
8876007Sthurlow 
8886007Sthurlow 	SMB_CO_LOCK(&smb_vclist);
8896007Sthurlow 
8906007Sthurlow 	if (smb_vclist.co_usecount > 1) {
8916007Sthurlow 		SMBERROR("%d connections still active\n",
8926007Sthurlow 		    smb_vclist.co_usecount - 1);
8936007Sthurlow 	}
8946007Sthurlow 
8956007Sthurlow 	/* var, head, next_field */
8966007Sthurlow 	SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
8976007Sthurlow 		vcp = CPTOVC(co);
8986007Sthurlow 
8996007Sthurlow 		if (vcp->vc_zoneid != zoneid)
9006007Sthurlow 			continue;
9016007Sthurlow 
9026007Sthurlow 		/* Debugging */
9036007Sthurlow 		lingering_vc(vcp);
9046007Sthurlow 	}
9056007Sthurlow 
9066007Sthurlow 	SMB_CO_UNLOCK(&smb_vclist);
9076007Sthurlow }
908