Deleted Added
full compact
smb_dev.c (248109) smb_dev.c (250236)
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

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.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

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netsmb/smb_dev.c 248109 2013-03-09 16:58:19Z davide $");
28__FBSDID("$FreeBSD: head/sys/netsmb/smb_dev.c 250236 2013-05-04 14:03:18Z davide $");
29
30#include <sys/param.h>
31#include <sys/kernel.h>
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