2 * Copyright (c) 2000-2001 Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
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
32 * $Id: smb_usr.c,v 1.15 2004/12/13 00:25:18 lindak Exp $
36 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
37 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
38 * Use is subject to license terms.
41 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/policy.h>
47 #include <sys/fcntl.h>
49 #include <sys/socket.h>
50 #include <sys/sunddi.h>
51 #include <sys/cmn_err.h>
53 #include <netsmb/smb_osdep.h>
55 #include <netsmb/smb.h>
56 #include <netsmb/smb_conn.h>
57 #include <netsmb/smb_rq.h>
58 #include <netsmb/smb_subr.h>
59 #include <netsmb/smb_dev.h>
61 static int smb_cpdatain(struct mbchain
*mbp
, int len
, char *data
, int seg
);
64 * Ioctl function for SMBIOC_FLAGS2
67 smb_usr_get_flags2(smb_dev_t
*sdp
, intptr_t arg
, int flags
)
69 struct smb_vc
*vcp
= NULL
;
71 /* This ioctl requires a session. */
72 if ((vcp
= sdp
->sd_vc
) == NULL
)
76 * Return the flags2 value.
78 if (ddi_copyout(&vcp
->vc_hflags2
, (void *)arg
,
79 sizeof (u_int16_t
), flags
))
86 * Ioctl function for SMBIOC_GETSSNKEY
87 * Size copied out is SMBIOC_HASH_SZ.
89 * The RPC library needs this for encrypting things
90 * like "set password" requests. This is called
91 * with an active RPC binding, so the connection
92 * will already be active (but this checks).
95 smb_usr_get_ssnkey(smb_dev_t
*sdp
, intptr_t arg
, int flags
)
97 struct smb_vc
*vcp
= NULL
;
99 /* This ioctl requires an active session. */
100 if ((vcp
= sdp
->sd_vc
) == NULL
)
102 if (vcp
->vc_state
!= SMBIOD_ST_VCACTIVE
)
106 * Return the session key.
108 if (ddi_copyout(vcp
->vc_ssn_key
, (void *)arg
,
109 SMBIOC_HASH_SZ
, flags
))
116 * Ioctl function for SMBIOC_REQUEST
119 smb_usr_simplerq(smb_dev_t
*sdp
, intptr_t arg
, int flags
, cred_t
*cr
)
121 struct smb_cred scred
;
122 struct smb_share
*ssp
;
123 smbioc_rq_t
*ioc
= NULL
;
124 struct smb_rq
*rqp
= NULL
;
130 /* This ioctl requires a share. */
131 if ((ssp
= sdp
->sd_share
) == NULL
)
134 smb_credinit(&scred
, cr
);
135 ioc
= kmem_alloc(sizeof (*ioc
), KM_SLEEP
);
136 if (ddi_copyin((void *) arg
, ioc
, sizeof (*ioc
), flags
)) {
141 /* See ddi_copyin, ddi_copyout */
142 mbseg
= (flags
& FKIOCTL
) ? MB_MSYSTEM
: MB_MUSER
;
145 * Lots of SMB commands could be safe, but
146 * these are the only ones used by libsmbfs.
148 switch (ioc
->ioc_cmd
) {
152 case SMB_COM_NT_CREATE_ANDX
:
153 case SMB_COM_OPEN_PRINT_FILE
:
154 case SMB_COM_CLOSE_PRINT_FILE
:
162 err
= smb_rq_alloc(SSTOCP(ssp
), ioc
->ioc_cmd
, &scred
, &rqp
);
167 err
= mb_put_mem(mbp
, ioc
->ioc_tbuf
, ioc
->ioc_tbufsz
, mbseg
);
169 err
= smb_rq_simple(rqp
);
172 * This may have been an open, so save the
173 * generation ID of the share, which we
174 * check before trying read or write.
176 sdp
->sd_vcgenid
= ssp
->ss_vcgenid
;
179 * Have reply data. to copyout.
180 * SMB header already parsed.
183 rsz
= msgdsize(mdp
->md_top
) - SMB_HDRLEN
;
184 if (ioc
->ioc_rbufsz
< rsz
) {
188 ioc
->ioc_rbufsz
= rsz
;
189 err
= md_get_mem(mdp
, ioc
->ioc_rbuf
, rsz
, mbseg
);
195 ioc
->ioc_errclass
= rqp
->sr_errclass
;
196 ioc
->ioc_serror
= rqp
->sr_serror
;
197 ioc
->ioc_error
= rqp
->sr_error
;
198 (void) ddi_copyout(ioc
, (void *)arg
, sizeof (*ioc
), flags
);
202 smb_rq_done(rqp
); /* free rqp */
203 kmem_free(ioc
, sizeof (*ioc
));
204 smb_credrele(&scred
);
211 * Ioctl function for SMBIOC_T2RQ
214 smb_usr_t2request(smb_dev_t
*sdp
, intptr_t arg
, int flags
, cred_t
*cr
)
216 struct smb_cred scred
;
217 struct smb_share
*ssp
;
218 smbioc_t2rq_t
*ioc
= NULL
;
219 struct smb_t2rq
*t2p
= NULL
;
223 /* This ioctl requires a share. */
224 if ((ssp
= sdp
->sd_share
) == NULL
)
227 smb_credinit(&scred
, cr
);
228 ioc
= kmem_alloc(sizeof (*ioc
), KM_SLEEP
);
229 if (ddi_copyin((void *) arg
, ioc
, sizeof (*ioc
), flags
)) {
234 /* See ddi_copyin, ddi_copyout */
235 mbseg
= (flags
& FKIOCTL
) ? MB_MSYSTEM
: MB_MUSER
;
237 if (ioc
->ioc_setupcnt
> SMBIOC_T2RQ_MAXSETUP
) {
243 * Fill in the FID for libsmbfs transact named pipe.
245 if (ioc
->ioc_setupcnt
> 1 && ioc
->ioc_setup
[1] == 0xFFFF) {
246 if (sdp
->sd_vcgenid
!= ssp
->ss_vcgenid
) {
250 ioc
->ioc_setup
[1] = (uint16_t)sdp
->sd_smbfid
;
253 t2p
= kmem_alloc(sizeof (*t2p
), KM_SLEEP
);
254 err
= smb_t2_init(t2p
, SSTOCP(ssp
),
255 ioc
->ioc_setup
, ioc
->ioc_setupcnt
, &scred
);
258 t2p
->t2_setupcount
= ioc
->ioc_setupcnt
;
259 t2p
->t2_setupdata
= ioc
->ioc_setup
;
261 /* This ioc member is a fixed-size array. */
262 if (ioc
->ioc_name
[0]) {
263 /* Get the name length - carefully! */
264 ioc
->ioc_name
[SMBIOC_T2RQ_MAXNAME
-1] = '\0';
265 t2p
->t_name_len
= strlen(ioc
->ioc_name
);
266 t2p
->t_name
= ioc
->ioc_name
;
268 t2p
->t2_maxscount
= 0;
269 t2p
->t2_maxpcount
= ioc
->ioc_rparamcnt
;
270 t2p
->t2_maxdcount
= ioc
->ioc_rdatacnt
;
272 /* Transmit parameters */
273 err
= smb_cpdatain(&t2p
->t2_tparam
,
274 ioc
->ioc_tparamcnt
, ioc
->ioc_tparam
, mbseg
);
279 err
= smb_cpdatain(&t2p
->t2_tdata
,
280 ioc
->ioc_tdatacnt
, ioc
->ioc_tdata
, mbseg
);
284 err
= smb_t2_request(t2p
);
286 /* Copyout returned parameters. */
287 mdp
= &t2p
->t2_rparam
;
288 if (err
== 0 && mdp
->md_top
!= NULL
) {
289 /* User's buffer large enough? */
290 len
= m_fixhdr(mdp
->md_top
);
291 if (len
> ioc
->ioc_rparamcnt
) {
295 ioc
->ioc_rparamcnt
= (ushort_t
)len
;
296 err
= md_get_mem(mdp
, ioc
->ioc_rparam
, len
, mbseg
);
300 ioc
->ioc_rparamcnt
= 0;
302 /* Copyout returned data. */
303 mdp
= &t2p
->t2_rdata
;
304 if (err
== 0 && mdp
->md_top
!= NULL
) {
305 /* User's buffer large enough? */
306 len
= m_fixhdr(mdp
->md_top
);
307 if (len
> ioc
->ioc_rdatacnt
) {
311 ioc
->ioc_rdatacnt
= (ushort_t
)len
;
312 err
= md_get_mem(mdp
, ioc
->ioc_rdata
, len
, mbseg
);
316 ioc
->ioc_rdatacnt
= 0;
318 ioc
->ioc_errclass
= t2p
->t2_sr_errclass
;
319 ioc
->ioc_serror
= t2p
->t2_sr_serror
;
320 ioc
->ioc_error
= t2p
->t2_sr_error
;
321 ioc
->ioc_rpflags2
= t2p
->t2_sr_rpflags2
;
323 (void) ddi_copyout(ioc
, (void *)arg
, sizeof (*ioc
), flags
);
328 /* Note: t2p->t_name no longer allocated */
330 kmem_free(t2p
, sizeof (*t2p
));
332 kmem_free(ioc
, sizeof (*ioc
));
333 smb_credrele(&scred
);
338 /* helper for _t2request */
340 smb_cpdatain(struct mbchain
*mbp
, int len
, char *data
, int mbseg
)
346 error
= mb_init(mbp
);
349 return (mb_put_mem(mbp
, data
, len
, mbseg
));
353 * Helper for nsmb_ioctl cases
354 * SMBIOC_READ, SMBIOC_WRITE
357 smb_usr_rw(smb_dev_t
*sdp
, int cmd
, intptr_t arg
, int flags
, cred_t
*cr
)
359 struct smb_cred scred
;
360 struct smb_share
*ssp
;
361 smbioc_rw_t
*ioc
= NULL
;
362 struct iovec aiov
[1];
368 /* This ioctl requires a share. */
369 if ((ssp
= sdp
->sd_share
) == NULL
)
372 /* After reconnect, force close+reopen */
373 if (sdp
->sd_vcgenid
!= ssp
->ss_vcgenid
)
376 smb_credinit(&scred
, cr
);
377 ioc
= kmem_alloc(sizeof (*ioc
), KM_SLEEP
);
378 if (ddi_copyin((void *) arg
, ioc
, sizeof (*ioc
), flags
)) {
396 * If caller passes -1 in ioc_fh, then
397 * use the FID from SMBIOC_NTCREATE.
399 if (ioc
->ioc_fh
== -1)
400 fh
= (uint16_t)sdp
->sd_smbfid
;
402 fh
= (uint16_t)ioc
->ioc_fh
;
404 aiov
[0].iov_base
= ioc
->ioc_base
;
405 aiov
[0].iov_len
= (size_t)ioc
->ioc_cnt
;
409 auio
.uio_loffset
= ioc
->ioc_offset
;
410 auio
.uio_segflg
= (flags
& FKIOCTL
) ?
411 UIO_SYSSPACE
: UIO_USERSPACE
;
413 auio
.uio_resid
= (size_t)ioc
->ioc_cnt
;
415 err
= smb_rwuio(ssp
, fh
, rw
, &auio
, &scred
, 0);
418 * On return ioc_cnt holds the
419 * number of bytes transferred.
421 ioc
->ioc_cnt
-= auio
.uio_resid
;
423 (void) ddi_copyout(ioc
, (void *)arg
, sizeof (*ioc
), flags
);
426 kmem_free(ioc
, sizeof (*ioc
));
427 smb_credrele(&scred
);
433 * Helper for nsmb_ioctl case
437 smb_usr_ntcreate(smb_dev_t
*sdp
, intptr_t arg
, int flags
, cred_t
*cr
)
439 struct smb_cred scred
;
440 struct mbchain name_mb
;
441 struct smb_share
*ssp
;
442 smbioc_ntcreate_t
*ioc
= NULL
;
446 /* This ioctl requires a share. */
447 if ((ssp
= sdp
->sd_share
) == NULL
)
450 /* Must not be already open. */
451 if (sdp
->sd_smbfid
!= -1)
455 smb_credinit(&scred
, cr
);
456 ioc
= kmem_alloc(sizeof (*ioc
), KM_SLEEP
);
457 if (ddi_copyin((void *) arg
, ioc
, sizeof (*ioc
), flags
)) {
463 ioc
->ioc_name
[SMBIOC_MAX_NAME
-1] = '\0';
464 nmlen
= strnlen(ioc
->ioc_name
, SMBIOC_MAX_NAME
-1);
465 err
= smb_put_dmem(&name_mb
, SSTOVC(ssp
),
466 ioc
->ioc_name
, nmlen
,
471 /* Do the OtW open, save the FID. */
472 err
= smb_smb_ntcreate(ssp
, &name_mb
,
473 0, /* create flags */
479 NTCREATEX_IMPERSONATION_IMPERSONATION
,
487 sdp
->sd_smbfid
= fid
;
488 sdp
->sd_vcgenid
= ssp
->ss_vcgenid
;
491 kmem_free(ioc
, sizeof (*ioc
));
492 smb_credrele(&scred
);
499 * Helper for nsmb_ioctl case
503 smb_usr_printjob(smb_dev_t
*sdp
, intptr_t arg
, int flags
, cred_t
*cr
)
505 struct smb_cred scred
;
506 struct smb_share
*ssp
;
507 smbioc_printjob_t
*ioc
= NULL
;
511 /* This ioctl requires a share. */
512 if ((ssp
= sdp
->sd_share
) == NULL
)
515 /* The share must be a print queue. */
516 if (ssp
->ss_type
!= STYPE_PRINTQ
)
519 /* Must not be already open. */
520 if (sdp
->sd_smbfid
!= -1)
523 smb_credinit(&scred
, cr
);
524 ioc
= kmem_alloc(sizeof (*ioc
), KM_SLEEP
);
525 if (ddi_copyin((void *) arg
, ioc
, sizeof (*ioc
), flags
)) {
529 ioc
->ioc_title
[SMBIOC_MAX_NAME
-1] = '\0';
531 /* Do the OtW open, save the FID. */
532 err
= smb_smb_open_prjob(ssp
, ioc
->ioc_title
,
533 ioc
->ioc_setuplen
, ioc
->ioc_prmode
,
538 sdp
->sd_smbfid
= fid
;
539 sdp
->sd_vcgenid
= ssp
->ss_vcgenid
;
542 kmem_free(ioc
, sizeof (*ioc
));
543 smb_credrele(&scred
);
549 * Helper for nsmb_ioctl case
553 smb_usr_closefh(smb_dev_t
*sdp
, cred_t
*cr
)
555 struct smb_cred scred
;
556 struct smb_share
*ssp
;
560 /* This ioctl requires a share. */
561 if ((ssp
= sdp
->sd_share
) == NULL
)
564 if (sdp
->sd_smbfid
== -1)
566 fid
= (uint16_t)sdp
->sd_smbfid
;
569 smb_credinit(&scred
, cr
);
570 if (ssp
->ss_type
== STYPE_PRINTQ
)
571 err
= smb_smb_close_prjob(ssp
, fid
, &scred
);
573 err
= smb_smb_close(ssp
, fid
, NULL
, &scred
);
574 smb_credrele(&scred
);
580 * Ioctl functions: SMBIOC_SSN_FIND, SMBIOC_SSN_CREATE
581 * Find or create a session (a.k.a. "VC" in here)
584 smb_usr_get_ssn(smb_dev_t
*sdp
, int cmd
, intptr_t arg
, int flags
, cred_t
*cr
)
586 struct smb_cred scred
;
587 smbioc_ossn_t
*ossn
= NULL
;
588 struct smb_vc
*vcp
= NULL
;
592 /* Should be no VC */
593 if (sdp
->sd_vc
!= NULL
)
596 smb_credinit(&scred
, cr
);
597 ossn
= kmem_alloc(sizeof (*ossn
), KM_SLEEP
);
598 if (ddi_copyin((void *)arg
, ossn
, sizeof (*ossn
), flags
)) {
604 * Only superuser can specify a UID or GID.
606 realuid
= crgetruid(cr
);
607 if (ossn
->ssn_owner
== SMBM_ANY_OWNER
)
608 ossn
->ssn_owner
= realuid
;
611 * Do we have the privilege to create with the
612 * specified uid? (does uid == cr->cr_uid, etc.)
614 if (secpolicy_vnode_owner(cr
, ossn
->ssn_owner
)) {
618 /* ossn->ssn_owner is OK */
622 * Make sure the strings are null terminated.
624 ossn
->ssn_srvname
[SMBIOC_MAX_NAME
-1] = '\0';
625 ossn
->ssn_id
.id_domain
[ SMBIOC_MAX_NAME
-1] = '\0';
626 ossn
->ssn_id
.id_user
[ SMBIOC_MAX_NAME
-1] = '\0';
628 if (cmd
== SMBIOC_SSN_CREATE
)
629 ossn
->ssn_vopt
|= SMBVOPT_CREATE
;
631 ossn
->ssn_vopt
&= ~SMBVOPT_CREATE
;
633 error
= smb_vc_findcreate(ossn
, &scred
, &vcp
);
639 * We have a VC, held, but not locked.
640 * If we're creating, mark this instance as
641 * an open from IOD so close can do cleanup.
643 * XXX: Would be nice to have a back pointer
644 * from the VC to this (IOD) sdp instance.
646 if (cmd
== SMBIOC_SSN_CREATE
) {
647 if (vcp
->iod_thr
!= NULL
) {
651 sdp
->sd_flags
|= NSMBFL_IOD
;
654 * Wait for it to finish connecting
655 * (or reconnect) if necessary.
657 if (vcp
->vc_state
!= SMBIOD_ST_VCACTIVE
) {
658 error
= smb_iod_reconnect(vcp
);
665 * The VC has a hold from _findvc
666 * which we keep until _SSN_RELE
669 sdp
->sd_level
= SMBL_VC
;
672 (void) ddi_copyout(ossn
, (void *)arg
, sizeof (*ossn
), flags
);
676 /* Error path: rele hold from _findcreate */
679 kmem_free(ossn
, sizeof (*ossn
));
680 smb_credrele(&scred
);
686 * Ioctl functions: SMBIOC_SSN_RELE, SMBIOC_SSN_KILL
687 * Release or kill the current session.
690 smb_usr_drop_ssn(smb_dev_t
*sdp
, int cmd
)
692 struct smb_vc
*vcp
= NULL
;
694 /* Must have a VC. */
695 if ((vcp
= sdp
->sd_vc
) == NULL
)
698 /* If we have a share ref, drop it too. */
700 smb_share_rele(sdp
->sd_share
);
701 sdp
->sd_share
= NULL
;
702 sdp
->sd_level
= SMBL_VC
;
705 if (cmd
== SMBIOC_SSN_KILL
)
708 /* Drop the VC ref. */
717 * Find or create a tree (connected share)
720 smb_usr_get_tree(smb_dev_t
*sdp
, int cmd
, intptr_t arg
, int flags
, cred_t
*cr
)
722 struct smb_cred scred
;
723 smbioc_tcon_t
*tcon
= NULL
;
724 struct smb_vc
*vcp
= NULL
;
725 struct smb_share
*ssp
= NULL
;
728 /* Must have a VC. */
729 if ((vcp
= sdp
->sd_vc
) == NULL
)
731 /* Should not have a share. */
732 if (sdp
->sd_share
!= NULL
)
735 smb_credinit(&scred
, cr
);
736 tcon
= kmem_alloc(sizeof (*tcon
), KM_SLEEP
);
737 if (ddi_copyin((void *)arg
, tcon
, sizeof (*tcon
), flags
)) {
743 * Make sure the strings are null terminated.
745 tcon
->tc_sh
.sh_name
[SMBIOC_MAX_NAME
-1] = '\0';
746 tcon
->tc_sh
.sh_pass
[SMBIOC_MAX_NAME
-1] = '\0';
748 if (cmd
== SMBIOC_TREE_CONNECT
)
749 tcon
->tc_opt
|= SMBSOPT_CREATE
;
751 tcon
->tc_opt
&= ~SMBSOPT_CREATE
;
753 error
= smb_share_findcreate(tcon
, vcp
, &ssp
, &scred
);
759 * We have a share, held, but not locked.
760 * If we're creating, do tree connect now,
761 * otherwise let that wait for a request.
763 if (cmd
== SMBIOC_TREE_CONNECT
) {
764 error
= smb_share_tcon(ssp
, &scred
);
770 * Give caller the real share type from
771 * the tree connect response, so they can
772 * see if they got the requested type.
774 tcon
->tc_sh
.sh_type
= ssp
->ss_type
;
777 * The share has a hold from _tcon
778 * which we keep until nsmb_close()
779 * or the SMBIOC_TDIS below.
781 sdp
->sd_level
= SMBL_SHARE
;
784 (void) ddi_copyout(tcon
, (void *)arg
, sizeof (*tcon
), flags
);
788 /* Error path: rele hold from _findcreate */
792 * This structure may contain a
793 * cleartext password, so zap it.
795 bzero(tcon
, sizeof (*tcon
));
796 kmem_free(tcon
, sizeof (*tcon
));
797 smb_credrele(&scred
);
803 * Ioctl functions: SMBIOC_TREE_RELE, SMBIOC_TREE_KILL
804 * Release or kill the current tree
807 smb_usr_drop_tree(smb_dev_t
*sdp
, int cmd
)
809 struct smb_share
*ssp
= NULL
;
811 /* Must have a VC and a share. */
812 if (sdp
->sd_vc
== NULL
)
814 if ((ssp
= sdp
->sd_share
) == NULL
)
817 if (cmd
== SMBIOC_TREE_KILL
)
820 /* Drop the share ref. */
821 smb_share_rele(sdp
->sd_share
);
822 sdp
->sd_share
= NULL
;
823 sdp
->sd_level
= SMBL_VC
;
830 * Ioctl function: SMBIOC_IOD_WORK
832 * Become the reader (IOD) thread, until either the connection is
833 * reset by the server, or until the connection is idle longer than
834 * some max time. (max idle time not yet implemented)
837 smb_usr_iod_work(smb_dev_t
*sdp
, intptr_t arg
, int flags
, cred_t
*cr
)
839 struct smb_vc
*vcp
= NULL
;
842 /* Must have a valid session. */
843 if ((vcp
= sdp
->sd_vc
) == NULL
)
845 if (vcp
->vc_flags
& SMBV_GONE
)
849 * Is there already an IOD for this VC?
850 * (Should never happen.)
853 if (vcp
->iod_thr
== NULL
)
854 vcp
->iod_thr
= curthread
;
862 * Copy the "work" state, etc. into the VC
863 * The MAC key is copied separately.
865 if (ddi_copyin((void *)arg
, &vcp
->vc_work
,
866 sizeof (smbioc_ssn_work_t
), flags
)) {
870 if (vcp
->vc_u_maclen
) {
871 vcp
->vc_mackeylen
= vcp
->vc_u_maclen
;
872 vcp
->vc_mackey
= kmem_alloc(vcp
->vc_mackeylen
, KM_SLEEP
);
873 if (ddi_copyin(vcp
->vc_u_mackey
.lp_ptr
, vcp
->vc_mackey
,
874 vcp
->vc_mackeylen
, flags
)) {
880 err
= smb_iod_vc_work(vcp
, cr
);
882 /* Caller wants state here. */
883 vcp
->vc_work
.wk_out_state
= vcp
->vc_state
;
885 (void) ddi_copyout(&vcp
->vc_work
, (void *)arg
,
886 sizeof (smbioc_ssn_work_t
), flags
);
889 if (vcp
->vc_mackey
) {
890 kmem_free(vcp
->vc_mackey
, vcp
->vc_mackeylen
);
891 vcp
->vc_mackey
= NULL
;
892 vcp
->vc_mackeylen
= 0;
896 * The IOD thread is leaving the driver. Clear iod_thr,
897 * and wake up anybody waiting for us to quit.
901 cv_broadcast(&vcp
->vc_statechg
);
908 * Ioctl functions: SMBIOC_IOD_IDLE, SMBIOC_IOD_RCFAIL
910 * Wait for user-level requests to be enqueued on this session,
911 * and then return to the user-space helper, which will then
912 * initiate a reconnect, etc.
915 smb_usr_iod_ioctl(smb_dev_t
*sdp
, int cmd
, intptr_t arg
, int flags
)
917 struct smb_vc
*vcp
= NULL
;
920 /* Must have a valid session. */
921 if ((vcp
= sdp
->sd_vc
) == NULL
)
923 if (vcp
->vc_flags
& SMBV_GONE
)
927 * Is there already an IOD for this VC?
928 * (Should never happen.)
931 if (vcp
->iod_thr
== NULL
)
932 vcp
->iod_thr
= curthread
;
939 /* nothing to copyin */
942 case SMBIOC_IOD_IDLE
:
943 err
= smb_iod_vc_idle(vcp
);
946 case SMBIOC_IOD_RCFAIL
:
947 err
= smb_iod_vc_rcfail(vcp
);
955 /* Both of these ioctls copy out the new state. */
956 (void) ddi_copyout(&vcp
->vc_state
, (void *)arg
,
957 sizeof (int), flags
);
961 * The IOD thread is leaving the driver. Clear iod_thr,
962 * and wake up anybody waiting for us to quit.
966 cv_broadcast(&vcp
->vc_statechg
);