17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
33 */
34 /*
35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
37 */
38
39 /*
40 * Connection engine.
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kmem.h>
46 #include <sys/proc.h>
47 #include <sys/lock.h>
48 #include <sys/vnode.h>
49 #include <sys/stream.h>
50 #include <sys/stropts.h>
51 #include <sys/socketvar.h>
52 #include <sys/cred.h>
53 #include <netinet/in.h>
54 #include <inet/ip.h>
55 #include <inet/ip6.h>
56 #include <sys/cmn_err.h>
57 #include <sys/thread.h>
58 #include <sys/atomic.h>
59 #include <sys/u8_textprep.h>
60
61 #include <netsmb/smb_osdep.h>
62
63 #include <netsmb/smb.h>
64 #include <netsmb/smb_conn.h>
65 #include <netsmb/smb_subr.h>
66 #include <netsmb/smb_tran.h>
67 #include <netsmb/smb_pass.h>
68
69 static struct smb_connobj smb_vclist;
70
71 void smb_co_init(struct smb_connobj *cp, int level, char *objname);
72 void smb_co_done(struct smb_connobj *cp);
73 void smb_co_hold(struct smb_connobj *cp);
74 void smb_co_rele(struct smb_connobj *cp);
75 void smb_co_kill(struct smb_connobj *cp);
76
77 static void smb_vc_free(struct smb_connobj *cp);
78 static void smb_vc_gone(struct smb_connobj *cp);
79
80 static void smb_share_free(struct smb_connobj *cp);
81 static void smb_share_gone(struct smb_connobj *cp);
82
83 int
84 smb_sm_init(void)
85 {
86 smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
87 return (0);
88 }
89
90 int
91 smb_sm_idle(void)
92 {
93 int error = 0;
94 SMB_CO_LOCK(&smb_vclist);
95 if (smb_vclist.co_usecount > 1) {
96 SMBSDEBUG("%d connections still active\n",
97 smb_vclist.co_usecount - 1);
98 error = EBUSY;
99 }
100 SMB_CO_UNLOCK(&smb_vclist);
101 return (error);
102 }
103
104 void
105 smb_sm_done(void)
106 {
107 /*
108 * XXX Q4BP why are we not iterating on smb_vclist here?
109 * Because the caller has just called smb_sm_idle() to
110 * make sure we have no VCs before calling this.
111 */
112 smb_co_done(&smb_vclist);
113 }
114
115
116
117 /*
118 * Common code for connection object
119 */
120 /*ARGSUSED*/
121 void
122 smb_co_init(struct smb_connobj *cp, int level, char *objname)
123 {
124
125 mutex_init(&cp->co_lock, objname, MUTEX_DRIVER, NULL);
126
127 cp->co_level = level;
128 cp->co_usecount = 1;
164 }
165
166 void
167 smb_co_hold(struct smb_connobj *cp)
168 {
169 SMB_CO_LOCK(cp);
170 cp->co_usecount++;
171 SMB_CO_UNLOCK(cp);
172 }
173
174 /*
175 * Called via smb_vc_rele, smb_share_rele
176 */
177 void
178 smb_co_rele(struct smb_connobj *co)
179 {
180 struct smb_connobj *parent;
181 int old_flags;
182
183 SMB_CO_LOCK(co);
184 if (co->co_usecount > 1) {
185 co->co_usecount--;
186 SMB_CO_UNLOCK(co);
187 return;
188 }
189 ASSERT(co->co_usecount == 1);
190 co->co_usecount = 0;
191
192 /*
193 * This list of children should be empty now.
194 * Check this while we're still linked, so
195 * we have a better chance of debugging.
196 */
197 ASSERT(SLIST_EMPTY(&co->co_children));
198
199 /*
200 * OK, this element is going away.
201 *
202 * We need to drop the lock on this CO so we can take the
203 * parent CO lock. The _GONE flag prevents this CO from
348 if (vcp->vc_tdata)
349 SMB_TRAN_DONE(vcp);
350
351 /*
352 * We are not using the iconv routines here. So commenting them for now.
353 * REVISIT.
354 */
355 #ifdef NOTYETDEFINED
356 if (vcp->vc_tolower)
357 iconv_close(vcp->vc_tolower);
358 if (vcp->vc_toupper)
359 iconv_close(vcp->vc_toupper);
360 if (vcp->vc_tolocal)
361 iconv_close(vcp->vc_tolocal);
362 if (vcp->vc_toserver)
363 iconv_close(vcp->vc_toserver);
364 #endif
365
366 if (vcp->vc_mackey != NULL)
367 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
368
369 cv_destroy(&vcp->iod_idle);
370 rw_destroy(&vcp->iod_rqlock);
371 sema_destroy(&vcp->vc_sendlock);
372 cv_destroy(&vcp->vc_statechg);
373 smb_co_done(VCTOCP(vcp));
374 kmem_free(vcp, sizeof (*vcp));
375 }
376
377 /*ARGSUSED*/
378 int
379 smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
380 {
381 static char objtype[] = "smb_vc";
382 cred_t *cr = scred->scr_cred;
383 struct smb_vc *vcp;
384 int error = 0;
385
386 ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
387
388 vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
389
390 smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
391 vcp->vc_co.co_free = smb_vc_free;
392 vcp->vc_co.co_gone = smb_vc_gone;
393
394 cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
395 sema_init(&vcp->vc_sendlock, 1, objtype, SEMA_DRIVER, NULL);
396 rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
397 cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
398
399 /* Expanded TAILQ_HEAD_INITIALIZER */
400 vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
401
402 vcp->vc_state = SMBIOD_ST_IDLE;
403
404 /*
405 * These identify the connection.
406 */
407 vcp->vc_zoneid = getzoneid();
408 bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
409
410 /* This fills in vcp->vc_tdata */
411 vcp->vc_tdesc = &smb_tran_nbtcp_desc;
412 if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
413 goto errout;
414
415 /* Success! */
416 smb_co_addchild(&smb_vclist, VCTOCP(vcp));
417 *vcpp = vcp;
418 return (0);
419
420 errout:
421 /*
422 * This will destroy the new vc.
595 {
596 smb_co_rele(SSTOCP(ssp));
597 }
598
599 void
600 smb_share_kill(struct smb_share *ssp)
601 {
602 smb_co_kill(SSTOCP(ssp));
603 }
604
605 /*
606 * Normally called via smb_share_rele()
607 * after co_usecount drops to zero.
608 * Also called via: smb_share_kill()
609 */
610 static void
611 smb_share_gone(struct smb_connobj *cp)
612 {
613 struct smb_cred scred;
614 struct smb_share *ssp = CPTOSS(cp);
615
616 smb_credinit(&scred, NULL);
617 smb_iod_shutdown_share(ssp);
618 (void) smb_smb_treedisconnect(ssp, &scred);
619 smb_credrele(&scred);
620 }
621
622 /*
623 * Normally called via smb_share_rele()
624 * after co_usecount drops to zero.
625 */
626 static void
627 smb_share_free(struct smb_connobj *cp)
628 {
629 struct smb_share *ssp = CPTOSS(cp);
630
631 cv_destroy(&ssp->ss_conn_done);
632 smb_co_done(SSTOCP(ssp));
633 kmem_free(ssp, sizeof (*ssp));
634 }
635
636 /*
637 * Allocate share structure and attach it to the given VC
638 * Connection expected to be locked on entry. Share will be returned
639 * in locked state.
640 */
641 /*ARGSUSED*/
642 int
643 smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
644 struct smb_share **sspp, struct smb_cred *scred)
645 {
646 static char objtype[] = "smb_ss";
647 struct smb_share *ssp;
648
649 ASSERT(MUTEX_HELD(&vcp->vc_lock));
650
651 ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
652 smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
653 ssp->ss_co.co_free = smb_share_free;
654 ssp->ss_co.co_gone = smb_share_gone;
655
656 cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
657 ssp->ss_tid = SMB_TID_UNKNOWN;
658
659 bcopy(&tcon->tc_sh, &ssp->ss_ioc,
660 sizeof (smbioc_oshare_t));
661
662 smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
663 *sspp = ssp;
664
665 return (0);
666 }
667
668 /*
669 * Find or create a share under the given VC
670 * and return it with a "hold", but not locked.
671 */
672
673 int
674 smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
675 struct smb_share **sspp, struct smb_cred *scred)
676 {
677 struct smb_connobj *co;
753 void
754 smb_share_invalidate(struct smb_share *ssp)
755 {
756
757 ASSERT(MUTEX_HELD(&ssp->ss_lock));
758
759 ssp->ss_flags &= ~SMBS_CONNECTED;
760 ssp->ss_tid = SMB_TID_UNKNOWN;
761 ssp->ss_vcgenid = 0;
762 }
763
764 /*
765 * Connect (or reconnect) a share object.
766 *
767 * Called by smb_usr_get_tree() for new connections,
768 * and called by smb_rq_enqueue() for reconnect.
769 */
770 int
771 smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
772 {
773 clock_t tmo;
774 int error;
775
776 SMB_SS_LOCK(ssp);
777
778 if (ssp->ss_flags & SMBS_CONNECTED) {
779 SMBIODEBUG("alread connected?");
780 error = 0;
781 goto out;
782 }
783
784 /*
785 * Wait for completion of any state changes
786 * that might be underway.
787 */
788 while (ssp->ss_flags & SMBS_RECONNECTING) {
789 ssp->ss_conn_waiters++;
790 tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
791 ssp->ss_conn_waiters--;
792 if (tmo == 0) {
796 }
797 }
798
799 /* Did someone else do it for us? */
800 if (ssp->ss_flags & SMBS_CONNECTED) {
801 error = 0;
802 goto out;
803 }
804
805 /*
806 * OK, we'll do the work.
807 */
808 ssp->ss_flags |= SMBS_RECONNECTING;
809
810 /*
811 * Drop the lock while doing the TCON.
812 * On success, sets ss_tid, ss_vcgenid,
813 * and ss_flags |= SMBS_CONNECTED;
814 */
815 SMB_SS_UNLOCK(ssp);
816 error = smb_smb_treeconnect(ssp, scred);
817 SMB_SS_LOCK(ssp);
818
819 ssp->ss_flags &= ~SMBS_RECONNECTING;
820
821 /* They can all go ahead! */
822 if (ssp->ss_conn_waiters)
823 cv_broadcast(&ssp->ss_conn_done);
824
825 out:
826 SMB_SS_UNLOCK(ssp);
827
828 return (error);
829 }
830
831 /*
832 * Solaris zones support
833 */
834 /*ARGSUSED*/
835 void
836 lingering_vc(struct smb_vc *vc)
837 {
838 /* good place for a breakpoint */
839 DEBUG_ENTER("lingering VC");
840 }
841
842 /*
843 * On zone shutdown, kill any IOD threads still running in this zone.
844 */
845 /* ARGSUSED */
846 void
847 nsmb_zone_shutdown(zoneid_t zoneid, void *data)
848 {
849 struct smb_connobj *co;
850 struct smb_vc *vcp;
851
|
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
33 */
34 /*
35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
37 *
38 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
39 */
40
41 /*
42 * Connection engine.
43 */
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kmem.h>
48 #include <sys/proc.h>
49 #include <sys/lock.h>
50 #include <sys/vnode.h>
51 #include <sys/stream.h>
52 #include <sys/stropts.h>
53 #include <sys/socketvar.h>
54 #include <sys/cred.h>
55 #include <netinet/in.h>
56 #include <inet/ip.h>
57 #include <inet/ip6.h>
58 #include <sys/cmn_err.h>
59 #include <sys/thread.h>
60 #include <sys/atomic.h>
61 #include <sys/u8_textprep.h>
62
63 #include <netsmb/smb_osdep.h>
64
65 #include <netsmb/smb.h>
66 #include <netsmb/smb2.h>
67 #include <netsmb/smb_conn.h>
68 #include <netsmb/smb_subr.h>
69 #include <netsmb/smb_tran.h>
70 #include <netsmb/smb_pass.h>
71
72 static struct smb_connobj smb_vclist;
73
74 void smb_co_init(struct smb_connobj *cp, int level, char *objname);
75 void smb_co_done(struct smb_connobj *cp);
76 void smb_co_hold(struct smb_connobj *cp);
77 void smb_co_rele(struct smb_connobj *cp);
78 void smb_co_kill(struct smb_connobj *cp);
79
80 static void smb_vc_free(struct smb_connobj *cp);
81 static void smb_vc_gone(struct smb_connobj *cp);
82
83 static void smb_share_free(struct smb_connobj *cp);
84 static void smb_share_gone(struct smb_connobj *cp);
85
86 static void smb_fh_free(struct smb_connobj *cp);
87 static void smb_fh_gone(struct smb_connobj *cp);
88
89 int
90 smb_sm_init(void)
91 {
92 smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
93 return (0);
94 }
95
96 int
97 smb_sm_idle(void)
98 {
99 int error = 0;
100 SMB_CO_LOCK(&smb_vclist);
101 if (smb_vclist.co_usecount > 1) {
102 SMBSDEBUG("%d connections still active\n",
103 smb_vclist.co_usecount - 1);
104 error = EBUSY;
105 }
106 SMB_CO_UNLOCK(&smb_vclist);
107 return (error);
108 }
109
110 void
111 smb_sm_done(void)
112 {
113 /*
114 * Why are we not iterating on smb_vclist here?
115 * Because the caller has just called smb_sm_idle() to
116 * make sure we have no VCs before calling this.
117 */
118 smb_co_done(&smb_vclist);
119 }
120
121
122
123 /*
124 * Common code for connection object
125 */
126 /*ARGSUSED*/
127 void
128 smb_co_init(struct smb_connobj *cp, int level, char *objname)
129 {
130
131 mutex_init(&cp->co_lock, objname, MUTEX_DRIVER, NULL);
132
133 cp->co_level = level;
134 cp->co_usecount = 1;
170 }
171
172 void
173 smb_co_hold(struct smb_connobj *cp)
174 {
175 SMB_CO_LOCK(cp);
176 cp->co_usecount++;
177 SMB_CO_UNLOCK(cp);
178 }
179
180 /*
181 * Called via smb_vc_rele, smb_share_rele
182 */
183 void
184 smb_co_rele(struct smb_connobj *co)
185 {
186 struct smb_connobj *parent;
187 int old_flags;
188
189 SMB_CO_LOCK(co);
190
191 /*
192 * When VC usecount goes from 2 to 1, signal the iod_idle CV.
193 * It's unfortunate to have object type-specific logic here,
194 * but it's hard to do this anywhere else.
195 */
196 if (co->co_level == SMBL_VC && co->co_usecount == 2) {
197 smb_vc_t *vcp = CPTOVC(co);
198 cv_signal(&vcp->iod_idle);
199 }
200 if (co->co_usecount > 1) {
201 co->co_usecount--;
202 SMB_CO_UNLOCK(co);
203 return;
204 }
205 ASSERT(co->co_usecount == 1);
206 co->co_usecount = 0;
207
208 /*
209 * This list of children should be empty now.
210 * Check this while we're still linked, so
211 * we have a better chance of debugging.
212 */
213 ASSERT(SLIST_EMPTY(&co->co_children));
214
215 /*
216 * OK, this element is going away.
217 *
218 * We need to drop the lock on this CO so we can take the
219 * parent CO lock. The _GONE flag prevents this CO from
364 if (vcp->vc_tdata)
365 SMB_TRAN_DONE(vcp);
366
367 /*
368 * We are not using the iconv routines here. So commenting them for now.
369 * REVISIT.
370 */
371 #ifdef NOTYETDEFINED
372 if (vcp->vc_tolower)
373 iconv_close(vcp->vc_tolower);
374 if (vcp->vc_toupper)
375 iconv_close(vcp->vc_toupper);
376 if (vcp->vc_tolocal)
377 iconv_close(vcp->vc_tolocal);
378 if (vcp->vc_toserver)
379 iconv_close(vcp->vc_toserver);
380 #endif
381
382 if (vcp->vc_mackey != NULL)
383 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
384 if (vcp->vc_ssnkey != NULL)
385 kmem_free(vcp->vc_ssnkey, vcp->vc_ssnkeylen);
386
387 cv_destroy(&vcp->iod_muxwait);
388 cv_destroy(&vcp->iod_idle);
389 rw_destroy(&vcp->iod_rqlock);
390 cv_destroy(&vcp->vc_statechg);
391 smb_co_done(VCTOCP(vcp));
392 kmem_free(vcp, sizeof (*vcp));
393 }
394
395 /*ARGSUSED*/
396 int
397 smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
398 {
399 static char objtype[] = "smb_vc";
400 cred_t *cr = scred->scr_cred;
401 struct smb_vc *vcp;
402 int error = 0;
403
404 ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
405
406 vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
407
408 smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
409 vcp->vc_co.co_free = smb_vc_free;
410 vcp->vc_co.co_gone = smb_vc_gone;
411
412 cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
413 rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
414 cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
415 cv_init(&vcp->iod_muxwait, objtype, CV_DRIVER, NULL);
416
417 /* Expanded TAILQ_HEAD_INITIALIZER */
418 vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
419
420 /* A brand new VC should connect. */
421 vcp->vc_state = SMBIOD_ST_RECONNECT;
422
423 /*
424 * These identify the connection.
425 */
426 vcp->vc_zoneid = getzoneid();
427 bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
428
429 /* This fills in vcp->vc_tdata */
430 vcp->vc_tdesc = &smb_tran_nbtcp_desc;
431 if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
432 goto errout;
433
434 /* Success! */
435 smb_co_addchild(&smb_vclist, VCTOCP(vcp));
436 *vcpp = vcp;
437 return (0);
438
439 errout:
440 /*
441 * This will destroy the new vc.
614 {
615 smb_co_rele(SSTOCP(ssp));
616 }
617
618 void
619 smb_share_kill(struct smb_share *ssp)
620 {
621 smb_co_kill(SSTOCP(ssp));
622 }
623
624 /*
625 * Normally called via smb_share_rele()
626 * after co_usecount drops to zero.
627 * Also called via: smb_share_kill()
628 */
629 static void
630 smb_share_gone(struct smb_connobj *cp)
631 {
632 struct smb_cred scred;
633 struct smb_share *ssp = CPTOSS(cp);
634 smb_vc_t *vcp = SSTOVC(ssp);
635
636 smb_credinit(&scred, NULL);
637 smb_iod_shutdown_share(ssp);
638 if (vcp->vc_flags & SMBV_SMB2)
639 (void) smb2_smb_treedisconnect(ssp, &scred);
640 else
641 (void) smb_smb_treedisconnect(ssp, &scred);
642 smb_credrele(&scred);
643 }
644
645 /*
646 * Normally called via smb_share_rele()
647 * after co_usecount drops to zero.
648 */
649 static void
650 smb_share_free(struct smb_connobj *cp)
651 {
652 struct smb_share *ssp = CPTOSS(cp);
653
654 cv_destroy(&ssp->ss_conn_done);
655 smb_co_done(SSTOCP(ssp));
656 kmem_free(ssp, sizeof (*ssp));
657 }
658
659 /*
660 * Allocate share structure and attach it to the given VC
661 * Connection expected to be locked on entry. Share will be returned
662 * in locked state.
663 */
664 /*ARGSUSED*/
665 int
666 smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
667 struct smb_share **sspp, struct smb_cred *scred)
668 {
669 static char objtype[] = "smb_ss";
670 struct smb_share *ssp;
671
672 ASSERT(MUTEX_HELD(&vcp->vc_lock));
673
674 ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
675 smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
676 ssp->ss_co.co_free = smb_share_free;
677 ssp->ss_co.co_gone = smb_share_gone;
678
679 cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
680 ssp->ss_tid = SMB_TID_UNKNOWN;
681 ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
682
683 bcopy(&tcon->tc_sh, &ssp->ss_ioc,
684 sizeof (smbioc_oshare_t));
685
686 smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
687 *sspp = ssp;
688
689 return (0);
690 }
691
692 /*
693 * Find or create a share under the given VC
694 * and return it with a "hold", but not locked.
695 */
696
697 int
698 smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
699 struct smb_share **sspp, struct smb_cred *scred)
700 {
701 struct smb_connobj *co;
777 void
778 smb_share_invalidate(struct smb_share *ssp)
779 {
780
781 ASSERT(MUTEX_HELD(&ssp->ss_lock));
782
783 ssp->ss_flags &= ~SMBS_CONNECTED;
784 ssp->ss_tid = SMB_TID_UNKNOWN;
785 ssp->ss_vcgenid = 0;
786 }
787
788 /*
789 * Connect (or reconnect) a share object.
790 *
791 * Called by smb_usr_get_tree() for new connections,
792 * and called by smb_rq_enqueue() for reconnect.
793 */
794 int
795 smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
796 {
797 smb_vc_t *vcp = SSTOVC(ssp);
798 clock_t tmo;
799 int error;
800
801 SMB_SS_LOCK(ssp);
802
803 if (ssp->ss_flags & SMBS_CONNECTED) {
804 SMBIODEBUG("alread connected?");
805 error = 0;
806 goto out;
807 }
808
809 /*
810 * Wait for completion of any state changes
811 * that might be underway.
812 */
813 while (ssp->ss_flags & SMBS_RECONNECTING) {
814 ssp->ss_conn_waiters++;
815 tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
816 ssp->ss_conn_waiters--;
817 if (tmo == 0) {
821 }
822 }
823
824 /* Did someone else do it for us? */
825 if (ssp->ss_flags & SMBS_CONNECTED) {
826 error = 0;
827 goto out;
828 }
829
830 /*
831 * OK, we'll do the work.
832 */
833 ssp->ss_flags |= SMBS_RECONNECTING;
834
835 /*
836 * Drop the lock while doing the TCON.
837 * On success, sets ss_tid, ss_vcgenid,
838 * and ss_flags |= SMBS_CONNECTED;
839 */
840 SMB_SS_UNLOCK(ssp);
841 if (vcp->vc_flags & SMBV_SMB2)
842 error = smb2_smb_treeconnect(ssp, scred);
843 else
844 error = smb_smb_treeconnect(ssp, scred);
845 SMB_SS_LOCK(ssp);
846
847 ssp->ss_flags &= ~SMBS_RECONNECTING;
848
849 /* They can all go ahead! */
850 if (ssp->ss_conn_waiters)
851 cv_broadcast(&ssp->ss_conn_done);
852
853 out:
854 SMB_SS_UNLOCK(ssp);
855
856 return (error);
857 }
858
859 /*
860 * File handle level functions
861 */
862
863 void
864 smb_fh_hold(struct smb_fh *fhp)
865 {
866 smb_co_hold(FHTOCP(fhp));
867 }
868
869 void
870 smb_fh_rele(struct smb_fh *fhp)
871 {
872 smb_co_rele(FHTOCP(fhp));
873 }
874
875 void
876 smb_fh_close(struct smb_fh *fhp)
877 {
878 smb_co_kill(FHTOCP(fhp));
879 }
880
881 /*
882 * Normally called via smb_fh_rele()
883 * after co_usecount drops to zero.
884 * Also called via: smb_fh_kill()
885 */
886 static void
887 smb_fh_gone(struct smb_connobj *cp)
888 {
889 struct smb_cred scred;
890 struct smb_fh *fhp = CPTOFH(cp);
891 smb_share_t *ssp = FHTOSS(fhp);
892 int err;
893
894 if ((fhp->fh_flags & SMBFH_VALID) == 0)
895 return;
896
897 /*
898 * We have no durable handles (yet) so if there has been a
899 * reconnect, don't bother to close this handle.
900 */
901 if (fhp->fh_vcgenid != ssp->ss_vcgenid)
902 return;
903
904 smb_credinit(&scred, NULL);
905 err = smb_smb_close(ssp, fhp, &scred);
906 smb_credrele(&scred);
907 if (err) {
908 SMBSDEBUG("close err=%d\n", err);
909 }
910 }
911
912 /*
913 * Normally called via smb_fh_rele()
914 * after co_usecount drops to zero.
915 */
916 static void
917 smb_fh_free(struct smb_connobj *cp)
918 {
919 struct smb_fh *fhp = CPTOFH(cp);
920
921 smb_co_done(FHTOCP(fhp));
922 kmem_free(fhp, sizeof (*fhp));
923 }
924
925 /*
926 * Allocate fh structure and attach it to the given share.
927 * Share expected to be locked on entry.
928 */
929 /*ARGSUSED*/
930 int
931 smb_fh_create(smb_share_t *ssp, struct smb_fh **fhpp)
932 {
933 static char objtype[] = "smb_fh";
934 struct smb_fh *fhp;
935
936 fhp = kmem_zalloc(sizeof (struct smb_fh), KM_SLEEP);
937 smb_co_init(FHTOCP(fhp), SMBL_FH, objtype);
938 fhp->fh_co.co_free = smb_fh_free;
939 fhp->fh_co.co_gone = smb_fh_gone;
940
941 SMB_SS_LOCK(ssp);
942 if ((ssp->ss_flags & SMBS_GONE) != 0) {
943 SMB_SS_UNLOCK(ssp);
944 smb_fh_free(FHTOCP(fhp));
945 return (ENOTCONN);
946 }
947
948 smb_co_addchild(SSTOCP(ssp), FHTOCP(fhp));
949 *fhpp = fhp;
950 SMB_SS_UNLOCK(ssp);
951
952 return (0);
953 }
954
955 void
956 smb_fh_opened(struct smb_fh *fhp)
957 {
958 smb_share_t *ssp = FHTOSS(fhp);
959
960 SMB_FH_LOCK(fhp);
961 fhp->fh_vcgenid = ssp->ss_vcgenid;
962 fhp->fh_flags |= SMBFH_VALID;
963 SMB_FH_UNLOCK(fhp);
964 }
965
966
967 /*
968 * Solaris zones support
969 */
970 /*ARGSUSED*/
971 void
972 lingering_vc(struct smb_vc *vc)
973 {
974 /* good place for a breakpoint */
975 DEBUG_ENTER("lingering VC");
976 }
977
978 /*
979 * On zone shutdown, kill any IOD threads still running in this zone.
980 */
981 /* ARGSUSED */
982 void
983 nsmb_zone_shutdown(zoneid_t zoneid, void *data)
984 {
985 struct smb_connobj *co;
986 struct smb_vc *vcp;
987
|