smb_dev.c (69e6d7b75e96c406d072cb83ffc9b26fbf1a86fb) | smb_dev.c (92a4d9bcc8361aabe232a0d731002564c6809bbd) |
---|---|
1/*- 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 15 unchanged lines hidden (view full) --- 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> | 1/*- 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 15 unchanged lines hidden (view full) --- 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> |
32#include <sys/capability.h> |
|
32#include <sys/module.h> 33#include <sys/systm.h> 34#include <sys/conf.h> 35#include <sys/fcntl.h> 36#include <sys/ioccom.h> 37#include <sys/lock.h> 38#include <sys/malloc.h> 39#include <sys/file.h> /* Must come after sys/malloc.h */ --- 10 unchanged lines hidden (view full) --- 50 51#include <net/if.h> 52 53#include <netsmb/smb.h> 54#include <netsmb/smb_conn.h> 55#include <netsmb/smb_subr.h> 56#include <netsmb/smb_dev.h> 57 | 33#include <sys/module.h> 34#include <sys/systm.h> 35#include <sys/conf.h> 36#include <sys/fcntl.h> 37#include <sys/ioccom.h> 38#include <sys/lock.h> 39#include <sys/malloc.h> 40#include <sys/file.h> /* Must come after sys/malloc.h */ --- 10 unchanged lines hidden (view full) --- 51 52#include <net/if.h> 53 54#include <netsmb/smb.h> 55#include <netsmb/smb_conn.h> 56#include <netsmb/smb_subr.h> 57#include <netsmb/smb_dev.h> 58 |
58#define SMB_GETDEV(dev) ((struct smb_dev*)(dev)->si_drv1) 59#define SMB_CHECKMINOR(dev) do { \ 60 sdp = SMB_GETDEV(dev); \ 61 if (sdp == NULL) return ENXIO; \ 62 } while(0) | 59static struct cdev *nsmb_dev; |
63 64static d_open_t nsmb_dev_open; | 60 61static d_open_t nsmb_dev_open; |
65static d_close_t nsmb_dev_close; | |
66static d_ioctl_t nsmb_dev_ioctl; 67 68MODULE_DEPEND(netsmb, libiconv, 1, 1, 2); 69MODULE_VERSION(netsmb, NSMB_VERSION); 70 71static int smb_version = NSMB_VERSION; | 62static d_ioctl_t nsmb_dev_ioctl; 63 64MODULE_DEPEND(netsmb, libiconv, 1, 1, 2); 65MODULE_VERSION(netsmb, NSMB_VERSION); 66 67static int smb_version = NSMB_VERSION; |
68struct sx smb_lock; |
|
72 73 74SYSCTL_DECL(_net_smb); 75SYSCTL_INT(_net_smb, OID_AUTO, version, CTLFLAG_RD, &smb_version, 0, ""); 76 77static MALLOC_DEFINE(M_NSMBDEV, "NETSMBDEV", "NET/SMB device"); 78 | 69 70 71SYSCTL_DECL(_net_smb); 72SYSCTL_INT(_net_smb, OID_AUTO, version, CTLFLAG_RD, &smb_version, 0, ""); 73 74static MALLOC_DEFINE(M_NSMBDEV, "NETSMBDEV", "NET/SMB device"); 75 |
79 80/* 81int smb_dev_queue(struct smb_dev *ndp, struct smb_rq *rqp, int prio); 82*/ 83 | |
84static struct cdevsw nsmb_cdevsw = { 85 .d_version = D_VERSION, | 76static struct cdevsw nsmb_cdevsw = { 77 .d_version = D_VERSION, |
86 .d_flags = D_NEEDGIANT | D_NEEDMINOR, | |
87 .d_open = nsmb_dev_open, | 78 .d_open = nsmb_dev_open, |
88 .d_close = nsmb_dev_close, | |
89 .d_ioctl = nsmb_dev_ioctl, 90 .d_name = NSMB_NAME 91}; 92 | 79 .d_ioctl = nsmb_dev_ioctl, 80 .d_name = NSMB_NAME 81}; 82 |
93static eventhandler_tag nsmb_dev_tag; 94static struct clonedevs *nsmb_clones; 95 96static void 97nsmb_dev_clone(void *arg, struct ucred *cred, char *name, int namelen, 98 struct cdev **dev) | 83static int 84nsmb_dev_init(void) |
99{ | 85{ |
100 int i, u; | |
101 | 86 |
102 if (*dev != NULL) 103 return; | 87 nsmb_dev = make_dev(&nsmb_cdevsw, 0, UID_ROOT, GID_OPERATOR, 88 0600, "nsmb"); 89 if (nsmb_dev == NULL) 90 return (ENOMEM); 91 return (0); 92} |
104 | 93 |
105 if (strcmp(name, NSMB_NAME) == 0) 106 u = -1; 107 else if (dev_stdclone(name, NULL, NSMB_NAME, &u) != 1) 108 return; 109 i = clone_create(&nsmb_clones, &nsmb_cdevsw, &u, dev, 0); 110 if (i) 111 *dev = make_dev_credf(MAKEDEV_REF, &nsmb_cdevsw, u, cred, 112 UID_ROOT, GID_WHEEL, 0600, "%s%d", NSMB_NAME, u); | 94static void 95nsmb_dev_destroy(void) 96{ 97 98 MPASS(nsmb_dev != NULL); 99 destroy_dev(nsmb_dev); 100 nsmb_dev = NULL; |
113} 114 | 101} 102 |
115static int 116nsmb_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) | 103static struct smb_dev * 104smbdev_alloc(struct cdev *dev) |
117{ 118 struct smb_dev *sdp; | 105{ 106 struct smb_dev *sdp; |
119 struct ucred *cred = td->td_ucred; 120 int s; | |
121 | 107 |
122 sdp = SMB_GETDEV(dev); 123 if (sdp && (sdp->sd_flags & NSMBFL_OPEN)) 124 return EBUSY; 125 if (sdp == NULL) { 126 sdp = malloc(sizeof(*sdp), M_NSMBDEV, M_WAITOK); 127 dev->si_drv1 = (void*)sdp; 128 } 129 /* 130 * XXX: this is just crazy - make a device for an already passed device... 131 * someone should take care of it. 132 */ 133 if ((dev->si_flags & SI_NAMED) == 0) 134 make_dev(&nsmb_cdevsw, dev2unit(dev), cred->cr_uid, 135 cred->cr_gid, 0700, NSMB_NAME"%d", dev2unit(dev)); 136 bzero(sdp, sizeof(*sdp)); 137/* 138 STAILQ_INIT(&sdp->sd_rqlist); 139 STAILQ_INIT(&sdp->sd_rplist); 140 bzero(&sdp->sd_pollinfo, sizeof(struct selinfo)); 141*/ 142 s = splimp(); | 108 sdp = malloc(sizeof(struct smb_dev), M_NSMBDEV, M_WAITOK | M_ZERO); 109 sdp->dev = dev; |
143 sdp->sd_level = -1; 144 sdp->sd_flags |= NSMBFL_OPEN; | 110 sdp->sd_level = -1; 111 sdp->sd_flags |= NSMBFL_OPEN; |
145 splx(s); 146 return 0; | 112 sdp->refcount = 1; 113 return (sdp); 114} 115 116void 117sdp_dtor(void *arg) 118{ 119 struct smb_dev *dev; 120 121 dev = (struct smb_dev *)arg; 122 SMB_LOCK(); 123 sdp_trydestroy(dev); 124 SMB_UNLOCK(); |
147} 148 149static int | 125} 126 127static int |
150nsmb_dev_close(struct cdev *dev, int flag, int fmt, struct thread *td) | 128nsmb_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) |
151{ 152 struct smb_dev *sdp; | 129{ 130 struct smb_dev *sdp; |
131 int error; 132 133 sdp = smbdev_alloc(dev); 134 error = devfs_set_cdevpriv(sdp, sdp_dtor); 135 if (error) { 136 free(sdp, M_NSMBDEV); 137 return (error); 138 } 139 return (0); 140} 141 142void 143sdp_trydestroy(struct smb_dev *sdp) 144{ |
|
153 struct smb_vc *vcp; 154 struct smb_share *ssp; 155 struct smb_cred *scred; | 145 struct smb_vc *vcp; 146 struct smb_share *ssp; 147 struct smb_cred *scred; |
156 int s; | |
157 | 148 |
149 SMB_LOCKASSERT(); 150 if (!sdp) 151 panic("No smb_dev upon device close"); 152 MPASS(sdp->refcount > 0); 153 sdp->refcount--; 154 if (sdp->refcount) 155 return; |
|
158 scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); | 156 scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); |
159 SMB_CHECKMINOR(dev); 160 s = splimp(); 161 if ((sdp->sd_flags & NSMBFL_OPEN) == 0) { 162 splx(s); 163 free(scred, M_NSMBDEV); 164 return EBADF; 165 } 166 smb_makescred(scred, td, NULL); | 157 smb_makescred(scred, curthread, NULL); |
167 ssp = sdp->sd_share; 168 if (ssp != NULL) 169 smb_share_rele(ssp, scred); 170 vcp = sdp->sd_vc; 171 if (vcp != NULL) 172 smb_vc_rele(vcp, scred); | 158 ssp = sdp->sd_share; 159 if (ssp != NULL) 160 smb_share_rele(ssp, scred); 161 vcp = sdp->sd_vc; 162 if (vcp != NULL) 163 smb_vc_rele(vcp, scred); |
173/* 174 smb_flushq(&sdp->sd_rqlist); 175 smb_flushq(&sdp->sd_rplist); 176*/ 177 dev->si_drv1 = NULL; 178 free(sdp, M_NSMBDEV); 179 destroy_dev_sched(dev); 180 splx(s); | |
181 free(scred, M_NSMBDEV); | 164 free(scred, M_NSMBDEV); |
182 return 0; | 165 free(sdp, M_NSMBDEV); 166 return; |
183} 184 185 186static int 187nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 188{ 189 struct smb_dev *sdp; 190 struct smb_vc *vcp; 191 struct smb_share *ssp; 192 struct smb_cred *scred; 193 int error = 0; 194 | 167} 168 169 170static int 171nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 172{ 173 struct smb_dev *sdp; 174 struct smb_vc *vcp; 175 struct smb_share *ssp; 176 struct smb_cred *scred; 177 int error = 0; 178 |
195 SMB_CHECKMINOR(dev); 196 if ((sdp->sd_flags & NSMBFL_OPEN) == 0) 197 return EBADF; 198 | 179 error = devfs_get_cdevpriv((void **)&sdp); 180 if (error) 181 return (error); |
199 scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); | 182 scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK); |
183 SMB_LOCK(); |
|
200 smb_makescred(scred, td, NULL); 201 switch (cmd) { 202 case SMBIOC_OPENSESSION: 203 if (sdp->sd_vc) { 204 error = EISCONN; 205 goto out; 206 } 207 error = smb_usr_opensession((struct smbioc_ossn*)data, --- 132 unchanged lines hidden (view full) --- 340 rwrq->ioc_cnt -= auio.uio_resid; 341 break; 342 } 343 default: 344 error = ENODEV; 345 } 346out: 347 free(scred, M_NSMBDEV); | 184 smb_makescred(scred, td, NULL); 185 switch (cmd) { 186 case SMBIOC_OPENSESSION: 187 if (sdp->sd_vc) { 188 error = EISCONN; 189 goto out; 190 } 191 error = smb_usr_opensession((struct smbioc_ossn*)data, --- 132 unchanged lines hidden (view full) --- 324 rwrq->ioc_cnt -= auio.uio_resid; 325 break; 326 } 327 default: 328 error = ENODEV; 329 } 330out: 331 free(scred, M_NSMBDEV); |
332 SMB_UNLOCK(); |
|
348 return error; 349} 350 351static int 352nsmb_dev_load(module_t mod, int cmd, void *arg) 353{ 354 int error = 0; 355 356 switch (cmd) { 357 case MOD_LOAD: 358 error = smb_sm_init(); 359 if (error) 360 break; 361 error = smb_iod_init(); 362 if (error) { 363 smb_sm_done(); 364 break; 365 } | 333 return error; 334} 335 336static int 337nsmb_dev_load(module_t mod, int cmd, void *arg) 338{ 339 int error = 0; 340 341 switch (cmd) { 342 case MOD_LOAD: 343 error = smb_sm_init(); 344 if (error) 345 break; 346 error = smb_iod_init(); 347 if (error) { 348 smb_sm_done(); 349 break; 350 } |
366 clone_setup(&nsmb_clones); 367 nsmb_dev_tag = EVENTHANDLER_REGISTER(dev_clone, nsmb_dev_clone, 0, 1000); | 351 error = nsmb_dev_init(); 352 if (error) 353 break; 354 sx_init(&smb_lock, "samba device lock"); |
368 break; 369 case MOD_UNLOAD: 370 smb_iod_done(); 371 error = smb_sm_done(); 372 if (error) 373 break; | 355 break; 356 case MOD_UNLOAD: 357 smb_iod_done(); 358 error = smb_sm_done(); 359 if (error) 360 break; |
374 EVENTHANDLER_DEREGISTER(dev_clone, nsmb_dev_tag); 375 drain_dev_clone_events(); 376 clone_cleanup(&nsmb_clones); 377 destroy_dev_drain(&nsmb_cdevsw); | 361 nsmb_dev_destroy(); 362 sx_destroy(&smb_lock); |
378 break; 379 default: 380 error = EINVAL; 381 break; 382 } 383 return error; 384} 385 386DEV_MODULE (dev_netsmb, nsmb_dev_load, 0); 387 | 363 break; 364 default: 365 error = EINVAL; 366 break; 367 } 368 return error; 369} 370 371DEV_MODULE (dev_netsmb, nsmb_dev_load, 0); 372 |
388/* 389 * Convert a file descriptor to appropriate smb_share pointer 390 */ 391static struct file* 392nsmb_getfp(struct filedesc* fdp, int fd, int flag) 393{ 394 struct file* fp; 395 396 FILEDESC_SLOCK(fdp); 397 if ((fp = fget_locked(fdp, fd)) == NULL || (fp->f_flag & flag) == 0) { 398 FILEDESC_SUNLOCK(fdp); 399 return (NULL); 400 } 401 fhold(fp); 402 FILEDESC_SUNLOCK(fdp); 403 return (fp); 404} 405 | |
406int 407smb_dev2share(int fd, int mode, struct smb_cred *scred, | 373int 374smb_dev2share(int fd, int mode, struct smb_cred *scred, |
408 struct smb_share **sspp) | 375 struct smb_share **sspp, struct smb_dev **ssdp) |
409{ | 376{ |
410 struct file *fp; 411 struct vnode *vp; | 377 struct file *fp, *fptmp; |
412 struct smb_dev *sdp; 413 struct smb_share *ssp; | 378 struct smb_dev *sdp; 379 struct smb_share *ssp; |
414 struct cdev *dev; | 380 struct thread *td; |
415 int error; 416 | 381 int error; 382 |
417 fp = nsmb_getfp(scred->scr_td->td_proc->p_fd, fd, FREAD | FWRITE); 418 if (fp == NULL) 419 return EBADF; 420 vp = fp->f_vnode; 421 if (vp == NULL) { 422 fdrop(fp, curthread); 423 return EBADF; 424 } 425 if (vp->v_type != VCHR) { 426 fdrop(fp, curthread); 427 return EBADF; 428 } 429 dev = vp->v_rdev; 430 SMB_CHECKMINOR(dev); | 383 td = curthread; 384 error = fget(td, fd, CAP_READ, &fp); 385 if (error) 386 return (error); 387 fptmp = td->td_fpop; 388 td->td_fpop = fp; 389 error = devfs_get_cdevpriv((void **)&sdp); 390 td->td_fpop = fptmp; 391 fdrop(fp, td); 392 if (error || sdp == NULL) 393 return (error); 394 SMB_LOCK(); 395 *ssdp = sdp; |
431 ssp = sdp->sd_share; 432 if (ssp == NULL) { | 396 ssp = sdp->sd_share; 397 if (ssp == NULL) { |
433 fdrop(fp, curthread); 434 return ENOTCONN; | 398 SMB_UNLOCK(); 399 return (ENOTCONN); |
435 } 436 error = smb_share_get(ssp, LK_EXCLUSIVE, scred); | 400 } 401 error = smb_share_get(ssp, LK_EXCLUSIVE, scred); |
437 if (error == 0) | 402 if (error == 0) { 403 sdp->refcount++; |
438 *sspp = ssp; | 404 *sspp = ssp; |
439 fdrop(fp, curthread); | 405 } 406 SMB_UNLOCK(); |
440 return error; 441} 442 | 407 return error; 408} 409 |