14bff34e3Sthurlow /* 24bff34e3Sthurlow * Copyright (c) 2000-2001 Boris Popov 34bff34e3Sthurlow * All rights reserved. 44bff34e3Sthurlow * 54bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 64bff34e3Sthurlow * modification, are permitted provided that the following conditions 74bff34e3Sthurlow * are met: 84bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 94bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 104bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 114bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 124bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 134bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 144bff34e3Sthurlow * must display the following acknowledgement: 154bff34e3Sthurlow * This product includes software developed by Boris Popov. 164bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 174bff34e3Sthurlow * may be used to endorse or promote products derived from this software 184bff34e3Sthurlow * without specific prior written permission. 194bff34e3Sthurlow * 204bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 214bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 244bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304bff34e3Sthurlow * SUCH DAMAGE. 314bff34e3Sthurlow * 324bff34e3Sthurlow * $Id: smb_usr.c,v 1.15 2004/12/13 00:25:18 lindak Exp $ 334bff34e3Sthurlow */ 344bff34e3Sthurlow 359c9af259SGordon Ross /* 36613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 379c9af259SGordon Ross * Use is subject to license terms. 38*40c0e231SGordon Ross * 39*40c0e231SGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 409c9af259SGordon Ross */ 414bff34e3Sthurlow 424bff34e3Sthurlow #include <sys/param.h> 434bff34e3Sthurlow #include <sys/kmem.h> 444bff34e3Sthurlow #include <sys/systm.h> 454bff34e3Sthurlow #include <sys/policy.h> 464bff34e3Sthurlow #include <sys/conf.h> 474bff34e3Sthurlow #include <sys/proc.h> 484bff34e3Sthurlow #include <sys/fcntl.h> 49613a2f6bSGordon Ross #include <sys/file.h> 504bff34e3Sthurlow #include <sys/socket.h> 51613a2f6bSGordon Ross #include <sys/sunddi.h> 524bff34e3Sthurlow #include <sys/cmn_err.h> 534bff34e3Sthurlow 544bff34e3Sthurlow #include <netsmb/smb_osdep.h> 554bff34e3Sthurlow 564bff34e3Sthurlow #include <netsmb/smb.h> 574bff34e3Sthurlow #include <netsmb/smb_conn.h> 584bff34e3Sthurlow #include <netsmb/smb_rq.h> 594bff34e3Sthurlow #include <netsmb/smb_subr.h> 604bff34e3Sthurlow #include <netsmb/smb_dev.h> 614bff34e3Sthurlow 62613a2f6bSGordon Ross static int smb_cpdatain(struct mbchain *mbp, int len, char *data, int seg); 63613a2f6bSGordon Ross 644bff34e3Sthurlow /* 65613a2f6bSGordon Ross * Ioctl function for SMBIOC_GETSSNKEY 66613a2f6bSGordon Ross * Size copied out is SMBIOC_HASH_SZ. 67613a2f6bSGordon Ross * 68613a2f6bSGordon Ross * The RPC library needs this for encrypting things 69613a2f6bSGordon Ross * like "set password" requests. This is called 70613a2f6bSGordon Ross * with an active RPC binding, so the connection 71613a2f6bSGordon Ross * will already be active (but this checks). 724bff34e3Sthurlow */ 73613a2f6bSGordon Ross int 74613a2f6bSGordon Ross smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags) 754bff34e3Sthurlow { 76613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 77613a2f6bSGordon Ross 78613a2f6bSGordon Ross /* This ioctl requires an active session. */ 79613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 80613a2f6bSGordon Ross return (ENOTCONN); 81613a2f6bSGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) 82613a2f6bSGordon Ross return (ENOTCONN); 834bff34e3Sthurlow 844bff34e3Sthurlow /* 85613a2f6bSGordon Ross * Return the session key. 864bff34e3Sthurlow */ 87*40c0e231SGordon Ross if (vcp->vc_ssnkey == NULL || 88*40c0e231SGordon Ross vcp->vc_ssnkeylen < SMBIOC_HASH_SZ) 89*40c0e231SGordon Ross return (EINVAL); 90*40c0e231SGordon Ross if (ddi_copyout(vcp->vc_ssnkey, (void *)arg, 91613a2f6bSGordon Ross SMBIOC_HASH_SZ, flags)) 92613a2f6bSGordon Ross return (EFAULT); 93613a2f6bSGordon Ross 94613a2f6bSGordon Ross return (0); 95613a2f6bSGordon Ross } 96613a2f6bSGordon Ross 97613a2f6bSGordon Ross /* 98*40c0e231SGordon Ross * Ioctl function for SMBIOC_XACTNP (transact named pipe) 99613a2f6bSGordon Ross */ 100613a2f6bSGordon Ross int 101*40c0e231SGordon Ross smb_usr_xnp(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 1024bff34e3Sthurlow { 103613a2f6bSGordon Ross struct smb_cred scred; 104613a2f6bSGordon Ross struct smb_share *ssp; 105*40c0e231SGordon Ross smbioc_xnp_t *ioc = NULL; 106613a2f6bSGordon Ross struct smb_t2rq *t2p = NULL; 107613a2f6bSGordon Ross struct mdchain *mdp; 108613a2f6bSGordon Ross int err, len, mbseg; 109*40c0e231SGordon Ross uint16_t setup[2]; 110613a2f6bSGordon Ross 111613a2f6bSGordon Ross /* This ioctl requires a share. */ 112613a2f6bSGordon Ross if ((ssp = sdp->sd_share) == NULL) 113613a2f6bSGordon Ross return (ENOTCONN); 1144bff34e3Sthurlow 115613a2f6bSGordon Ross smb_credinit(&scred, cr); 116613a2f6bSGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 117613a2f6bSGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 118613a2f6bSGordon Ross err = EFAULT; 119613a2f6bSGordon Ross goto out; 1204bff34e3Sthurlow } 121613a2f6bSGordon Ross 122613a2f6bSGordon Ross /* See ddi_copyin, ddi_copyout */ 123613a2f6bSGordon Ross mbseg = (flags & FKIOCTL) ? MB_MSYSTEM : MB_MUSER; 124613a2f6bSGordon Ross 125430b4c46SGordon Ross /* 126430b4c46SGordon Ross * Fill in the FID for libsmbfs transact named pipe. 127430b4c46SGordon Ross */ 128*40c0e231SGordon Ross if (ioc->ioc_fh == -1) { 129430b4c46SGordon Ross if (sdp->sd_vcgenid != ssp->ss_vcgenid) { 130430b4c46SGordon Ross err = ESTALE; 131430b4c46SGordon Ross goto out; 132430b4c46SGordon Ross } 133*40c0e231SGordon Ross ioc->ioc_fh = sdp->sd_smbfid; 134430b4c46SGordon Ross } 135430b4c46SGordon Ross 136*40c0e231SGordon Ross setup[0] = TRANS_TRANSACT_NAMED_PIPE; 137*40c0e231SGordon Ross setup[1] = (uint16_t)ioc->ioc_fh; 138*40c0e231SGordon Ross 139613a2f6bSGordon Ross t2p = kmem_alloc(sizeof (*t2p), KM_SLEEP); 140*40c0e231SGordon Ross err = smb_t2_init(t2p, SSTOCP(ssp), setup, 2, &scred); 141613a2f6bSGordon Ross if (err) 142613a2f6bSGordon Ross goto out; 143*40c0e231SGordon Ross t2p->t2_setupcount = 2; 144*40c0e231SGordon Ross t2p->t2_setupdata = setup; 145*40c0e231SGordon Ross 146*40c0e231SGordon Ross t2p->t_name = "\\PIPE\\"; 147*40c0e231SGordon Ross t2p->t_name_len = 6; 148*40c0e231SGordon Ross 149613a2f6bSGordon Ross t2p->t2_maxscount = 0; 150*40c0e231SGordon Ross t2p->t2_maxpcount = 0; 151*40c0e231SGordon Ross t2p->t2_maxdcount = ioc->ioc_rdlen; 152613a2f6bSGordon Ross 153*40c0e231SGordon Ross /* Transmit parameters (none) */ 154613a2f6bSGordon Ross 155613a2f6bSGordon Ross /* Transmit data */ 156613a2f6bSGordon Ross err = smb_cpdatain(&t2p->t2_tdata, 157*40c0e231SGordon Ross ioc->ioc_tdlen, ioc->ioc_tdata, mbseg); 158613a2f6bSGordon Ross if (err) 159613a2f6bSGordon Ross goto out; 160613a2f6bSGordon Ross 161613a2f6bSGordon Ross err = smb_t2_request(t2p); 162613a2f6bSGordon Ross 163*40c0e231SGordon Ross /* No returned parameters. */ 164613a2f6bSGordon Ross 165613a2f6bSGordon Ross /* Copyout returned data. */ 166613a2f6bSGordon Ross mdp = &t2p->t2_rdata; 167613a2f6bSGordon Ross if (err == 0 && mdp->md_top != NULL) { 168613a2f6bSGordon Ross /* User's buffer large enough? */ 169613a2f6bSGordon Ross len = m_fixhdr(mdp->md_top); 170*40c0e231SGordon Ross if (len > ioc->ioc_rdlen) { 171613a2f6bSGordon Ross err = EMSGSIZE; 172613a2f6bSGordon Ross goto out; 173613a2f6bSGordon Ross } 174*40c0e231SGordon Ross ioc->ioc_rdlen = (ushort_t)len; 175613a2f6bSGordon Ross err = md_get_mem(mdp, ioc->ioc_rdata, len, mbseg); 176613a2f6bSGordon Ross if (err) 177613a2f6bSGordon Ross goto out; 178613a2f6bSGordon Ross } else 179*40c0e231SGordon Ross ioc->ioc_rdlen = 0; 180613a2f6bSGordon Ross 181*40c0e231SGordon Ross if (t2p->t2_sr_error == NT_STATUS_BUFFER_OVERFLOW) 182*40c0e231SGordon Ross ioc->ioc_more = 1; 183613a2f6bSGordon Ross 18402d09e03SGordon Ross (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags); 185613a2f6bSGordon Ross 186613a2f6bSGordon Ross 187613a2f6bSGordon Ross out: 188613a2f6bSGordon Ross if (t2p != NULL) { 189613a2f6bSGordon Ross /* Note: t2p->t_name no longer allocated */ 190613a2f6bSGordon Ross smb_t2_done(t2p); 191613a2f6bSGordon Ross kmem_free(t2p, sizeof (*t2p)); 192613a2f6bSGordon Ross } 193430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 194613a2f6bSGordon Ross smb_credrele(&scred); 195613a2f6bSGordon Ross 196613a2f6bSGordon Ross return (err); 1974bff34e3Sthurlow } 1984bff34e3Sthurlow 199613a2f6bSGordon Ross /* helper for _t2request */ 2004bff34e3Sthurlow static int 201613a2f6bSGordon Ross smb_cpdatain(struct mbchain *mbp, int len, char *data, int mbseg) 2024bff34e3Sthurlow { 203613a2f6bSGordon Ross int error; 204613a2f6bSGordon Ross 205613a2f6bSGordon Ross if (len == 0) 206613a2f6bSGordon Ross return (0); 207613a2f6bSGordon Ross error = mb_init(mbp); 208613a2f6bSGordon Ross if (error) 209613a2f6bSGordon Ross return (error); 210613a2f6bSGordon Ross return (mb_put_mem(mbp, data, len, mbseg)); 2114bff34e3Sthurlow } 2124bff34e3Sthurlow 213613a2f6bSGordon Ross /* 214613a2f6bSGordon Ross * Helper for nsmb_ioctl cases 215613a2f6bSGordon Ross * SMBIOC_READ, SMBIOC_WRITE 216613a2f6bSGordon Ross */ 2171b34bc4aSbs int 218613a2f6bSGordon Ross smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 2191b34bc4aSbs { 220613a2f6bSGordon Ross struct smb_cred scred; 221613a2f6bSGordon Ross struct smb_share *ssp; 222613a2f6bSGordon Ross smbioc_rw_t *ioc = NULL; 223613a2f6bSGordon Ross struct iovec aiov[1]; 224613a2f6bSGordon Ross struct uio auio; 225430b4c46SGordon Ross uint16_t fh; 226613a2f6bSGordon Ross int err; 227613a2f6bSGordon Ross uio_rw_t rw; 2281b34bc4aSbs 229613a2f6bSGordon Ross /* This ioctl requires a share. */ 230613a2f6bSGordon Ross if ((ssp = sdp->sd_share) == NULL) 231613a2f6bSGordon Ross return (ENOTCONN); 232613a2f6bSGordon Ross 233613a2f6bSGordon Ross /* After reconnect, force close+reopen */ 234613a2f6bSGordon Ross if (sdp->sd_vcgenid != ssp->ss_vcgenid) 235613a2f6bSGordon Ross return (ESTALE); 236613a2f6bSGordon Ross 237613a2f6bSGordon Ross smb_credinit(&scred, cr); 238613a2f6bSGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 239613a2f6bSGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 240613a2f6bSGordon Ross err = EFAULT; 2411b34bc4aSbs goto out; 242613a2f6bSGordon Ross } 243613a2f6bSGordon Ross 244613a2f6bSGordon Ross switch (cmd) { 245613a2f6bSGordon Ross case SMBIOC_READ: 246613a2f6bSGordon Ross rw = UIO_READ; 247613a2f6bSGordon Ross break; 248613a2f6bSGordon Ross case SMBIOC_WRITE: 249613a2f6bSGordon Ross rw = UIO_WRITE; 250613a2f6bSGordon Ross break; 251613a2f6bSGordon Ross default: 252613a2f6bSGordon Ross err = ENODEV; 253613a2f6bSGordon Ross goto out; 254613a2f6bSGordon Ross } 255613a2f6bSGordon Ross 256430b4c46SGordon Ross /* 257430b4c46SGordon Ross * If caller passes -1 in ioc_fh, then 258430b4c46SGordon Ross * use the FID from SMBIOC_NTCREATE. 259430b4c46SGordon Ross */ 260430b4c46SGordon Ross if (ioc->ioc_fh == -1) 261430b4c46SGordon Ross fh = (uint16_t)sdp->sd_smbfid; 262430b4c46SGordon Ross else 263430b4c46SGordon Ross fh = (uint16_t)ioc->ioc_fh; 264613a2f6bSGordon Ross 265613a2f6bSGordon Ross aiov[0].iov_base = ioc->ioc_base; 266613a2f6bSGordon Ross aiov[0].iov_len = (size_t)ioc->ioc_cnt; 267613a2f6bSGordon Ross 268613a2f6bSGordon Ross auio.uio_iov = aiov; 269613a2f6bSGordon Ross auio.uio_iovcnt = 1; 270613a2f6bSGordon Ross auio.uio_loffset = ioc->ioc_offset; 271613a2f6bSGordon Ross auio.uio_segflg = (flags & FKIOCTL) ? 272613a2f6bSGordon Ross UIO_SYSSPACE : UIO_USERSPACE; 273613a2f6bSGordon Ross auio.uio_fmode = 0; 274613a2f6bSGordon Ross auio.uio_resid = (size_t)ioc->ioc_cnt; 275613a2f6bSGordon Ross 276613a2f6bSGordon Ross err = smb_rwuio(ssp, fh, rw, &auio, &scred, 0); 277613a2f6bSGordon Ross 278613a2f6bSGordon Ross /* 279613a2f6bSGordon Ross * On return ioc_cnt holds the 280613a2f6bSGordon Ross * number of bytes transferred. 281613a2f6bSGordon Ross */ 282613a2f6bSGordon Ross ioc->ioc_cnt -= auio.uio_resid; 283613a2f6bSGordon Ross 28402d09e03SGordon Ross (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags); 285613a2f6bSGordon Ross 2861b34bc4aSbs out: 287430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 288430b4c46SGordon Ross smb_credrele(&scred); 289430b4c46SGordon Ross 290430b4c46SGordon Ross return (err); 291430b4c46SGordon Ross } 292430b4c46SGordon Ross 293430b4c46SGordon Ross /* 294430b4c46SGordon Ross * Helper for nsmb_ioctl case 295430b4c46SGordon Ross * SMBIOC_NTCREATE 296430b4c46SGordon Ross */ 297430b4c46SGordon Ross int 298430b4c46SGordon Ross smb_usr_ntcreate(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 299430b4c46SGordon Ross { 300430b4c46SGordon Ross struct smb_cred scred; 301430b4c46SGordon Ross struct mbchain name_mb; 302430b4c46SGordon Ross struct smb_share *ssp; 303430b4c46SGordon Ross smbioc_ntcreate_t *ioc = NULL; 304430b4c46SGordon Ross uint16_t fid; 305430b4c46SGordon Ross int err, nmlen; 306430b4c46SGordon Ross 307430b4c46SGordon Ross /* This ioctl requires a share. */ 308430b4c46SGordon Ross if ((ssp = sdp->sd_share) == NULL) 309430b4c46SGordon Ross return (ENOTCONN); 310430b4c46SGordon Ross 311430b4c46SGordon Ross /* Must not be already open. */ 312430b4c46SGordon Ross if (sdp->sd_smbfid != -1) 313430b4c46SGordon Ross return (EINVAL); 314430b4c46SGordon Ross 315430b4c46SGordon Ross mb_init(&name_mb); 316430b4c46SGordon Ross smb_credinit(&scred, cr); 317430b4c46SGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 318430b4c46SGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 319430b4c46SGordon Ross err = EFAULT; 320430b4c46SGordon Ross goto out; 321430b4c46SGordon Ross } 322430b4c46SGordon Ross 323430b4c46SGordon Ross /* Build name_mb */ 324430b4c46SGordon Ross ioc->ioc_name[SMBIOC_MAX_NAME-1] = '\0'; 325430b4c46SGordon Ross nmlen = strnlen(ioc->ioc_name, SMBIOC_MAX_NAME-1); 326430b4c46SGordon Ross err = smb_put_dmem(&name_mb, SSTOVC(ssp), 327430b4c46SGordon Ross ioc->ioc_name, nmlen, 328430b4c46SGordon Ross SMB_CS_NONE, NULL); 329430b4c46SGordon Ross if (err != 0) 330430b4c46SGordon Ross goto out; 331430b4c46SGordon Ross 332430b4c46SGordon Ross /* Do the OtW open, save the FID. */ 333430b4c46SGordon Ross err = smb_smb_ntcreate(ssp, &name_mb, 334430b4c46SGordon Ross 0, /* create flags */ 335430b4c46SGordon Ross ioc->ioc_req_acc, 336430b4c46SGordon Ross ioc->ioc_efattr, 337430b4c46SGordon Ross ioc->ioc_share_acc, 338430b4c46SGordon Ross ioc->ioc_open_disp, 339430b4c46SGordon Ross ioc->ioc_creat_opts, 340430b4c46SGordon Ross NTCREATEX_IMPERSONATION_IMPERSONATION, 341430b4c46SGordon Ross &scred, 342430b4c46SGordon Ross &fid, 343430b4c46SGordon Ross NULL, 344430b4c46SGordon Ross NULL); 345430b4c46SGordon Ross if (err != 0) 346430b4c46SGordon Ross goto out; 347430b4c46SGordon Ross 348430b4c46SGordon Ross sdp->sd_smbfid = fid; 349430b4c46SGordon Ross sdp->sd_vcgenid = ssp->ss_vcgenid; 350430b4c46SGordon Ross 351430b4c46SGordon Ross out: 352430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 353430b4c46SGordon Ross smb_credrele(&scred); 354430b4c46SGordon Ross mb_done(&name_mb); 355430b4c46SGordon Ross 356430b4c46SGordon Ross return (err); 357430b4c46SGordon Ross } 358430b4c46SGordon Ross 359430b4c46SGordon Ross /* 360430b4c46SGordon Ross * Helper for nsmb_ioctl case 361430b4c46SGordon Ross * SMBIOC_PRINTJOB 362430b4c46SGordon Ross */ 363430b4c46SGordon Ross int 364430b4c46SGordon Ross smb_usr_printjob(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 365430b4c46SGordon Ross { 366430b4c46SGordon Ross struct smb_cred scred; 367430b4c46SGordon Ross struct smb_share *ssp; 368430b4c46SGordon Ross smbioc_printjob_t *ioc = NULL; 369430b4c46SGordon Ross uint16_t fid; 370430b4c46SGordon Ross int err; 371430b4c46SGordon Ross 372430b4c46SGordon Ross /* This ioctl requires a share. */ 373430b4c46SGordon Ross if ((ssp = sdp->sd_share) == NULL) 374430b4c46SGordon Ross return (ENOTCONN); 375430b4c46SGordon Ross 376430b4c46SGordon Ross /* The share must be a print queue. */ 377430b4c46SGordon Ross if (ssp->ss_type != STYPE_PRINTQ) 378430b4c46SGordon Ross return (EINVAL); 379430b4c46SGordon Ross 380430b4c46SGordon Ross /* Must not be already open. */ 381430b4c46SGordon Ross if (sdp->sd_smbfid != -1) 382430b4c46SGordon Ross return (EINVAL); 383430b4c46SGordon Ross 384430b4c46SGordon Ross smb_credinit(&scred, cr); 385430b4c46SGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 386430b4c46SGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 387430b4c46SGordon Ross err = EFAULT; 388430b4c46SGordon Ross goto out; 389430b4c46SGordon Ross } 390430b4c46SGordon Ross ioc->ioc_title[SMBIOC_MAX_NAME-1] = '\0'; 391430b4c46SGordon Ross 392430b4c46SGordon Ross /* Do the OtW open, save the FID. */ 393430b4c46SGordon Ross err = smb_smb_open_prjob(ssp, ioc->ioc_title, 394430b4c46SGordon Ross ioc->ioc_setuplen, ioc->ioc_prmode, 395430b4c46SGordon Ross &scred, &fid); 396430b4c46SGordon Ross if (err != 0) 397430b4c46SGordon Ross goto out; 398430b4c46SGordon Ross 399430b4c46SGordon Ross sdp->sd_smbfid = fid; 400430b4c46SGordon Ross sdp->sd_vcgenid = ssp->ss_vcgenid; 401430b4c46SGordon Ross 402430b4c46SGordon Ross out: 403430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 404430b4c46SGordon Ross smb_credrele(&scred); 405430b4c46SGordon Ross 406430b4c46SGordon Ross return (err); 407430b4c46SGordon Ross } 408430b4c46SGordon Ross 409430b4c46SGordon Ross /* 410430b4c46SGordon Ross * Helper for nsmb_ioctl case 411430b4c46SGordon Ross * SMBIOC_CLOSEFH 412430b4c46SGordon Ross */ 413430b4c46SGordon Ross int 414430b4c46SGordon Ross smb_usr_closefh(smb_dev_t *sdp, cred_t *cr) 415430b4c46SGordon Ross { 416430b4c46SGordon Ross struct smb_cred scred; 417430b4c46SGordon Ross struct smb_share *ssp; 418430b4c46SGordon Ross uint16_t fid; 419430b4c46SGordon Ross int err; 420430b4c46SGordon Ross 421430b4c46SGordon Ross /* This ioctl requires a share. */ 422430b4c46SGordon Ross if ((ssp = sdp->sd_share) == NULL) 423430b4c46SGordon Ross return (ENOTCONN); 424430b4c46SGordon Ross 425430b4c46SGordon Ross if (sdp->sd_smbfid == -1) 426430b4c46SGordon Ross return (0); 427430b4c46SGordon Ross fid = (uint16_t)sdp->sd_smbfid; 428430b4c46SGordon Ross sdp->sd_smbfid = -1; 429430b4c46SGordon Ross 430430b4c46SGordon Ross smb_credinit(&scred, cr); 431430b4c46SGordon Ross if (ssp->ss_type == STYPE_PRINTQ) 432430b4c46SGordon Ross err = smb_smb_close_prjob(ssp, fid, &scred); 433430b4c46SGordon Ross else 434430b4c46SGordon Ross err = smb_smb_close(ssp, fid, NULL, &scred); 435613a2f6bSGordon Ross smb_credrele(&scred); 436613a2f6bSGordon Ross 437613a2f6bSGordon Ross return (err); 4381b34bc4aSbs } 4391b34bc4aSbs 440613a2f6bSGordon Ross /* 441613a2f6bSGordon Ross * Ioctl functions: SMBIOC_SSN_FIND, SMBIOC_SSN_CREATE 442613a2f6bSGordon Ross * Find or create a session (a.k.a. "VC" in here) 443613a2f6bSGordon Ross */ 4444bff34e3Sthurlow int 445613a2f6bSGordon Ross smb_usr_get_ssn(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 4464bff34e3Sthurlow { 447613a2f6bSGordon Ross struct smb_cred scred; 448613a2f6bSGordon Ross smbioc_ossn_t *ossn = NULL; 4494bff34e3Sthurlow struct smb_vc *vcp = NULL; 4504bff34e3Sthurlow int error = 0; 451613a2f6bSGordon Ross uid_t realuid; 4524bff34e3Sthurlow 453613a2f6bSGordon Ross /* Should be no VC */ 454613a2f6bSGordon Ross if (sdp->sd_vc != NULL) 455613a2f6bSGordon Ross return (EISCONN); 456613a2f6bSGordon Ross 457613a2f6bSGordon Ross smb_credinit(&scred, cr); 458613a2f6bSGordon Ross ossn = kmem_alloc(sizeof (*ossn), KM_SLEEP); 459613a2f6bSGordon Ross if (ddi_copyin((void *)arg, ossn, sizeof (*ossn), flags)) { 460613a2f6bSGordon Ross error = EFAULT; 461613a2f6bSGordon Ross goto out; 4624bff34e3Sthurlow } 463613a2f6bSGordon Ross 464613a2f6bSGordon Ross /* 465613a2f6bSGordon Ross * Only superuser can specify a UID or GID. 466613a2f6bSGordon Ross */ 467613a2f6bSGordon Ross realuid = crgetruid(cr); 468613a2f6bSGordon Ross if (ossn->ssn_owner == SMBM_ANY_OWNER) 469613a2f6bSGordon Ross ossn->ssn_owner = realuid; 470613a2f6bSGordon Ross else { 4714bff34e3Sthurlow /* 472613a2f6bSGordon Ross * Do we have the privilege to create with the 473613a2f6bSGordon Ross * specified uid? (does uid == cr->cr_uid, etc.) 4744bff34e3Sthurlow */ 475613a2f6bSGordon Ross if (secpolicy_vnode_owner(cr, ossn->ssn_owner)) { 476613a2f6bSGordon Ross error = EPERM; 477613a2f6bSGordon Ross goto out; 4784bff34e3Sthurlow } 479613a2f6bSGordon Ross /* ossn->ssn_owner is OK */ 4804bff34e3Sthurlow } 4814bff34e3Sthurlow 482613a2f6bSGordon Ross /* 483613a2f6bSGordon Ross * Make sure the strings are null terminated. 484613a2f6bSGordon Ross */ 485613a2f6bSGordon Ross ossn->ssn_srvname[SMBIOC_MAX_NAME-1] = '\0'; 486613a2f6bSGordon Ross ossn->ssn_id.id_domain[ SMBIOC_MAX_NAME-1] = '\0'; 487613a2f6bSGordon Ross ossn->ssn_id.id_user[ SMBIOC_MAX_NAME-1] = '\0'; 4884bff34e3Sthurlow 489613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_CREATE) 490613a2f6bSGordon Ross ossn->ssn_vopt |= SMBVOPT_CREATE; 491613a2f6bSGordon Ross else /* FIND */ 492613a2f6bSGordon Ross ossn->ssn_vopt &= ~SMBVOPT_CREATE; 4934bff34e3Sthurlow 494613a2f6bSGordon Ross error = smb_vc_findcreate(ossn, &scred, &vcp); 4954bff34e3Sthurlow if (error) 4964bff34e3Sthurlow goto out; 497613a2f6bSGordon Ross ASSERT(vcp != NULL); 4984bff34e3Sthurlow 4994bff34e3Sthurlow /* 500613a2f6bSGordon Ross * We have a VC, held, but not locked. 501613a2f6bSGordon Ross * If we're creating, mark this instance as 502613a2f6bSGordon Ross * an open from IOD so close can do cleanup. 503613a2f6bSGordon Ross * 504613a2f6bSGordon Ross * XXX: Would be nice to have a back pointer 505613a2f6bSGordon Ross * from the VC to this (IOD) sdp instance. 5064bff34e3Sthurlow */ 507613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_CREATE) { 508613a2f6bSGordon Ross if (vcp->iod_thr != NULL) { 509613a2f6bSGordon Ross error = EEXIST; 510613a2f6bSGordon Ross goto out; 511613a2f6bSGordon Ross } 512613a2f6bSGordon Ross sdp->sd_flags |= NSMBFL_IOD; 513613a2f6bSGordon Ross } else { 514613a2f6bSGordon Ross /* 515613a2f6bSGordon Ross * Wait for it to finish connecting 516613a2f6bSGordon Ross * (or reconnect) if necessary. 517613a2f6bSGordon Ross */ 518613a2f6bSGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 519613a2f6bSGordon Ross error = smb_iod_reconnect(vcp); 520613a2f6bSGordon Ross if (error != 0) 521613a2f6bSGordon Ross goto out; 522613a2f6bSGordon Ross } 523613a2f6bSGordon Ross } 524613a2f6bSGordon Ross 525613a2f6bSGordon Ross /* 526613a2f6bSGordon Ross * The VC has a hold from _findvc 527613a2f6bSGordon Ross * which we keep until _SSN_RELE 528613a2f6bSGordon Ross * or nsmb_close(). 529613a2f6bSGordon Ross */ 530613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 531613a2f6bSGordon Ross sdp->sd_vc = vcp; 532613a2f6bSGordon Ross vcp = NULL; 533613a2f6bSGordon Ross (void) ddi_copyout(ossn, (void *)arg, sizeof (*ossn), flags); 5344bff34e3Sthurlow 5354bff34e3Sthurlow out: 536613a2f6bSGordon Ross if (vcp) { 537613a2f6bSGordon Ross /* Error path: rele hold from _findcreate */ 538613a2f6bSGordon Ross smb_vc_rele(vcp); 539613a2f6bSGordon Ross } 540430b4c46SGordon Ross kmem_free(ossn, sizeof (*ossn)); 541613a2f6bSGordon Ross smb_credrele(&scred); 542613a2f6bSGordon Ross 5434bff34e3Sthurlow return (error); 5444bff34e3Sthurlow } 5454bff34e3Sthurlow 546613a2f6bSGordon Ross /* 547613a2f6bSGordon Ross * Ioctl functions: SMBIOC_SSN_RELE, SMBIOC_SSN_KILL 548613a2f6bSGordon Ross * Release or kill the current session. 549613a2f6bSGordon Ross */ 5504bff34e3Sthurlow int 551613a2f6bSGordon Ross smb_usr_drop_ssn(smb_dev_t *sdp, int cmd) 5524bff34e3Sthurlow { 553613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 5544bff34e3Sthurlow 555613a2f6bSGordon Ross /* Must have a VC. */ 556613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 557613a2f6bSGordon Ross return (ENOTCONN); 5584bff34e3Sthurlow 559613a2f6bSGordon Ross /* If we have a share ref, drop it too. */ 560613a2f6bSGordon Ross if (sdp->sd_share) { 561613a2f6bSGordon Ross smb_share_rele(sdp->sd_share); 562613a2f6bSGordon Ross sdp->sd_share = NULL; 563613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 5644bff34e3Sthurlow } 5654bff34e3Sthurlow 566613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_KILL) 567613a2f6bSGordon Ross smb_vc_kill(vcp); 5684bff34e3Sthurlow 569613a2f6bSGordon Ross /* Drop the VC ref. */ 570613a2f6bSGordon Ross smb_vc_rele(vcp); 571613a2f6bSGordon Ross sdp->sd_vc = NULL; 572613a2f6bSGordon Ross sdp->sd_level = 0; 573613a2f6bSGordon Ross 574613a2f6bSGordon Ross return (0); 5754bff34e3Sthurlow } 5764bff34e3Sthurlow 5774bff34e3Sthurlow /* 578613a2f6bSGordon Ross * Find or create a tree (connected share) 5794bff34e3Sthurlow */ 5804bff34e3Sthurlow int 581613a2f6bSGordon Ross smb_usr_get_tree(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 5824bff34e3Sthurlow { 583613a2f6bSGordon Ross struct smb_cred scred; 584613a2f6bSGordon Ross smbioc_tcon_t *tcon = NULL; 585613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 586613a2f6bSGordon Ross struct smb_share *ssp = NULL; 587613a2f6bSGordon Ross int error = 0; 5884bff34e3Sthurlow 589613a2f6bSGordon Ross /* Must have a VC. */ 590613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 591613a2f6bSGordon Ross return (ENOTCONN); 592613a2f6bSGordon Ross /* Should not have a share. */ 593613a2f6bSGordon Ross if (sdp->sd_share != NULL) 594613a2f6bSGordon Ross return (EISCONN); 595613a2f6bSGordon Ross 596613a2f6bSGordon Ross smb_credinit(&scred, cr); 597613a2f6bSGordon Ross tcon = kmem_alloc(sizeof (*tcon), KM_SLEEP); 598613a2f6bSGordon Ross if (ddi_copyin((void *)arg, tcon, sizeof (*tcon), flags)) { 599613a2f6bSGordon Ross error = EFAULT; 600613a2f6bSGordon Ross goto out; 6014bff34e3Sthurlow } 602613a2f6bSGordon Ross 603613a2f6bSGordon Ross /* 604613a2f6bSGordon Ross * Make sure the strings are null terminated. 605613a2f6bSGordon Ross */ 606613a2f6bSGordon Ross tcon->tc_sh.sh_name[SMBIOC_MAX_NAME-1] = '\0'; 607613a2f6bSGordon Ross tcon->tc_sh.sh_pass[SMBIOC_MAX_NAME-1] = '\0'; 608613a2f6bSGordon Ross 609613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_CONNECT) 610613a2f6bSGordon Ross tcon->tc_opt |= SMBSOPT_CREATE; 611613a2f6bSGordon Ross else /* FIND */ 612613a2f6bSGordon Ross tcon->tc_opt &= ~SMBSOPT_CREATE; 613613a2f6bSGordon Ross 614613a2f6bSGordon Ross error = smb_share_findcreate(tcon, vcp, &ssp, &scred); 6154bff34e3Sthurlow if (error) 616613a2f6bSGordon Ross goto out; 617613a2f6bSGordon Ross ASSERT(ssp != NULL); 618613a2f6bSGordon Ross 619613a2f6bSGordon Ross /* 620613a2f6bSGordon Ross * We have a share, held, but not locked. 621613a2f6bSGordon Ross * If we're creating, do tree connect now, 622613a2f6bSGordon Ross * otherwise let that wait for a request. 623613a2f6bSGordon Ross */ 624613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_CONNECT) { 625613a2f6bSGordon Ross error = smb_share_tcon(ssp, &scred); 626613a2f6bSGordon Ross if (error) 627613a2f6bSGordon Ross goto out; 6284bff34e3Sthurlow } 629613a2f6bSGordon Ross 630613a2f6bSGordon Ross /* 631613a2f6bSGordon Ross * Give caller the real share type from 632613a2f6bSGordon Ross * the tree connect response, so they can 633613a2f6bSGordon Ross * see if they got the requested type. 634613a2f6bSGordon Ross */ 635430b4c46SGordon Ross tcon->tc_sh.sh_type = ssp->ss_type; 636613a2f6bSGordon Ross 637613a2f6bSGordon Ross /* 638613a2f6bSGordon Ross * The share has a hold from _tcon 639613a2f6bSGordon Ross * which we keep until nsmb_close() 640613a2f6bSGordon Ross * or the SMBIOC_TDIS below. 641613a2f6bSGordon Ross */ 642613a2f6bSGordon Ross sdp->sd_level = SMBL_SHARE; 643613a2f6bSGordon Ross sdp->sd_share = ssp; 644613a2f6bSGordon Ross ssp = NULL; 645613a2f6bSGordon Ross (void) ddi_copyout(tcon, (void *)arg, sizeof (*tcon), flags); 646613a2f6bSGordon Ross 647613a2f6bSGordon Ross out: 648613a2f6bSGordon Ross if (ssp) { 649613a2f6bSGordon Ross /* Error path: rele hold from _findcreate */ 650613a2f6bSGordon Ross smb_share_rele(ssp); 6514bff34e3Sthurlow } 652430b4c46SGordon Ross /* 653430b4c46SGordon Ross * This structure may contain a 654430b4c46SGordon Ross * cleartext password, so zap it. 655430b4c46SGordon Ross */ 656430b4c46SGordon Ross bzero(tcon, sizeof (*tcon)); 657430b4c46SGordon Ross kmem_free(tcon, sizeof (*tcon)); 658613a2f6bSGordon Ross smb_credrele(&scred); 6594bff34e3Sthurlow 660613a2f6bSGordon Ross return (error); 6614bff34e3Sthurlow } 6624bff34e3Sthurlow 663613a2f6bSGordon Ross /* 664613a2f6bSGordon Ross * Ioctl functions: SMBIOC_TREE_RELE, SMBIOC_TREE_KILL 665613a2f6bSGordon Ross * Release or kill the current tree 666613a2f6bSGordon Ross */ 667613a2f6bSGordon Ross int 668613a2f6bSGordon Ross smb_usr_drop_tree(smb_dev_t *sdp, int cmd) 6694bff34e3Sthurlow { 670613a2f6bSGordon Ross struct smb_share *ssp = NULL; 6714bff34e3Sthurlow 672613a2f6bSGordon Ross /* Must have a VC and a share. */ 673613a2f6bSGordon Ross if (sdp->sd_vc == NULL) 674613a2f6bSGordon Ross return (ENOTCONN); 675613a2f6bSGordon Ross if ((ssp = sdp->sd_share) == NULL) 676613a2f6bSGordon Ross return (ENOTCONN); 677613a2f6bSGordon Ross 678613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_KILL) 679613a2f6bSGordon Ross smb_share_kill(ssp); 680613a2f6bSGordon Ross 681613a2f6bSGordon Ross /* Drop the share ref. */ 682613a2f6bSGordon Ross smb_share_rele(sdp->sd_share); 683613a2f6bSGordon Ross sdp->sd_share = NULL; 684613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 685613a2f6bSGordon Ross 686613a2f6bSGordon Ross return (0); 6874bff34e3Sthurlow } 6884bff34e3Sthurlow 689613a2f6bSGordon Ross /* 690*40c0e231SGordon Ross * Ioctl handler for all SMBIOC_IOD_... 691613a2f6bSGordon Ross */ 6924bff34e3Sthurlow int 693*40c0e231SGordon Ross smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 6944bff34e3Sthurlow { 695*40c0e231SGordon Ross struct smb_vc *vcp; 696613a2f6bSGordon Ross int err = 0; 6974bff34e3Sthurlow 698*40c0e231SGordon Ross /* Must be the IOD. */ 699*40c0e231SGordon Ross if ((sdp->sd_flags & NSMBFL_IOD) == 0) 700*40c0e231SGordon Ross return (EINVAL); 701*40c0e231SGordon Ross /* Must have a VC and no share. */ 702613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 7034bff34e3Sthurlow return (EINVAL); 704*40c0e231SGordon Ross if (sdp->sd_share != NULL) 705613a2f6bSGordon Ross return (EINVAL); 706613a2f6bSGordon Ross 707613a2f6bSGordon Ross /* 708613a2f6bSGordon Ross * Is there already an IOD for this VC? 709613a2f6bSGordon Ross * (Should never happen.) 710613a2f6bSGordon Ross */ 711613a2f6bSGordon Ross SMB_VC_LOCK(vcp); 712613a2f6bSGordon Ross if (vcp->iod_thr == NULL) 713613a2f6bSGordon Ross vcp->iod_thr = curthread; 714613a2f6bSGordon Ross else 715613a2f6bSGordon Ross err = EEXIST; 716613a2f6bSGordon Ross SMB_VC_UNLOCK(vcp); 717613a2f6bSGordon Ross if (err) 718613a2f6bSGordon Ross return (err); 719613a2f6bSGordon Ross 720613a2f6bSGordon Ross /* 721*40c0e231SGordon Ross * Copy the "work" state, etc. into the VC, 722*40c0e231SGordon Ross * and back to the caller on the way out. 723*40c0e231SGordon Ross * Clear the "out only" part. 724613a2f6bSGordon Ross */ 725613a2f6bSGordon Ross if (ddi_copyin((void *)arg, &vcp->vc_work, 726613a2f6bSGordon Ross sizeof (smbioc_ssn_work_t), flags)) { 727613a2f6bSGordon Ross err = EFAULT; 728613a2f6bSGordon Ross goto out; 7294bff34e3Sthurlow } 730*40c0e231SGordon Ross vcp->vc_work.wk_out_state = 0; 731613a2f6bSGordon Ross 732*40c0e231SGordon Ross switch (cmd) { 733613a2f6bSGordon Ross 734*40c0e231SGordon Ross case SMBIOC_IOD_CONNECT: 735*40c0e231SGordon Ross err = nsmb_iod_connect(vcp); 736*40c0e231SGordon Ross break; 737613a2f6bSGordon Ross 738*40c0e231SGordon Ross case SMBIOC_IOD_NEGOTIATE: 739*40c0e231SGordon Ross err = nsmb_iod_negotiate(vcp, cr); 740*40c0e231SGordon Ross break; 741613a2f6bSGordon Ross 742*40c0e231SGordon Ross case SMBIOC_IOD_SSNSETUP: 743*40c0e231SGordon Ross err = nsmb_iod_ssnsetup(vcp, cr); 744*40c0e231SGordon Ross break; 745*40c0e231SGordon Ross 746*40c0e231SGordon Ross case SMBIOC_IOD_WORK: 747*40c0e231SGordon Ross err = smb_iod_vc_work(vcp, flags, cr); 748*40c0e231SGordon Ross break; 749*40c0e231SGordon Ross 750*40c0e231SGordon Ross case SMBIOC_IOD_IDLE: 751*40c0e231SGordon Ross err = smb_iod_vc_idle(vcp); 752*40c0e231SGordon Ross break; 753*40c0e231SGordon Ross 754*40c0e231SGordon Ross case SMBIOC_IOD_RCFAIL: 755*40c0e231SGordon Ross err = smb_iod_vc_rcfail(vcp); 756*40c0e231SGordon Ross break; 757*40c0e231SGordon Ross 758*40c0e231SGordon Ross default: 759*40c0e231SGordon Ross err = ENOTTY; 760*40c0e231SGordon Ross break; 761613a2f6bSGordon Ross } 762613a2f6bSGordon Ross 763*40c0e231SGordon Ross out: 764*40c0e231SGordon Ross vcp->vc_work.wk_out_state = vcp->vc_state; 765*40c0e231SGordon Ross (void) ddi_copyout(&vcp->vc_work, (void *)arg, 766*40c0e231SGordon Ross sizeof (smbioc_ssn_work_t), flags); 767*40c0e231SGordon Ross 768613a2f6bSGordon Ross /* 769613a2f6bSGordon Ross * The IOD thread is leaving the driver. Clear iod_thr, 770613a2f6bSGordon Ross * and wake up anybody waiting for us to quit. 771613a2f6bSGordon Ross */ 772613a2f6bSGordon Ross SMB_VC_LOCK(vcp); 773613a2f6bSGordon Ross vcp->iod_thr = NULL; 774613a2f6bSGordon Ross cv_broadcast(&vcp->vc_statechg); 775613a2f6bSGordon Ross SMB_VC_UNLOCK(vcp); 776613a2f6bSGordon Ross 777613a2f6bSGordon Ross return (err); 7784bff34e3Sthurlow } 7794bff34e3Sthurlow 7804bff34e3Sthurlow int 781*40c0e231SGordon Ross smb_usr_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 7824bff34e3Sthurlow { 783*40c0e231SGordon Ross int err; 784613a2f6bSGordon Ross 785613a2f6bSGordon Ross /* 786*40c0e231SGordon Ross * Serialize ioctl calls. The smb_usr_... functions 787*40c0e231SGordon Ross * don't expect concurrent calls on a given sdp. 788613a2f6bSGordon Ross */ 789*40c0e231SGordon Ross mutex_enter(&sdp->sd_lock); 790*40c0e231SGordon Ross if ((sdp->sd_flags & NSMBFL_IOCTL) != 0) { 791*40c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 792*40c0e231SGordon Ross return (EBUSY); 793*40c0e231SGordon Ross } 794*40c0e231SGordon Ross sdp->sd_flags |= NSMBFL_IOCTL; 795*40c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 7964bff34e3Sthurlow 797*40c0e231SGordon Ross err = 0; 7984bff34e3Sthurlow switch (cmd) { 799*40c0e231SGordon Ross case SMBIOC_GETVERS: 800*40c0e231SGordon Ross (void) ddi_copyout(&nsmb_version, (void *)arg, 801*40c0e231SGordon Ross sizeof (nsmb_version), flags); 802*40c0e231SGordon Ross break; 803*40c0e231SGordon Ross 804*40c0e231SGordon Ross case SMBIOC_GETSSNKEY: 805*40c0e231SGordon Ross err = smb_usr_get_ssnkey(sdp, arg, flags); 806*40c0e231SGordon Ross break; 807*40c0e231SGordon Ross 808*40c0e231SGordon Ross case SMBIOC_DUP_DEV: 809*40c0e231SGordon Ross err = smb_usr_dup_dev(sdp, arg, flags); 810*40c0e231SGordon Ross break; 811*40c0e231SGordon Ross 812*40c0e231SGordon Ross case SMBIOC_XACTNP: 813*40c0e231SGordon Ross err = smb_usr_xnp(sdp, arg, flags, cr); 814*40c0e231SGordon Ross break; 815*40c0e231SGordon Ross 816*40c0e231SGordon Ross case SMBIOC_READ: 817*40c0e231SGordon Ross case SMBIOC_WRITE: 818*40c0e231SGordon Ross err = smb_usr_rw(sdp, cmd, arg, flags, cr); 819*40c0e231SGordon Ross break; 820*40c0e231SGordon Ross 821*40c0e231SGordon Ross case SMBIOC_NTCREATE: 822*40c0e231SGordon Ross err = smb_usr_ntcreate(sdp, arg, flags, cr); 823*40c0e231SGordon Ross break; 824*40c0e231SGordon Ross 825*40c0e231SGordon Ross case SMBIOC_PRINTJOB: 826*40c0e231SGordon Ross err = smb_usr_printjob(sdp, arg, flags, cr); 8274bff34e3Sthurlow break; 828613a2f6bSGordon Ross 829*40c0e231SGordon Ross case SMBIOC_CLOSEFH: 830*40c0e231SGordon Ross err = smb_usr_closefh(sdp, cr); 831*40c0e231SGordon Ross break; 832*40c0e231SGordon Ross 833*40c0e231SGordon Ross case SMBIOC_SSN_CREATE: 834*40c0e231SGordon Ross case SMBIOC_SSN_FIND: 835*40c0e231SGordon Ross err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); 836*40c0e231SGordon Ross break; 837*40c0e231SGordon Ross 838*40c0e231SGordon Ross case SMBIOC_SSN_KILL: 839*40c0e231SGordon Ross case SMBIOC_SSN_RELE: 840*40c0e231SGordon Ross err = smb_usr_drop_ssn(sdp, cmd); 841*40c0e231SGordon Ross break; 842*40c0e231SGordon Ross 843*40c0e231SGordon Ross case SMBIOC_TREE_CONNECT: 844*40c0e231SGordon Ross case SMBIOC_TREE_FIND: 845*40c0e231SGordon Ross err = smb_usr_get_tree(sdp, cmd, arg, flags, cr); 846*40c0e231SGordon Ross break; 847*40c0e231SGordon Ross 848*40c0e231SGordon Ross case SMBIOC_TREE_KILL: 849*40c0e231SGordon Ross case SMBIOC_TREE_RELE: 850*40c0e231SGordon Ross err = smb_usr_drop_tree(sdp, cmd); 851*40c0e231SGordon Ross break; 852*40c0e231SGordon Ross 853*40c0e231SGordon Ross case SMBIOC_IOD_CONNECT: 854*40c0e231SGordon Ross case SMBIOC_IOD_NEGOTIATE: 855*40c0e231SGordon Ross case SMBIOC_IOD_SSNSETUP: 856*40c0e231SGordon Ross case SMBIOC_IOD_WORK: 857*40c0e231SGordon Ross case SMBIOC_IOD_IDLE: 858613a2f6bSGordon Ross case SMBIOC_IOD_RCFAIL: 859*40c0e231SGordon Ross err = smb_usr_iod_ioctl(sdp, cmd, arg, flags, cr); 860*40c0e231SGordon Ross break; 861*40c0e231SGordon Ross 862*40c0e231SGordon Ross case SMBIOC_PK_ADD: 863*40c0e231SGordon Ross case SMBIOC_PK_DEL: 864*40c0e231SGordon Ross case SMBIOC_PK_CHK: 865*40c0e231SGordon Ross case SMBIOC_PK_DEL_OWNER: 866*40c0e231SGordon Ross case SMBIOC_PK_DEL_EVERYONE: 867*40c0e231SGordon Ross err = smb_pkey_ioctl(cmd, arg, flags, cr); 8684bff34e3Sthurlow break; 869613a2f6bSGordon Ross 8704bff34e3Sthurlow default: 871613a2f6bSGordon Ross err = ENOTTY; 872*40c0e231SGordon Ross break; 8734bff34e3Sthurlow } 8744bff34e3Sthurlow 875*40c0e231SGordon Ross mutex_enter(&sdp->sd_lock); 876*40c0e231SGordon Ross sdp->sd_flags &= ~NSMBFL_IOCTL; 877*40c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 8784bff34e3Sthurlow 879613a2f6bSGordon Ross return (err); 8804bff34e3Sthurlow } 881