1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000-2001 Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: smb_usr.c,v 1.15 2004/12/13 00:25:18 lindak Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 36*4bff34e3Sthurlow 37*4bff34e3Sthurlow #include <sys/param.h> 38*4bff34e3Sthurlow #include <sys/kmem.h> 39*4bff34e3Sthurlow #include <sys/systm.h> 40*4bff34e3Sthurlow #include <sys/policy.h> 41*4bff34e3Sthurlow #include <sys/conf.h> 42*4bff34e3Sthurlow #include <sys/proc.h> 43*4bff34e3Sthurlow #include <sys/fcntl.h> 44*4bff34e3Sthurlow #include <sys/socket.h> 45*4bff34e3Sthurlow #include <sys/cmn_err.h> 46*4bff34e3Sthurlow 47*4bff34e3Sthurlow #ifdef APPLE 48*4bff34e3Sthurlow #include <sys/smb_apple.h> 49*4bff34e3Sthurlow #include <sys/smb_iconv.h> 50*4bff34e3Sthurlow #else 51*4bff34e3Sthurlow #include <netsmb/smb_osdep.h> 52*4bff34e3Sthurlow #endif 53*4bff34e3Sthurlow 54*4bff34e3Sthurlow #include <netsmb/smb.h> 55*4bff34e3Sthurlow #include <netsmb/smb_conn.h> 56*4bff34e3Sthurlow #include <netsmb/smb_rq.h> 57*4bff34e3Sthurlow #include <netsmb/smb_subr.h> 58*4bff34e3Sthurlow #include <netsmb/smb_dev.h> 59*4bff34e3Sthurlow 60*4bff34e3Sthurlow /* 61*4bff34e3Sthurlow * helpers for nsmb device. Can be moved to the smb_dev.c file. 62*4bff34e3Sthurlow */ 63*4bff34e3Sthurlow static void smb_usr_vcspec_free(struct smb_vcspec *spec); 64*4bff34e3Sthurlow 65*4bff34e3Sthurlow /* 66*4bff34e3Sthurlow * Moved the access checks here, just becuase 67*4bff34e3Sthurlow * this was a more convenient place to do it 68*4bff34e3Sthurlow * than in every function calling this. 69*4bff34e3Sthurlow */ 70*4bff34e3Sthurlow static int 71*4bff34e3Sthurlow smb_usr_ioc2vcspec(struct smbioc_ossn *dp, struct smb_vcspec *spec) 72*4bff34e3Sthurlow { 73*4bff34e3Sthurlow cred_t *cr = CRED(); 74*4bff34e3Sthurlow uid_t realuid; 75*4bff34e3Sthurlow 76*4bff34e3Sthurlow /* 77*4bff34e3Sthurlow * Only superuser can specify a UID or GID. 78*4bff34e3Sthurlow */ 79*4bff34e3Sthurlow realuid = crgetruid(cr); 80*4bff34e3Sthurlow if (dp->ioc_owner == SMBM_ANY_OWNER) 81*4bff34e3Sthurlow spec->owner = realuid; 82*4bff34e3Sthurlow else { 83*4bff34e3Sthurlow /* 84*4bff34e3Sthurlow * Do we have the privilege to create with the 85*4bff34e3Sthurlow * specified uid? (does uid == cr->cr_uid, etc.) 86*4bff34e3Sthurlow * MacOS would want suser(), or similar here. 87*4bff34e3Sthurlow */ 88*4bff34e3Sthurlow if (secpolicy_vnode_owner(cr, dp->ioc_owner)) 89*4bff34e3Sthurlow return (EPERM); 90*4bff34e3Sthurlow spec->owner = dp->ioc_owner; 91*4bff34e3Sthurlow } 92*4bff34e3Sthurlow if (dp->ioc_group == SMBM_ANY_GROUP) 93*4bff34e3Sthurlow spec->group = crgetgid(cr); 94*4bff34e3Sthurlow else { 95*4bff34e3Sthurlow /* 96*4bff34e3Sthurlow * Do we have the privilege to create with the 97*4bff34e3Sthurlow * specified gid? (one of our groups?) 98*4bff34e3Sthurlow */ 99*4bff34e3Sthurlow if (groupmember(dp->ioc_group, cr) || 100*4bff34e3Sthurlow secpolicy_vnode_create_gid(cr) == 0) 101*4bff34e3Sthurlow spec->group = dp->ioc_group; 102*4bff34e3Sthurlow else 103*4bff34e3Sthurlow return (EPERM); 104*4bff34e3Sthurlow } 105*4bff34e3Sthurlow 106*4bff34e3Sthurlow /* 107*4bff34e3Sthurlow * Valid codesets? XXX 108*4bff34e3Sthurlow */ 109*4bff34e3Sthurlow if (dp->ioc_localcs[0] == 0) { 110*4bff34e3Sthurlow spec->localcs = "ISO8859-1"; 111*4bff34e3Sthurlow #ifdef NOTYETRESOLVED 112*4bff34e3Sthurlow SMBERROR("no local charset ? dp->ioc_localcs[0]: %d\n", 113*4bff34e3Sthurlow dp->ioc_localcs[0]); 114*4bff34e3Sthurlow return (EINVAL); 115*4bff34e3Sthurlow #endif 116*4bff34e3Sthurlow } else 117*4bff34e3Sthurlow spec->localcs = spec->localcs; 118*4bff34e3Sthurlow 119*4bff34e3Sthurlow /* 120*4bff34e3Sthurlow * Check for valid sa_family. 121*4bff34e3Sthurlow * XXX: Just NetBIOS for now. 122*4bff34e3Sthurlow */ 123*4bff34e3Sthurlow if (dp->ioc_server.sa.sa_family != AF_NETBIOS) 124*4bff34e3Sthurlow return (EINVAL); 125*4bff34e3Sthurlow spec->sap = &dp->ioc_server.sa; 126*4bff34e3Sthurlow 127*4bff34e3Sthurlow if (dp->ioc_local.sa.sa_family) { 128*4bff34e3Sthurlow /* If specified, local AF must be the same. */ 129*4bff34e3Sthurlow if (dp->ioc_local.sa.sa_family != 130*4bff34e3Sthurlow dp->ioc_server.sa.sa_family) 131*4bff34e3Sthurlow return (EINVAL); 132*4bff34e3Sthurlow spec->lap = &dp->ioc_local.sa; 133*4bff34e3Sthurlow } 134*4bff34e3Sthurlow 135*4bff34e3Sthurlow if (dp->ioc_intok) { 136*4bff34e3Sthurlow spec->tok = smb_memdupin(dp->ioc_intok, dp->ioc_intoklen); 137*4bff34e3Sthurlow if (spec->tok == NULL) 138*4bff34e3Sthurlow return (EFAULT); 139*4bff34e3Sthurlow spec->toklen = dp->ioc_intoklen; 140*4bff34e3Sthurlow } 141*4bff34e3Sthurlow 142*4bff34e3Sthurlow spec->srvname = dp->ioc_srvname; 143*4bff34e3Sthurlow spec->pass = dp->ioc_password; 144*4bff34e3Sthurlow spec->domain = dp->ioc_workgroup; 145*4bff34e3Sthurlow spec->username = dp->ioc_user; 146*4bff34e3Sthurlow spec->mode = dp->ioc_mode; 147*4bff34e3Sthurlow spec->rights = dp->ioc_rights; 148*4bff34e3Sthurlow spec->servercs = dp->ioc_servercs; 149*4bff34e3Sthurlow spec->optflags = dp->ioc_opt; 150*4bff34e3Sthurlow 151*4bff34e3Sthurlow return (0); 152*4bff34e3Sthurlow } 153*4bff34e3Sthurlow 154*4bff34e3Sthurlow static void 155*4bff34e3Sthurlow smb_usr_shspec_free(struct smb_sharespec *sspec) 156*4bff34e3Sthurlow { 157*4bff34e3Sthurlow kmem_free(sspec, sizeof (struct smb_sharespec)); 158*4bff34e3Sthurlow } 159*4bff34e3Sthurlow 160*4bff34e3Sthurlow static void 161*4bff34e3Sthurlow smb_usr_vcspec_free(struct smb_vcspec *spec) 162*4bff34e3Sthurlow { 163*4bff34e3Sthurlow 164*4bff34e3Sthurlow if (spec->tok) { 165*4bff34e3Sthurlow kmem_free(spec->tok, spec->toklen); 166*4bff34e3Sthurlow } 167*4bff34e3Sthurlow kmem_free(spec, sizeof (*spec)); 168*4bff34e3Sthurlow } 169*4bff34e3Sthurlow 170*4bff34e3Sthurlow static int 171*4bff34e3Sthurlow smb_usr_ioc2sharespec(struct smbioc_oshare *dp, struct smb_sharespec *spec) 172*4bff34e3Sthurlow { 173*4bff34e3Sthurlow bzero(spec, sizeof (*spec)); 174*4bff34e3Sthurlow spec->name = dp->ioc_share; 175*4bff34e3Sthurlow spec->pass = dp->ioc_password; 176*4bff34e3Sthurlow spec->mode = dp->ioc_mode; 177*4bff34e3Sthurlow spec->rights = dp->ioc_rights; 178*4bff34e3Sthurlow spec->owner = dp->ioc_owner; 179*4bff34e3Sthurlow spec->group = dp->ioc_group; 180*4bff34e3Sthurlow spec->stype = dp->ioc_stype; 181*4bff34e3Sthurlow spec->optflags = dp->ioc_opt; 182*4bff34e3Sthurlow return (0); 183*4bff34e3Sthurlow } 184*4bff34e3Sthurlow 185*4bff34e3Sthurlow int 186*4bff34e3Sthurlow smb_usr_negotiate(struct smbioc_lookup *dp, struct smb_cred *scred, 187*4bff34e3Sthurlow struct smb_vc **vcpp) 188*4bff34e3Sthurlow { 189*4bff34e3Sthurlow struct smb_vc *vcp = NULL; 190*4bff34e3Sthurlow struct smb_vcspec *vspec = NULL; 191*4bff34e3Sthurlow struct smb_sharespec *sspecp = NULL; 192*4bff34e3Sthurlow int error = 0; 193*4bff34e3Sthurlow 194*4bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 195*4bff34e3Sthurlow return (EINVAL); 196*4bff34e3Sthurlow vspec = kmem_zalloc(sizeof (struct smb_vcspec), KM_SLEEP); 197*4bff34e3Sthurlow error = smb_usr_ioc2vcspec(&dp->ioc_ssn, vspec); 198*4bff34e3Sthurlow if (error) 199*4bff34e3Sthurlow return (error); 200*4bff34e3Sthurlow if (dp->ioc_flags & SMBLK_CREATE) 201*4bff34e3Sthurlow vspec->optflags |= SMBVOPT_CREATE; 202*4bff34e3Sthurlow if (dp->ioc_level >= SMBL_SHARE) { 203*4bff34e3Sthurlow sspecp = kmem_alloc(sizeof (*sspecp), KM_SLEEP); 204*4bff34e3Sthurlow error = smb_usr_ioc2sharespec(&dp->ioc_sh, sspecp); 205*4bff34e3Sthurlow if (error) 206*4bff34e3Sthurlow goto out; 207*4bff34e3Sthurlow } 208*4bff34e3Sthurlow error = smb_sm_negotiate(vspec, scred, &vcp); 209*4bff34e3Sthurlow if (error == 0) { 210*4bff34e3Sthurlow *vcpp = vcp; 211*4bff34e3Sthurlow /* 212*4bff34e3Sthurlow * Used to copyout ioc_outtok, outtoklen here, 213*4bff34e3Sthurlow * but that's now in smb_dev. (our caller) 214*4bff34e3Sthurlow * 215*4bff34e3Sthurlow * If this call asked for extended security and 216*4bff34e3Sthurlow * the server does not support it, clear the 217*4bff34e3Sthurlow * flag so the caller knows this. 218*4bff34e3Sthurlow * 219*4bff34e3Sthurlow * XXX: Should just add sv_caps to ioc_ssn, 220*4bff34e3Sthurlow * set the new sv_caps field here, and let 221*4bff34e3Sthurlow * let the copyout of ioc_ssn handle it. 222*4bff34e3Sthurlow */ 223*4bff34e3Sthurlow if (!(vcp->vc_sopt.sv_caps & SMB_CAP_EXT_SECURITY) && 224*4bff34e3Sthurlow (dp->ioc_ssn.ioc_opt & SMBVOPT_EXT_SEC)) { 225*4bff34e3Sthurlow dp->ioc_ssn.ioc_opt &= ~SMBVOPT_EXT_SEC; 226*4bff34e3Sthurlow SMBSDEBUG("turned off extended security"); 227*4bff34e3Sthurlow } 228*4bff34e3Sthurlow } 229*4bff34e3Sthurlow out: 230*4bff34e3Sthurlow smb_usr_vcspec_free(vspec); 231*4bff34e3Sthurlow smb_usr_shspec_free(sspecp); 232*4bff34e3Sthurlow return (error); 233*4bff34e3Sthurlow } 234*4bff34e3Sthurlow 235*4bff34e3Sthurlow int 236*4bff34e3Sthurlow smb_usr_ssnsetup(struct smbioc_lookup *dp, struct smb_cred *scred, 237*4bff34e3Sthurlow struct smb_vc *vcp) 238*4bff34e3Sthurlow { 239*4bff34e3Sthurlow struct smb_vcspec *vspec = NULL; 240*4bff34e3Sthurlow int error; 241*4bff34e3Sthurlow 242*4bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 243*4bff34e3Sthurlow return (EINVAL); 244*4bff34e3Sthurlow 245*4bff34e3Sthurlow vspec = kmem_zalloc(sizeof (struct smb_vcspec), KM_SLEEP); 246*4bff34e3Sthurlow error = smb_usr_ioc2vcspec(&dp->ioc_ssn, vspec); 247*4bff34e3Sthurlow if (error) 248*4bff34e3Sthurlow goto out; 249*4bff34e3Sthurlow 250*4bff34e3Sthurlow error = smb_sm_ssnsetup(vspec, scred, vcp); 251*4bff34e3Sthurlow /* 252*4bff34e3Sthurlow * Moved the copyout of ioc_outtok to 253*4bff34e3Sthurlow * smb_dev.c (our caller) 254*4bff34e3Sthurlow */ 255*4bff34e3Sthurlow 256*4bff34e3Sthurlow out: 257*4bff34e3Sthurlow smb_usr_vcspec_free(vspec); 258*4bff34e3Sthurlow return (error); 259*4bff34e3Sthurlow } 260*4bff34e3Sthurlow 261*4bff34e3Sthurlow 262*4bff34e3Sthurlow int 263*4bff34e3Sthurlow smb_usr_tcon(struct smbioc_lookup *dp, struct smb_cred *scred, 264*4bff34e3Sthurlow struct smb_vc *vcp, struct smb_share **sspp) 265*4bff34e3Sthurlow { 266*4bff34e3Sthurlow struct smb_sharespec *sspecp = NULL; 267*4bff34e3Sthurlow int error; 268*4bff34e3Sthurlow 269*4bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 270*4bff34e3Sthurlow return (EINVAL); 271*4bff34e3Sthurlow 272*4bff34e3Sthurlow if (dp->ioc_level >= SMBL_SHARE) { 273*4bff34e3Sthurlow sspecp = kmem_alloc(sizeof (*sspecp), KM_SLEEP); 274*4bff34e3Sthurlow error = smb_usr_ioc2sharespec(&dp->ioc_sh, sspecp); 275*4bff34e3Sthurlow if (error) 276*4bff34e3Sthurlow goto out; 277*4bff34e3Sthurlow } 278*4bff34e3Sthurlow error = smb_sm_tcon(sspecp, scred, vcp, sspp); 279*4bff34e3Sthurlow 280*4bff34e3Sthurlow out: 281*4bff34e3Sthurlow if (sspecp) 282*4bff34e3Sthurlow smb_usr_shspec_free(sspecp); 283*4bff34e3Sthurlow 284*4bff34e3Sthurlow return (error); 285*4bff34e3Sthurlow } 286*4bff34e3Sthurlow 287*4bff34e3Sthurlow /* 288*4bff34e3Sthurlow * Connect to the resource specified by smbioc_ossn structure. 289*4bff34e3Sthurlow * It may either find an existing connection or try to establish a new one. 290*4bff34e3Sthurlow * If no errors occured smb_vc returned locked and referenced. 291*4bff34e3Sthurlow */ 292*4bff34e3Sthurlow 293*4bff34e3Sthurlow int 294*4bff34e3Sthurlow smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp, 295*4bff34e3Sthurlow struct smb_cred *scred) 296*4bff34e3Sthurlow { 297*4bff34e3Sthurlow struct smb_rq rq, *rqp = &rq; 298*4bff34e3Sthurlow struct mbchain *mbp; 299*4bff34e3Sthurlow struct mdchain *mdp; 300*4bff34e3Sthurlow char *p; 301*4bff34e3Sthurlow size_t wc2; 302*4bff34e3Sthurlow u_int8_t wc; 303*4bff34e3Sthurlow u_int16_t bc; 304*4bff34e3Sthurlow int error; 305*4bff34e3Sthurlow 306*4bff34e3Sthurlow switch (dp->ioc_cmd) { 307*4bff34e3Sthurlow case SMB_COM_TRANSACTION2: 308*4bff34e3Sthurlow case SMB_COM_TRANSACTION2_SECONDARY: 309*4bff34e3Sthurlow case SMB_COM_CLOSE_AND_TREE_DISC: 310*4bff34e3Sthurlow case SMB_COM_TREE_CONNECT: 311*4bff34e3Sthurlow case SMB_COM_TREE_DISCONNECT: 312*4bff34e3Sthurlow case SMB_COM_NEGOTIATE: 313*4bff34e3Sthurlow case SMB_COM_SESSION_SETUP_ANDX: 314*4bff34e3Sthurlow case SMB_COM_LOGOFF_ANDX: 315*4bff34e3Sthurlow case SMB_COM_TREE_CONNECT_ANDX: 316*4bff34e3Sthurlow return (EPERM); 317*4bff34e3Sthurlow } 318*4bff34e3Sthurlow error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred); 319*4bff34e3Sthurlow if (error) 320*4bff34e3Sthurlow return (error); 321*4bff34e3Sthurlow mbp = &rqp->sr_rq; 322*4bff34e3Sthurlow smb_rq_wstart(rqp); 323*4bff34e3Sthurlow error = mb_put_mem(mbp, dp->ioc_twords, 324*4bff34e3Sthurlow dp->ioc_twc * 2, MB_MUSER); 325*4bff34e3Sthurlow if (error) 326*4bff34e3Sthurlow goto bad; 327*4bff34e3Sthurlow smb_rq_wend(rqp); 328*4bff34e3Sthurlow smb_rq_bstart(rqp); 329*4bff34e3Sthurlow error = mb_put_mem(mbp, dp->ioc_tbytes, 330*4bff34e3Sthurlow dp->ioc_tbc, MB_MUSER); 331*4bff34e3Sthurlow if (error) 332*4bff34e3Sthurlow goto bad; 333*4bff34e3Sthurlow smb_rq_bend(rqp); 334*4bff34e3Sthurlow error = smb_rq_simple(rqp); 335*4bff34e3Sthurlow if (error) 336*4bff34e3Sthurlow goto bad; 337*4bff34e3Sthurlow mdp = &rqp->sr_rp; 338*4bff34e3Sthurlow md_get_uint8(mdp, &wc); 339*4bff34e3Sthurlow dp->ioc_rwc = wc; 340*4bff34e3Sthurlow wc2 = wc * 2; 341*4bff34e3Sthurlow if (wc2 > dp->ioc_rpbufsz) { 342*4bff34e3Sthurlow error = EBADRPC; 343*4bff34e3Sthurlow goto bad; 344*4bff34e3Sthurlow } 345*4bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rpbuf, wc2, MB_MUSER); 346*4bff34e3Sthurlow if (error) 347*4bff34e3Sthurlow goto bad; 348*4bff34e3Sthurlow md_get_uint16le(mdp, &bc); 349*4bff34e3Sthurlow if ((wc2 + bc) > dp->ioc_rpbufsz) { 350*4bff34e3Sthurlow error = EBADRPC; 351*4bff34e3Sthurlow goto bad; 352*4bff34e3Sthurlow } 353*4bff34e3Sthurlow dp->ioc_rbc = bc; 354*4bff34e3Sthurlow p = dp->ioc_rpbuf; 355*4bff34e3Sthurlow error = md_get_mem(mdp, p + wc2, bc, MB_MUSER); 356*4bff34e3Sthurlow bad: 357*4bff34e3Sthurlow dp->ioc_errclass = rqp->sr_errclass; 358*4bff34e3Sthurlow dp->ioc_serror = rqp->sr_serror; 359*4bff34e3Sthurlow dp->ioc_error = rqp->sr_error; 360*4bff34e3Sthurlow smb_rq_done(rqp); 361*4bff34e3Sthurlow return (error); 362*4bff34e3Sthurlow 363*4bff34e3Sthurlow } 364*4bff34e3Sthurlow 365*4bff34e3Sthurlow static int 366*4bff34e3Sthurlow smb_cpdatain(struct mbchain *mbp, int len, char *data) 367*4bff34e3Sthurlow { 368*4bff34e3Sthurlow int error; 369*4bff34e3Sthurlow 370*4bff34e3Sthurlow if (len == 0) 371*4bff34e3Sthurlow return (0); 372*4bff34e3Sthurlow error = mb_init(mbp); 373*4bff34e3Sthurlow if (error) 374*4bff34e3Sthurlow return (error); 375*4bff34e3Sthurlow return (mb_put_mem(mbp, data, len, MB_MUSER)); 376*4bff34e3Sthurlow } 377*4bff34e3Sthurlow 378*4bff34e3Sthurlow int 379*4bff34e3Sthurlow smb_usr_t2request(struct smb_share *ssp, smbioc_t2rq_t *dp, 380*4bff34e3Sthurlow struct smb_cred *scred) 381*4bff34e3Sthurlow { 382*4bff34e3Sthurlow struct smb_t2rq t2, *t2p = &t2; 383*4bff34e3Sthurlow struct mdchain *mdp; 384*4bff34e3Sthurlow int error, len; 385*4bff34e3Sthurlow 386*4bff34e3Sthurlow if (dp->ioc_setupcnt > SMB_MAXSETUPWORDS) 387*4bff34e3Sthurlow return (EINVAL); 388*4bff34e3Sthurlow 389*4bff34e3Sthurlow t2p = (struct smb_t2rq *)kmem_alloc(sizeof (struct smb_t2rq), KM_SLEEP); 390*4bff34e3Sthurlow if (t2p == NULL) 391*4bff34e3Sthurlow return (ENOMEM); 392*4bff34e3Sthurlow error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup, dp->ioc_setupcnt, 393*4bff34e3Sthurlow scred); 394*4bff34e3Sthurlow if (error) 395*4bff34e3Sthurlow return (error); 396*4bff34e3Sthurlow len = t2p->t2_setupcount = dp->ioc_setupcnt; 397*4bff34e3Sthurlow if (len > 1) 398*4bff34e3Sthurlow t2p->t2_setupdata = dp->ioc_setup; 399*4bff34e3Sthurlow if (dp->ioc_name) { 400*4bff34e3Sthurlow bcopy(dp->ioc_name, t2p->t_name, 128); 401*4bff34e3Sthurlow if (t2p->t_name == NULL) { 402*4bff34e3Sthurlow error = ENOMEM; 403*4bff34e3Sthurlow goto bad; 404*4bff34e3Sthurlow } 405*4bff34e3Sthurlow } 406*4bff34e3Sthurlow t2p->t2_maxscount = 0; 407*4bff34e3Sthurlow t2p->t2_maxpcount = dp->ioc_rparamcnt; 408*4bff34e3Sthurlow t2p->t2_maxdcount = dp->ioc_rdatacnt; 409*4bff34e3Sthurlow error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, 410*4bff34e3Sthurlow dp->ioc_tparam); 411*4bff34e3Sthurlow if (error) 412*4bff34e3Sthurlow goto bad; 413*4bff34e3Sthurlow error = smb_cpdatain(&t2p->t2_tdata, 414*4bff34e3Sthurlow dp->ioc_tdatacnt, dp->ioc_tdata); 415*4bff34e3Sthurlow if (error) 416*4bff34e3Sthurlow goto bad; 417*4bff34e3Sthurlow error = smb_t2_request(t2p); 418*4bff34e3Sthurlow dp->ioc_errclass = t2p->t2_sr_errclass; 419*4bff34e3Sthurlow dp->ioc_serror = t2p->t2_sr_serror; 420*4bff34e3Sthurlow dp->ioc_error = t2p->t2_sr_error; 421*4bff34e3Sthurlow dp->ioc_rpflags2 = t2p->t2_sr_rpflags2; 422*4bff34e3Sthurlow if (error) 423*4bff34e3Sthurlow goto bad; 424*4bff34e3Sthurlow mdp = &t2p->t2_rparam; 425*4bff34e3Sthurlow if (mdp->md_top) { 426*4bff34e3Sthurlow mblk_t *m = mdp->md_top; 427*4bff34e3Sthurlow #ifdef lint 428*4bff34e3Sthurlow m = m; 429*4bff34e3Sthurlow #endif 430*4bff34e3Sthurlow len = m_fixhdr(mdp->md_top); 431*4bff34e3Sthurlow if (len > dp->ioc_rparamcnt) { 432*4bff34e3Sthurlow error = EMSGSIZE; 433*4bff34e3Sthurlow goto bad; 434*4bff34e3Sthurlow } 435*4bff34e3Sthurlow dp->ioc_rparamcnt = (ushort_t)len; 436*4bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rparam, 437*4bff34e3Sthurlow len, MB_MUSER); 438*4bff34e3Sthurlow if (error) { 439*4bff34e3Sthurlow goto bad; 440*4bff34e3Sthurlow } 441*4bff34e3Sthurlow } else 442*4bff34e3Sthurlow dp->ioc_rparamcnt = 0; 443*4bff34e3Sthurlow mdp = &t2p->t2_rdata; 444*4bff34e3Sthurlow if (mdp->md_top) { 445*4bff34e3Sthurlow mblk_t *m = mdp->md_top; 446*4bff34e3Sthurlow #ifdef lint 447*4bff34e3Sthurlow m = m; 448*4bff34e3Sthurlow #endif 449*4bff34e3Sthurlow len = m_fixhdr(mdp->md_top); 450*4bff34e3Sthurlow if (len > dp->ioc_rdatacnt) { 451*4bff34e3Sthurlow error = EMSGSIZE; 452*4bff34e3Sthurlow goto bad; 453*4bff34e3Sthurlow } 454*4bff34e3Sthurlow dp->ioc_rdatacnt = (ushort_t)len; 455*4bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rdata, 456*4bff34e3Sthurlow len, MB_MUSER); 457*4bff34e3Sthurlow if (error) { 458*4bff34e3Sthurlow goto bad; 459*4bff34e3Sthurlow } 460*4bff34e3Sthurlow } else 461*4bff34e3Sthurlow dp->ioc_rdatacnt = 0; 462*4bff34e3Sthurlow bad: 463*4bff34e3Sthurlow smb_t2_done(t2p); 464*4bff34e3Sthurlow return (error); 465*4bff34e3Sthurlow } 466*4bff34e3Sthurlow 467*4bff34e3Sthurlow /* 468*4bff34e3Sthurlow * Helper for nsmb_ioctl cases 469*4bff34e3Sthurlow * SMBIOC_READ, SMBIOC_WRITE 470*4bff34e3Sthurlow */ 471*4bff34e3Sthurlow int 472*4bff34e3Sthurlow smb_usr_rw(struct smb_share *ssp, smbioc_rw_t *rwrq, 473*4bff34e3Sthurlow int cmd, struct smb_cred *scred) 474*4bff34e3Sthurlow { 475*4bff34e3Sthurlow struct iovec aiov[1]; 476*4bff34e3Sthurlow struct uio auio; 477*4bff34e3Sthurlow u_int16_t fh; 478*4bff34e3Sthurlow int error; 479*4bff34e3Sthurlow uio_rw_t rw; 480*4bff34e3Sthurlow 481*4bff34e3Sthurlow switch (cmd) { 482*4bff34e3Sthurlow case SMBIOC_READ: 483*4bff34e3Sthurlow rw = UIO_READ; 484*4bff34e3Sthurlow break; 485*4bff34e3Sthurlow case SMBIOC_WRITE: 486*4bff34e3Sthurlow rw = UIO_WRITE; 487*4bff34e3Sthurlow break; 488*4bff34e3Sthurlow default: 489*4bff34e3Sthurlow return (ENODEV); 490*4bff34e3Sthurlow } 491*4bff34e3Sthurlow 492*4bff34e3Sthurlow fh = htoles(rwrq->ioc_fh); 493*4bff34e3Sthurlow 494*4bff34e3Sthurlow aiov[0].iov_base = rwrq->ioc_base; 495*4bff34e3Sthurlow aiov[0].iov_len = (size_t)rwrq->ioc_cnt; 496*4bff34e3Sthurlow 497*4bff34e3Sthurlow auio.uio_iov = aiov; 498*4bff34e3Sthurlow auio.uio_iovcnt = 1; 499*4bff34e3Sthurlow auio.uio_loffset = rwrq->ioc_offset; 500*4bff34e3Sthurlow auio.uio_segflg = UIO_USERSPACE; 501*4bff34e3Sthurlow auio.uio_fmode = 0; 502*4bff34e3Sthurlow auio.uio_resid = (size_t)rwrq->ioc_cnt; 503*4bff34e3Sthurlow 504*4bff34e3Sthurlow error = smb_rwuio(ssp, fh, rw, &auio, scred, 0); 505*4bff34e3Sthurlow 506*4bff34e3Sthurlow /* 507*4bff34e3Sthurlow * On return ioc_cnt holds the 508*4bff34e3Sthurlow * number of bytes transferred. 509*4bff34e3Sthurlow */ 510*4bff34e3Sthurlow rwrq->ioc_cnt -= auio.uio_resid; 511*4bff34e3Sthurlow 512*4bff34e3Sthurlow return (error); 513*4bff34e3Sthurlow } 514