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 354bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 364bff34e3Sthurlow 374bff34e3Sthurlow #include <sys/param.h> 384bff34e3Sthurlow #include <sys/kmem.h> 394bff34e3Sthurlow #include <sys/systm.h> 404bff34e3Sthurlow #include <sys/policy.h> 414bff34e3Sthurlow #include <sys/conf.h> 424bff34e3Sthurlow #include <sys/proc.h> 434bff34e3Sthurlow #include <sys/fcntl.h> 444bff34e3Sthurlow #include <sys/socket.h> 454bff34e3Sthurlow #include <sys/cmn_err.h> 464bff34e3Sthurlow 474bff34e3Sthurlow #ifdef APPLE 484bff34e3Sthurlow #include <sys/smb_apple.h> 494bff34e3Sthurlow #include <sys/smb_iconv.h> 504bff34e3Sthurlow #else 514bff34e3Sthurlow #include <netsmb/smb_osdep.h> 524bff34e3Sthurlow #endif 534bff34e3Sthurlow 544bff34e3Sthurlow #include <netsmb/smb.h> 554bff34e3Sthurlow #include <netsmb/smb_conn.h> 564bff34e3Sthurlow #include <netsmb/smb_rq.h> 574bff34e3Sthurlow #include <netsmb/smb_subr.h> 584bff34e3Sthurlow #include <netsmb/smb_dev.h> 594bff34e3Sthurlow 604bff34e3Sthurlow /* 614bff34e3Sthurlow * helpers for nsmb device. Can be moved to the smb_dev.c file. 624bff34e3Sthurlow */ 634bff34e3Sthurlow static void smb_usr_vcspec_free(struct smb_vcspec *spec); 644bff34e3Sthurlow 654bff34e3Sthurlow /* 664bff34e3Sthurlow * Moved the access checks here, just becuase 674bff34e3Sthurlow * this was a more convenient place to do it 684bff34e3Sthurlow * than in every function calling this. 694bff34e3Sthurlow */ 704bff34e3Sthurlow static int 714bff34e3Sthurlow smb_usr_ioc2vcspec(struct smbioc_ossn *dp, struct smb_vcspec *spec) 724bff34e3Sthurlow { 734bff34e3Sthurlow cred_t *cr = CRED(); 744bff34e3Sthurlow uid_t realuid; 754bff34e3Sthurlow 764bff34e3Sthurlow /* 774bff34e3Sthurlow * Only superuser can specify a UID or GID. 784bff34e3Sthurlow */ 794bff34e3Sthurlow realuid = crgetruid(cr); 804bff34e3Sthurlow if (dp->ioc_owner == SMBM_ANY_OWNER) 814bff34e3Sthurlow spec->owner = realuid; 824bff34e3Sthurlow else { 834bff34e3Sthurlow /* 844bff34e3Sthurlow * Do we have the privilege to create with the 854bff34e3Sthurlow * specified uid? (does uid == cr->cr_uid, etc.) 864bff34e3Sthurlow * MacOS would want suser(), or similar here. 874bff34e3Sthurlow */ 884bff34e3Sthurlow if (secpolicy_vnode_owner(cr, dp->ioc_owner)) 894bff34e3Sthurlow return (EPERM); 904bff34e3Sthurlow spec->owner = dp->ioc_owner; 914bff34e3Sthurlow } 924bff34e3Sthurlow if (dp->ioc_group == SMBM_ANY_GROUP) 934bff34e3Sthurlow spec->group = crgetgid(cr); 944bff34e3Sthurlow else { 954bff34e3Sthurlow /* 964bff34e3Sthurlow * Do we have the privilege to create with the 974bff34e3Sthurlow * specified gid? (one of our groups?) 984bff34e3Sthurlow */ 994bff34e3Sthurlow if (groupmember(dp->ioc_group, cr) || 1004bff34e3Sthurlow secpolicy_vnode_create_gid(cr) == 0) 1014bff34e3Sthurlow spec->group = dp->ioc_group; 1024bff34e3Sthurlow else 1034bff34e3Sthurlow return (EPERM); 1044bff34e3Sthurlow } 1054bff34e3Sthurlow 1064bff34e3Sthurlow /* 1074bff34e3Sthurlow * Valid codesets? XXX 1084bff34e3Sthurlow */ 1094bff34e3Sthurlow if (dp->ioc_localcs[0] == 0) { 1104bff34e3Sthurlow spec->localcs = "ISO8859-1"; 1114bff34e3Sthurlow #ifdef NOTYETRESOLVED 1124bff34e3Sthurlow SMBERROR("no local charset ? dp->ioc_localcs[0]: %d\n", 1134bff34e3Sthurlow dp->ioc_localcs[0]); 1144bff34e3Sthurlow return (EINVAL); 1154bff34e3Sthurlow #endif 1164bff34e3Sthurlow } else 1174bff34e3Sthurlow spec->localcs = spec->localcs; 1184bff34e3Sthurlow 1194bff34e3Sthurlow /* 1204bff34e3Sthurlow * Check for valid sa_family. 1214bff34e3Sthurlow * XXX: Just NetBIOS for now. 1224bff34e3Sthurlow */ 1234bff34e3Sthurlow if (dp->ioc_server.sa.sa_family != AF_NETBIOS) 1244bff34e3Sthurlow return (EINVAL); 1254bff34e3Sthurlow spec->sap = &dp->ioc_server.sa; 1264bff34e3Sthurlow 1274bff34e3Sthurlow if (dp->ioc_local.sa.sa_family) { 1284bff34e3Sthurlow /* If specified, local AF must be the same. */ 1294bff34e3Sthurlow if (dp->ioc_local.sa.sa_family != 1304bff34e3Sthurlow dp->ioc_server.sa.sa_family) 1314bff34e3Sthurlow return (EINVAL); 1324bff34e3Sthurlow spec->lap = &dp->ioc_local.sa; 1334bff34e3Sthurlow } 1344bff34e3Sthurlow 1354bff34e3Sthurlow if (dp->ioc_intok) { 1364bff34e3Sthurlow spec->tok = smb_memdupin(dp->ioc_intok, dp->ioc_intoklen); 1374bff34e3Sthurlow if (spec->tok == NULL) 1384bff34e3Sthurlow return (EFAULT); 1394bff34e3Sthurlow spec->toklen = dp->ioc_intoklen; 1404bff34e3Sthurlow } 1414bff34e3Sthurlow 1424bff34e3Sthurlow spec->srvname = dp->ioc_srvname; 1434bff34e3Sthurlow spec->pass = dp->ioc_password; 1444bff34e3Sthurlow spec->domain = dp->ioc_workgroup; 1454bff34e3Sthurlow spec->username = dp->ioc_user; 1464bff34e3Sthurlow spec->mode = dp->ioc_mode; 1474bff34e3Sthurlow spec->rights = dp->ioc_rights; 1484bff34e3Sthurlow spec->servercs = dp->ioc_servercs; 1494bff34e3Sthurlow spec->optflags = dp->ioc_opt; 1504bff34e3Sthurlow 1514bff34e3Sthurlow return (0); 1524bff34e3Sthurlow } 1534bff34e3Sthurlow 1544bff34e3Sthurlow static void 1554bff34e3Sthurlow smb_usr_shspec_free(struct smb_sharespec *sspec) 1564bff34e3Sthurlow { 1574bff34e3Sthurlow kmem_free(sspec, sizeof (struct smb_sharespec)); 1584bff34e3Sthurlow } 1594bff34e3Sthurlow 1604bff34e3Sthurlow static void 1614bff34e3Sthurlow smb_usr_vcspec_free(struct smb_vcspec *spec) 1624bff34e3Sthurlow { 1634bff34e3Sthurlow 1644bff34e3Sthurlow if (spec->tok) { 1654bff34e3Sthurlow kmem_free(spec->tok, spec->toklen); 1664bff34e3Sthurlow } 1674bff34e3Sthurlow kmem_free(spec, sizeof (*spec)); 1684bff34e3Sthurlow } 1694bff34e3Sthurlow 1704bff34e3Sthurlow static int 1714bff34e3Sthurlow smb_usr_ioc2sharespec(struct smbioc_oshare *dp, struct smb_sharespec *spec) 1724bff34e3Sthurlow { 1734bff34e3Sthurlow bzero(spec, sizeof (*spec)); 1744bff34e3Sthurlow spec->name = dp->ioc_share; 1754bff34e3Sthurlow spec->pass = dp->ioc_password; 1764bff34e3Sthurlow spec->mode = dp->ioc_mode; 1774bff34e3Sthurlow spec->rights = dp->ioc_rights; 1784bff34e3Sthurlow spec->owner = dp->ioc_owner; 1794bff34e3Sthurlow spec->group = dp->ioc_group; 1804bff34e3Sthurlow spec->stype = dp->ioc_stype; 1814bff34e3Sthurlow spec->optflags = dp->ioc_opt; 1824bff34e3Sthurlow return (0); 1834bff34e3Sthurlow } 1844bff34e3Sthurlow 185*1b34bc4aSbs int 186*1b34bc4aSbs smb_usr_findvc(struct smbioc_lookup *dp, struct smb_cred *scred, 187*1b34bc4aSbs struct smb_vc **vcpp) 188*1b34bc4aSbs { 189*1b34bc4aSbs struct smb_vc *vcp = NULL; 190*1b34bc4aSbs struct smb_vcspec *vspec = NULL; 191*1b34bc4aSbs int error = 0; 192*1b34bc4aSbs 193*1b34bc4aSbs if (dp->ioc_flags & SMBLK_CREATE) 194*1b34bc4aSbs return (EINVAL); 195*1b34bc4aSbs if (dp->ioc_level != SMBL_VC) 196*1b34bc4aSbs return (EINVAL); 197*1b34bc4aSbs vspec = kmem_zalloc(sizeof (struct smb_vcspec), KM_SLEEP); 198*1b34bc4aSbs error = smb_usr_ioc2vcspec(&dp->ioc_ssn, vspec); 199*1b34bc4aSbs if (error) 200*1b34bc4aSbs goto out; 201*1b34bc4aSbs error = smb_sm_findvc(vspec, scred, &vcp); 202*1b34bc4aSbs if (error == 0) 203*1b34bc4aSbs *vcpp = vcp; 204*1b34bc4aSbs out: 205*1b34bc4aSbs smb_usr_vcspec_free(vspec); 206*1b34bc4aSbs return (error); 207*1b34bc4aSbs } 208*1b34bc4aSbs 2094bff34e3Sthurlow int 2104bff34e3Sthurlow smb_usr_negotiate(struct smbioc_lookup *dp, struct smb_cred *scred, 2114bff34e3Sthurlow struct smb_vc **vcpp) 2124bff34e3Sthurlow { 2134bff34e3Sthurlow struct smb_vc *vcp = NULL; 2144bff34e3Sthurlow struct smb_vcspec *vspec = NULL; 2154bff34e3Sthurlow struct smb_sharespec *sspecp = NULL; 2164bff34e3Sthurlow int error = 0; 2174bff34e3Sthurlow 2184bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 2194bff34e3Sthurlow return (EINVAL); 2204bff34e3Sthurlow vspec = kmem_zalloc(sizeof (struct smb_vcspec), KM_SLEEP); 2214bff34e3Sthurlow error = smb_usr_ioc2vcspec(&dp->ioc_ssn, vspec); 2224bff34e3Sthurlow if (error) 2234bff34e3Sthurlow return (error); 2244bff34e3Sthurlow if (dp->ioc_flags & SMBLK_CREATE) 2254bff34e3Sthurlow vspec->optflags |= SMBVOPT_CREATE; 2264bff34e3Sthurlow if (dp->ioc_level >= SMBL_SHARE) { 2274bff34e3Sthurlow sspecp = kmem_alloc(sizeof (*sspecp), KM_SLEEP); 2284bff34e3Sthurlow error = smb_usr_ioc2sharespec(&dp->ioc_sh, sspecp); 2294bff34e3Sthurlow if (error) 2304bff34e3Sthurlow goto out; 2314bff34e3Sthurlow } 2324bff34e3Sthurlow error = smb_sm_negotiate(vspec, scred, &vcp); 2334bff34e3Sthurlow if (error == 0) { 2344bff34e3Sthurlow *vcpp = vcp; 2354bff34e3Sthurlow /* 2364bff34e3Sthurlow * Used to copyout ioc_outtok, outtoklen here, 2374bff34e3Sthurlow * but that's now in smb_dev. (our caller) 2384bff34e3Sthurlow * 2394bff34e3Sthurlow * If this call asked for extended security and 2404bff34e3Sthurlow * the server does not support it, clear the 2414bff34e3Sthurlow * flag so the caller knows this. 2424bff34e3Sthurlow * 2434bff34e3Sthurlow * XXX: Should just add sv_caps to ioc_ssn, 2444bff34e3Sthurlow * set the new sv_caps field here, and let 2454bff34e3Sthurlow * let the copyout of ioc_ssn handle it. 2464bff34e3Sthurlow */ 2474bff34e3Sthurlow if (!(vcp->vc_sopt.sv_caps & SMB_CAP_EXT_SECURITY) && 2484bff34e3Sthurlow (dp->ioc_ssn.ioc_opt & SMBVOPT_EXT_SEC)) { 2494bff34e3Sthurlow dp->ioc_ssn.ioc_opt &= ~SMBVOPT_EXT_SEC; 2504bff34e3Sthurlow SMBSDEBUG("turned off extended security"); 2514bff34e3Sthurlow } 2524bff34e3Sthurlow } 2534bff34e3Sthurlow out: 2544bff34e3Sthurlow smb_usr_vcspec_free(vspec); 2554bff34e3Sthurlow smb_usr_shspec_free(sspecp); 2564bff34e3Sthurlow return (error); 2574bff34e3Sthurlow } 2584bff34e3Sthurlow 2594bff34e3Sthurlow int 2604bff34e3Sthurlow smb_usr_ssnsetup(struct smbioc_lookup *dp, struct smb_cred *scred, 2614bff34e3Sthurlow struct smb_vc *vcp) 2624bff34e3Sthurlow { 2634bff34e3Sthurlow struct smb_vcspec *vspec = NULL; 2644bff34e3Sthurlow int error; 2654bff34e3Sthurlow 2664bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 2674bff34e3Sthurlow return (EINVAL); 2684bff34e3Sthurlow 2694bff34e3Sthurlow vspec = kmem_zalloc(sizeof (struct smb_vcspec), KM_SLEEP); 2704bff34e3Sthurlow error = smb_usr_ioc2vcspec(&dp->ioc_ssn, vspec); 2714bff34e3Sthurlow if (error) 2724bff34e3Sthurlow goto out; 2734bff34e3Sthurlow 2744bff34e3Sthurlow error = smb_sm_ssnsetup(vspec, scred, vcp); 2754bff34e3Sthurlow /* 2764bff34e3Sthurlow * Moved the copyout of ioc_outtok to 2774bff34e3Sthurlow * smb_dev.c (our caller) 2784bff34e3Sthurlow */ 2794bff34e3Sthurlow 2804bff34e3Sthurlow out: 2814bff34e3Sthurlow smb_usr_vcspec_free(vspec); 2824bff34e3Sthurlow return (error); 2834bff34e3Sthurlow } 2844bff34e3Sthurlow 2854bff34e3Sthurlow 2864bff34e3Sthurlow int 2874bff34e3Sthurlow smb_usr_tcon(struct smbioc_lookup *dp, struct smb_cred *scred, 2884bff34e3Sthurlow struct smb_vc *vcp, struct smb_share **sspp) 2894bff34e3Sthurlow { 2904bff34e3Sthurlow struct smb_sharespec *sspecp = NULL; 2914bff34e3Sthurlow int error; 2924bff34e3Sthurlow 2934bff34e3Sthurlow if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 2944bff34e3Sthurlow return (EINVAL); 2954bff34e3Sthurlow 2964bff34e3Sthurlow if (dp->ioc_level >= SMBL_SHARE) { 2974bff34e3Sthurlow sspecp = kmem_alloc(sizeof (*sspecp), KM_SLEEP); 2984bff34e3Sthurlow error = smb_usr_ioc2sharespec(&dp->ioc_sh, sspecp); 2994bff34e3Sthurlow if (error) 3004bff34e3Sthurlow goto out; 3014bff34e3Sthurlow } 3024bff34e3Sthurlow error = smb_sm_tcon(sspecp, scred, vcp, sspp); 3034bff34e3Sthurlow 3044bff34e3Sthurlow out: 3054bff34e3Sthurlow if (sspecp) 3064bff34e3Sthurlow smb_usr_shspec_free(sspecp); 3074bff34e3Sthurlow 3084bff34e3Sthurlow return (error); 3094bff34e3Sthurlow } 3104bff34e3Sthurlow 3114bff34e3Sthurlow /* 3124bff34e3Sthurlow * Connect to the resource specified by smbioc_ossn structure. 3134bff34e3Sthurlow * It may either find an existing connection or try to establish a new one. 3144bff34e3Sthurlow * If no errors occured smb_vc returned locked and referenced. 3154bff34e3Sthurlow */ 3164bff34e3Sthurlow 3174bff34e3Sthurlow int 3184bff34e3Sthurlow smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp, 3194bff34e3Sthurlow struct smb_cred *scred) 3204bff34e3Sthurlow { 3214bff34e3Sthurlow struct smb_rq rq, *rqp = &rq; 3224bff34e3Sthurlow struct mbchain *mbp; 3234bff34e3Sthurlow struct mdchain *mdp; 3244bff34e3Sthurlow char *p; 3254bff34e3Sthurlow size_t wc2; 3264bff34e3Sthurlow u_int8_t wc; 3274bff34e3Sthurlow u_int16_t bc; 3284bff34e3Sthurlow int error; 3294bff34e3Sthurlow 3304bff34e3Sthurlow switch (dp->ioc_cmd) { 3314bff34e3Sthurlow case SMB_COM_TRANSACTION2: 3324bff34e3Sthurlow case SMB_COM_TRANSACTION2_SECONDARY: 3334bff34e3Sthurlow case SMB_COM_CLOSE_AND_TREE_DISC: 3344bff34e3Sthurlow case SMB_COM_TREE_CONNECT: 3354bff34e3Sthurlow case SMB_COM_TREE_DISCONNECT: 3364bff34e3Sthurlow case SMB_COM_NEGOTIATE: 3374bff34e3Sthurlow case SMB_COM_SESSION_SETUP_ANDX: 3384bff34e3Sthurlow case SMB_COM_LOGOFF_ANDX: 3394bff34e3Sthurlow case SMB_COM_TREE_CONNECT_ANDX: 3404bff34e3Sthurlow return (EPERM); 3414bff34e3Sthurlow } 3424bff34e3Sthurlow error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred); 3434bff34e3Sthurlow if (error) 3444bff34e3Sthurlow return (error); 3454bff34e3Sthurlow mbp = &rqp->sr_rq; 3464bff34e3Sthurlow smb_rq_wstart(rqp); 3474bff34e3Sthurlow error = mb_put_mem(mbp, dp->ioc_twords, 3484bff34e3Sthurlow dp->ioc_twc * 2, MB_MUSER); 3494bff34e3Sthurlow if (error) 3504bff34e3Sthurlow goto bad; 3514bff34e3Sthurlow smb_rq_wend(rqp); 3524bff34e3Sthurlow smb_rq_bstart(rqp); 3534bff34e3Sthurlow error = mb_put_mem(mbp, dp->ioc_tbytes, 3544bff34e3Sthurlow dp->ioc_tbc, MB_MUSER); 3554bff34e3Sthurlow if (error) 3564bff34e3Sthurlow goto bad; 3574bff34e3Sthurlow smb_rq_bend(rqp); 3584bff34e3Sthurlow error = smb_rq_simple(rqp); 3594bff34e3Sthurlow if (error) 3604bff34e3Sthurlow goto bad; 3614bff34e3Sthurlow mdp = &rqp->sr_rp; 3624bff34e3Sthurlow md_get_uint8(mdp, &wc); 3634bff34e3Sthurlow dp->ioc_rwc = wc; 3644bff34e3Sthurlow wc2 = wc * 2; 3654bff34e3Sthurlow if (wc2 > dp->ioc_rpbufsz) { 3664bff34e3Sthurlow error = EBADRPC; 3674bff34e3Sthurlow goto bad; 3684bff34e3Sthurlow } 3694bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rpbuf, wc2, MB_MUSER); 3704bff34e3Sthurlow if (error) 3714bff34e3Sthurlow goto bad; 3724bff34e3Sthurlow md_get_uint16le(mdp, &bc); 3734bff34e3Sthurlow if ((wc2 + bc) > dp->ioc_rpbufsz) { 3744bff34e3Sthurlow error = EBADRPC; 3754bff34e3Sthurlow goto bad; 3764bff34e3Sthurlow } 3774bff34e3Sthurlow dp->ioc_rbc = bc; 3784bff34e3Sthurlow p = dp->ioc_rpbuf; 3794bff34e3Sthurlow error = md_get_mem(mdp, p + wc2, bc, MB_MUSER); 3804bff34e3Sthurlow bad: 3814bff34e3Sthurlow dp->ioc_errclass = rqp->sr_errclass; 3824bff34e3Sthurlow dp->ioc_serror = rqp->sr_serror; 3834bff34e3Sthurlow dp->ioc_error = rqp->sr_error; 3844bff34e3Sthurlow smb_rq_done(rqp); 3854bff34e3Sthurlow return (error); 3864bff34e3Sthurlow 3874bff34e3Sthurlow } 3884bff34e3Sthurlow 3894bff34e3Sthurlow static int 3904bff34e3Sthurlow smb_cpdatain(struct mbchain *mbp, int len, char *data) 3914bff34e3Sthurlow { 3924bff34e3Sthurlow int error; 3934bff34e3Sthurlow 3944bff34e3Sthurlow if (len == 0) 3954bff34e3Sthurlow return (0); 3964bff34e3Sthurlow error = mb_init(mbp); 3974bff34e3Sthurlow if (error) 3984bff34e3Sthurlow return (error); 3994bff34e3Sthurlow return (mb_put_mem(mbp, data, len, MB_MUSER)); 4004bff34e3Sthurlow } 4014bff34e3Sthurlow 4024bff34e3Sthurlow int 4034bff34e3Sthurlow smb_usr_t2request(struct smb_share *ssp, smbioc_t2rq_t *dp, 4044bff34e3Sthurlow struct smb_cred *scred) 4054bff34e3Sthurlow { 4064bff34e3Sthurlow struct smb_t2rq t2, *t2p = &t2; 4074bff34e3Sthurlow struct mdchain *mdp; 4084bff34e3Sthurlow int error, len; 4094bff34e3Sthurlow 4104bff34e3Sthurlow if (dp->ioc_setupcnt > SMB_MAXSETUPWORDS) 4114bff34e3Sthurlow return (EINVAL); 4124bff34e3Sthurlow 4134bff34e3Sthurlow t2p = (struct smb_t2rq *)kmem_alloc(sizeof (struct smb_t2rq), KM_SLEEP); 4144bff34e3Sthurlow if (t2p == NULL) 4154bff34e3Sthurlow return (ENOMEM); 4164bff34e3Sthurlow error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup, dp->ioc_setupcnt, 4174bff34e3Sthurlow scred); 4184bff34e3Sthurlow if (error) 4194bff34e3Sthurlow return (error); 4204bff34e3Sthurlow len = t2p->t2_setupcount = dp->ioc_setupcnt; 4214bff34e3Sthurlow if (len > 1) 4224bff34e3Sthurlow t2p->t2_setupdata = dp->ioc_setup; 4234bff34e3Sthurlow if (dp->ioc_name) { 4244bff34e3Sthurlow bcopy(dp->ioc_name, t2p->t_name, 128); 4254bff34e3Sthurlow if (t2p->t_name == NULL) { 4264bff34e3Sthurlow error = ENOMEM; 4274bff34e3Sthurlow goto bad; 4284bff34e3Sthurlow } 4294bff34e3Sthurlow } 4304bff34e3Sthurlow t2p->t2_maxscount = 0; 4314bff34e3Sthurlow t2p->t2_maxpcount = dp->ioc_rparamcnt; 4324bff34e3Sthurlow t2p->t2_maxdcount = dp->ioc_rdatacnt; 4334bff34e3Sthurlow error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, 4344bff34e3Sthurlow dp->ioc_tparam); 4354bff34e3Sthurlow if (error) 4364bff34e3Sthurlow goto bad; 4374bff34e3Sthurlow error = smb_cpdatain(&t2p->t2_tdata, 4384bff34e3Sthurlow dp->ioc_tdatacnt, dp->ioc_tdata); 4394bff34e3Sthurlow if (error) 4404bff34e3Sthurlow goto bad; 4414bff34e3Sthurlow error = smb_t2_request(t2p); 4424bff34e3Sthurlow dp->ioc_errclass = t2p->t2_sr_errclass; 4434bff34e3Sthurlow dp->ioc_serror = t2p->t2_sr_serror; 4444bff34e3Sthurlow dp->ioc_error = t2p->t2_sr_error; 4454bff34e3Sthurlow dp->ioc_rpflags2 = t2p->t2_sr_rpflags2; 4464bff34e3Sthurlow if (error) 4474bff34e3Sthurlow goto bad; 4484bff34e3Sthurlow mdp = &t2p->t2_rparam; 4494bff34e3Sthurlow if (mdp->md_top) { 4504bff34e3Sthurlow mblk_t *m = mdp->md_top; 4514bff34e3Sthurlow #ifdef lint 4524bff34e3Sthurlow m = m; 4534bff34e3Sthurlow #endif 4544bff34e3Sthurlow len = m_fixhdr(mdp->md_top); 4554bff34e3Sthurlow if (len > dp->ioc_rparamcnt) { 4564bff34e3Sthurlow error = EMSGSIZE; 4574bff34e3Sthurlow goto bad; 4584bff34e3Sthurlow } 4594bff34e3Sthurlow dp->ioc_rparamcnt = (ushort_t)len; 4604bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rparam, 4614bff34e3Sthurlow len, MB_MUSER); 4624bff34e3Sthurlow if (error) { 4634bff34e3Sthurlow goto bad; 4644bff34e3Sthurlow } 4654bff34e3Sthurlow } else 4664bff34e3Sthurlow dp->ioc_rparamcnt = 0; 4674bff34e3Sthurlow mdp = &t2p->t2_rdata; 4684bff34e3Sthurlow if (mdp->md_top) { 4694bff34e3Sthurlow mblk_t *m = mdp->md_top; 4704bff34e3Sthurlow #ifdef lint 4714bff34e3Sthurlow m = m; 4724bff34e3Sthurlow #endif 4734bff34e3Sthurlow len = m_fixhdr(mdp->md_top); 4744bff34e3Sthurlow if (len > dp->ioc_rdatacnt) { 4754bff34e3Sthurlow error = EMSGSIZE; 4764bff34e3Sthurlow goto bad; 4774bff34e3Sthurlow } 4784bff34e3Sthurlow dp->ioc_rdatacnt = (ushort_t)len; 4794bff34e3Sthurlow error = md_get_mem(mdp, dp->ioc_rdata, 4804bff34e3Sthurlow len, MB_MUSER); 4814bff34e3Sthurlow if (error) { 4824bff34e3Sthurlow goto bad; 4834bff34e3Sthurlow } 4844bff34e3Sthurlow } else 4854bff34e3Sthurlow dp->ioc_rdatacnt = 0; 4864bff34e3Sthurlow bad: 4874bff34e3Sthurlow smb_t2_done(t2p); 4884bff34e3Sthurlow return (error); 4894bff34e3Sthurlow } 4904bff34e3Sthurlow 4914bff34e3Sthurlow /* 4924bff34e3Sthurlow * Helper for nsmb_ioctl cases 4934bff34e3Sthurlow * SMBIOC_READ, SMBIOC_WRITE 4944bff34e3Sthurlow */ 4954bff34e3Sthurlow int 4964bff34e3Sthurlow smb_usr_rw(struct smb_share *ssp, smbioc_rw_t *rwrq, 4974bff34e3Sthurlow int cmd, struct smb_cred *scred) 4984bff34e3Sthurlow { 4994bff34e3Sthurlow struct iovec aiov[1]; 5004bff34e3Sthurlow struct uio auio; 5014bff34e3Sthurlow u_int16_t fh; 5024bff34e3Sthurlow int error; 5034bff34e3Sthurlow uio_rw_t rw; 5044bff34e3Sthurlow 5054bff34e3Sthurlow switch (cmd) { 5064bff34e3Sthurlow case SMBIOC_READ: 5074bff34e3Sthurlow rw = UIO_READ; 5084bff34e3Sthurlow break; 5094bff34e3Sthurlow case SMBIOC_WRITE: 5104bff34e3Sthurlow rw = UIO_WRITE; 5114bff34e3Sthurlow break; 5124bff34e3Sthurlow default: 5134bff34e3Sthurlow return (ENODEV); 5144bff34e3Sthurlow } 5154bff34e3Sthurlow 5164bff34e3Sthurlow fh = htoles(rwrq->ioc_fh); 5174bff34e3Sthurlow 5184bff34e3Sthurlow aiov[0].iov_base = rwrq->ioc_base; 5194bff34e3Sthurlow aiov[0].iov_len = (size_t)rwrq->ioc_cnt; 5204bff34e3Sthurlow 5214bff34e3Sthurlow auio.uio_iov = aiov; 5224bff34e3Sthurlow auio.uio_iovcnt = 1; 5234bff34e3Sthurlow auio.uio_loffset = rwrq->ioc_offset; 5244bff34e3Sthurlow auio.uio_segflg = UIO_USERSPACE; 5254bff34e3Sthurlow auio.uio_fmode = 0; 5264bff34e3Sthurlow auio.uio_resid = (size_t)rwrq->ioc_cnt; 5274bff34e3Sthurlow 5284bff34e3Sthurlow error = smb_rwuio(ssp, fh, rw, &auio, scred, 0); 5294bff34e3Sthurlow 5304bff34e3Sthurlow /* 5314bff34e3Sthurlow * On return ioc_cnt holds the 5324bff34e3Sthurlow * number of bytes transferred. 5334bff34e3Sthurlow */ 5344bff34e3Sthurlow rwrq->ioc_cnt -= auio.uio_resid; 5354bff34e3Sthurlow 5364bff34e3Sthurlow return (error); 5374bff34e3Sthurlow } 538