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. 3840c0e231SGordon Ross * 3940c0e231SGordon 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 56*adee6784SGordon Ross #include <smb/winioctl.h> 574bff34e3Sthurlow #include <netsmb/smb.h> 584bff34e3Sthurlow #include <netsmb/smb_conn.h> 594bff34e3Sthurlow #include <netsmb/smb_rq.h> 604bff34e3Sthurlow #include <netsmb/smb_subr.h> 614bff34e3Sthurlow #include <netsmb/smb_dev.h> 624bff34e3Sthurlow 63613a2f6bSGordon Ross static int smb_cpdatain(struct mbchain *mbp, int len, char *data, int seg); 64613a2f6bSGordon Ross 654bff34e3Sthurlow /* 66613a2f6bSGordon Ross * Ioctl function for SMBIOC_GETSSNKEY 67613a2f6bSGordon Ross * Size copied out is SMBIOC_HASH_SZ. 68613a2f6bSGordon Ross * 69613a2f6bSGordon Ross * The RPC library needs this for encrypting things 70613a2f6bSGordon Ross * like "set password" requests. This is called 71613a2f6bSGordon Ross * with an active RPC binding, so the connection 72613a2f6bSGordon Ross * will already be active (but this checks). 734bff34e3Sthurlow */ 74613a2f6bSGordon Ross int 75613a2f6bSGordon Ross smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags) 764bff34e3Sthurlow { 77613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 78613a2f6bSGordon Ross 79613a2f6bSGordon Ross /* This ioctl requires an active session. */ 80613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 81613a2f6bSGordon Ross return (ENOTCONN); 82613a2f6bSGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) 83613a2f6bSGordon Ross return (ENOTCONN); 844bff34e3Sthurlow 854bff34e3Sthurlow /* 86613a2f6bSGordon Ross * Return the session key. 874bff34e3Sthurlow */ 8840c0e231SGordon Ross if (vcp->vc_ssnkey == NULL || 8940c0e231SGordon Ross vcp->vc_ssnkeylen < SMBIOC_HASH_SZ) 9040c0e231SGordon Ross return (EINVAL); 9140c0e231SGordon Ross if (ddi_copyout(vcp->vc_ssnkey, (void *)arg, 92613a2f6bSGordon Ross SMBIOC_HASH_SZ, flags)) 93613a2f6bSGordon Ross return (EFAULT); 94613a2f6bSGordon Ross 95613a2f6bSGordon Ross return (0); 96613a2f6bSGordon Ross } 97613a2f6bSGordon Ross 98613a2f6bSGordon Ross /* 9940c0e231SGordon Ross * Ioctl function for SMBIOC_XACTNP (transact named pipe) 100613a2f6bSGordon Ross */ 101613a2f6bSGordon Ross int 10240c0e231SGordon Ross smb_usr_xnp(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 1034bff34e3Sthurlow { 104613a2f6bSGordon Ross struct smb_cred scred; 105613a2f6bSGordon Ross struct smb_share *ssp; 106*adee6784SGordon Ross struct smb_fh *fhp; 10740c0e231SGordon Ross smbioc_xnp_t *ioc = NULL; 108*adee6784SGordon Ross struct mbchain send_mb; 109*adee6784SGordon Ross struct mdchain recv_md; 110*adee6784SGordon Ross uint32_t rdlen; 111*adee6784SGordon Ross int err, mbseg; 112613a2f6bSGordon Ross 113*adee6784SGordon Ross /* This ioctl requires a file handle. */ 114*adee6784SGordon Ross if ((fhp = sdp->sd_fh) == NULL) 115*adee6784SGordon Ross return (EINVAL); 116*adee6784SGordon Ross ssp = FHTOSS(fhp); 117*adee6784SGordon Ross 118*adee6784SGordon Ross /* After reconnect, force close+reopen */ 119*adee6784SGordon Ross if (fhp->fh_vcgenid != ssp->ss_vcgenid) 120*adee6784SGordon Ross return (ESTALE); 121*adee6784SGordon Ross 122*adee6784SGordon Ross bzero(&send_mb, sizeof (send_mb)); 123*adee6784SGordon Ross bzero(&recv_md, sizeof (recv_md)); 1244bff34e3Sthurlow 125613a2f6bSGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 126613a2f6bSGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 127613a2f6bSGordon Ross err = EFAULT; 128613a2f6bSGordon Ross goto out; 1294bff34e3Sthurlow } 130613a2f6bSGordon Ross 131430b4c46SGordon Ross /* 132*adee6784SGordon Ross * Copyin the send data, into an mbchain, 133*adee6784SGordon Ross * save output buffer size. 134430b4c46SGordon Ross */ 135*adee6784SGordon Ross mbseg = (flags & FKIOCTL) ? MB_MSYSTEM : MB_MUSER; 136*adee6784SGordon Ross err = smb_cpdatain(&send_mb, ioc->ioc_tdlen, ioc->ioc_tdata, mbseg); 137613a2f6bSGordon Ross if (err) 138613a2f6bSGordon Ross goto out; 139*adee6784SGordon Ross rdlen = ioc->ioc_rdlen; 140613a2f6bSGordon Ross 141*adee6784SGordon Ross /* 142*adee6784SGordon Ross * Run the SMB2 ioctl or SMB1 trans2 143*adee6784SGordon Ross */ 144*adee6784SGordon Ross smb_credinit(&scred, cr); 145*adee6784SGordon Ross if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 146*adee6784SGordon Ross err = smb2_smb_ioctl(ssp, &fhp->fh_fid2, 147*adee6784SGordon Ross &send_mb, &recv_md, &rdlen, 148*adee6784SGordon Ross FSCTL_PIPE_TRANSCEIVE, &scred); 149*adee6784SGordon Ross } else { 150*adee6784SGordon Ross err = smb_t2_xnp(ssp, fhp->fh_fid1, 151*adee6784SGordon Ross &send_mb, &recv_md, &rdlen, 152*adee6784SGordon Ross &ioc->ioc_more, &scred); 153*adee6784SGordon Ross } 154*adee6784SGordon Ross smb_credrele(&scred); 155613a2f6bSGordon Ross 156613a2f6bSGordon Ross /* Copyout returned data. */ 157*adee6784SGordon Ross if (err == 0 && recv_md.md_top != NULL) { 158*adee6784SGordon Ross /* User's buffer large enough for copyout? */ 159*adee6784SGordon Ross size_t len = m_fixhdr(recv_md.md_top); 16040c0e231SGordon Ross if (len > ioc->ioc_rdlen) { 161613a2f6bSGordon Ross err = EMSGSIZE; 162613a2f6bSGordon Ross goto out; 163613a2f6bSGordon Ross } 164*adee6784SGordon Ross err = md_get_mem(&recv_md, ioc->ioc_rdata, len, mbseg); 165613a2f6bSGordon Ross if (err) 166613a2f6bSGordon Ross goto out; 167613a2f6bSGordon Ross } else 16840c0e231SGordon Ross ioc->ioc_rdlen = 0; 169613a2f6bSGordon Ross 170*adee6784SGordon Ross /* Tell caller received length */ 171*adee6784SGordon Ross if (rdlen <= ioc->ioc_rdlen) { 172*adee6784SGordon Ross /* Normal case */ 173*adee6784SGordon Ross ioc->ioc_rdlen = rdlen; 174*adee6784SGordon Ross } else { 175*adee6784SGordon Ross /* Buffer overlow. Leave ioc_rdlen */ 17640c0e231SGordon Ross ioc->ioc_more = 1; 177*adee6784SGordon Ross } 178613a2f6bSGordon Ross 17902d09e03SGordon Ross (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags); 180613a2f6bSGordon Ross 181613a2f6bSGordon Ross out: 182430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 183613a2f6bSGordon Ross 184613a2f6bSGordon Ross return (err); 1854bff34e3Sthurlow } 1864bff34e3Sthurlow 187613a2f6bSGordon Ross /* helper for _t2request */ 1884bff34e3Sthurlow static int 189613a2f6bSGordon Ross smb_cpdatain(struct mbchain *mbp, int len, char *data, int mbseg) 1904bff34e3Sthurlow { 191613a2f6bSGordon Ross int error; 192613a2f6bSGordon Ross 193613a2f6bSGordon Ross if (len == 0) 194613a2f6bSGordon Ross return (0); 195613a2f6bSGordon Ross error = mb_init(mbp); 196613a2f6bSGordon Ross if (error) 197613a2f6bSGordon Ross return (error); 198613a2f6bSGordon Ross return (mb_put_mem(mbp, data, len, mbseg)); 1994bff34e3Sthurlow } 2004bff34e3Sthurlow 201613a2f6bSGordon Ross /* 202613a2f6bSGordon Ross * Helper for nsmb_ioctl cases 203613a2f6bSGordon Ross * SMBIOC_READ, SMBIOC_WRITE 204613a2f6bSGordon Ross */ 2051b34bc4aSbs int 206613a2f6bSGordon Ross smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 2071b34bc4aSbs { 208613a2f6bSGordon Ross struct smb_cred scred; 209613a2f6bSGordon Ross struct smb_share *ssp; 210*adee6784SGordon Ross struct smb_fh *fhp; 211613a2f6bSGordon Ross smbioc_rw_t *ioc = NULL; 212613a2f6bSGordon Ross struct iovec aiov[1]; 213613a2f6bSGordon Ross struct uio auio; 214613a2f6bSGordon Ross int err; 215613a2f6bSGordon Ross uio_rw_t rw; 2161b34bc4aSbs 217*adee6784SGordon Ross /* This ioctl requires a file handle. */ 218*adee6784SGordon Ross if ((fhp = sdp->sd_fh) == NULL) 219*adee6784SGordon Ross return (EINVAL); 220*adee6784SGordon Ross ssp = FHTOSS(fhp); 221613a2f6bSGordon Ross 222613a2f6bSGordon Ross /* After reconnect, force close+reopen */ 223*adee6784SGordon Ross if (fhp->fh_vcgenid != ssp->ss_vcgenid) 224613a2f6bSGordon Ross return (ESTALE); 225613a2f6bSGordon Ross 226613a2f6bSGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 227613a2f6bSGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 228613a2f6bSGordon Ross err = EFAULT; 2291b34bc4aSbs goto out; 230613a2f6bSGordon Ross } 231613a2f6bSGordon Ross 232613a2f6bSGordon Ross switch (cmd) { 233613a2f6bSGordon Ross case SMBIOC_READ: 234613a2f6bSGordon Ross rw = UIO_READ; 235613a2f6bSGordon Ross break; 236613a2f6bSGordon Ross case SMBIOC_WRITE: 237613a2f6bSGordon Ross rw = UIO_WRITE; 238613a2f6bSGordon Ross break; 239613a2f6bSGordon Ross default: 240613a2f6bSGordon Ross err = ENODEV; 241613a2f6bSGordon Ross goto out; 242613a2f6bSGordon Ross } 243613a2f6bSGordon Ross 244613a2f6bSGordon Ross aiov[0].iov_base = ioc->ioc_base; 245613a2f6bSGordon Ross aiov[0].iov_len = (size_t)ioc->ioc_cnt; 246613a2f6bSGordon Ross 247613a2f6bSGordon Ross auio.uio_iov = aiov; 248613a2f6bSGordon Ross auio.uio_iovcnt = 1; 249613a2f6bSGordon Ross auio.uio_loffset = ioc->ioc_offset; 250613a2f6bSGordon Ross auio.uio_segflg = (flags & FKIOCTL) ? 251613a2f6bSGordon Ross UIO_SYSSPACE : UIO_USERSPACE; 252613a2f6bSGordon Ross auio.uio_fmode = 0; 253613a2f6bSGordon Ross auio.uio_resid = (size_t)ioc->ioc_cnt; 254613a2f6bSGordon Ross 255*adee6784SGordon Ross smb_credinit(&scred, cr); 256*adee6784SGordon Ross err = smb_rwuio(fhp, rw, &auio, &scred, 0); 257*adee6784SGordon Ross smb_credrele(&scred); 258613a2f6bSGordon Ross 259613a2f6bSGordon Ross /* 260613a2f6bSGordon Ross * On return ioc_cnt holds the 261613a2f6bSGordon Ross * number of bytes transferred. 262613a2f6bSGordon Ross */ 263613a2f6bSGordon Ross ioc->ioc_cnt -= auio.uio_resid; 264613a2f6bSGordon Ross 26502d09e03SGordon Ross (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags); 266613a2f6bSGordon Ross 2671b34bc4aSbs out: 268430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 269430b4c46SGordon Ross 270430b4c46SGordon Ross return (err); 271430b4c46SGordon Ross } 272430b4c46SGordon Ross 273430b4c46SGordon Ross /* 274430b4c46SGordon Ross * Helper for nsmb_ioctl case 275430b4c46SGordon Ross * SMBIOC_NTCREATE 276430b4c46SGordon Ross */ 277430b4c46SGordon Ross int 278430b4c46SGordon Ross smb_usr_ntcreate(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 279430b4c46SGordon Ross { 280430b4c46SGordon Ross struct smb_cred scred; 281430b4c46SGordon Ross struct mbchain name_mb; 282430b4c46SGordon Ross struct smb_share *ssp; 283*adee6784SGordon Ross struct smb_fh *fhp = NULL; 284430b4c46SGordon Ross smbioc_ntcreate_t *ioc = NULL; 285430b4c46SGordon Ross int err, nmlen; 286430b4c46SGordon Ross 287*adee6784SGordon Ross mb_init(&name_mb); 288*adee6784SGordon Ross 289430b4c46SGordon Ross /* This ioctl requires a share. */ 290430b4c46SGordon Ross if ((ssp = sdp->sd_share) == NULL) 291430b4c46SGordon Ross return (ENOTCONN); 292430b4c46SGordon Ross 293*adee6784SGordon Ross /* Must not already have a file handle. */ 294*adee6784SGordon Ross if (sdp->sd_fh != NULL) 295430b4c46SGordon Ross return (EINVAL); 296430b4c46SGordon Ross 297430b4c46SGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 298430b4c46SGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 299430b4c46SGordon Ross err = EFAULT; 300430b4c46SGordon Ross goto out; 301430b4c46SGordon Ross } 302430b4c46SGordon Ross 303430b4c46SGordon Ross /* Build name_mb */ 304430b4c46SGordon Ross ioc->ioc_name[SMBIOC_MAX_NAME-1] = '\0'; 305430b4c46SGordon Ross nmlen = strnlen(ioc->ioc_name, SMBIOC_MAX_NAME-1); 306430b4c46SGordon Ross err = smb_put_dmem(&name_mb, SSTOVC(ssp), 307430b4c46SGordon Ross ioc->ioc_name, nmlen, 308430b4c46SGordon Ross SMB_CS_NONE, NULL); 309430b4c46SGordon Ross if (err != 0) 310430b4c46SGordon Ross goto out; 311430b4c46SGordon Ross 312*adee6784SGordon Ross err = smb_fh_create(ssp, &fhp); 313*adee6784SGordon Ross if (err != 0) 314*adee6784SGordon Ross goto out; 315*adee6784SGordon Ross 316*adee6784SGordon Ross /* 317*adee6784SGordon Ross * Do the OtW open, save the FID. 318*adee6784SGordon Ross */ 319*adee6784SGordon Ross smb_credinit(&scred, cr); 320430b4c46SGordon Ross err = smb_smb_ntcreate(ssp, &name_mb, 321430b4c46SGordon Ross 0, /* create flags */ 322430b4c46SGordon Ross ioc->ioc_req_acc, 323430b4c46SGordon Ross ioc->ioc_efattr, 324430b4c46SGordon Ross ioc->ioc_share_acc, 325430b4c46SGordon Ross ioc->ioc_open_disp, 326430b4c46SGordon Ross ioc->ioc_creat_opts, 327430b4c46SGordon Ross NTCREATEX_IMPERSONATION_IMPERSONATION, 328430b4c46SGordon Ross &scred, 329*adee6784SGordon Ross fhp, 330430b4c46SGordon Ross NULL, 331430b4c46SGordon Ross NULL); 332*adee6784SGordon Ross smb_credrele(&scred); 333430b4c46SGordon Ross if (err != 0) 334430b4c46SGordon Ross goto out; 335430b4c46SGordon Ross 336*adee6784SGordon Ross fhp->fh_rights = ioc->ioc_req_acc; 337*adee6784SGordon Ross smb_fh_opened(fhp); 338*adee6784SGordon Ross sdp->sd_fh = fhp; 339*adee6784SGordon Ross fhp = NULL; 340430b4c46SGordon Ross 341430b4c46SGordon Ross out: 342*adee6784SGordon Ross if (fhp != NULL) 343*adee6784SGordon Ross smb_fh_rele(fhp); 344430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 345430b4c46SGordon Ross mb_done(&name_mb); 346430b4c46SGordon Ross 347430b4c46SGordon Ross return (err); 348430b4c46SGordon Ross } 349430b4c46SGordon Ross 350430b4c46SGordon Ross /* 351430b4c46SGordon Ross * Helper for nsmb_ioctl case 352430b4c46SGordon Ross * SMBIOC_PRINTJOB 353430b4c46SGordon Ross */ 354430b4c46SGordon Ross int 355430b4c46SGordon Ross smb_usr_printjob(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) 356430b4c46SGordon Ross { 357*adee6784SGordon Ross static const char invalid_chars[] = SMB_FILENAME_INVALID_CHARS; 358430b4c46SGordon Ross struct smb_cred scred; 359*adee6784SGordon Ross struct mbchain name_mb; 360430b4c46SGordon Ross struct smb_share *ssp; 361*adee6784SGordon Ross struct smb_fh *fhp = NULL; 362430b4c46SGordon Ross smbioc_printjob_t *ioc = NULL; 363*adee6784SGordon Ross int err, cklen, nmlen; 364*adee6784SGordon Ross uint32_t access = SA_RIGHT_FILE_WRITE_DATA | 365*adee6784SGordon Ross SA_RIGHT_FILE_READ_ATTRIBUTES; 366*adee6784SGordon Ross 367*adee6784SGordon Ross mb_init(&name_mb); 368430b4c46SGordon Ross 369430b4c46SGordon Ross /* This ioctl requires a share. */ 370430b4c46SGordon Ross if ((ssp = sdp->sd_share) == NULL) 371430b4c46SGordon Ross return (ENOTCONN); 372430b4c46SGordon Ross 373430b4c46SGordon Ross /* The share must be a print queue. */ 374430b4c46SGordon Ross if (ssp->ss_type != STYPE_PRINTQ) 375430b4c46SGordon Ross return (EINVAL); 376430b4c46SGordon Ross 377*adee6784SGordon Ross /* Must not already have a file handle. */ 378*adee6784SGordon Ross if (sdp->sd_fh != NULL) 379430b4c46SGordon Ross return (EINVAL); 380430b4c46SGordon Ross 381430b4c46SGordon Ross smb_credinit(&scred, cr); 382430b4c46SGordon Ross ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); 383430b4c46SGordon Ross if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { 384430b4c46SGordon Ross err = EFAULT; 385430b4c46SGordon Ross goto out; 386430b4c46SGordon Ross } 387*adee6784SGordon Ross 388*adee6784SGordon Ross /* 389*adee6784SGordon Ross * Use the print job title as the file name to open, but 390*adee6784SGordon Ross * check for invalid characters first. See the notes in 391*adee6784SGordon Ross * libsmbfs/smb/print.c about job name sanitizing. 392*adee6784SGordon Ross */ 393430b4c46SGordon Ross ioc->ioc_title[SMBIOC_MAX_NAME-1] = '\0'; 394*adee6784SGordon Ross nmlen = strnlen(ioc->ioc_title, SMBIOC_MAX_NAME-1); 395*adee6784SGordon Ross cklen = strcspn(ioc->ioc_title, invalid_chars); 396*adee6784SGordon Ross if (cklen < nmlen) { 397*adee6784SGordon Ross err = EINVAL; 398*adee6784SGordon Ross goto out; 399*adee6784SGordon Ross } 400430b4c46SGordon Ross 401*adee6784SGordon Ross /* Build name_mb */ 402*adee6784SGordon Ross err = smb_put_dmem(&name_mb, SSTOVC(ssp), 403*adee6784SGordon Ross ioc->ioc_title, nmlen, 404*adee6784SGordon Ross SMB_CS_NONE, NULL); 405430b4c46SGordon Ross if (err != 0) 406430b4c46SGordon Ross goto out; 407430b4c46SGordon Ross 408*adee6784SGordon Ross err = smb_fh_create(ssp, &fhp); 409*adee6784SGordon Ross if (err != 0) 410*adee6784SGordon Ross goto out; 411*adee6784SGordon Ross 412*adee6784SGordon Ross /* 413*adee6784SGordon Ross * Do the OtW open, save the FID. 414*adee6784SGordon Ross */ 415*adee6784SGordon Ross smb_credinit(&scred, cr); 416*adee6784SGordon Ross if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) { 417*adee6784SGordon Ross err = smb2_smb_ntcreate(ssp, &name_mb, 418*adee6784SGordon Ross NULL, NULL, /* cctx in, out */ 419*adee6784SGordon Ross 0, /* create flags */ 420*adee6784SGordon Ross access, 421*adee6784SGordon Ross SMB_EFA_NORMAL, 422*adee6784SGordon Ross NTCREATEX_SHARE_ACCESS_NONE, 423*adee6784SGordon Ross NTCREATEX_DISP_CREATE, 424*adee6784SGordon Ross NTCREATEX_OPTIONS_NON_DIRECTORY_FILE, 425*adee6784SGordon Ross NTCREATEX_IMPERSONATION_IMPERSONATION, 426*adee6784SGordon Ross &scred, 427*adee6784SGordon Ross &fhp->fh_fid2, 428*adee6784SGordon Ross NULL, 429*adee6784SGordon Ross NULL); 430*adee6784SGordon Ross } else { 431*adee6784SGordon Ross err = smb_smb_open_prjob(ssp, ioc->ioc_title, 432*adee6784SGordon Ross ioc->ioc_setuplen, ioc->ioc_prmode, 433*adee6784SGordon Ross &scred, &fhp->fh_fid1); 434*adee6784SGordon Ross } 435*adee6784SGordon Ross smb_credrele(&scred); 436*adee6784SGordon Ross if (err != 0) 437*adee6784SGordon Ross goto out; 438*adee6784SGordon Ross 439*adee6784SGordon Ross fhp->fh_rights = access; 440*adee6784SGordon Ross smb_fh_opened(fhp); 441*adee6784SGordon Ross sdp->sd_fh = fhp; 442*adee6784SGordon Ross fhp = NULL; 443430b4c46SGordon Ross 444430b4c46SGordon Ross out: 445*adee6784SGordon Ross if (fhp != NULL) 446*adee6784SGordon Ross smb_fh_rele(fhp); 447430b4c46SGordon Ross kmem_free(ioc, sizeof (*ioc)); 448*adee6784SGordon Ross mb_done(&name_mb); 449430b4c46SGordon Ross 450430b4c46SGordon Ross return (err); 451430b4c46SGordon Ross } 452430b4c46SGordon Ross 453430b4c46SGordon Ross /* 454430b4c46SGordon Ross * Helper for nsmb_ioctl case 455430b4c46SGordon Ross * SMBIOC_CLOSEFH 456430b4c46SGordon Ross */ 457*adee6784SGordon Ross /*ARGSUSED*/ 458430b4c46SGordon Ross int 459430b4c46SGordon Ross smb_usr_closefh(smb_dev_t *sdp, cred_t *cr) 460430b4c46SGordon Ross { 461*adee6784SGordon Ross struct smb_fh *fhp; 462430b4c46SGordon Ross 463*adee6784SGordon Ross /* This ioctl requires a file handle. */ 464*adee6784SGordon Ross if ((fhp = sdp->sd_fh) == NULL) 465*adee6784SGordon Ross return (EINVAL); 466*adee6784SGordon Ross sdp->sd_fh = NULL; 467430b4c46SGordon Ross 468*adee6784SGordon Ross smb_fh_close(fhp); 469*adee6784SGordon Ross smb_fh_rele(fhp); 470613a2f6bSGordon Ross 471*adee6784SGordon Ross return (0); 4721b34bc4aSbs } 4731b34bc4aSbs 474613a2f6bSGordon Ross /* 475613a2f6bSGordon Ross * Ioctl functions: SMBIOC_SSN_FIND, SMBIOC_SSN_CREATE 476613a2f6bSGordon Ross * Find or create a session (a.k.a. "VC" in here) 477613a2f6bSGordon Ross */ 4784bff34e3Sthurlow int 479613a2f6bSGordon Ross smb_usr_get_ssn(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 4804bff34e3Sthurlow { 481613a2f6bSGordon Ross struct smb_cred scred; 482613a2f6bSGordon Ross smbioc_ossn_t *ossn = NULL; 4834bff34e3Sthurlow struct smb_vc *vcp = NULL; 4844bff34e3Sthurlow int error = 0; 485613a2f6bSGordon Ross uid_t realuid; 4864bff34e3Sthurlow 487613a2f6bSGordon Ross /* Should be no VC */ 488613a2f6bSGordon Ross if (sdp->sd_vc != NULL) 489613a2f6bSGordon Ross return (EISCONN); 490613a2f6bSGordon Ross 491613a2f6bSGordon Ross smb_credinit(&scred, cr); 492613a2f6bSGordon Ross ossn = kmem_alloc(sizeof (*ossn), KM_SLEEP); 493613a2f6bSGordon Ross if (ddi_copyin((void *)arg, ossn, sizeof (*ossn), flags)) { 494613a2f6bSGordon Ross error = EFAULT; 495613a2f6bSGordon Ross goto out; 4964bff34e3Sthurlow } 497613a2f6bSGordon Ross 498613a2f6bSGordon Ross /* 499613a2f6bSGordon Ross * Only superuser can specify a UID or GID. 500613a2f6bSGordon Ross */ 501613a2f6bSGordon Ross realuid = crgetruid(cr); 502613a2f6bSGordon Ross if (ossn->ssn_owner == SMBM_ANY_OWNER) 503613a2f6bSGordon Ross ossn->ssn_owner = realuid; 504613a2f6bSGordon Ross else { 5054bff34e3Sthurlow /* 506613a2f6bSGordon Ross * Do we have the privilege to create with the 507613a2f6bSGordon Ross * specified uid? (does uid == cr->cr_uid, etc.) 5084bff34e3Sthurlow */ 509613a2f6bSGordon Ross if (secpolicy_vnode_owner(cr, ossn->ssn_owner)) { 510613a2f6bSGordon Ross error = EPERM; 511613a2f6bSGordon Ross goto out; 5124bff34e3Sthurlow } 513613a2f6bSGordon Ross /* ossn->ssn_owner is OK */ 5144bff34e3Sthurlow } 5154bff34e3Sthurlow 516613a2f6bSGordon Ross /* 517613a2f6bSGordon Ross * Make sure the strings are null terminated. 518613a2f6bSGordon Ross */ 519613a2f6bSGordon Ross ossn->ssn_srvname[SMBIOC_MAX_NAME-1] = '\0'; 520613a2f6bSGordon Ross ossn->ssn_id.id_domain[ SMBIOC_MAX_NAME-1] = '\0'; 521613a2f6bSGordon Ross ossn->ssn_id.id_user[ SMBIOC_MAX_NAME-1] = '\0'; 5224bff34e3Sthurlow 523613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_CREATE) 524613a2f6bSGordon Ross ossn->ssn_vopt |= SMBVOPT_CREATE; 525613a2f6bSGordon Ross else /* FIND */ 526613a2f6bSGordon Ross ossn->ssn_vopt &= ~SMBVOPT_CREATE; 5274bff34e3Sthurlow 528613a2f6bSGordon Ross error = smb_vc_findcreate(ossn, &scred, &vcp); 5294bff34e3Sthurlow if (error) 5304bff34e3Sthurlow goto out; 531613a2f6bSGordon Ross ASSERT(vcp != NULL); 5324bff34e3Sthurlow 5334bff34e3Sthurlow /* 534613a2f6bSGordon Ross * We have a VC, held, but not locked. 535613a2f6bSGordon Ross * If we're creating, mark this instance as 536613a2f6bSGordon Ross * an open from IOD so close can do cleanup. 537613a2f6bSGordon Ross * 538613a2f6bSGordon Ross * XXX: Would be nice to have a back pointer 539613a2f6bSGordon Ross * from the VC to this (IOD) sdp instance. 5404bff34e3Sthurlow */ 541613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_CREATE) { 542613a2f6bSGordon Ross if (vcp->iod_thr != NULL) { 543613a2f6bSGordon Ross error = EEXIST; 544613a2f6bSGordon Ross goto out; 545613a2f6bSGordon Ross } 546613a2f6bSGordon Ross sdp->sd_flags |= NSMBFL_IOD; 547613a2f6bSGordon Ross } else { 548613a2f6bSGordon Ross /* 549613a2f6bSGordon Ross * Wait for it to finish connecting 550613a2f6bSGordon Ross * (or reconnect) if necessary. 551613a2f6bSGordon Ross */ 552613a2f6bSGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 553613a2f6bSGordon Ross error = smb_iod_reconnect(vcp); 554613a2f6bSGordon Ross if (error != 0) 555613a2f6bSGordon Ross goto out; 556613a2f6bSGordon Ross } 557613a2f6bSGordon Ross } 558613a2f6bSGordon Ross 559613a2f6bSGordon Ross /* 560613a2f6bSGordon Ross * The VC has a hold from _findvc 561613a2f6bSGordon Ross * which we keep until _SSN_RELE 562613a2f6bSGordon Ross * or nsmb_close(). 563613a2f6bSGordon Ross */ 564613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 565613a2f6bSGordon Ross sdp->sd_vc = vcp; 566613a2f6bSGordon Ross vcp = NULL; 567613a2f6bSGordon Ross (void) ddi_copyout(ossn, (void *)arg, sizeof (*ossn), flags); 5684bff34e3Sthurlow 5694bff34e3Sthurlow out: 570613a2f6bSGordon Ross if (vcp) { 571613a2f6bSGordon Ross /* Error path: rele hold from _findcreate */ 572613a2f6bSGordon Ross smb_vc_rele(vcp); 573613a2f6bSGordon Ross } 574430b4c46SGordon Ross kmem_free(ossn, sizeof (*ossn)); 575613a2f6bSGordon Ross smb_credrele(&scred); 576613a2f6bSGordon Ross 5774bff34e3Sthurlow return (error); 5784bff34e3Sthurlow } 5794bff34e3Sthurlow 580613a2f6bSGordon Ross /* 581613a2f6bSGordon Ross * Ioctl functions: SMBIOC_SSN_RELE, SMBIOC_SSN_KILL 582613a2f6bSGordon Ross * Release or kill the current session. 583613a2f6bSGordon Ross */ 5844bff34e3Sthurlow int 585613a2f6bSGordon Ross smb_usr_drop_ssn(smb_dev_t *sdp, int cmd) 5864bff34e3Sthurlow { 587613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 5884bff34e3Sthurlow 589613a2f6bSGordon Ross /* Must have a VC. */ 590613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 591613a2f6bSGordon Ross return (ENOTCONN); 5924bff34e3Sthurlow 593613a2f6bSGordon Ross /* If we have a share ref, drop it too. */ 594613a2f6bSGordon Ross if (sdp->sd_share) { 595613a2f6bSGordon Ross smb_share_rele(sdp->sd_share); 596613a2f6bSGordon Ross sdp->sd_share = NULL; 597613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 5984bff34e3Sthurlow } 5994bff34e3Sthurlow 600613a2f6bSGordon Ross if (cmd == SMBIOC_SSN_KILL) 601613a2f6bSGordon Ross smb_vc_kill(vcp); 6024bff34e3Sthurlow 603613a2f6bSGordon Ross /* Drop the VC ref. */ 604613a2f6bSGordon Ross smb_vc_rele(vcp); 605613a2f6bSGordon Ross sdp->sd_vc = NULL; 606613a2f6bSGordon Ross sdp->sd_level = 0; 607613a2f6bSGordon Ross 608613a2f6bSGordon Ross return (0); 6094bff34e3Sthurlow } 6104bff34e3Sthurlow 6114bff34e3Sthurlow /* 612613a2f6bSGordon Ross * Find or create a tree (connected share) 6134bff34e3Sthurlow */ 6144bff34e3Sthurlow int 615613a2f6bSGordon Ross smb_usr_get_tree(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 6164bff34e3Sthurlow { 617613a2f6bSGordon Ross struct smb_cred scred; 618613a2f6bSGordon Ross smbioc_tcon_t *tcon = NULL; 619613a2f6bSGordon Ross struct smb_vc *vcp = NULL; 620613a2f6bSGordon Ross struct smb_share *ssp = NULL; 621613a2f6bSGordon Ross int error = 0; 6224bff34e3Sthurlow 623613a2f6bSGordon Ross /* Must have a VC. */ 624613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 625613a2f6bSGordon Ross return (ENOTCONN); 626613a2f6bSGordon Ross /* Should not have a share. */ 627613a2f6bSGordon Ross if (sdp->sd_share != NULL) 628613a2f6bSGordon Ross return (EISCONN); 629613a2f6bSGordon Ross 630613a2f6bSGordon Ross smb_credinit(&scred, cr); 631613a2f6bSGordon Ross tcon = kmem_alloc(sizeof (*tcon), KM_SLEEP); 632613a2f6bSGordon Ross if (ddi_copyin((void *)arg, tcon, sizeof (*tcon), flags)) { 633613a2f6bSGordon Ross error = EFAULT; 634613a2f6bSGordon Ross goto out; 6354bff34e3Sthurlow } 636613a2f6bSGordon Ross 637613a2f6bSGordon Ross /* 638613a2f6bSGordon Ross * Make sure the strings are null terminated. 639613a2f6bSGordon Ross */ 640613a2f6bSGordon Ross tcon->tc_sh.sh_name[SMBIOC_MAX_NAME-1] = '\0'; 641613a2f6bSGordon Ross tcon->tc_sh.sh_pass[SMBIOC_MAX_NAME-1] = '\0'; 642613a2f6bSGordon Ross 643613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_CONNECT) 644613a2f6bSGordon Ross tcon->tc_opt |= SMBSOPT_CREATE; 645613a2f6bSGordon Ross else /* FIND */ 646613a2f6bSGordon Ross tcon->tc_opt &= ~SMBSOPT_CREATE; 647613a2f6bSGordon Ross 648613a2f6bSGordon Ross error = smb_share_findcreate(tcon, vcp, &ssp, &scred); 6494bff34e3Sthurlow if (error) 650613a2f6bSGordon Ross goto out; 651613a2f6bSGordon Ross ASSERT(ssp != NULL); 652613a2f6bSGordon Ross 653613a2f6bSGordon Ross /* 654613a2f6bSGordon Ross * We have a share, held, but not locked. 655613a2f6bSGordon Ross * If we're creating, do tree connect now, 656613a2f6bSGordon Ross * otherwise let that wait for a request. 657613a2f6bSGordon Ross */ 658613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_CONNECT) { 659613a2f6bSGordon Ross error = smb_share_tcon(ssp, &scred); 660613a2f6bSGordon Ross if (error) 661613a2f6bSGordon Ross goto out; 6624bff34e3Sthurlow } 663613a2f6bSGordon Ross 664613a2f6bSGordon Ross /* 665613a2f6bSGordon Ross * Give caller the real share type from 666613a2f6bSGordon Ross * the tree connect response, so they can 667613a2f6bSGordon Ross * see if they got the requested type. 668613a2f6bSGordon Ross */ 669430b4c46SGordon Ross tcon->tc_sh.sh_type = ssp->ss_type; 670613a2f6bSGordon Ross 671613a2f6bSGordon Ross /* 672613a2f6bSGordon Ross * The share has a hold from _tcon 673613a2f6bSGordon Ross * which we keep until nsmb_close() 674613a2f6bSGordon Ross * or the SMBIOC_TDIS below. 675613a2f6bSGordon Ross */ 676613a2f6bSGordon Ross sdp->sd_level = SMBL_SHARE; 677613a2f6bSGordon Ross sdp->sd_share = ssp; 678613a2f6bSGordon Ross ssp = NULL; 679613a2f6bSGordon Ross (void) ddi_copyout(tcon, (void *)arg, sizeof (*tcon), flags); 680613a2f6bSGordon Ross 681613a2f6bSGordon Ross out: 682613a2f6bSGordon Ross if (ssp) { 683613a2f6bSGordon Ross /* Error path: rele hold from _findcreate */ 684613a2f6bSGordon Ross smb_share_rele(ssp); 6854bff34e3Sthurlow } 686430b4c46SGordon Ross /* 687430b4c46SGordon Ross * This structure may contain a 688430b4c46SGordon Ross * cleartext password, so zap it. 689430b4c46SGordon Ross */ 690430b4c46SGordon Ross bzero(tcon, sizeof (*tcon)); 691430b4c46SGordon Ross kmem_free(tcon, sizeof (*tcon)); 692613a2f6bSGordon Ross smb_credrele(&scred); 6934bff34e3Sthurlow 694613a2f6bSGordon Ross return (error); 6954bff34e3Sthurlow } 6964bff34e3Sthurlow 697613a2f6bSGordon Ross /* 698613a2f6bSGordon Ross * Ioctl functions: SMBIOC_TREE_RELE, SMBIOC_TREE_KILL 699613a2f6bSGordon Ross * Release or kill the current tree 700613a2f6bSGordon Ross */ 701613a2f6bSGordon Ross int 702613a2f6bSGordon Ross smb_usr_drop_tree(smb_dev_t *sdp, int cmd) 7034bff34e3Sthurlow { 704613a2f6bSGordon Ross struct smb_share *ssp = NULL; 7054bff34e3Sthurlow 706613a2f6bSGordon Ross /* Must have a VC and a share. */ 707613a2f6bSGordon Ross if (sdp->sd_vc == NULL) 708613a2f6bSGordon Ross return (ENOTCONN); 709613a2f6bSGordon Ross if ((ssp = sdp->sd_share) == NULL) 710613a2f6bSGordon Ross return (ENOTCONN); 711613a2f6bSGordon Ross 712613a2f6bSGordon Ross if (cmd == SMBIOC_TREE_KILL) 713613a2f6bSGordon Ross smb_share_kill(ssp); 714613a2f6bSGordon Ross 715613a2f6bSGordon Ross /* Drop the share ref. */ 716613a2f6bSGordon Ross smb_share_rele(sdp->sd_share); 717613a2f6bSGordon Ross sdp->sd_share = NULL; 718613a2f6bSGordon Ross sdp->sd_level = SMBL_VC; 719613a2f6bSGordon Ross 720613a2f6bSGordon Ross return (0); 7214bff34e3Sthurlow } 7224bff34e3Sthurlow 723613a2f6bSGordon Ross /* 72440c0e231SGordon Ross * Ioctl handler for all SMBIOC_IOD_... 725613a2f6bSGordon Ross */ 7264bff34e3Sthurlow int 72740c0e231SGordon Ross smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 7284bff34e3Sthurlow { 72940c0e231SGordon Ross struct smb_vc *vcp; 730613a2f6bSGordon Ross int err = 0; 7314bff34e3Sthurlow 73240c0e231SGordon Ross /* Must be the IOD. */ 73340c0e231SGordon Ross if ((sdp->sd_flags & NSMBFL_IOD) == 0) 73440c0e231SGordon Ross return (EINVAL); 73540c0e231SGordon Ross /* Must have a VC and no share. */ 736613a2f6bSGordon Ross if ((vcp = sdp->sd_vc) == NULL) 7374bff34e3Sthurlow return (EINVAL); 73840c0e231SGordon Ross if (sdp->sd_share != NULL) 739613a2f6bSGordon Ross return (EINVAL); 740613a2f6bSGordon Ross 741613a2f6bSGordon Ross /* 742613a2f6bSGordon Ross * Is there already an IOD for this VC? 743613a2f6bSGordon Ross * (Should never happen.) 744613a2f6bSGordon Ross */ 745613a2f6bSGordon Ross SMB_VC_LOCK(vcp); 746613a2f6bSGordon Ross if (vcp->iod_thr == NULL) 747613a2f6bSGordon Ross vcp->iod_thr = curthread; 748613a2f6bSGordon Ross else 749613a2f6bSGordon Ross err = EEXIST; 750613a2f6bSGordon Ross SMB_VC_UNLOCK(vcp); 751613a2f6bSGordon Ross if (err) 752613a2f6bSGordon Ross return (err); 753613a2f6bSGordon Ross 754613a2f6bSGordon Ross /* 75540c0e231SGordon Ross * Copy the "work" state, etc. into the VC, 75640c0e231SGordon Ross * and back to the caller on the way out. 75740c0e231SGordon Ross * Clear the "out only" part. 758613a2f6bSGordon Ross */ 759613a2f6bSGordon Ross if (ddi_copyin((void *)arg, &vcp->vc_work, 760613a2f6bSGordon Ross sizeof (smbioc_ssn_work_t), flags)) { 761613a2f6bSGordon Ross err = EFAULT; 762613a2f6bSGordon Ross goto out; 7634bff34e3Sthurlow } 76440c0e231SGordon Ross vcp->vc_work.wk_out_state = 0; 765613a2f6bSGordon Ross 76640c0e231SGordon Ross switch (cmd) { 767613a2f6bSGordon Ross 76840c0e231SGordon Ross case SMBIOC_IOD_CONNECT: 769*adee6784SGordon Ross err = nsmb_iod_connect(vcp, cr); 77040c0e231SGordon Ross break; 771613a2f6bSGordon Ross 77240c0e231SGordon Ross case SMBIOC_IOD_NEGOTIATE: 77340c0e231SGordon Ross err = nsmb_iod_negotiate(vcp, cr); 77440c0e231SGordon Ross break; 775613a2f6bSGordon Ross 77640c0e231SGordon Ross case SMBIOC_IOD_SSNSETUP: 77740c0e231SGordon Ross err = nsmb_iod_ssnsetup(vcp, cr); 77840c0e231SGordon Ross break; 77940c0e231SGordon Ross 78040c0e231SGordon Ross case SMBIOC_IOD_WORK: 78140c0e231SGordon Ross err = smb_iod_vc_work(vcp, flags, cr); 78240c0e231SGordon Ross break; 78340c0e231SGordon Ross 78440c0e231SGordon Ross case SMBIOC_IOD_IDLE: 78540c0e231SGordon Ross err = smb_iod_vc_idle(vcp); 78640c0e231SGordon Ross break; 78740c0e231SGordon Ross 78840c0e231SGordon Ross case SMBIOC_IOD_RCFAIL: 78940c0e231SGordon Ross err = smb_iod_vc_rcfail(vcp); 79040c0e231SGordon Ross break; 79140c0e231SGordon Ross 79240c0e231SGordon Ross default: 79340c0e231SGordon Ross err = ENOTTY; 79440c0e231SGordon Ross break; 795613a2f6bSGordon Ross } 796613a2f6bSGordon Ross 79740c0e231SGordon Ross out: 79840c0e231SGordon Ross vcp->vc_work.wk_out_state = vcp->vc_state; 79940c0e231SGordon Ross (void) ddi_copyout(&vcp->vc_work, (void *)arg, 80040c0e231SGordon Ross sizeof (smbioc_ssn_work_t), flags); 80140c0e231SGordon Ross 802613a2f6bSGordon Ross /* 803613a2f6bSGordon Ross * The IOD thread is leaving the driver. Clear iod_thr, 804613a2f6bSGordon Ross * and wake up anybody waiting for us to quit. 805613a2f6bSGordon Ross */ 806613a2f6bSGordon Ross SMB_VC_LOCK(vcp); 807613a2f6bSGordon Ross vcp->iod_thr = NULL; 808613a2f6bSGordon Ross cv_broadcast(&vcp->vc_statechg); 809613a2f6bSGordon Ross SMB_VC_UNLOCK(vcp); 810613a2f6bSGordon Ross 811613a2f6bSGordon Ross return (err); 8124bff34e3Sthurlow } 8134bff34e3Sthurlow 8144bff34e3Sthurlow int 81540c0e231SGordon Ross smb_usr_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr) 8164bff34e3Sthurlow { 81740c0e231SGordon Ross int err; 818613a2f6bSGordon Ross 819613a2f6bSGordon Ross /* 82040c0e231SGordon Ross * Serialize ioctl calls. The smb_usr_... functions 82140c0e231SGordon Ross * don't expect concurrent calls on a given sdp. 822613a2f6bSGordon Ross */ 82340c0e231SGordon Ross mutex_enter(&sdp->sd_lock); 82440c0e231SGordon Ross if ((sdp->sd_flags & NSMBFL_IOCTL) != 0) { 82540c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 82640c0e231SGordon Ross return (EBUSY); 82740c0e231SGordon Ross } 82840c0e231SGordon Ross sdp->sd_flags |= NSMBFL_IOCTL; 82940c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 8304bff34e3Sthurlow 83140c0e231SGordon Ross err = 0; 8324bff34e3Sthurlow switch (cmd) { 83340c0e231SGordon Ross case SMBIOC_GETVERS: 83440c0e231SGordon Ross (void) ddi_copyout(&nsmb_version, (void *)arg, 83540c0e231SGordon Ross sizeof (nsmb_version), flags); 83640c0e231SGordon Ross break; 83740c0e231SGordon Ross 83840c0e231SGordon Ross case SMBIOC_GETSSNKEY: 83940c0e231SGordon Ross err = smb_usr_get_ssnkey(sdp, arg, flags); 84040c0e231SGordon Ross break; 84140c0e231SGordon Ross 84240c0e231SGordon Ross case SMBIOC_DUP_DEV: 84340c0e231SGordon Ross err = smb_usr_dup_dev(sdp, arg, flags); 84440c0e231SGordon Ross break; 84540c0e231SGordon Ross 84640c0e231SGordon Ross case SMBIOC_XACTNP: 84740c0e231SGordon Ross err = smb_usr_xnp(sdp, arg, flags, cr); 84840c0e231SGordon Ross break; 84940c0e231SGordon Ross 85040c0e231SGordon Ross case SMBIOC_READ: 85140c0e231SGordon Ross case SMBIOC_WRITE: 85240c0e231SGordon Ross err = smb_usr_rw(sdp, cmd, arg, flags, cr); 85340c0e231SGordon Ross break; 85440c0e231SGordon Ross 85540c0e231SGordon Ross case SMBIOC_NTCREATE: 85640c0e231SGordon Ross err = smb_usr_ntcreate(sdp, arg, flags, cr); 85740c0e231SGordon Ross break; 85840c0e231SGordon Ross 85940c0e231SGordon Ross case SMBIOC_PRINTJOB: 86040c0e231SGordon Ross err = smb_usr_printjob(sdp, arg, flags, cr); 8614bff34e3Sthurlow break; 862613a2f6bSGordon Ross 86340c0e231SGordon Ross case SMBIOC_CLOSEFH: 86440c0e231SGordon Ross err = smb_usr_closefh(sdp, cr); 86540c0e231SGordon Ross break; 86640c0e231SGordon Ross 86740c0e231SGordon Ross case SMBIOC_SSN_CREATE: 86840c0e231SGordon Ross case SMBIOC_SSN_FIND: 86940c0e231SGordon Ross err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); 87040c0e231SGordon Ross break; 87140c0e231SGordon Ross 87240c0e231SGordon Ross case SMBIOC_SSN_KILL: 87340c0e231SGordon Ross case SMBIOC_SSN_RELE: 87440c0e231SGordon Ross err = smb_usr_drop_ssn(sdp, cmd); 87540c0e231SGordon Ross break; 87640c0e231SGordon Ross 87740c0e231SGordon Ross case SMBIOC_TREE_CONNECT: 87840c0e231SGordon Ross case SMBIOC_TREE_FIND: 87940c0e231SGordon Ross err = smb_usr_get_tree(sdp, cmd, arg, flags, cr); 88040c0e231SGordon Ross break; 88140c0e231SGordon Ross 88240c0e231SGordon Ross case SMBIOC_TREE_KILL: 88340c0e231SGordon Ross case SMBIOC_TREE_RELE: 88440c0e231SGordon Ross err = smb_usr_drop_tree(sdp, cmd); 88540c0e231SGordon Ross break; 88640c0e231SGordon Ross 88740c0e231SGordon Ross case SMBIOC_IOD_CONNECT: 88840c0e231SGordon Ross case SMBIOC_IOD_NEGOTIATE: 88940c0e231SGordon Ross case SMBIOC_IOD_SSNSETUP: 89040c0e231SGordon Ross case SMBIOC_IOD_WORK: 89140c0e231SGordon Ross case SMBIOC_IOD_IDLE: 892613a2f6bSGordon Ross case SMBIOC_IOD_RCFAIL: 89340c0e231SGordon Ross err = smb_usr_iod_ioctl(sdp, cmd, arg, flags, cr); 89440c0e231SGordon Ross break; 89540c0e231SGordon Ross 89640c0e231SGordon Ross case SMBIOC_PK_ADD: 89740c0e231SGordon Ross case SMBIOC_PK_DEL: 89840c0e231SGordon Ross case SMBIOC_PK_CHK: 89940c0e231SGordon Ross case SMBIOC_PK_DEL_OWNER: 90040c0e231SGordon Ross case SMBIOC_PK_DEL_EVERYONE: 90140c0e231SGordon Ross err = smb_pkey_ioctl(cmd, arg, flags, cr); 9024bff34e3Sthurlow break; 903613a2f6bSGordon Ross 9044bff34e3Sthurlow default: 905613a2f6bSGordon Ross err = ENOTTY; 90640c0e231SGordon Ross break; 9074bff34e3Sthurlow } 9084bff34e3Sthurlow 90940c0e231SGordon Ross mutex_enter(&sdp->sd_lock); 91040c0e231SGordon Ross sdp->sd_flags &= ~NSMBFL_IOCTL; 91140c0e231SGordon Ross mutex_exit(&sdp->sd_lock); 9124bff34e3Sthurlow 913613a2f6bSGordon Ross return (err); 9144bff34e3Sthurlow } 915