1c398230bSWarner Losh /*- 2*fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*fe267a55SPedro F. Giffuni * 4681a5bbeSBoris Popov * Copyright (c) 2000-2001 Boris Popov 5681a5bbeSBoris Popov * All rights reserved. 6681a5bbeSBoris Popov * 7681a5bbeSBoris Popov * Redistribution and use in source and binary forms, with or without 8681a5bbeSBoris Popov * modification, are permitted provided that the following conditions 9681a5bbeSBoris Popov * are met: 10681a5bbeSBoris Popov * 1. Redistributions of source code must retain the above copyright 11681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer. 12681a5bbeSBoris Popov * 2. Redistributions in binary form must reproduce the above copyright 13681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer in the 14681a5bbeSBoris Popov * documentation and/or other materials provided with the distribution. 15681a5bbeSBoris Popov * 16681a5bbeSBoris Popov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17681a5bbeSBoris Popov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18681a5bbeSBoris Popov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19681a5bbeSBoris Popov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20681a5bbeSBoris Popov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21681a5bbeSBoris Popov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22681a5bbeSBoris Popov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23681a5bbeSBoris Popov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24681a5bbeSBoris Popov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25681a5bbeSBoris Popov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26681a5bbeSBoris Popov * SUCH DAMAGE. 27681a5bbeSBoris Popov */ 28ab0de15bSDavid E. O'Brien 29ab0de15bSDavid E. O'Brien #include <sys/cdefs.h> 30ab0de15bSDavid E. O'Brien __FBSDID("$FreeBSD$"); 31ab0de15bSDavid E. O'Brien 32681a5bbeSBoris Popov #include <sys/param.h> 33681a5bbeSBoris Popov #include <sys/malloc.h> 34681a5bbeSBoris Popov #include <sys/kernel.h> 35681a5bbeSBoris Popov #include <sys/systm.h> 36681a5bbeSBoris Popov #include <sys/conf.h> 37681a5bbeSBoris Popov #include <sys/proc.h> 38681a5bbeSBoris Popov #include <sys/fcntl.h> 39681a5bbeSBoris Popov #include <sys/socket.h> 40681a5bbeSBoris Popov #include <sys/socketvar.h> 41681a5bbeSBoris Popov #include <sys/sysctl.h> 429f86067aSPoul-Henning Kamp #include <sys/mbuf.h> 43681a5bbeSBoris Popov 44681a5bbeSBoris Popov #include <sys/iconv.h> 45681a5bbeSBoris Popov 46681a5bbeSBoris Popov #include <netsmb/smb.h> 47681a5bbeSBoris Popov #include <netsmb/smb_conn.h> 48681a5bbeSBoris Popov #include <netsmb/smb_rq.h> 49681a5bbeSBoris Popov #include <netsmb/smb_subr.h> 50681a5bbeSBoris Popov #include <netsmb/smb_dev.h> 51681a5bbeSBoris Popov 52681a5bbeSBoris Popov /* 53681a5bbeSBoris Popov * helpers for nsmb device. Can be moved to the smb_dev.c file. 54681a5bbeSBoris Popov */ 55681a5bbeSBoris Popov static void smb_usr_vcspec_free(struct smb_vcspec *spec); 56681a5bbeSBoris Popov 57681a5bbeSBoris Popov static int 58681a5bbeSBoris Popov smb_usr_vc2spec(struct smbioc_ossn *dp, struct smb_vcspec *spec) 59681a5bbeSBoris Popov { 60681a5bbeSBoris Popov int flags = 0; 61681a5bbeSBoris Popov 62681a5bbeSBoris Popov bzero(spec, sizeof(*spec)); 63994ad180SBoris Popov 64994ad180SBoris Popov #ifdef NETSMB_NO_ANON_USER 65681a5bbeSBoris Popov if (dp->ioc_user[0] == 0) 66681a5bbeSBoris Popov return EINVAL; 67994ad180SBoris Popov #endif 68994ad180SBoris Popov 69681a5bbeSBoris Popov if (dp->ioc_server == NULL) 70681a5bbeSBoris Popov return EINVAL; 71681a5bbeSBoris Popov if (dp->ioc_localcs[0] == 0) { 72681a5bbeSBoris Popov SMBERROR("no local charset ?\n"); 73681a5bbeSBoris Popov return EINVAL; 74681a5bbeSBoris Popov } 75681a5bbeSBoris Popov 76681a5bbeSBoris Popov spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen); 77681a5bbeSBoris Popov if (spec->sap == NULL) 78681a5bbeSBoris Popov return ENOMEM; 79681a5bbeSBoris Popov if (dp->ioc_local) { 80681a5bbeSBoris Popov spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen); 81681a5bbeSBoris Popov if (spec->lap == NULL) { 82681a5bbeSBoris Popov smb_usr_vcspec_free(spec); 83681a5bbeSBoris Popov return ENOMEM; 84681a5bbeSBoris Popov } 85681a5bbeSBoris Popov } 86681a5bbeSBoris Popov spec->srvname = dp->ioc_srvname; 87681a5bbeSBoris Popov spec->pass = dp->ioc_password; 88681a5bbeSBoris Popov spec->domain = dp->ioc_workgroup; 89681a5bbeSBoris Popov spec->username = dp->ioc_user; 90681a5bbeSBoris Popov spec->mode = dp->ioc_mode; 91681a5bbeSBoris Popov spec->rights = dp->ioc_rights; 92681a5bbeSBoris Popov spec->owner = dp->ioc_owner; 93681a5bbeSBoris Popov spec->group = dp->ioc_group; 94681a5bbeSBoris Popov spec->localcs = dp->ioc_localcs; 95681a5bbeSBoris Popov spec->servercs = dp->ioc_servercs; 96681a5bbeSBoris Popov if (dp->ioc_opt & SMBVOPT_PRIVATE) 97681a5bbeSBoris Popov flags |= SMBV_PRIVATE; 98681a5bbeSBoris Popov if (dp->ioc_opt & SMBVOPT_SINGLESHARE) 99681a5bbeSBoris Popov flags |= SMBV_PRIVATE | SMBV_SINGLESHARE; 100681a5bbeSBoris Popov spec->flags = flags; 101681a5bbeSBoris Popov return 0; 102681a5bbeSBoris Popov } 103681a5bbeSBoris Popov 104681a5bbeSBoris Popov static void 105681a5bbeSBoris Popov smb_usr_vcspec_free(struct smb_vcspec *spec) 106681a5bbeSBoris Popov { 107681a5bbeSBoris Popov if (spec->sap) 108681a5bbeSBoris Popov smb_memfree(spec->sap); 109681a5bbeSBoris Popov if (spec->lap) 110681a5bbeSBoris Popov smb_memfree(spec->lap); 111681a5bbeSBoris Popov } 112681a5bbeSBoris Popov 113681a5bbeSBoris Popov static int 114681a5bbeSBoris Popov smb_usr_share2spec(struct smbioc_oshare *dp, struct smb_sharespec *spec) 115681a5bbeSBoris Popov { 116681a5bbeSBoris Popov bzero(spec, sizeof(*spec)); 117681a5bbeSBoris Popov spec->mode = dp->ioc_mode; 118681a5bbeSBoris Popov spec->rights = dp->ioc_rights; 119681a5bbeSBoris Popov spec->owner = dp->ioc_owner; 120681a5bbeSBoris Popov spec->group = dp->ioc_group; 121681a5bbeSBoris Popov spec->name = dp->ioc_share; 122681a5bbeSBoris Popov spec->stype = dp->ioc_stype; 123681a5bbeSBoris Popov spec->pass = dp->ioc_password; 124681a5bbeSBoris Popov return 0; 125681a5bbeSBoris Popov } 126681a5bbeSBoris Popov 127681a5bbeSBoris Popov int 128681a5bbeSBoris Popov smb_usr_lookup(struct smbioc_lookup *dp, struct smb_cred *scred, 129681a5bbeSBoris Popov struct smb_vc **vcpp, struct smb_share **sspp) 130681a5bbeSBoris Popov { 131681a5bbeSBoris Popov struct smb_vc *vcp = NULL; 132afe09751SDavide Italiano struct smb_vcspec vspec; /* XXX */ 133afe09751SDavide Italiano struct smb_sharespec sspec, *sspecp = NULL; /* XXX */ 134681a5bbeSBoris Popov int error; 135681a5bbeSBoris Popov 136681a5bbeSBoris Popov if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE) 137681a5bbeSBoris Popov return EINVAL; 138681a5bbeSBoris Popov error = smb_usr_vc2spec(&dp->ioc_ssn, &vspec); 139681a5bbeSBoris Popov if (error) 140681a5bbeSBoris Popov return error; 141681a5bbeSBoris Popov if (dp->ioc_flags & SMBLK_CREATE) 142681a5bbeSBoris Popov vspec.flags |= SMBV_CREATE; 143681a5bbeSBoris Popov 144681a5bbeSBoris Popov if (dp->ioc_level >= SMBL_SHARE) { 145681a5bbeSBoris Popov error = smb_usr_share2spec(&dp->ioc_sh, &sspec); 146681a5bbeSBoris Popov if (error) 147681a5bbeSBoris Popov goto out; 148681a5bbeSBoris Popov sspecp = &sspec; 149681a5bbeSBoris Popov } 150681a5bbeSBoris Popov error = smb_sm_lookup(&vspec, sspecp, scred, &vcp); 151681a5bbeSBoris Popov if (error == 0) { 152681a5bbeSBoris Popov *vcpp = vcp; 153681a5bbeSBoris Popov *sspp = vspec.ssp; 154681a5bbeSBoris Popov } 155681a5bbeSBoris Popov out: 156681a5bbeSBoris Popov smb_usr_vcspec_free(&vspec); 157681a5bbeSBoris Popov return error; 158681a5bbeSBoris Popov } 159681a5bbeSBoris Popov 160681a5bbeSBoris Popov /* 161681a5bbeSBoris Popov * Connect to the resource specified by smbioc_ossn structure. 162681a5bbeSBoris Popov * It may either find an existing connection or try to establish a new one. 163a4641f4eSPedro F. Giffuni * If no errors occurred smb_vc returned locked and referenced. 164681a5bbeSBoris Popov */ 165681a5bbeSBoris Popov int 166681a5bbeSBoris Popov smb_usr_opensession(struct smbioc_ossn *dp, struct smb_cred *scred, 167681a5bbeSBoris Popov struct smb_vc **vcpp) 168681a5bbeSBoris Popov { 169681a5bbeSBoris Popov struct smb_vc *vcp = NULL; 170681a5bbeSBoris Popov struct smb_vcspec vspec; 171681a5bbeSBoris Popov int error; 172681a5bbeSBoris Popov 173681a5bbeSBoris Popov error = smb_usr_vc2spec(dp, &vspec); 174681a5bbeSBoris Popov if (error) 175681a5bbeSBoris Popov return error; 176681a5bbeSBoris Popov if (dp->ioc_opt & SMBVOPT_CREATE) 177681a5bbeSBoris Popov vspec.flags |= SMBV_CREATE; 178681a5bbeSBoris Popov 179681a5bbeSBoris Popov error = smb_sm_lookup(&vspec, NULL, scred, &vcp); 180681a5bbeSBoris Popov smb_usr_vcspec_free(&vspec); 181681a5bbeSBoris Popov return error; 182681a5bbeSBoris Popov } 183681a5bbeSBoris Popov 184681a5bbeSBoris Popov int 185681a5bbeSBoris Popov smb_usr_openshare(struct smb_vc *vcp, struct smbioc_oshare *dp, 186681a5bbeSBoris Popov struct smb_cred *scred, struct smb_share **sspp) 187681a5bbeSBoris Popov { 188681a5bbeSBoris Popov struct smb_share *ssp; 189681a5bbeSBoris Popov struct smb_sharespec shspec; 190681a5bbeSBoris Popov int error; 191681a5bbeSBoris Popov 192681a5bbeSBoris Popov error = smb_usr_share2spec(dp, &shspec); 193681a5bbeSBoris Popov if (error) 194681a5bbeSBoris Popov return error; 195681a5bbeSBoris Popov error = smb_vc_lookupshare(vcp, &shspec, scred, &ssp); 196681a5bbeSBoris Popov if (error == 0) { 197681a5bbeSBoris Popov *sspp = ssp; 198681a5bbeSBoris Popov return 0; 199681a5bbeSBoris Popov } 200681a5bbeSBoris Popov if ((dp->ioc_opt & SMBSOPT_CREATE) == 0) 201681a5bbeSBoris Popov return error; 202681a5bbeSBoris Popov error = smb_share_create(vcp, &shspec, scred, &ssp); 203681a5bbeSBoris Popov if (error) 204681a5bbeSBoris Popov return error; 205681a5bbeSBoris Popov error = smb_smb_treeconnect(ssp, scred); 206681a5bbeSBoris Popov if (error) { 207681a5bbeSBoris Popov smb_share_put(ssp, scred); 208681a5bbeSBoris Popov } else 209681a5bbeSBoris Popov *sspp = ssp; 210681a5bbeSBoris Popov return error; 211681a5bbeSBoris Popov } 212681a5bbeSBoris Popov 213681a5bbeSBoris Popov int 214681a5bbeSBoris Popov smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp, 215681a5bbeSBoris Popov struct smb_cred *scred) 216681a5bbeSBoris Popov { 217afe09751SDavide Italiano struct smb_rq *rqp; 218681a5bbeSBoris Popov struct mbchain *mbp; 219681a5bbeSBoris Popov struct mdchain *mdp; 220681a5bbeSBoris Popov u_int8_t wc; 221681a5bbeSBoris Popov u_int16_t bc; 222681a5bbeSBoris Popov int error; 223681a5bbeSBoris Popov 224681a5bbeSBoris Popov switch (dp->ioc_cmd) { 225681a5bbeSBoris Popov case SMB_COM_TRANSACTION2: 226681a5bbeSBoris Popov case SMB_COM_TRANSACTION2_SECONDARY: 227681a5bbeSBoris Popov case SMB_COM_CLOSE_AND_TREE_DISC: 228681a5bbeSBoris Popov case SMB_COM_TREE_CONNECT: 229681a5bbeSBoris Popov case SMB_COM_TREE_DISCONNECT: 230681a5bbeSBoris Popov case SMB_COM_NEGOTIATE: 231681a5bbeSBoris Popov case SMB_COM_SESSION_SETUP_ANDX: 232681a5bbeSBoris Popov case SMB_COM_LOGOFF_ANDX: 233681a5bbeSBoris Popov case SMB_COM_TREE_CONNECT_ANDX: 234681a5bbeSBoris Popov return EPERM; 235681a5bbeSBoris Popov } 236afe09751SDavide Italiano rqp = malloc(sizeof(struct smb_rq), M_SMBTEMP, M_WAITOK); 237681a5bbeSBoris Popov error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred); 238afe09751SDavide Italiano if (error) { 239afe09751SDavide Italiano free(rqp, M_SMBTEMP); 240681a5bbeSBoris Popov return error; 241afe09751SDavide Italiano } 242681a5bbeSBoris Popov mbp = &rqp->sr_rq; 243681a5bbeSBoris Popov smb_rq_wstart(rqp); 244681a5bbeSBoris Popov error = mb_put_mem(mbp, dp->ioc_twords, dp->ioc_twc * 2, MB_MUSER); 245681a5bbeSBoris Popov if (error) 246681a5bbeSBoris Popov goto bad; 247681a5bbeSBoris Popov smb_rq_wend(rqp); 248681a5bbeSBoris Popov smb_rq_bstart(rqp); 249681a5bbeSBoris Popov error = mb_put_mem(mbp, dp->ioc_tbytes, dp->ioc_tbc, MB_MUSER); 250681a5bbeSBoris Popov if (error) 251681a5bbeSBoris Popov goto bad; 252681a5bbeSBoris Popov smb_rq_bend(rqp); 253681a5bbeSBoris Popov error = smb_rq_simple(rqp); 254681a5bbeSBoris Popov if (error) 255681a5bbeSBoris Popov goto bad; 256681a5bbeSBoris Popov mdp = &rqp->sr_rp; 257681a5bbeSBoris Popov md_get_uint8(mdp, &wc); 258681a5bbeSBoris Popov dp->ioc_rwc = wc; 259681a5bbeSBoris Popov wc *= 2; 260681a5bbeSBoris Popov if (wc > dp->ioc_rpbufsz) { 261681a5bbeSBoris Popov error = EBADRPC; 262681a5bbeSBoris Popov goto bad; 263681a5bbeSBoris Popov } 264681a5bbeSBoris Popov error = md_get_mem(mdp, dp->ioc_rpbuf, wc, MB_MUSER); 265681a5bbeSBoris Popov if (error) 266681a5bbeSBoris Popov goto bad; 267681a5bbeSBoris Popov md_get_uint16le(mdp, &bc); 268681a5bbeSBoris Popov if ((wc + bc) > dp->ioc_rpbufsz) { 269681a5bbeSBoris Popov error = EBADRPC; 270681a5bbeSBoris Popov goto bad; 271681a5bbeSBoris Popov } 272681a5bbeSBoris Popov dp->ioc_rbc = bc; 273681a5bbeSBoris Popov error = md_get_mem(mdp, dp->ioc_rpbuf + wc, bc, MB_MUSER); 274681a5bbeSBoris Popov bad: 275681a5bbeSBoris Popov dp->ioc_errclass = rqp->sr_errclass; 276681a5bbeSBoris Popov dp->ioc_serror = rqp->sr_serror; 277681a5bbeSBoris Popov dp->ioc_error = rqp->sr_error; 278681a5bbeSBoris Popov smb_rq_done(rqp); 279afe09751SDavide Italiano free(rqp, M_SMBTEMP); 280681a5bbeSBoris Popov return error; 281681a5bbeSBoris Popov 282681a5bbeSBoris Popov } 283681a5bbeSBoris Popov 284681a5bbeSBoris Popov static int 285681a5bbeSBoris Popov smb_cpdatain(struct mbchain *mbp, int len, caddr_t data) 286681a5bbeSBoris Popov { 287681a5bbeSBoris Popov int error; 288681a5bbeSBoris Popov 289681a5bbeSBoris Popov if (len == 0) 290681a5bbeSBoris Popov return 0; 291681a5bbeSBoris Popov error = mb_init(mbp); 292681a5bbeSBoris Popov if (error) 293681a5bbeSBoris Popov return error; 294681a5bbeSBoris Popov return mb_put_mem(mbp, data, len, MB_MUSER); 295681a5bbeSBoris Popov } 296681a5bbeSBoris Popov 297681a5bbeSBoris Popov int 298681a5bbeSBoris Popov smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp, 299681a5bbeSBoris Popov struct smb_cred *scred) 300681a5bbeSBoris Popov { 301afe09751SDavide Italiano struct smb_t2rq *t2p; 302681a5bbeSBoris Popov struct mdchain *mdp; 303681a5bbeSBoris Popov int error, len; 304681a5bbeSBoris Popov 3057d6207b7SPeter Wemm if (dp->ioc_setupcnt > 3) 306681a5bbeSBoris Popov return EINVAL; 307afe09751SDavide Italiano t2p = malloc(sizeof(struct smb_t2rq), M_SMBTEMP, M_WAITOK); 308681a5bbeSBoris Popov error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup[0], scred); 309afe09751SDavide Italiano if (error) { 310afe09751SDavide Italiano free(t2p, M_SMBTEMP); 311681a5bbeSBoris Popov return error; 312afe09751SDavide Italiano } 313681a5bbeSBoris Popov len = t2p->t2_setupcount = dp->ioc_setupcnt; 314681a5bbeSBoris Popov if (len > 1) 315681a5bbeSBoris Popov t2p->t2_setupdata = dp->ioc_setup; 316681a5bbeSBoris Popov if (dp->ioc_name) { 317681a5bbeSBoris Popov t2p->t_name = smb_strdupin(dp->ioc_name, 128); 318681a5bbeSBoris Popov if (t2p->t_name == NULL) { 319681a5bbeSBoris Popov error = ENOMEM; 320681a5bbeSBoris Popov goto bad; 321681a5bbeSBoris Popov } 322681a5bbeSBoris Popov } 323681a5bbeSBoris Popov t2p->t2_maxscount = 0; 324681a5bbeSBoris Popov t2p->t2_maxpcount = dp->ioc_rparamcnt; 325681a5bbeSBoris Popov t2p->t2_maxdcount = dp->ioc_rdatacnt; 326681a5bbeSBoris Popov error = smb_cpdatain(&t2p->t2_tparam, dp->ioc_tparamcnt, dp->ioc_tparam); 327681a5bbeSBoris Popov if (error) 328681a5bbeSBoris Popov goto bad; 329681a5bbeSBoris Popov error = smb_cpdatain(&t2p->t2_tdata, dp->ioc_tdatacnt, dp->ioc_tdata); 330681a5bbeSBoris Popov if (error) 331681a5bbeSBoris Popov goto bad; 332681a5bbeSBoris Popov error = smb_t2_request(t2p); 333681a5bbeSBoris Popov if (error) 334681a5bbeSBoris Popov goto bad; 335681a5bbeSBoris Popov mdp = &t2p->t2_rparam; 336681a5bbeSBoris Popov if (mdp->md_top) { 337681a5bbeSBoris Popov len = m_fixhdr(mdp->md_top); 338681a5bbeSBoris Popov if (len > dp->ioc_rparamcnt) { 339681a5bbeSBoris Popov error = EMSGSIZE; 340681a5bbeSBoris Popov goto bad; 341681a5bbeSBoris Popov } 342681a5bbeSBoris Popov dp->ioc_rparamcnt = len; 343681a5bbeSBoris Popov error = md_get_mem(mdp, dp->ioc_rparam, len, MB_MUSER); 344681a5bbeSBoris Popov if (error) 345681a5bbeSBoris Popov goto bad; 346681a5bbeSBoris Popov } else 347681a5bbeSBoris Popov dp->ioc_rparamcnt = 0; 348681a5bbeSBoris Popov mdp = &t2p->t2_rdata; 349681a5bbeSBoris Popov if (mdp->md_top) { 350681a5bbeSBoris Popov len = m_fixhdr(mdp->md_top); 351681a5bbeSBoris Popov if (len > dp->ioc_rdatacnt) { 352681a5bbeSBoris Popov error = EMSGSIZE; 353681a5bbeSBoris Popov goto bad; 354681a5bbeSBoris Popov } 355681a5bbeSBoris Popov dp->ioc_rdatacnt = len; 356681a5bbeSBoris Popov error = md_get_mem(mdp, dp->ioc_rdata, len, MB_MUSER); 357681a5bbeSBoris Popov } else 358681a5bbeSBoris Popov dp->ioc_rdatacnt = 0; 359681a5bbeSBoris Popov bad: 360681a5bbeSBoris Popov if (t2p->t_name) 361681a5bbeSBoris Popov smb_strfree(t2p->t_name); 362681a5bbeSBoris Popov smb_t2_done(t2p); 363afe09751SDavide Italiano free(t2p, M_SMBTEMP); 364681a5bbeSBoris Popov return error; 365681a5bbeSBoris Popov } 366