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