1c398230bSWarner Losh /*- 2681a5bbeSBoris Popov * Copyright (c) 2000-2001 Boris Popov 3681a5bbeSBoris Popov * All rights reserved. 4681a5bbeSBoris Popov * 5681a5bbeSBoris Popov * Redistribution and use in source and binary forms, with or without 6681a5bbeSBoris Popov * modification, are permitted provided that the following conditions 7681a5bbeSBoris Popov * are met: 8681a5bbeSBoris Popov * 1. Redistributions of source code must retain the above copyright 9681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer. 10681a5bbeSBoris Popov * 2. Redistributions in binary form must reproduce the above copyright 11681a5bbeSBoris Popov * notice, this list of conditions and the following disclaimer in the 12681a5bbeSBoris Popov * documentation and/or other materials provided with the distribution. 13681a5bbeSBoris Popov * 14681a5bbeSBoris Popov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15681a5bbeSBoris Popov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16681a5bbeSBoris Popov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17681a5bbeSBoris Popov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18681a5bbeSBoris Popov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19681a5bbeSBoris Popov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20681a5bbeSBoris Popov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21681a5bbeSBoris Popov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22681a5bbeSBoris Popov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23681a5bbeSBoris Popov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24681a5bbeSBoris Popov * SUCH DAMAGE. 25681a5bbeSBoris Popov */ 26ab0de15bSDavid E. O'Brien 27ab0de15bSDavid E. O'Brien #include <sys/cdefs.h> 28ab0de15bSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29ab0de15bSDavid E. O'Brien 30681a5bbeSBoris Popov #include <sys/param.h> 31681a5bbeSBoris Popov #include <sys/kernel.h> 32*92a4d9bcSDavide Italiano #include <sys/capability.h> 335dba30f1SPoul-Henning Kamp #include <sys/module.h> 34681a5bbeSBoris Popov #include <sys/systm.h> 35681a5bbeSBoris Popov #include <sys/conf.h> 36681a5bbeSBoris Popov #include <sys/fcntl.h> 37fb919e4dSMark Murray #include <sys/ioccom.h> 38fb919e4dSMark Murray #include <sys/lock.h> 39fb919e4dSMark Murray #include <sys/malloc.h> 40fb919e4dSMark Murray #include <sys/file.h> /* Must come after sys/malloc.h */ 4113438f68SAlfred Perlstein #include <sys/filedesc.h> 42fb919e4dSMark Murray #include <sys/mbuf.h> 43681a5bbeSBoris Popov #include <sys/poll.h> 44fb919e4dSMark Murray #include <sys/proc.h> 45fb919e4dSMark Murray #include <sys/select.h> 46fb919e4dSMark Murray #include <sys/socket.h> 47681a5bbeSBoris Popov #include <sys/socketvar.h> 48681a5bbeSBoris Popov #include <sys/sysctl.h> 49fb919e4dSMark Murray #include <sys/uio.h> 50681a5bbeSBoris Popov #include <sys/vnode.h> 51681a5bbeSBoris Popov 52681a5bbeSBoris Popov #include <net/if.h> 53681a5bbeSBoris Popov 54681a5bbeSBoris Popov #include <netsmb/smb.h> 55681a5bbeSBoris Popov #include <netsmb/smb_conn.h> 56681a5bbeSBoris Popov #include <netsmb/smb_subr.h> 57681a5bbeSBoris Popov #include <netsmb/smb_dev.h> 58681a5bbeSBoris Popov 59*92a4d9bcSDavide Italiano static struct cdev *nsmb_dev; 60681a5bbeSBoris Popov 61681a5bbeSBoris Popov static d_open_t nsmb_dev_open; 62681a5bbeSBoris Popov static d_ioctl_t nsmb_dev_ioctl; 63681a5bbeSBoris Popov 64c4f02a89SMax Khon MODULE_DEPEND(netsmb, libiconv, 1, 1, 2); 65681a5bbeSBoris Popov MODULE_VERSION(netsmb, NSMB_VERSION); 66681a5bbeSBoris Popov 67681a5bbeSBoris Popov static int smb_version = NSMB_VERSION; 68*92a4d9bcSDavide Italiano struct sx smb_lock; 69681a5bbeSBoris Popov 70681a5bbeSBoris Popov 71681a5bbeSBoris Popov SYSCTL_DECL(_net_smb); 72681a5bbeSBoris Popov SYSCTL_INT(_net_smb, OID_AUTO, version, CTLFLAG_RD, &smb_version, 0, ""); 73681a5bbeSBoris Popov 74681a5bbeSBoris Popov static MALLOC_DEFINE(M_NSMBDEV, "NETSMBDEV", "NET/SMB device"); 75681a5bbeSBoris Popov 76681a5bbeSBoris Popov static struct cdevsw nsmb_cdevsw = { 77dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 787ac40f5fSPoul-Henning Kamp .d_open = nsmb_dev_open, 797ac40f5fSPoul-Henning Kamp .d_ioctl = nsmb_dev_ioctl, 80fd13f792STim J. Robbins .d_name = NSMB_NAME 81681a5bbeSBoris Popov }; 82681a5bbeSBoris Popov 83*92a4d9bcSDavide Italiano static int 84*92a4d9bcSDavide Italiano nsmb_dev_init(void) 85*92a4d9bcSDavide Italiano { 86*92a4d9bcSDavide Italiano 87*92a4d9bcSDavide Italiano nsmb_dev = make_dev(&nsmb_cdevsw, 0, UID_ROOT, GID_OPERATOR, 88*92a4d9bcSDavide Italiano 0600, "nsmb"); 89*92a4d9bcSDavide Italiano if (nsmb_dev == NULL) 90*92a4d9bcSDavide Italiano return (ENOMEM); 91*92a4d9bcSDavide Italiano return (0); 92*92a4d9bcSDavide Italiano } 93681a5bbeSBoris Popov 94681a5bbeSBoris Popov static void 95*92a4d9bcSDavide Italiano nsmb_dev_destroy(void) 96681a5bbeSBoris Popov { 97681a5bbeSBoris Popov 98*92a4d9bcSDavide Italiano MPASS(nsmb_dev != NULL); 99*92a4d9bcSDavide Italiano destroy_dev(nsmb_dev); 100*92a4d9bcSDavide Italiano nsmb_dev = NULL; 101*92a4d9bcSDavide Italiano } 102339f72c7SRobert Watson 103*92a4d9bcSDavide Italiano static struct smb_dev * 104*92a4d9bcSDavide Italiano smbdev_alloc(struct cdev *dev) 105*92a4d9bcSDavide Italiano { 106*92a4d9bcSDavide Italiano struct smb_dev *sdp; 107*92a4d9bcSDavide Italiano 108*92a4d9bcSDavide Italiano sdp = malloc(sizeof(struct smb_dev), M_NSMBDEV, M_WAITOK | M_ZERO); 109*92a4d9bcSDavide Italiano sdp->dev = dev; 110*92a4d9bcSDavide Italiano sdp->sd_level = -1; 111*92a4d9bcSDavide Italiano sdp->sd_flags |= NSMBFL_OPEN; 112*92a4d9bcSDavide Italiano sdp->refcount = 1; 113*92a4d9bcSDavide Italiano return (sdp); 114*92a4d9bcSDavide Italiano } 115*92a4d9bcSDavide Italiano 116*92a4d9bcSDavide Italiano void 117*92a4d9bcSDavide Italiano sdp_dtor(void *arg) 118*92a4d9bcSDavide Italiano { 119*92a4d9bcSDavide Italiano struct smb_dev *dev; 120*92a4d9bcSDavide Italiano 121*92a4d9bcSDavide Italiano dev = (struct smb_dev *)arg; 122*92a4d9bcSDavide Italiano SMB_LOCK(); 123*92a4d9bcSDavide Italiano sdp_trydestroy(dev); 124*92a4d9bcSDavide Italiano SMB_UNLOCK(); 125681a5bbeSBoris Popov } 126681a5bbeSBoris Popov 127681a5bbeSBoris Popov static int 12889c9c53dSPoul-Henning Kamp nsmb_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 129681a5bbeSBoris Popov { 130681a5bbeSBoris Popov struct smb_dev *sdp; 131*92a4d9bcSDavide Italiano int error; 132681a5bbeSBoris Popov 133*92a4d9bcSDavide Italiano sdp = smbdev_alloc(dev); 134*92a4d9bcSDavide Italiano error = devfs_set_cdevpriv(sdp, sdp_dtor); 135*92a4d9bcSDavide Italiano if (error) { 136*92a4d9bcSDavide Italiano free(sdp, M_NSMBDEV); 137*92a4d9bcSDavide Italiano return (error); 138681a5bbeSBoris Popov } 139*92a4d9bcSDavide Italiano return (0); 140681a5bbeSBoris Popov } 141681a5bbeSBoris Popov 142*92a4d9bcSDavide Italiano void 143*92a4d9bcSDavide Italiano sdp_trydestroy(struct smb_dev *sdp) 144681a5bbeSBoris Popov { 145681a5bbeSBoris Popov struct smb_vc *vcp; 146681a5bbeSBoris Popov struct smb_share *ssp; 147afe09751SDavide Italiano struct smb_cred *scred; 148681a5bbeSBoris Popov 149*92a4d9bcSDavide Italiano SMB_LOCKASSERT(); 150*92a4d9bcSDavide Italiano if (!sdp) 151*92a4d9bcSDavide Italiano panic("No smb_dev upon device close"); 152*92a4d9bcSDavide Italiano MPASS(sdp->refcount > 0); 153*92a4d9bcSDavide Italiano sdp->refcount--; 154*92a4d9bcSDavide Italiano if (sdp->refcount) 155*92a4d9bcSDavide Italiano return; 156afe09751SDavide Italiano scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); 157*92a4d9bcSDavide Italiano smb_makescred(scred, curthread, NULL); 158681a5bbeSBoris Popov ssp = sdp->sd_share; 159681a5bbeSBoris Popov if (ssp != NULL) 160afe09751SDavide Italiano smb_share_rele(ssp, scred); 161681a5bbeSBoris Popov vcp = sdp->sd_vc; 162681a5bbeSBoris Popov if (vcp != NULL) 163afe09751SDavide Italiano smb_vc_rele(vcp, scred); 164afe09751SDavide Italiano free(scred, M_NSMBDEV); 165*92a4d9bcSDavide Italiano free(sdp, M_NSMBDEV); 166*92a4d9bcSDavide Italiano return; 167681a5bbeSBoris Popov } 168681a5bbeSBoris Popov 169681a5bbeSBoris Popov 170681a5bbeSBoris Popov static int 17189c9c53dSPoul-Henning Kamp nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 172681a5bbeSBoris Popov { 173681a5bbeSBoris Popov struct smb_dev *sdp; 174681a5bbeSBoris Popov struct smb_vc *vcp; 175681a5bbeSBoris Popov struct smb_share *ssp; 176afe09751SDavide Italiano struct smb_cred *scred; 177681a5bbeSBoris Popov int error = 0; 178681a5bbeSBoris Popov 179*92a4d9bcSDavide Italiano error = devfs_get_cdevpriv((void **)&sdp); 180*92a4d9bcSDavide Italiano if (error) 181*92a4d9bcSDavide Italiano return (error); 182afe09751SDavide Italiano scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); 183*92a4d9bcSDavide Italiano SMB_LOCK(); 184afe09751SDavide Italiano smb_makescred(scred, td, NULL); 185681a5bbeSBoris Popov switch (cmd) { 186681a5bbeSBoris Popov case SMBIOC_OPENSESSION: 187afe09751SDavide Italiano if (sdp->sd_vc) { 188afe09751SDavide Italiano error = EISCONN; 189afe09751SDavide Italiano goto out; 190afe09751SDavide Italiano } 191681a5bbeSBoris Popov error = smb_usr_opensession((struct smbioc_ossn*)data, 192afe09751SDavide Italiano scred, &vcp); 193681a5bbeSBoris Popov if (error) 194681a5bbeSBoris Popov break; 195681a5bbeSBoris Popov sdp->sd_vc = vcp; 1962b7da2dbSRobert Watson smb_vc_unlock(vcp, 0); 197681a5bbeSBoris Popov sdp->sd_level = SMBL_VC; 198681a5bbeSBoris Popov break; 199681a5bbeSBoris Popov case SMBIOC_OPENSHARE: 200afe09751SDavide Italiano if (sdp->sd_share) { 201afe09751SDavide Italiano error = EISCONN; 202afe09751SDavide Italiano goto out; 203afe09751SDavide Italiano } 204afe09751SDavide Italiano if (sdp->sd_vc == NULL) { 205afe09751SDavide Italiano error = ENOTCONN; 206afe09751SDavide Italiano goto out; 207afe09751SDavide Italiano } 208681a5bbeSBoris Popov error = smb_usr_openshare(sdp->sd_vc, 209afe09751SDavide Italiano (struct smbioc_oshare*)data, scred, &ssp); 210681a5bbeSBoris Popov if (error) 211681a5bbeSBoris Popov break; 212681a5bbeSBoris Popov sdp->sd_share = ssp; 2132b7da2dbSRobert Watson smb_share_unlock(ssp, 0); 214681a5bbeSBoris Popov sdp->sd_level = SMBL_SHARE; 215681a5bbeSBoris Popov break; 216681a5bbeSBoris Popov case SMBIOC_REQUEST: 217afe09751SDavide Italiano if (sdp->sd_share == NULL) { 218afe09751SDavide Italiano error = ENOTCONN; 219afe09751SDavide Italiano goto out; 220afe09751SDavide Italiano } 221681a5bbeSBoris Popov error = smb_usr_simplerequest(sdp->sd_share, 222afe09751SDavide Italiano (struct smbioc_rq*)data, scred); 223681a5bbeSBoris Popov break; 224681a5bbeSBoris Popov case SMBIOC_T2RQ: 225afe09751SDavide Italiano if (sdp->sd_share == NULL) { 226afe09751SDavide Italiano error = ENOTCONN; 227afe09751SDavide Italiano goto out; 228afe09751SDavide Italiano } 229681a5bbeSBoris Popov error = smb_usr_t2request(sdp->sd_share, 230afe09751SDavide Italiano (struct smbioc_t2rq*)data, scred); 231681a5bbeSBoris Popov break; 232681a5bbeSBoris Popov case SMBIOC_SETFLAGS: { 233681a5bbeSBoris Popov struct smbioc_flags *fl = (struct smbioc_flags*)data; 234681a5bbeSBoris Popov int on; 235681a5bbeSBoris Popov 236681a5bbeSBoris Popov if (fl->ioc_level == SMBL_VC) { 237681a5bbeSBoris Popov if (fl->ioc_mask & SMBV_PERMANENT) { 238681a5bbeSBoris Popov on = fl->ioc_flags & SMBV_PERMANENT; 239afe09751SDavide Italiano if ((vcp = sdp->sd_vc) == NULL) { 240afe09751SDavide Italiano error = ENOTCONN; 241afe09751SDavide Italiano goto out; 242afe09751SDavide Italiano } 243afe09751SDavide Italiano error = smb_vc_get(vcp, LK_EXCLUSIVE, scred); 244681a5bbeSBoris Popov if (error) 245681a5bbeSBoris Popov break; 246681a5bbeSBoris Popov if (on && (vcp->obj.co_flags & SMBV_PERMANENT) == 0) { 247681a5bbeSBoris Popov vcp->obj.co_flags |= SMBV_PERMANENT; 248fce6fbfaSBoris Popov smb_vc_ref(vcp); 249681a5bbeSBoris Popov } else if (!on && (vcp->obj.co_flags & SMBV_PERMANENT)) { 250681a5bbeSBoris Popov vcp->obj.co_flags &= ~SMBV_PERMANENT; 251afe09751SDavide Italiano smb_vc_rele(vcp, scred); 252681a5bbeSBoris Popov } 253afe09751SDavide Italiano smb_vc_put(vcp, scred); 254681a5bbeSBoris Popov } else 255681a5bbeSBoris Popov error = EINVAL; 256681a5bbeSBoris Popov } else if (fl->ioc_level == SMBL_SHARE) { 257681a5bbeSBoris Popov if (fl->ioc_mask & SMBS_PERMANENT) { 258681a5bbeSBoris Popov on = fl->ioc_flags & SMBS_PERMANENT; 259afe09751SDavide Italiano if ((ssp = sdp->sd_share) == NULL) { 260afe09751SDavide Italiano error = ENOTCONN; 261afe09751SDavide Italiano goto out; 262afe09751SDavide Italiano } 263afe09751SDavide Italiano error = smb_share_get(ssp, LK_EXCLUSIVE, scred); 264681a5bbeSBoris Popov if (error) 265681a5bbeSBoris Popov break; 266681a5bbeSBoris Popov if (on && (ssp->obj.co_flags & SMBS_PERMANENT) == 0) { 267681a5bbeSBoris Popov ssp->obj.co_flags |= SMBS_PERMANENT; 268fce6fbfaSBoris Popov smb_share_ref(ssp); 269681a5bbeSBoris Popov } else if (!on && (ssp->obj.co_flags & SMBS_PERMANENT)) { 270681a5bbeSBoris Popov ssp->obj.co_flags &= ~SMBS_PERMANENT; 271afe09751SDavide Italiano smb_share_rele(ssp, scred); 272681a5bbeSBoris Popov } 273afe09751SDavide Italiano smb_share_put(ssp, scred); 274681a5bbeSBoris Popov } else 275681a5bbeSBoris Popov error = EINVAL; 276681a5bbeSBoris Popov break; 277681a5bbeSBoris Popov } else 278681a5bbeSBoris Popov error = EINVAL; 279681a5bbeSBoris Popov break; 280681a5bbeSBoris Popov } 281681a5bbeSBoris Popov case SMBIOC_LOOKUP: 282afe09751SDavide Italiano if (sdp->sd_vc || sdp->sd_share) { 283afe09751SDavide Italiano error = EISCONN; 284afe09751SDavide Italiano goto out; 285afe09751SDavide Italiano } 286681a5bbeSBoris Popov vcp = NULL; 287681a5bbeSBoris Popov ssp = NULL; 288afe09751SDavide Italiano error = smb_usr_lookup((struct smbioc_lookup*)data, scred, &vcp, &ssp); 289681a5bbeSBoris Popov if (error) 290681a5bbeSBoris Popov break; 291681a5bbeSBoris Popov if (vcp) { 292681a5bbeSBoris Popov sdp->sd_vc = vcp; 2932b7da2dbSRobert Watson smb_vc_unlock(vcp, 0); 294681a5bbeSBoris Popov sdp->sd_level = SMBL_VC; 295681a5bbeSBoris Popov } 296681a5bbeSBoris Popov if (ssp) { 297681a5bbeSBoris Popov sdp->sd_share = ssp; 2982b7da2dbSRobert Watson smb_share_unlock(ssp, 0); 299681a5bbeSBoris Popov sdp->sd_level = SMBL_SHARE; 300681a5bbeSBoris Popov } 301681a5bbeSBoris Popov break; 302681a5bbeSBoris Popov case SMBIOC_READ: case SMBIOC_WRITE: { 303681a5bbeSBoris Popov struct smbioc_rw *rwrq = (struct smbioc_rw*)data; 304681a5bbeSBoris Popov struct uio auio; 305681a5bbeSBoris Popov struct iovec iov; 306681a5bbeSBoris Popov 307afe09751SDavide Italiano if ((ssp = sdp->sd_share) == NULL) { 308afe09751SDavide Italiano error = ENOTCONN; 309afe09751SDavide Italiano goto out; 310afe09751SDavide Italiano } 311681a5bbeSBoris Popov iov.iov_base = rwrq->ioc_base; 312681a5bbeSBoris Popov iov.iov_len = rwrq->ioc_cnt; 313681a5bbeSBoris Popov auio.uio_iov = &iov; 314681a5bbeSBoris Popov auio.uio_iovcnt = 1; 315681a5bbeSBoris Popov auio.uio_offset = rwrq->ioc_offset; 316681a5bbeSBoris Popov auio.uio_resid = rwrq->ioc_cnt; 317681a5bbeSBoris Popov auio.uio_segflg = UIO_USERSPACE; 318681a5bbeSBoris Popov auio.uio_rw = (cmd == SMBIOC_READ) ? UIO_READ : UIO_WRITE; 319fce6fbfaSBoris Popov auio.uio_td = td; 320681a5bbeSBoris Popov if (cmd == SMBIOC_READ) 321afe09751SDavide Italiano error = smb_read(ssp, rwrq->ioc_fh, &auio, scred); 322681a5bbeSBoris Popov else 323afe09751SDavide Italiano error = smb_write(ssp, rwrq->ioc_fh, &auio, scred); 324681a5bbeSBoris Popov rwrq->ioc_cnt -= auio.uio_resid; 325681a5bbeSBoris Popov break; 326681a5bbeSBoris Popov } 327681a5bbeSBoris Popov default: 328681a5bbeSBoris Popov error = ENODEV; 329681a5bbeSBoris Popov } 330afe09751SDavide Italiano out: 331afe09751SDavide Italiano free(scred, M_NSMBDEV); 332*92a4d9bcSDavide Italiano SMB_UNLOCK(); 333681a5bbeSBoris Popov return error; 334681a5bbeSBoris Popov } 335681a5bbeSBoris Popov 336681a5bbeSBoris Popov static int 337681a5bbeSBoris Popov nsmb_dev_load(module_t mod, int cmd, void *arg) 338681a5bbeSBoris Popov { 339681a5bbeSBoris Popov int error = 0; 340681a5bbeSBoris Popov 341681a5bbeSBoris Popov switch (cmd) { 342681a5bbeSBoris Popov case MOD_LOAD: 343681a5bbeSBoris Popov error = smb_sm_init(); 344681a5bbeSBoris Popov if (error) 345681a5bbeSBoris Popov break; 346681a5bbeSBoris Popov error = smb_iod_init(); 347681a5bbeSBoris Popov if (error) { 348681a5bbeSBoris Popov smb_sm_done(); 349681a5bbeSBoris Popov break; 350681a5bbeSBoris Popov } 351*92a4d9bcSDavide Italiano error = nsmb_dev_init(); 352*92a4d9bcSDavide Italiano if (error) 353*92a4d9bcSDavide Italiano break; 354*92a4d9bcSDavide Italiano sx_init(&smb_lock, "samba device lock"); 355681a5bbeSBoris Popov break; 356681a5bbeSBoris Popov case MOD_UNLOAD: 357681a5bbeSBoris Popov smb_iod_done(); 358681a5bbeSBoris Popov error = smb_sm_done(); 35919caf6c0SBoris Popov if (error) 36019caf6c0SBoris Popov break; 361*92a4d9bcSDavide Italiano nsmb_dev_destroy(); 362*92a4d9bcSDavide Italiano sx_destroy(&smb_lock); 363681a5bbeSBoris Popov break; 364681a5bbeSBoris Popov default: 365681a5bbeSBoris Popov error = EINVAL; 366681a5bbeSBoris Popov break; 367681a5bbeSBoris Popov } 368681a5bbeSBoris Popov return error; 369681a5bbeSBoris Popov } 370681a5bbeSBoris Popov 371681a5bbeSBoris Popov DEV_MODULE (dev_netsmb, nsmb_dev_load, 0); 372681a5bbeSBoris Popov 373681a5bbeSBoris Popov int 374681a5bbeSBoris Popov smb_dev2share(int fd, int mode, struct smb_cred *scred, 375*92a4d9bcSDavide Italiano struct smb_share **sspp, struct smb_dev **ssdp) 376681a5bbeSBoris Popov { 377*92a4d9bcSDavide Italiano struct file *fp, *fptmp; 378681a5bbeSBoris Popov struct smb_dev *sdp; 379681a5bbeSBoris Popov struct smb_share *ssp; 380*92a4d9bcSDavide Italiano struct thread *td; 381681a5bbeSBoris Popov int error; 382681a5bbeSBoris Popov 383*92a4d9bcSDavide Italiano td = curthread; 384*92a4d9bcSDavide Italiano error = fget(td, fd, CAP_READ, &fp); 385*92a4d9bcSDavide Italiano if (error) 386*92a4d9bcSDavide Italiano return (error); 387*92a4d9bcSDavide Italiano fptmp = td->td_fpop; 388*92a4d9bcSDavide Italiano td->td_fpop = fp; 389*92a4d9bcSDavide Italiano error = devfs_get_cdevpriv((void **)&sdp); 390*92a4d9bcSDavide Italiano td->td_fpop = fptmp; 391*92a4d9bcSDavide Italiano fdrop(fp, td); 392*92a4d9bcSDavide Italiano if (error || sdp == NULL) 393*92a4d9bcSDavide Italiano return (error); 394*92a4d9bcSDavide Italiano SMB_LOCK(); 395*92a4d9bcSDavide Italiano *ssdp = sdp; 396681a5bbeSBoris Popov ssp = sdp->sd_share; 397426da3bcSAlfred Perlstein if (ssp == NULL) { 398*92a4d9bcSDavide Italiano SMB_UNLOCK(); 399*92a4d9bcSDavide Italiano return (ENOTCONN); 400426da3bcSAlfred Perlstein } 401681a5bbeSBoris Popov error = smb_share_get(ssp, LK_EXCLUSIVE, scred); 402*92a4d9bcSDavide Italiano if (error == 0) { 403*92a4d9bcSDavide Italiano sdp->refcount++; 404681a5bbeSBoris Popov *sspp = ssp; 405*92a4d9bcSDavide Italiano } 406*92a4d9bcSDavide Italiano SMB_UNLOCK(); 407426da3bcSAlfred Perlstein return error; 408681a5bbeSBoris Popov } 409681a5bbeSBoris Popov 410