proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / netproto / ncp / ncp_subr.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1999, 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
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.
19 *
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
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: src/sys/netncp/ncp_subr.c,v 1.2.2.1 2001/02/22 08:54:11 bp Exp $
dadab5e9 33 * $DragonFly: src/sys/netproto/ncp/ncp_subr.c,v 1.3 2003/06/25 03:56:05 dillon Exp $
984263bc
MD
34 */
35#include <sys/param.h>
36#include <sys/errno.h>
37#include <sys/proc.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/malloc.h>
41#include <sys/time.h>
42#include <sys/uio.h>
43#include <sys/mbuf.h>
44
45#include <netncp/ncp.h>
46#include <netncp/ncp_conn.h>
47#include <netncp/ncp_sock.h>
48#include <netncp/ncp_subr.h>
49#include <netncp/ncp_rq.h>
50#include <netncp/ncp_ncp.h>
51#include <netncp/nwerror.h>
52
53int ncp_debuglevel = 0;
54
55struct callout_handle ncp_timer_handle;
56
dadab5e9 57static void ncp_at_exit(struct thread *td);
984263bc
MD
58static void ncp_timer(void *arg);
59
60/*
61 * duplicate string from user space. It should be very-very slow.
62 */
63char *
dadab5e9
MD
64ncp_str_dup(char *s)
65{
984263bc
MD
66 char *p, bt;
67 int len = 0;
68
69 for (p = s;;p++) {
70 if (copyin(p, &bt, 1)) return NULL;
71 len++;
72 if (bt == 0) break;
73 }
74 MALLOC(p, char*, len, M_NCPDATA, M_WAITOK);
75 copyin(s, p, len);
76 return p;
77}
78
79
80void
dadab5e9
MD
81ncp_at_exit(struct thread *td)
82{
984263bc 83 struct ncp_conn *ncp, *nncp;
dadab5e9
MD
84 struct ucred *cred;
85
86 KKASSERT(td->td_proc);
87 cred = td->td_proc->p_ucred;
984263bc 88
dadab5e9 89 if (ncp_conn_putprochandles(td) == 0) return;
984263bc 90
dadab5e9 91 ncp_conn_locklist(LK_EXCLUSIVE, td);
984263bc
MD
92 for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
93 nncp = SLIST_NEXT(ncp, nc_next);
94 if (ncp->ref_cnt != 0) continue;
dadab5e9 95 if (ncp_conn_lock(ncp, td, cred, NCPM_READ|NCPM_EXECUTE|NCPM_WRITE))
984263bc
MD
96 continue;
97 if (ncp_disconnect(ncp) != 0)
dadab5e9 98 ncp_conn_unlock(ncp, td);
984263bc 99 }
dadab5e9 100 ncp_conn_unlocklist(td);
984263bc
MD
101}
102
103int
dadab5e9
MD
104ncp_init(void)
105{
984263bc
MD
106 ncp_conn_init();
107 if (at_exit(ncp_at_exit)) {
108 NCPFATAL("can't register at_exit handler\n");
109 return ENOMEM;
110 }
111 ncp_timer_handle = timeout(ncp_timer,NULL,NCP_TIMER_TICK);
112 return 0;
113}
114
115void
dadab5e9
MD
116ncp_done(void)
117{
984263bc 118 struct ncp_conn *ncp, *nncp;
dadab5e9
MD
119 struct thread *td = curthread; /* XXX */
120 struct ucred *cred;
121
122 KKASSERT(td->td_proc);
123 cred = td->td_proc->p_ucred;
984263bc
MD
124
125 untimeout(ncp_timer,NULL,ncp_timer_handle);
126 rm_at_exit(ncp_at_exit);
dadab5e9 127 ncp_conn_locklist(LK_EXCLUSIVE, td);
984263bc
MD
128 for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
129 nncp = SLIST_NEXT(ncp, nc_next);
130 ncp->ref_cnt = 0;
dadab5e9 131 if (ncp_conn_lock(ncp, td, cred,NCPM_READ|NCPM_EXECUTE|NCPM_WRITE)) {
984263bc
MD
132 NCPFATAL("Can't lock connection !\n");
133 continue;
134 }
135 if (ncp_disconnect(ncp) != 0)
dadab5e9 136 ncp_conn_unlock(ncp, td);
984263bc 137 }
dadab5e9 138 ncp_conn_unlocklist(td);
984263bc
MD
139}
140
141
142/* tick every second and check for watch dog packets and lost connections */
143static void
144ncp_timer(void *arg){
145 struct ncp_conn *conn;
146
147 if(ncp_conn_locklist(LK_SHARED | LK_NOWAIT, NULL) == 0) {
148 SLIST_FOREACH(conn, &conn_list, nc_next)
149 ncp_check_conn(conn);
150 ncp_conn_unlocklist(NULL);
151 }
152 ncp_timer_handle = timeout(ncp_timer,NULL,NCP_TIMER_TICK);
153}
154
155int
156ncp_get_bindery_object_id(struct ncp_conn *conn,
157 u_int16_t object_type, char *object_name,
158 struct ncp_bindery_object *target,
dadab5e9 159 struct thread *td,struct ucred *cred)
984263bc
MD
160{
161 int error;
162 DECLARE_RQ;
163
dadab5e9 164 NCP_RQ_HEAD_S(23,53,td,cred);
984263bc
MD
165 ncp_rq_word_hl(rqp, object_type);
166 ncp_rq_pstring(rqp, object_name);
167 checkbad(ncp_request(conn,rqp));
168 if (rqp->rpsize < 54) {
169 printf("ncp_rp_size %d < 54\n", rqp->rpsize);
170 error = EINVAL;
171 goto bad;
172 }
173 target->object_id = ncp_rp_dword_hl(rqp);
174 target->object_type = ncp_rp_word_hl(rqp);
175 ncp_rp_mem(rqp,(caddr_t)target->object_name, 48);
176 NCP_RQ_EXIT;
177 return error;
178}
179
180int
181ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred) {
182 int error = 0, len = 0, retlen=0, tsiz, burstio;
183 DECLARE_RQ;
184
185 tsiz = uiop->uio_resid;
186#ifdef NCPBURST
187 burstio = (ncp_burst_enabled && tsiz > conn->buffer_size);
188#else
189 burstio = 0;
190#endif
191
192 while (tsiz > 0) {
193 if (!burstio) {
194 len = min(4096 - (uiop->uio_offset % 4096), tsiz);
195 len = min(len, conn->buffer_size);
dadab5e9 196 NCP_RQ_HEAD(72,uiop->uio_td,cred);
984263bc
MD
197 ncp_rq_byte(rqp, 0);
198 ncp_rq_mem(rqp, (caddr_t)file, 6);
199 ncp_rq_dword(rqp, htonl(uiop->uio_offset));
200 ncp_rq_word(rqp, htons(len));
201 checkbad(ncp_request(conn,rqp));
202 retlen = ncp_rp_word_hl(rqp);
203 if (uiop->uio_offset & 1)
204 ncp_rp_byte(rqp);
205 error = nwfs_mbuftouio(&rqp->mrp,uiop,retlen,&rqp->bpos);
206 NCP_RQ_EXIT;
207 } else {
208#ifdef NCPBURST
209 error = ncp_burst_read(conn, file, tsiz, &len, &retlen, uiop, cred);
210#endif
211 }
212 if (error) break;
213 tsiz -= retlen;
214 if (retlen < len)
215 break;
216 }
217 return (error);
218}
219
220int
221ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
222{
223 int error = 0, len, tsiz, backup;
224 DECLARE_RQ;
225
226 if (uiop->uio_iovcnt != 1) {
227 printf("%s: can't handle iovcnt>1 !!!\n", __FUNCTION__);
228 return EIO;
229 }
230 tsiz = uiop->uio_resid;
231 while (tsiz > 0) {
232 len = min(4096 - (uiop->uio_offset % 4096), tsiz);
233 len = min(len, conn->buffer_size);
234 if (len == 0) {
235 printf("gotcha!\n");
236 }
237 /* rq head */
dadab5e9 238 NCP_RQ_HEAD(73,uiop->uio_td,cred);
984263bc
MD
239 ncp_rq_byte(rqp, 0);
240 ncp_rq_mem(rqp, (caddr_t)file, 6);
241 ncp_rq_dword(rqp, htonl(uiop->uio_offset));
242 ncp_rq_word_hl(rqp, len);
243 nwfs_uiotombuf(uiop,&rqp->mrq,len,&rqp->bpos);
244 checkbad(ncp_request(conn,rqp));
245 if (len == 0)
246 break;
247 NCP_RQ_EXIT;
248 if (error) {
249 backup = len;
250 uiop->uio_iov->iov_base -= backup;
251 uiop->uio_iov->iov_len += backup;
252 uiop->uio_offset -= backup;
253 uiop->uio_resid += backup;
254 break;
255 }
256 tsiz -= len;
257 }
258 if (error)
259 uiop->uio_resid = tsiz;
260 switch (error) {
261 case NWE_INSUFFICIENT_SPACE:
262 error = ENOSPC;
263 break;
264 }
265 return (error);
266}