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 $
33 * $DragonFly: src/sys/netproto/smb/smb_dev.c,v 1.18 2007/05/08 02:31:42 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/fcntl.h>
41 #include <sys/malloc.h>
42 #include <sys/file.h> /* Must come after sys/malloc.h */
45 #include <sys/select.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/sysctl.h>
50 #include <sys/vnode.h>
51 #include <sys/thread2.h>
52 #include <sys/devfs.h>
60 #define SMB_GETDEV(dev) ((struct smb_dev*)(dev)->si_drv1)
61 #define SMB_CHECKMINOR(dev) do { \
62 sdp = SMB_GETDEV(dev); \
63 if (sdp == NULL) return ENXIO; \
66 static d_open_t nsmb_dev_open
;
67 static d_close_t nsmb_dev_close
;
68 static d_read_t nsmb_dev_read
;
69 static d_write_t nsmb_dev_write
;
70 static d_ioctl_t nsmb_dev_ioctl
;
71 static d_poll_t nsmb_dev_poll
;
72 static d_clone_t nsmbclone
;
73 DEVFS_DECLARE_CLONE_BITMAP(nsmb
);
75 MODULE_VERSION(netsmb
, NSMB_VERSION
);
79 static int smb_version
= NSMB_VERSION
;
82 SYSCTL_DECL(_net_smb
);
83 SYSCTL_INT(_net_smb
, OID_AUTO
, version
, CTLFLAG_RD
, &smb_version
, 0, "");
85 static MALLOC_DEFINE(M_NSMBDEV
, "NETSMBDEV", "NET/SMB device");
89 int smb_dev_queue(struct smb_dev *ndp, struct smb_rq *rqp, int prio);
92 static struct dev_ops nsmb_ops
= {
93 { NSMB_NAME
, NSMB_MAJOR
, 0 },
94 .d_open
= nsmb_dev_open
,
95 .d_close
= nsmb_dev_close
,
96 .d_read
= nsmb_dev_read
,
97 .d_write
= nsmb_dev_write
,
98 .d_ioctl
= nsmb_dev_ioctl
,
99 .d_poll
= nsmb_dev_poll
,
104 nsmb_dev_open(struct dev_open_args
*ap
)
106 cdev_t dev
= ap
->a_head
.a_dev
;
109 sdp
= SMB_GETDEV(dev
);
110 if (sdp
&& (sdp
->sd_flags
& NSMBFL_OPEN
))
113 sdp
= kmalloc(sizeof(*sdp
), M_NSMBDEV
, M_WAITOK
);
114 dev
->si_drv1
= (void*)sdp
;
117 * XXX: this is just crazy - make a device for an already passed
118 * device... someone should take care of it.
121 if ((dev
->si_flags
& SI_NAMED
) == 0) {
122 make_dev(&nsmb_ops
, minor(dev
),
123 ap
->a_cred
->cr_uid
, ap
->a_cred
->cr_gid
,
124 0700, NSMB_NAME
"%d", lminor(dev
));
127 bzero(sdp
, sizeof(*sdp
));
129 STAILQ_INIT(&sdp->sd_rqlist);
130 STAILQ_INIT(&sdp->sd_rplist);
131 bzero(&sdp->sd_pollinfo, sizeof(struct selinfo));
135 sdp
->sd_flags
|= NSMBFL_OPEN
;
141 nsmb_dev_close(struct dev_close_args
*ap
)
143 cdev_t dev
= ap
->a_head
.a_dev
;
146 struct smb_share
*ssp
;
147 struct smb_cred scred
;
151 if ((sdp
->sd_flags
& NSMBFL_OPEN
) == 0) {
155 smb_makescred(&scred
, curthread
, NULL
);
158 smb_share_rele(ssp
, &scred
);
161 smb_vc_rele(vcp
, &scred
);
163 smb_flushq(&sdp->sd_rqlist);
164 smb_flushq(&sdp->sd_rplist);
167 kfree(sdp
, M_NSMBDEV
);
169 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(nsmb
), dev
->si_uminor
);
176 nsmb_dev_ioctl(struct dev_ioctl_args
*ap
)
178 cdev_t dev
= ap
->a_head
.a_dev
;
179 caddr_t data
= ap
->a_data
;
182 struct smb_share
*ssp
;
183 struct smb_cred scred
;
187 if ((sdp
->sd_flags
& NSMBFL_OPEN
) == 0)
190 smb_makescred(&scred
, NULL
, ap
->a_cred
);
192 case SMBIOC_OPENSESSION
:
195 error
= smb_usr_opensession((struct smbioc_ossn
*)data
,
200 smb_vc_unlock(vcp
, 0);
201 sdp
->sd_level
= SMBL_VC
;
203 case SMBIOC_OPENSHARE
:
206 if (sdp
->sd_vc
== NULL
)
208 error
= smb_usr_openshare(sdp
->sd_vc
,
209 (struct smbioc_oshare
*)data
, &scred
, &ssp
);
213 smb_share_unlock(ssp
, 0);
214 sdp
->sd_level
= SMBL_SHARE
;
217 if (sdp
->sd_share
== NULL
)
219 error
= smb_usr_simplerequest(sdp
->sd_share
,
220 (struct smbioc_rq
*)data
, &scred
);
223 if (sdp
->sd_share
== NULL
)
225 error
= smb_usr_t2request(sdp
->sd_share
,
226 (struct smbioc_t2rq
*)data
, &scred
);
228 case SMBIOC_SETFLAGS
: {
229 struct smbioc_flags
*fl
= (struct smbioc_flags
*)data
;
232 if (fl
->ioc_level
== SMBL_VC
) {
233 if (fl
->ioc_mask
& SMBV_PERMANENT
) {
234 on
= fl
->ioc_flags
& SMBV_PERMANENT
;
235 if ((vcp
= sdp
->sd_vc
) == NULL
)
237 error
= smb_vc_get(vcp
, LK_EXCLUSIVE
, &scred
);
240 if (on
&& (vcp
->obj
.co_flags
& SMBV_PERMANENT
) == 0) {
241 vcp
->obj
.co_flags
|= SMBV_PERMANENT
;
243 } else if (!on
&& (vcp
->obj
.co_flags
& SMBV_PERMANENT
)) {
244 vcp
->obj
.co_flags
&= ~SMBV_PERMANENT
;
245 smb_vc_rele(vcp
, &scred
);
247 smb_vc_put(vcp
, &scred
);
250 } else if (fl
->ioc_level
== SMBL_SHARE
) {
251 if (fl
->ioc_mask
& SMBS_PERMANENT
) {
252 on
= fl
->ioc_flags
& SMBS_PERMANENT
;
253 if ((ssp
= sdp
->sd_share
) == NULL
)
255 error
= smb_share_get(ssp
, LK_EXCLUSIVE
, &scred
);
258 if (on
&& (ssp
->obj
.co_flags
& SMBS_PERMANENT
) == 0) {
259 ssp
->obj
.co_flags
|= SMBS_PERMANENT
;
261 } else if (!on
&& (ssp
->obj
.co_flags
& SMBS_PERMANENT
)) {
262 ssp
->obj
.co_flags
&= ~SMBS_PERMANENT
;
263 smb_share_rele(ssp
, &scred
);
265 smb_share_put(ssp
, &scred
);
274 if (sdp
->sd_vc
|| sdp
->sd_share
)
278 error
= smb_usr_lookup((struct smbioc_lookup
*)data
, &scred
, &vcp
, &ssp
);
283 smb_vc_unlock(vcp
, 0);
284 sdp
->sd_level
= SMBL_VC
;
288 smb_share_unlock(ssp
, 0);
289 sdp
->sd_level
= SMBL_SHARE
;
292 case SMBIOC_READ
: case SMBIOC_WRITE
: {
293 struct smbioc_rw
*rwrq
= (struct smbioc_rw
*)data
;
297 if ((ssp
= sdp
->sd_share
) == NULL
)
299 iov
.iov_base
= rwrq
->ioc_base
;
300 iov
.iov_len
= rwrq
->ioc_cnt
;
303 auio
.uio_offset
= rwrq
->ioc_offset
;
304 auio
.uio_resid
= rwrq
->ioc_cnt
;
305 auio
.uio_segflg
= UIO_USERSPACE
;
306 auio
.uio_rw
= (ap
->a_cmd
== SMBIOC_READ
) ? UIO_READ
: UIO_WRITE
;
307 auio
.uio_td
= curthread
;
308 if (ap
->a_cmd
== SMBIOC_READ
)
309 error
= smb_read(ssp
, rwrq
->ioc_fh
, &auio
, &scred
);
311 error
= smb_write(ssp
, rwrq
->ioc_fh
, &auio
, &scred
);
312 rwrq
->ioc_cnt
-= auio
.uio_resid
;
322 nsmb_dev_read(struct dev_read_args
*ap
)
328 nsmb_dev_write(struct dev_write_args
*ap
)
334 nsmb_dev_poll(struct dev_poll_args
*ap
)
340 nsmbclone(struct dev_clone_args
*ap
)
344 unit
= devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(nsmb
), 0);
345 ap
->a_dev
= make_only_dev(&nsmb_ops
, unit
, 0, 0, 0600,
346 NSMB_NAME
"%d", unit
);
352 nsmb_dev_load(module_t mod
, int cmd
, void *arg
)
358 error
= smb_sm_init();
361 error
= smb_iod_init();
366 make_autoclone_dev(&nsmb_ops
, &DEVFS_CLONE_BITMAP(nsmb
),
367 nsmbclone
, 0, 0, 0700, NSMB_NAME
);
369 kprintf("netsmb_dev: loaded\n");
373 error
= smb_sm_done();
375 devfs_clone_handler_del(NSMB_NAME
);
376 dev_ops_remove_all(&nsmb_ops
);
377 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(nsmb
));
378 kprintf("netsmb_dev: unloaded\n");
387 DEV_MODULE (dev_netsmb
, nsmb_dev_load
, 0);
390 smb_dev2share(int fd
, int mode
, struct smb_cred
*scred
,
391 struct smb_share
**sspp
)
396 struct smb_share
*ssp
;
400 KKASSERT(scred
->scr_td
->td_proc
);
402 fp
= holdfp(scred
->scr_td
->td_proc
->p_fd
, fd
, FREAD
|FWRITE
);
406 vp
= (struct vnode
*)fp
->f_data
;
422 error
= smb_share_get(ssp
, LK_EXCLUSIVE
, scred
);