2 * Copyright (c) 2000-2001 Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/sys/netsmb/smb_dev.c,v 1.2.2.1 2001/05/22 08:32:33 bp Exp $
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/fcntl.h>
40 #include <sys/malloc.h>
41 #include <sys/file.h> /* Must come after sys/malloc.h */
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/sysctl.h>
47 #include <sys/vnode.h>
48 #include <sys/thread2.h>
49 #include <sys/devfs.h>
57 #define SMB_GETDEV(dev) ((struct smb_dev*)(dev)->si_drv1)
58 #define SMB_CHECKMINOR(dev) do { \
59 sdp = SMB_GETDEV(dev); \
60 if (sdp == NULL) return ENXIO; \
63 static d_open_t nsmb_dev_open
;
64 static d_close_t nsmb_dev_close
;
65 static d_read_t nsmb_dev_read
;
66 static d_write_t nsmb_dev_write
;
67 static d_ioctl_t nsmb_dev_ioctl
;
68 static d_clone_t nsmbclone
;
69 DEVFS_DEFINE_CLONE_BITMAP(nsmb
);
71 MODULE_VERSION(netsmb
, NSMB_VERSION
);
75 static int smb_version
= NSMB_VERSION
;
78 SYSCTL_DECL(_net_smb
);
79 SYSCTL_INT(_net_smb
, OID_AUTO
, version
, CTLFLAG_RD
, &smb_version
, 0, "");
81 static MALLOC_DEFINE(M_NSMBDEV
, "NETSMBDEV", "NET/SMB device");
85 int smb_dev_queue(struct smb_dev *ndp, struct smb_rq *rqp, int prio);
88 static struct dev_ops nsmb_ops
= {
90 .d_open
= nsmb_dev_open
,
91 .d_close
= nsmb_dev_close
,
92 .d_read
= nsmb_dev_read
,
93 .d_write
= nsmb_dev_write
,
94 .d_ioctl
= nsmb_dev_ioctl
,
99 nsmb_dev_open(struct dev_open_args
*ap
)
101 cdev_t dev
= ap
->a_head
.a_dev
;
104 sdp
= SMB_GETDEV(dev
);
105 if (sdp
&& (sdp
->sd_flags
& NSMBFL_OPEN
))
108 sdp
= kmalloc(sizeof(*sdp
), M_NSMBDEV
, M_WAITOK
);
109 dev
->si_drv1
= (void*)sdp
;
112 * XXX: this is just crazy - make a device for an already passed
113 * device... someone should take care of it.
116 if ((dev
->si_flags
& SI_NAMED
) == 0) {
117 make_dev(&nsmb_ops
, minor(dev
),
118 ap
->a_cred
->cr_uid
, ap
->a_cred
->cr_gid
,
119 0700, NSMB_NAME
"%d", lminor(dev
));
122 bzero(sdp
, sizeof(*sdp
));
124 STAILQ_INIT(&sdp->sd_rqlist);
125 STAILQ_INIT(&sdp->sd_rplist);
126 bzero(&sdp->sd_pollinfo, sizeof(struct kqinfo));
130 sdp
->sd_flags
|= NSMBFL_OPEN
;
136 nsmb_dev_close(struct dev_close_args
*ap
)
138 cdev_t dev
= ap
->a_head
.a_dev
;
141 struct smb_share
*ssp
;
142 struct smb_cred scred
;
146 if ((sdp
->sd_flags
& NSMBFL_OPEN
) == 0) {
150 smb_makescred(&scred
, curthread
, NULL
);
153 smb_share_rele(ssp
, &scred
);
156 smb_vc_rele(vcp
, &scred
);
158 smb_flushq(&sdp->sd_rqlist);
159 smb_flushq(&sdp->sd_rplist);
162 kfree(sdp
, M_NSMBDEV
);
164 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(nsmb
), dev
->si_uminor
);
171 nsmb_dev_ioctl(struct dev_ioctl_args
*ap
)
173 cdev_t dev
= ap
->a_head
.a_dev
;
174 caddr_t data
= ap
->a_data
;
177 struct smb_share
*ssp
;
178 struct smb_cred scred
;
182 if ((sdp
->sd_flags
& NSMBFL_OPEN
) == 0)
185 smb_makescred(&scred
, NULL
, ap
->a_cred
);
187 case SMBIOC_OPENSESSION
:
190 error
= smb_usr_opensession((struct smbioc_ossn
*)data
,
195 smb_vc_unlock(vcp
, 0);
196 sdp
->sd_level
= SMBL_VC
;
198 case SMBIOC_OPENSHARE
:
201 if (sdp
->sd_vc
== NULL
)
203 error
= smb_usr_openshare(sdp
->sd_vc
,
204 (struct smbioc_oshare
*)data
, &scred
, &ssp
);
208 smb_share_unlock(ssp
, 0);
209 sdp
->sd_level
= SMBL_SHARE
;
212 if (sdp
->sd_share
== NULL
)
214 error
= smb_usr_simplerequest(sdp
->sd_share
,
215 (struct smbioc_rq
*)data
, &scred
);
218 if (sdp
->sd_share
== NULL
)
220 error
= smb_usr_t2request(sdp
->sd_share
,
221 (struct smbioc_t2rq
*)data
, &scred
);
223 case SMBIOC_SETFLAGS
: {
224 struct smbioc_flags
*fl
= (struct smbioc_flags
*)data
;
227 if (fl
->ioc_level
== SMBL_VC
) {
228 if (fl
->ioc_mask
& SMBV_PERMANENT
) {
229 on
= fl
->ioc_flags
& SMBV_PERMANENT
;
230 if ((vcp
= sdp
->sd_vc
) == NULL
)
232 error
= smb_vc_get(vcp
, LK_EXCLUSIVE
, &scred
);
235 if (on
&& (vcp
->obj
.co_flags
& SMBV_PERMANENT
) == 0) {
236 vcp
->obj
.co_flags
|= SMBV_PERMANENT
;
238 } else if (!on
&& (vcp
->obj
.co_flags
& SMBV_PERMANENT
)) {
239 vcp
->obj
.co_flags
&= ~SMBV_PERMANENT
;
240 smb_vc_rele(vcp
, &scred
);
242 smb_vc_put(vcp
, &scred
);
245 } else if (fl
->ioc_level
== SMBL_SHARE
) {
246 if (fl
->ioc_mask
& SMBS_PERMANENT
) {
247 on
= fl
->ioc_flags
& SMBS_PERMANENT
;
248 if ((ssp
= sdp
->sd_share
) == NULL
)
250 error
= smb_share_get(ssp
, LK_EXCLUSIVE
, &scred
);
253 if (on
&& (ssp
->obj
.co_flags
& SMBS_PERMANENT
) == 0) {
254 ssp
->obj
.co_flags
|= SMBS_PERMANENT
;
256 } else if (!on
&& (ssp
->obj
.co_flags
& SMBS_PERMANENT
)) {
257 ssp
->obj
.co_flags
&= ~SMBS_PERMANENT
;
258 smb_share_rele(ssp
, &scred
);
260 smb_share_put(ssp
, &scred
);
269 if (sdp
->sd_vc
|| sdp
->sd_share
)
273 error
= smb_usr_lookup((struct smbioc_lookup
*)data
, &scred
, &vcp
, &ssp
);
278 smb_vc_unlock(vcp
, 0);
279 sdp
->sd_level
= SMBL_VC
;
283 smb_share_unlock(ssp
, 0);
284 sdp
->sd_level
= SMBL_SHARE
;
287 case SMBIOC_READ
: case SMBIOC_WRITE
: {
288 struct smbioc_rw
*rwrq
= (struct smbioc_rw
*)data
;
292 if ((ssp
= sdp
->sd_share
) == NULL
)
294 iov
.iov_base
= rwrq
->ioc_base
;
295 iov
.iov_len
= rwrq
->ioc_cnt
;
298 auio
.uio_offset
= rwrq
->ioc_offset
;
299 auio
.uio_resid
= rwrq
->ioc_cnt
;
300 auio
.uio_segflg
= UIO_USERSPACE
;
301 auio
.uio_rw
= (ap
->a_cmd
== SMBIOC_READ
) ? UIO_READ
: UIO_WRITE
;
302 auio
.uio_td
= curthread
;
303 if (ap
->a_cmd
== SMBIOC_READ
)
304 error
= smb_read(ssp
, rwrq
->ioc_fh
, &auio
, &scred
);
306 error
= smb_write(ssp
, rwrq
->ioc_fh
, &auio
, &scred
);
307 rwrq
->ioc_cnt
-= auio
.uio_resid
;
317 nsmb_dev_read(struct dev_read_args
*ap
)
323 nsmb_dev_write(struct dev_write_args
*ap
)
329 nsmbclone(struct dev_clone_args
*ap
)
333 unit
= devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(nsmb
), 0);
334 ap
->a_dev
= make_only_dev(&nsmb_ops
, unit
, 0, 0, 0600,
335 NSMB_NAME
"%d", unit
);
341 nsmb_dev_load(module_t mod
, int cmd
, void *arg
)
347 error
= smb_sm_init();
350 error
= smb_iod_init();
355 make_autoclone_dev(&nsmb_ops
, &DEVFS_CLONE_BITMAP(nsmb
),
356 nsmbclone
, 0, 0, 0700, NSMB_NAME
);
358 kprintf("netsmb_dev: loaded\n");
362 error
= smb_sm_done();
364 devfs_clone_handler_del(NSMB_NAME
);
365 dev_ops_remove_all(&nsmb_ops
);
366 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(nsmb
));
367 kprintf("netsmb_dev: unloaded\n");
376 DEV_MODULE (dev_netsmb
, nsmb_dev_load
, 0);
379 smb_dev2share(int fd
, int mode
, struct smb_cred
*scred
,
380 struct smb_share
**sspp
)
385 struct smb_share
*ssp
;
389 KKASSERT(scred
->scr_td
->td_proc
);
391 fp
= holdfp_fdp(scred
->scr_td
->td_proc
->p_fd
, fd
, FREAD
|FWRITE
);
395 vp
= (struct vnode
*)fp
->f_data
;
411 error
= smb_share_get(ssp
, LK_EXCLUSIVE
, scred
);