Linux Audio

Check our new training course

Loading...
v3.1
  1/*
  2 *  linux/fs/ncpfs/sock.c
  3 *
  4 *  Copyright (C) 1992, 1993  Rick Sladkey
  5 *
  6 *  Modified 1995, 1996 by Volker Lendecke to be usable for ncp
  7 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
  8 *
  9 */
 10
 11
 12#include <linux/time.h>
 13#include <linux/errno.h>
 14#include <linux/socket.h>
 15#include <linux/fcntl.h>
 16#include <linux/stat.h>
 17#include <linux/string.h>
 18#include <asm/uaccess.h>
 19#include <linux/in.h>
 20#include <linux/net.h>
 21#include <linux/mm.h>
 22#include <linux/netdevice.h>
 23#include <linux/signal.h>
 24#include <linux/slab.h>
 25#include <net/scm.h>
 26#include <net/sock.h>
 27#include <linux/ipx.h>
 28#include <linux/poll.h>
 29#include <linux/file.h>
 30
 31#include "ncp_fs.h"
 32
 33#include "ncpsign_kernel.h"
 34
 35static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
 36{
 37	struct msghdr msg = {NULL, };
 38	struct kvec iov = {buf, size};
 39	return kernel_recvmsg(sock, &msg, &iov, 1, size, flags);
 40}
 41
 42static inline int do_send(struct socket *sock, struct kvec *vec, int count,
 43			  int len, unsigned flags)
 44{
 45	struct msghdr msg = { .msg_flags = flags };
 46	return kernel_sendmsg(sock, &msg, vec, count, len);
 47}
 48
 49static int _send(struct socket *sock, const void *buff, int len)
 50{
 51	struct kvec vec;
 52	vec.iov_base = (void *) buff;
 53	vec.iov_len = len;
 54	return do_send(sock, &vec, 1, len, 0);
 55}
 56
 57struct ncp_request_reply {
 58	struct list_head req;
 59	wait_queue_head_t wq;
 60	atomic_t refs;
 61	unsigned char* reply_buf;
 62	size_t datalen;
 63	int result;
 64	enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
 65	struct kvec* tx_ciov;
 66	size_t tx_totallen;
 67	size_t tx_iovlen;
 68	struct kvec tx_iov[3];
 69	u_int16_t tx_type;
 70	u_int32_t sign[6];
 71};
 72
 73static inline struct ncp_request_reply* ncp_alloc_req(void)
 74{
 75	struct ncp_request_reply *req;
 76
 77	req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
 78	if (!req)
 79		return NULL;
 80
 81	init_waitqueue_head(&req->wq);
 82	atomic_set(&req->refs, (1));
 83	req->status = RQ_IDLE;
 84
 85	return req;
 86}
 87
 88static void ncp_req_get(struct ncp_request_reply *req)
 89{
 90	atomic_inc(&req->refs);
 91}
 92
 93static void ncp_req_put(struct ncp_request_reply *req)
 94{
 95	if (atomic_dec_and_test(&req->refs))
 96		kfree(req);
 97}
 98
 99void ncp_tcp_data_ready(struct sock *sk, int len)
100{
101	struct ncp_server *server = sk->sk_user_data;
102
103	server->data_ready(sk, len);
104	schedule_work(&server->rcv.tq);
105}
106
107void ncp_tcp_error_report(struct sock *sk)
108{
109	struct ncp_server *server = sk->sk_user_data;
110	
111	server->error_report(sk);
112	schedule_work(&server->rcv.tq);
113}
114
115void ncp_tcp_write_space(struct sock *sk)
116{
117	struct ncp_server *server = sk->sk_user_data;
118	
119	/* We do not need any locking: we first set tx.creq, and then we do sendmsg,
120	   not vice versa... */
121	server->write_space(sk);
122	if (server->tx.creq)
123		schedule_work(&server->tx.tq);
124}
125
126void ncpdgram_timeout_call(unsigned long v)
127{
128	struct ncp_server *server = (void*)v;
129	
130	schedule_work(&server->timeout_tq);
131}
132
133static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
134{
135	req->result = result;
136	if (req->status != RQ_ABANDONED)
137		memcpy(req->reply_buf, server->rxbuf, req->datalen);
138	req->status = RQ_DONE;
139	wake_up_all(&req->wq);
140	ncp_req_put(req);
141}
142
143static void __abort_ncp_connection(struct ncp_server *server)
144{
145	struct ncp_request_reply *req;
146
147	ncp_invalidate_conn(server);
148	del_timer(&server->timeout_tm);
149	while (!list_empty(&server->tx.requests)) {
150		req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
151		
152		list_del_init(&req->req);
153		ncp_finish_request(server, req, -EIO);
154	}
155	req = server->rcv.creq;
156	if (req) {
157		server->rcv.creq = NULL;
158		ncp_finish_request(server, req, -EIO);
159		server->rcv.ptr = NULL;
160		server->rcv.state = 0;
161	}
162	req = server->tx.creq;
163	if (req) {
164		server->tx.creq = NULL;
165		ncp_finish_request(server, req, -EIO);
166	}
167}
168
169static inline int get_conn_number(struct ncp_reply_header *rp)
170{
171	return rp->conn_low | (rp->conn_high << 8);
172}
173
174static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
175{
176	/* If req is done, we got signal, but we also received answer... */
177	switch (req->status) {
178		case RQ_IDLE:
179		case RQ_DONE:
180			break;
181		case RQ_QUEUED:
182			list_del_init(&req->req);
183			ncp_finish_request(server, req, err);
184			break;
185		case RQ_INPROGRESS:
186			req->status = RQ_ABANDONED;
187			break;
188		case RQ_ABANDONED:
189			break;
190	}
191}
192
193static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
194{
195	mutex_lock(&server->rcv.creq_mutex);
196	__ncp_abort_request(server, req, err);
197	mutex_unlock(&server->rcv.creq_mutex);
198}
199
200static inline void __ncptcp_abort(struct ncp_server *server)
201{
202	__abort_ncp_connection(server);
203}
204
205static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
206{
207	struct kvec vec[3];
208	/* sock_sendmsg updates iov pointers for us :-( */
209	memcpy(vec, req->tx_ciov, req->tx_iovlen * sizeof(vec[0]));
210	return do_send(sock, vec, req->tx_iovlen,
211		       req->tx_totallen, MSG_DONTWAIT);
212}
213
214static void __ncptcp_try_send(struct ncp_server *server)
215{
216	struct ncp_request_reply *rq;
217	struct kvec *iov;
218	struct kvec iovc[3];
219	int result;
220
221	rq = server->tx.creq;
222	if (!rq)
223		return;
224
225	/* sock_sendmsg updates iov pointers for us :-( */
226	memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
227	result = do_send(server->ncp_sock, iovc, rq->tx_iovlen,
228			 rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT);
229
230	if (result == -EAGAIN)
231		return;
232
233	if (result < 0) {
234		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
235		__ncp_abort_request(server, rq, result);
236		return;
237	}
238	if (result >= rq->tx_totallen) {
239		server->rcv.creq = rq;
240		server->tx.creq = NULL;
241		return;
242	}
243	rq->tx_totallen -= result;
244	iov = rq->tx_ciov;
245	while (iov->iov_len <= result) {
246		result -= iov->iov_len;
247		iov++;
248		rq->tx_iovlen--;
249	}
250	iov->iov_base += result;
251	iov->iov_len -= result;
252	rq->tx_ciov = iov;
253}
254
255static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
256{
257	req->status = RQ_INPROGRESS;
258	h->conn_low = server->connection;
259	h->conn_high = server->connection >> 8;
260	h->sequence = ++server->sequence;
261}
262	
263static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
264{
265	size_t signlen;
266	struct ncp_request_header* h;
267	
268	req->tx_ciov = req->tx_iov + 1;
269
270	h = req->tx_iov[1].iov_base;
271	ncp_init_header(server, req, h);
272	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, 
273			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
274			cpu_to_le32(req->tx_totallen), req->sign);
275	if (signlen) {
276		req->tx_ciov[1].iov_base = req->sign;
277		req->tx_ciov[1].iov_len = signlen;
278		req->tx_iovlen += 1;
279		req->tx_totallen += signlen;
280	}
281	server->rcv.creq = req;
282	server->timeout_last = server->m.time_out;
283	server->timeout_retries = server->m.retry_count;
284	ncpdgram_send(server->ncp_sock, req);
285	mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
286}
287
288#define NCP_TCP_XMIT_MAGIC	(0x446D6454)
289#define NCP_TCP_XMIT_VERSION	(1)
290#define NCP_TCP_RCVD_MAGIC	(0x744E6350)
291
292static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
293{
294	size_t signlen;
295	struct ncp_request_header* h;
296
297	req->tx_ciov = req->tx_iov;
298	h = req->tx_iov[1].iov_base;
299	ncp_init_header(server, req, h);
300	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
301			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
302			cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16;
303
304	req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
305	req->sign[1] = htonl(req->tx_totallen + signlen);
306	req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
307	req->sign[3] = htonl(req->datalen + 8);
308	req->tx_iov[0].iov_base = req->sign;
309	req->tx_iov[0].iov_len = signlen;
310	req->tx_iovlen += 1;
311	req->tx_totallen += signlen;
312
313	server->tx.creq = req;
314	__ncptcp_try_send(server);
315}
316
317static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
318{
319	/* we copy the data so that we do not depend on the caller
320	   staying alive */
321	memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
322	req->tx_iov[1].iov_base = server->txbuf;
323
324	if (server->ncp_sock->type == SOCK_STREAM)
325		ncptcp_start_request(server, req);
326	else
327		ncpdgram_start_request(server, req);
328}
329
330static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
331{
332	mutex_lock(&server->rcv.creq_mutex);
333	if (!ncp_conn_valid(server)) {
334		mutex_unlock(&server->rcv.creq_mutex);
335		printk(KERN_ERR "ncpfs: tcp: Server died\n");
336		return -EIO;
337	}
338	ncp_req_get(req);
339	if (server->tx.creq || server->rcv.creq) {
340		req->status = RQ_QUEUED;
341		list_add_tail(&req->req, &server->tx.requests);
342		mutex_unlock(&server->rcv.creq_mutex);
343		return 0;
344	}
345	__ncp_start_request(server, req);
346	mutex_unlock(&server->rcv.creq_mutex);
347	return 0;
348}
349
350static void __ncp_next_request(struct ncp_server *server)
351{
352	struct ncp_request_reply *req;
353
354	server->rcv.creq = NULL;
355	if (list_empty(&server->tx.requests)) {
356		return;
357	}
358	req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
359	list_del_init(&req->req);
360	__ncp_start_request(server, req);
361}
362
363static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
364{
365	if (server->info_sock) {
366		struct kvec iov[2];
367		__be32 hdr[2];
368	
369		hdr[0] = cpu_to_be32(len + 8);
370		hdr[1] = cpu_to_be32(id);
371	
372		iov[0].iov_base = hdr;
373		iov[0].iov_len = 8;
374		iov[1].iov_base = (void *) data;
375		iov[1].iov_len = len;
376
377		do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL);
378	}
379}
380
381void ncpdgram_rcv_proc(struct work_struct *work)
382{
383	struct ncp_server *server =
384		container_of(work, struct ncp_server, rcv.tq);
385	struct socket* sock;
386	
387	sock = server->ncp_sock;
388	
389	while (1) {
390		struct ncp_reply_header reply;
391		int result;
392
393		result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
394		if (result < 0) {
395			break;
396		}
397		if (result >= sizeof(reply)) {
398			struct ncp_request_reply *req;
399	
400			if (reply.type == NCP_WATCHDOG) {
401				unsigned char buf[10];
402
403				if (server->connection != get_conn_number(&reply)) {
404					goto drop;
405				}
406				result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
407				if (result < 0) {
408					DPRINTK("recv failed with %d\n", result);
409					continue;
410				}
411				if (result < 10) {
412					DPRINTK("too short (%u) watchdog packet\n", result);
413					continue;
414				}
415				if (buf[9] != '?') {
416					DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
417					continue;
418				}
419				buf[9] = 'Y';
420				_send(sock, buf, sizeof(buf));
421				continue;
422			}
423			if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
424				result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
425				if (result < 0) {
426					continue;
427				}
428				info_server(server, 0, server->unexpected_packet.data, result);
429				continue;
430			}
431			mutex_lock(&server->rcv.creq_mutex);
432			req = server->rcv.creq;
433			if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
434					server->connection == get_conn_number(&reply)))) {
435				if (reply.type == NCP_POSITIVE_ACK) {
436					server->timeout_retries = server->m.retry_count;
437					server->timeout_last = NCP_MAX_RPC_TIMEOUT;
438					mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
439				} else if (reply.type == NCP_REPLY) {
440					result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
441#ifdef CONFIG_NCPFS_PACKET_SIGNING
442					if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
443						if (result < 8 + 8) {
444							result = -EIO;
445						} else {
446							unsigned int hdrl;
447							
448							result -= 8;
449							hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
450							if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
451								printk(KERN_INFO "ncpfs: Signature violation\n");
452								result = -EIO;
453							}
454						}
455					}
456#endif
457					del_timer(&server->timeout_tm);
458				     	server->rcv.creq = NULL;
459					ncp_finish_request(server, req, result);
460					__ncp_next_request(server);
461					mutex_unlock(&server->rcv.creq_mutex);
462					continue;
463				}
464			}
465			mutex_unlock(&server->rcv.creq_mutex);
466		}
467drop:;		
468		_recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
469	}
470}
471
472static void __ncpdgram_timeout_proc(struct ncp_server *server)
473{
474	/* If timer is pending, we are processing another request... */
475	if (!timer_pending(&server->timeout_tm)) {
476		struct ncp_request_reply* req;
477		
478		req = server->rcv.creq;
479		if (req) {
480			int timeout;
481			
482			if (server->m.flags & NCP_MOUNT_SOFT) {
483				if (server->timeout_retries-- == 0) {
484					__ncp_abort_request(server, req, -ETIMEDOUT);
485					return;
486				}
487			}
488			/* Ignore errors */
489			ncpdgram_send(server->ncp_sock, req);
490			timeout = server->timeout_last << 1;
491			if (timeout > NCP_MAX_RPC_TIMEOUT) {
492				timeout = NCP_MAX_RPC_TIMEOUT;
493			}
494			server->timeout_last = timeout;
495			mod_timer(&server->timeout_tm, jiffies + timeout);
496		}
497	}
498}
499
500void ncpdgram_timeout_proc(struct work_struct *work)
501{
502	struct ncp_server *server =
503		container_of(work, struct ncp_server, timeout_tq);
504	mutex_lock(&server->rcv.creq_mutex);
505	__ncpdgram_timeout_proc(server);
506	mutex_unlock(&server->rcv.creq_mutex);
507}
508
509static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
510{
511	int result;
512	
513	if (buffer) {
514		result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
515	} else {
516		static unsigned char dummy[1024];
517			
518		if (len > sizeof(dummy)) {
519			len = sizeof(dummy);
520		}
521		result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
522	}
523	if (result < 0) {
524		return result;
525	}
526	if (result > len) {
527		printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
528		return -EIO;			
529	}
530	return result;
531}	
532
533static int __ncptcp_rcv_proc(struct ncp_server *server)
534{
535	/* We have to check the result, so store the complete header */
536	while (1) {
537		int result;
538		struct ncp_request_reply *req;
539		int datalen;
540		int type;
541
542		while (server->rcv.len) {
543			result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
544			if (result == -EAGAIN) {
545				return 0;
546			}
547			if (result <= 0) {
548				req = server->rcv.creq;
549				if (req) {
550					__ncp_abort_request(server, req, -EIO);
551				} else {
552					__ncptcp_abort(server);
553				}
554				if (result < 0) {
555					printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
556				} else {
557					DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
558				}
559				return -EIO;
560			}
561			if (server->rcv.ptr) {
562				server->rcv.ptr += result;
563			}
564			server->rcv.len -= result;
565		}
566		switch (server->rcv.state) {
567			case 0:
568				if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
569					printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
570					__ncptcp_abort(server);
571					return -EIO;
572				}
573				datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
574				if (datalen < 10) {
575					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
576					__ncptcp_abort(server);
577					return -EIO;
578				}
579#ifdef CONFIG_NCPFS_PACKET_SIGNING				
580				if (server->sign_active) {
581					if (datalen < 18) {
582						printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
583						__ncptcp_abort(server);
584						return -EIO;
585					}
586					server->rcv.buf.len = datalen - 8;
587					server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
588					server->rcv.len = 8;
589					server->rcv.state = 4;
590					break;
591				}
592#endif				
593				type = ntohs(server->rcv.buf.type);
594#ifdef CONFIG_NCPFS_PACKET_SIGNING				
595cont:;				
596#endif
597				if (type != NCP_REPLY) {
598					if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
599						*(__u16*)(server->unexpected_packet.data) = htons(type);
600						server->unexpected_packet.len = datalen - 8;
601
602						server->rcv.state = 5;
603						server->rcv.ptr = server->unexpected_packet.data + 2;
604						server->rcv.len = datalen - 10;
605						break;
606					}					
607					DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
608skipdata2:;
609					server->rcv.state = 2;
610skipdata:;
611					server->rcv.ptr = NULL;
612					server->rcv.len = datalen - 10;
613					break;
614				}
615				req = server->rcv.creq;
616				if (!req) {
617					DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
618					goto skipdata2;
619				}
620				if (datalen > req->datalen + 8) {
621					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
622					server->rcv.state = 3;
623					goto skipdata;
624				}
625				req->datalen = datalen - 8;
626				((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
627				server->rcv.ptr = server->rxbuf + 2;
628				server->rcv.len = datalen - 10;
629				server->rcv.state = 1;
630				break;
631#ifdef CONFIG_NCPFS_PACKET_SIGNING				
632			case 4:
633				datalen = server->rcv.buf.len;
634				type = ntohs(server->rcv.buf.type2);
635				goto cont;
636#endif
637			case 1:
638				req = server->rcv.creq;
639				if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
640					if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
641						printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
642						__ncp_abort_request(server, req, -EIO);
643						return -EIO;
644					}
645					if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
646						printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
647						__ncp_abort_request(server, req, -EIO);
648						return -EIO;
649					}
650				}
651#ifdef CONFIG_NCPFS_PACKET_SIGNING				
652				if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
653					if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
654						printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
655						__ncp_abort_request(server, req, -EIO);
656						return -EIO;
657					}
658				}
659#endif				
660				ncp_finish_request(server, req, req->datalen);
661			nextreq:;
662				__ncp_next_request(server);
663			case 2:
664			next:;
665				server->rcv.ptr = (unsigned char*)&server->rcv.buf;
666				server->rcv.len = 10;
667				server->rcv.state = 0;
668				break;
669			case 3:
670				ncp_finish_request(server, server->rcv.creq, -EIO);
671				goto nextreq;
672			case 5:
673				info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
674				goto next;
675		}
676	}
677}
678
679void ncp_tcp_rcv_proc(struct work_struct *work)
680{
681	struct ncp_server *server =
682		container_of(work, struct ncp_server, rcv.tq);
683
684	mutex_lock(&server->rcv.creq_mutex);
685	__ncptcp_rcv_proc(server);
686	mutex_unlock(&server->rcv.creq_mutex);
687}
688
689void ncp_tcp_tx_proc(struct work_struct *work)
690{
691	struct ncp_server *server =
692		container_of(work, struct ncp_server, tx.tq);
693	
694	mutex_lock(&server->rcv.creq_mutex);
695	__ncptcp_try_send(server);
696	mutex_unlock(&server->rcv.creq_mutex);
697}
698
699static int do_ncp_rpc_call(struct ncp_server *server, int size,
700		unsigned char* reply_buf, int max_reply_size)
701{
702	int result;
703	struct ncp_request_reply *req;
704
705	req = ncp_alloc_req();
706	if (!req)
707		return -ENOMEM;
708
709	req->reply_buf = reply_buf;
710	req->datalen = max_reply_size;
711	req->tx_iov[1].iov_base = server->packet;
712	req->tx_iov[1].iov_len = size;
713	req->tx_iovlen = 1;
714	req->tx_totallen = size;
715	req->tx_type = *(u_int16_t*)server->packet;
716
717	result = ncp_add_request(server, req);
718	if (result < 0)
719		goto out;
720
721	if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
722		ncp_abort_request(server, req, -EINTR);
723		result = -EINTR;
724		goto out;
725	}
726
727	result = req->result;
728
729out:
730	ncp_req_put(req);
731
732	return result;
733}
734
735/*
736 * We need the server to be locked here, so check!
737 */
738
739static int ncp_do_request(struct ncp_server *server, int size,
740		void* reply, int max_reply_size)
741{
742	int result;
743
744	if (server->lock == 0) {
745		printk(KERN_ERR "ncpfs: Server not locked!\n");
746		return -EIO;
747	}
748	if (!ncp_conn_valid(server)) {
749		return -EIO;
750	}
751	{
752		sigset_t old_set;
753		unsigned long mask, flags;
754
755		spin_lock_irqsave(&current->sighand->siglock, flags);
756		old_set = current->blocked;
757		if (current->flags & PF_EXITING)
758			mask = 0;
759		else
760			mask = sigmask(SIGKILL);
761		if (server->m.flags & NCP_MOUNT_INTR) {
762			/* FIXME: This doesn't seem right at all.  So, like,
763			   we can't handle SIGINT and get whatever to stop?
764			   What if we've blocked it ourselves?  What about
765			   alarms?  Why, in fact, are we mucking with the
766			   sigmask at all? -- r~ */
767			if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
768				mask |= sigmask(SIGINT);
769			if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
770				mask |= sigmask(SIGQUIT);
771		}
772		siginitsetinv(&current->blocked, mask);
773		recalc_sigpending();
774		spin_unlock_irqrestore(&current->sighand->siglock, flags);
775		
776		result = do_ncp_rpc_call(server, size, reply, max_reply_size);
777
778		spin_lock_irqsave(&current->sighand->siglock, flags);
779		current->blocked = old_set;
780		recalc_sigpending();
781		spin_unlock_irqrestore(&current->sighand->siglock, flags);
782	}
783
784	DDPRINTK("do_ncp_rpc_call returned %d\n", result);
785
786	return result;
787}
788
789/* ncp_do_request assures that at least a complete reply header is
790 * received. It assumes that server->current_size contains the ncp
791 * request size
792 */
793int ncp_request2(struct ncp_server *server, int function, 
794		void* rpl, int size)
795{
796	struct ncp_request_header *h;
797	struct ncp_reply_header* reply = rpl;
798	int result;
799
800	h = (struct ncp_request_header *) (server->packet);
801	if (server->has_subfunction != 0) {
802		*(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
803	}
804	h->type = NCP_REQUEST;
805	/*
806	 * The server shouldn't know or care what task is making a
807	 * request, so we always use the same task number.
808	 */
809	h->task = 2; /* (current->pid) & 0xff; */
810	h->function = function;
811
812	result = ncp_do_request(server, server->current_size, reply, size);
813	if (result < 0) {
814		DPRINTK("ncp_request_error: %d\n", result);
815		goto out;
816	}
817	server->completion = reply->completion_code;
818	server->conn_status = reply->connection_state;
819	server->reply_size = result;
820	server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
821
822	result = reply->completion_code;
823
824	if (result != 0)
825		PPRINTK("ncp_request: completion code=%x\n", result);
826out:
827	return result;
828}
829
830int ncp_connect(struct ncp_server *server)
831{
832	struct ncp_request_header *h;
833	int result;
834
835	server->connection = 0xFFFF;
836	server->sequence = 255;
837
838	h = (struct ncp_request_header *) (server->packet);
839	h->type = NCP_ALLOC_SLOT_REQUEST;
840	h->task		= 2; /* see above */
841	h->function	= 0;
842
843	result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
844	if (result < 0)
845		goto out;
846	server->connection = h->conn_low + (h->conn_high * 256);
847	result = 0;
848out:
849	return result;
850}
851
852int ncp_disconnect(struct ncp_server *server)
853{
854	struct ncp_request_header *h;
855
856	h = (struct ncp_request_header *) (server->packet);
857	h->type = NCP_DEALLOC_SLOT_REQUEST;
858	h->task		= 2; /* see above */
859	h->function	= 0;
860
861	return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
862}
863
864void ncp_lock_server(struct ncp_server *server)
865{
866	mutex_lock(&server->mutex);
867	if (server->lock)
868		printk(KERN_WARNING "ncp_lock_server: was locked!\n");
869	server->lock = 1;
870}
871
872void ncp_unlock_server(struct ncp_server *server)
873{
874	if (!server->lock) {
875		printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
876		return;
877	}
878	server->lock = 0;
879	mutex_unlock(&server->mutex);
880}
v3.5.6
  1/*
  2 *  linux/fs/ncpfs/sock.c
  3 *
  4 *  Copyright (C) 1992, 1993  Rick Sladkey
  5 *
  6 *  Modified 1995, 1996 by Volker Lendecke to be usable for ncp
  7 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
  8 *
  9 */
 10
 11
 12#include <linux/time.h>
 13#include <linux/errno.h>
 14#include <linux/socket.h>
 15#include <linux/fcntl.h>
 16#include <linux/stat.h>
 17#include <linux/string.h>
 18#include <asm/uaccess.h>
 19#include <linux/in.h>
 20#include <linux/net.h>
 21#include <linux/mm.h>
 22#include <linux/netdevice.h>
 23#include <linux/signal.h>
 24#include <linux/slab.h>
 25#include <net/scm.h>
 26#include <net/sock.h>
 27#include <linux/ipx.h>
 28#include <linux/poll.h>
 29#include <linux/file.h>
 30
 31#include "ncp_fs.h"
 32
 33#include "ncpsign_kernel.h"
 34
 35static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
 36{
 37	struct msghdr msg = {NULL, };
 38	struct kvec iov = {buf, size};
 39	return kernel_recvmsg(sock, &msg, &iov, 1, size, flags);
 40}
 41
 42static inline int do_send(struct socket *sock, struct kvec *vec, int count,
 43			  int len, unsigned flags)
 44{
 45	struct msghdr msg = { .msg_flags = flags };
 46	return kernel_sendmsg(sock, &msg, vec, count, len);
 47}
 48
 49static int _send(struct socket *sock, const void *buff, int len)
 50{
 51	struct kvec vec;
 52	vec.iov_base = (void *) buff;
 53	vec.iov_len = len;
 54	return do_send(sock, &vec, 1, len, 0);
 55}
 56
 57struct ncp_request_reply {
 58	struct list_head req;
 59	wait_queue_head_t wq;
 60	atomic_t refs;
 61	unsigned char* reply_buf;
 62	size_t datalen;
 63	int result;
 64	enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
 65	struct kvec* tx_ciov;
 66	size_t tx_totallen;
 67	size_t tx_iovlen;
 68	struct kvec tx_iov[3];
 69	u_int16_t tx_type;
 70	u_int32_t sign[6];
 71};
 72
 73static inline struct ncp_request_reply* ncp_alloc_req(void)
 74{
 75	struct ncp_request_reply *req;
 76
 77	req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
 78	if (!req)
 79		return NULL;
 80
 81	init_waitqueue_head(&req->wq);
 82	atomic_set(&req->refs, (1));
 83	req->status = RQ_IDLE;
 84
 85	return req;
 86}
 87
 88static void ncp_req_get(struct ncp_request_reply *req)
 89{
 90	atomic_inc(&req->refs);
 91}
 92
 93static void ncp_req_put(struct ncp_request_reply *req)
 94{
 95	if (atomic_dec_and_test(&req->refs))
 96		kfree(req);
 97}
 98
 99void ncp_tcp_data_ready(struct sock *sk, int len)
100{
101	struct ncp_server *server = sk->sk_user_data;
102
103	server->data_ready(sk, len);
104	schedule_work(&server->rcv.tq);
105}
106
107void ncp_tcp_error_report(struct sock *sk)
108{
109	struct ncp_server *server = sk->sk_user_data;
110	
111	server->error_report(sk);
112	schedule_work(&server->rcv.tq);
113}
114
115void ncp_tcp_write_space(struct sock *sk)
116{
117	struct ncp_server *server = sk->sk_user_data;
118	
119	/* We do not need any locking: we first set tx.creq, and then we do sendmsg,
120	   not vice versa... */
121	server->write_space(sk);
122	if (server->tx.creq)
123		schedule_work(&server->tx.tq);
124}
125
126void ncpdgram_timeout_call(unsigned long v)
127{
128	struct ncp_server *server = (void*)v;
129	
130	schedule_work(&server->timeout_tq);
131}
132
133static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
134{
135	req->result = result;
136	if (req->status != RQ_ABANDONED)
137		memcpy(req->reply_buf, server->rxbuf, req->datalen);
138	req->status = RQ_DONE;
139	wake_up_all(&req->wq);
140	ncp_req_put(req);
141}
142
143static void __abort_ncp_connection(struct ncp_server *server)
144{
145	struct ncp_request_reply *req;
146
147	ncp_invalidate_conn(server);
148	del_timer(&server->timeout_tm);
149	while (!list_empty(&server->tx.requests)) {
150		req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
151		
152		list_del_init(&req->req);
153		ncp_finish_request(server, req, -EIO);
154	}
155	req = server->rcv.creq;
156	if (req) {
157		server->rcv.creq = NULL;
158		ncp_finish_request(server, req, -EIO);
159		server->rcv.ptr = NULL;
160		server->rcv.state = 0;
161	}
162	req = server->tx.creq;
163	if (req) {
164		server->tx.creq = NULL;
165		ncp_finish_request(server, req, -EIO);
166	}
167}
168
169static inline int get_conn_number(struct ncp_reply_header *rp)
170{
171	return rp->conn_low | (rp->conn_high << 8);
172}
173
174static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
175{
176	/* If req is done, we got signal, but we also received answer... */
177	switch (req->status) {
178		case RQ_IDLE:
179		case RQ_DONE:
180			break;
181		case RQ_QUEUED:
182			list_del_init(&req->req);
183			ncp_finish_request(server, req, err);
184			break;
185		case RQ_INPROGRESS:
186			req->status = RQ_ABANDONED;
187			break;
188		case RQ_ABANDONED:
189			break;
190	}
191}
192
193static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
194{
195	mutex_lock(&server->rcv.creq_mutex);
196	__ncp_abort_request(server, req, err);
197	mutex_unlock(&server->rcv.creq_mutex);
198}
199
200static inline void __ncptcp_abort(struct ncp_server *server)
201{
202	__abort_ncp_connection(server);
203}
204
205static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
206{
207	struct kvec vec[3];
208	/* sock_sendmsg updates iov pointers for us :-( */
209	memcpy(vec, req->tx_ciov, req->tx_iovlen * sizeof(vec[0]));
210	return do_send(sock, vec, req->tx_iovlen,
211		       req->tx_totallen, MSG_DONTWAIT);
212}
213
214static void __ncptcp_try_send(struct ncp_server *server)
215{
216	struct ncp_request_reply *rq;
217	struct kvec *iov;
218	struct kvec iovc[3];
219	int result;
220
221	rq = server->tx.creq;
222	if (!rq)
223		return;
224
225	/* sock_sendmsg updates iov pointers for us :-( */
226	memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
227	result = do_send(server->ncp_sock, iovc, rq->tx_iovlen,
228			 rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT);
229
230	if (result == -EAGAIN)
231		return;
232
233	if (result < 0) {
234		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
235		__ncp_abort_request(server, rq, result);
236		return;
237	}
238	if (result >= rq->tx_totallen) {
239		server->rcv.creq = rq;
240		server->tx.creq = NULL;
241		return;
242	}
243	rq->tx_totallen -= result;
244	iov = rq->tx_ciov;
245	while (iov->iov_len <= result) {
246		result -= iov->iov_len;
247		iov++;
248		rq->tx_iovlen--;
249	}
250	iov->iov_base += result;
251	iov->iov_len -= result;
252	rq->tx_ciov = iov;
253}
254
255static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
256{
257	req->status = RQ_INPROGRESS;
258	h->conn_low = server->connection;
259	h->conn_high = server->connection >> 8;
260	h->sequence = ++server->sequence;
261}
262	
263static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
264{
265	size_t signlen;
266	struct ncp_request_header* h;
267	
268	req->tx_ciov = req->tx_iov + 1;
269
270	h = req->tx_iov[1].iov_base;
271	ncp_init_header(server, req, h);
272	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, 
273			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
274			cpu_to_le32(req->tx_totallen), req->sign);
275	if (signlen) {
276		req->tx_ciov[1].iov_base = req->sign;
277		req->tx_ciov[1].iov_len = signlen;
278		req->tx_iovlen += 1;
279		req->tx_totallen += signlen;
280	}
281	server->rcv.creq = req;
282	server->timeout_last = server->m.time_out;
283	server->timeout_retries = server->m.retry_count;
284	ncpdgram_send(server->ncp_sock, req);
285	mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
286}
287
288#define NCP_TCP_XMIT_MAGIC	(0x446D6454)
289#define NCP_TCP_XMIT_VERSION	(1)
290#define NCP_TCP_RCVD_MAGIC	(0x744E6350)
291
292static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
293{
294	size_t signlen;
295	struct ncp_request_header* h;
296
297	req->tx_ciov = req->tx_iov;
298	h = req->tx_iov[1].iov_base;
299	ncp_init_header(server, req, h);
300	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
301			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
302			cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16;
303
304	req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
305	req->sign[1] = htonl(req->tx_totallen + signlen);
306	req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
307	req->sign[3] = htonl(req->datalen + 8);
308	req->tx_iov[0].iov_base = req->sign;
309	req->tx_iov[0].iov_len = signlen;
310	req->tx_iovlen += 1;
311	req->tx_totallen += signlen;
312
313	server->tx.creq = req;
314	__ncptcp_try_send(server);
315}
316
317static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
318{
319	/* we copy the data so that we do not depend on the caller
320	   staying alive */
321	memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
322	req->tx_iov[1].iov_base = server->txbuf;
323
324	if (server->ncp_sock->type == SOCK_STREAM)
325		ncptcp_start_request(server, req);
326	else
327		ncpdgram_start_request(server, req);
328}
329
330static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
331{
332	mutex_lock(&server->rcv.creq_mutex);
333	if (!ncp_conn_valid(server)) {
334		mutex_unlock(&server->rcv.creq_mutex);
335		printk(KERN_ERR "ncpfs: tcp: Server died\n");
336		return -EIO;
337	}
338	ncp_req_get(req);
339	if (server->tx.creq || server->rcv.creq) {
340		req->status = RQ_QUEUED;
341		list_add_tail(&req->req, &server->tx.requests);
342		mutex_unlock(&server->rcv.creq_mutex);
343		return 0;
344	}
345	__ncp_start_request(server, req);
346	mutex_unlock(&server->rcv.creq_mutex);
347	return 0;
348}
349
350static void __ncp_next_request(struct ncp_server *server)
351{
352	struct ncp_request_reply *req;
353
354	server->rcv.creq = NULL;
355	if (list_empty(&server->tx.requests)) {
356		return;
357	}
358	req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
359	list_del_init(&req->req);
360	__ncp_start_request(server, req);
361}
362
363static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
364{
365	if (server->info_sock) {
366		struct kvec iov[2];
367		__be32 hdr[2];
368	
369		hdr[0] = cpu_to_be32(len + 8);
370		hdr[1] = cpu_to_be32(id);
371	
372		iov[0].iov_base = hdr;
373		iov[0].iov_len = 8;
374		iov[1].iov_base = (void *) data;
375		iov[1].iov_len = len;
376
377		do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL);
378	}
379}
380
381void ncpdgram_rcv_proc(struct work_struct *work)
382{
383	struct ncp_server *server =
384		container_of(work, struct ncp_server, rcv.tq);
385	struct socket* sock;
386	
387	sock = server->ncp_sock;
388	
389	while (1) {
390		struct ncp_reply_header reply;
391		int result;
392
393		result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
394		if (result < 0) {
395			break;
396		}
397		if (result >= sizeof(reply)) {
398			struct ncp_request_reply *req;
399	
400			if (reply.type == NCP_WATCHDOG) {
401				unsigned char buf[10];
402
403				if (server->connection != get_conn_number(&reply)) {
404					goto drop;
405				}
406				result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
407				if (result < 0) {
408					DPRINTK("recv failed with %d\n", result);
409					continue;
410				}
411				if (result < 10) {
412					DPRINTK("too short (%u) watchdog packet\n", result);
413					continue;
414				}
415				if (buf[9] != '?') {
416					DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
417					continue;
418				}
419				buf[9] = 'Y';
420				_send(sock, buf, sizeof(buf));
421				continue;
422			}
423			if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
424				result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
425				if (result < 0) {
426					continue;
427				}
428				info_server(server, 0, server->unexpected_packet.data, result);
429				continue;
430			}
431			mutex_lock(&server->rcv.creq_mutex);
432			req = server->rcv.creq;
433			if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
434					server->connection == get_conn_number(&reply)))) {
435				if (reply.type == NCP_POSITIVE_ACK) {
436					server->timeout_retries = server->m.retry_count;
437					server->timeout_last = NCP_MAX_RPC_TIMEOUT;
438					mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
439				} else if (reply.type == NCP_REPLY) {
440					result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
441#ifdef CONFIG_NCPFS_PACKET_SIGNING
442					if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
443						if (result < 8 + 8) {
444							result = -EIO;
445						} else {
446							unsigned int hdrl;
447							
448							result -= 8;
449							hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
450							if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
451								printk(KERN_INFO "ncpfs: Signature violation\n");
452								result = -EIO;
453							}
454						}
455					}
456#endif
457					del_timer(&server->timeout_tm);
458				     	server->rcv.creq = NULL;
459					ncp_finish_request(server, req, result);
460					__ncp_next_request(server);
461					mutex_unlock(&server->rcv.creq_mutex);
462					continue;
463				}
464			}
465			mutex_unlock(&server->rcv.creq_mutex);
466		}
467drop:;		
468		_recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
469	}
470}
471
472static void __ncpdgram_timeout_proc(struct ncp_server *server)
473{
474	/* If timer is pending, we are processing another request... */
475	if (!timer_pending(&server->timeout_tm)) {
476		struct ncp_request_reply* req;
477		
478		req = server->rcv.creq;
479		if (req) {
480			int timeout;
481			
482			if (server->m.flags & NCP_MOUNT_SOFT) {
483				if (server->timeout_retries-- == 0) {
484					__ncp_abort_request(server, req, -ETIMEDOUT);
485					return;
486				}
487			}
488			/* Ignore errors */
489			ncpdgram_send(server->ncp_sock, req);
490			timeout = server->timeout_last << 1;
491			if (timeout > NCP_MAX_RPC_TIMEOUT) {
492				timeout = NCP_MAX_RPC_TIMEOUT;
493			}
494			server->timeout_last = timeout;
495			mod_timer(&server->timeout_tm, jiffies + timeout);
496		}
497	}
498}
499
500void ncpdgram_timeout_proc(struct work_struct *work)
501{
502	struct ncp_server *server =
503		container_of(work, struct ncp_server, timeout_tq);
504	mutex_lock(&server->rcv.creq_mutex);
505	__ncpdgram_timeout_proc(server);
506	mutex_unlock(&server->rcv.creq_mutex);
507}
508
509static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
510{
511	int result;
512	
513	if (buffer) {
514		result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
515	} else {
516		static unsigned char dummy[1024];
517			
518		if (len > sizeof(dummy)) {
519			len = sizeof(dummy);
520		}
521		result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
522	}
523	if (result < 0) {
524		return result;
525	}
526	if (result > len) {
527		printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
528		return -EIO;			
529	}
530	return result;
531}	
532
533static int __ncptcp_rcv_proc(struct ncp_server *server)
534{
535	/* We have to check the result, so store the complete header */
536	while (1) {
537		int result;
538		struct ncp_request_reply *req;
539		int datalen;
540		int type;
541
542		while (server->rcv.len) {
543			result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
544			if (result == -EAGAIN) {
545				return 0;
546			}
547			if (result <= 0) {
548				req = server->rcv.creq;
549				if (req) {
550					__ncp_abort_request(server, req, -EIO);
551				} else {
552					__ncptcp_abort(server);
553				}
554				if (result < 0) {
555					printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
556				} else {
557					DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
558				}
559				return -EIO;
560			}
561			if (server->rcv.ptr) {
562				server->rcv.ptr += result;
563			}
564			server->rcv.len -= result;
565		}
566		switch (server->rcv.state) {
567			case 0:
568				if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
569					printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
570					__ncptcp_abort(server);
571					return -EIO;
572				}
573				datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
574				if (datalen < 10) {
575					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
576					__ncptcp_abort(server);
577					return -EIO;
578				}
579#ifdef CONFIG_NCPFS_PACKET_SIGNING				
580				if (server->sign_active) {
581					if (datalen < 18) {
582						printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
583						__ncptcp_abort(server);
584						return -EIO;
585					}
586					server->rcv.buf.len = datalen - 8;
587					server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
588					server->rcv.len = 8;
589					server->rcv.state = 4;
590					break;
591				}
592#endif				
593				type = ntohs(server->rcv.buf.type);
594#ifdef CONFIG_NCPFS_PACKET_SIGNING				
595cont:;				
596#endif
597				if (type != NCP_REPLY) {
598					if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
599						*(__u16*)(server->unexpected_packet.data) = htons(type);
600						server->unexpected_packet.len = datalen - 8;
601
602						server->rcv.state = 5;
603						server->rcv.ptr = server->unexpected_packet.data + 2;
604						server->rcv.len = datalen - 10;
605						break;
606					}					
607					DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
608skipdata2:;
609					server->rcv.state = 2;
610skipdata:;
611					server->rcv.ptr = NULL;
612					server->rcv.len = datalen - 10;
613					break;
614				}
615				req = server->rcv.creq;
616				if (!req) {
617					DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
618					goto skipdata2;
619				}
620				if (datalen > req->datalen + 8) {
621					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
622					server->rcv.state = 3;
623					goto skipdata;
624				}
625				req->datalen = datalen - 8;
626				((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
627				server->rcv.ptr = server->rxbuf + 2;
628				server->rcv.len = datalen - 10;
629				server->rcv.state = 1;
630				break;
631#ifdef CONFIG_NCPFS_PACKET_SIGNING				
632			case 4:
633				datalen = server->rcv.buf.len;
634				type = ntohs(server->rcv.buf.type2);
635				goto cont;
636#endif
637			case 1:
638				req = server->rcv.creq;
639				if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
640					if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
641						printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
642						__ncp_abort_request(server, req, -EIO);
643						return -EIO;
644					}
645					if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
646						printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
647						__ncp_abort_request(server, req, -EIO);
648						return -EIO;
649					}
650				}
651#ifdef CONFIG_NCPFS_PACKET_SIGNING				
652				if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
653					if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
654						printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
655						__ncp_abort_request(server, req, -EIO);
656						return -EIO;
657					}
658				}
659#endif				
660				ncp_finish_request(server, req, req->datalen);
661			nextreq:;
662				__ncp_next_request(server);
663			case 2:
664			next:;
665				server->rcv.ptr = (unsigned char*)&server->rcv.buf;
666				server->rcv.len = 10;
667				server->rcv.state = 0;
668				break;
669			case 3:
670				ncp_finish_request(server, server->rcv.creq, -EIO);
671				goto nextreq;
672			case 5:
673				info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
674				goto next;
675		}
676	}
677}
678
679void ncp_tcp_rcv_proc(struct work_struct *work)
680{
681	struct ncp_server *server =
682		container_of(work, struct ncp_server, rcv.tq);
683
684	mutex_lock(&server->rcv.creq_mutex);
685	__ncptcp_rcv_proc(server);
686	mutex_unlock(&server->rcv.creq_mutex);
687}
688
689void ncp_tcp_tx_proc(struct work_struct *work)
690{
691	struct ncp_server *server =
692		container_of(work, struct ncp_server, tx.tq);
693	
694	mutex_lock(&server->rcv.creq_mutex);
695	__ncptcp_try_send(server);
696	mutex_unlock(&server->rcv.creq_mutex);
697}
698
699static int do_ncp_rpc_call(struct ncp_server *server, int size,
700		unsigned char* reply_buf, int max_reply_size)
701{
702	int result;
703	struct ncp_request_reply *req;
704
705	req = ncp_alloc_req();
706	if (!req)
707		return -ENOMEM;
708
709	req->reply_buf = reply_buf;
710	req->datalen = max_reply_size;
711	req->tx_iov[1].iov_base = server->packet;
712	req->tx_iov[1].iov_len = size;
713	req->tx_iovlen = 1;
714	req->tx_totallen = size;
715	req->tx_type = *(u_int16_t*)server->packet;
716
717	result = ncp_add_request(server, req);
718	if (result < 0)
719		goto out;
720
721	if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
722		ncp_abort_request(server, req, -EINTR);
723		result = -EINTR;
724		goto out;
725	}
726
727	result = req->result;
728
729out:
730	ncp_req_put(req);
731
732	return result;
733}
734
735/*
736 * We need the server to be locked here, so check!
737 */
738
739static int ncp_do_request(struct ncp_server *server, int size,
740		void* reply, int max_reply_size)
741{
742	int result;
743
744	if (server->lock == 0) {
745		printk(KERN_ERR "ncpfs: Server not locked!\n");
746		return -EIO;
747	}
748	if (!ncp_conn_valid(server)) {
749		return -EIO;
750	}
751	{
752		sigset_t old_set;
753		unsigned long mask, flags;
754
755		spin_lock_irqsave(&current->sighand->siglock, flags);
756		old_set = current->blocked;
757		if (current->flags & PF_EXITING)
758			mask = 0;
759		else
760			mask = sigmask(SIGKILL);
761		if (server->m.flags & NCP_MOUNT_INTR) {
762			/* FIXME: This doesn't seem right at all.  So, like,
763			   we can't handle SIGINT and get whatever to stop?
764			   What if we've blocked it ourselves?  What about
765			   alarms?  Why, in fact, are we mucking with the
766			   sigmask at all? -- r~ */
767			if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
768				mask |= sigmask(SIGINT);
769			if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
770				mask |= sigmask(SIGQUIT);
771		}
772		siginitsetinv(&current->blocked, mask);
773		recalc_sigpending();
774		spin_unlock_irqrestore(&current->sighand->siglock, flags);
775		
776		result = do_ncp_rpc_call(server, size, reply, max_reply_size);
777
778		spin_lock_irqsave(&current->sighand->siglock, flags);
779		current->blocked = old_set;
780		recalc_sigpending();
781		spin_unlock_irqrestore(&current->sighand->siglock, flags);
782	}
783
784	DDPRINTK("do_ncp_rpc_call returned %d\n", result);
785
786	return result;
787}
788
789/* ncp_do_request assures that at least a complete reply header is
790 * received. It assumes that server->current_size contains the ncp
791 * request size
792 */
793int ncp_request2(struct ncp_server *server, int function, 
794		void* rpl, int size)
795{
796	struct ncp_request_header *h;
797	struct ncp_reply_header* reply = rpl;
798	int result;
799
800	h = (struct ncp_request_header *) (server->packet);
801	if (server->has_subfunction != 0) {
802		*(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
803	}
804	h->type = NCP_REQUEST;
805	/*
806	 * The server shouldn't know or care what task is making a
807	 * request, so we always use the same task number.
808	 */
809	h->task = 2; /* (current->pid) & 0xff; */
810	h->function = function;
811
812	result = ncp_do_request(server, server->current_size, reply, size);
813	if (result < 0) {
814		DPRINTK("ncp_request_error: %d\n", result);
815		goto out;
816	}
817	server->completion = reply->completion_code;
818	server->conn_status = reply->connection_state;
819	server->reply_size = result;
820	server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
821
822	result = reply->completion_code;
823
824	if (result != 0)
825		PPRINTK("ncp_request: completion code=%x\n", result);
826out:
827	return result;
828}
829
830int ncp_connect(struct ncp_server *server)
831{
832	struct ncp_request_header *h;
833	int result;
834
835	server->connection = 0xFFFF;
836	server->sequence = 255;
837
838	h = (struct ncp_request_header *) (server->packet);
839	h->type = NCP_ALLOC_SLOT_REQUEST;
840	h->task		= 2; /* see above */
841	h->function	= 0;
842
843	result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
844	if (result < 0)
845		goto out;
846	server->connection = h->conn_low + (h->conn_high * 256);
847	result = 0;
848out:
849	return result;
850}
851
852int ncp_disconnect(struct ncp_server *server)
853{
854	struct ncp_request_header *h;
855
856	h = (struct ncp_request_header *) (server->packet);
857	h->type = NCP_DEALLOC_SLOT_REQUEST;
858	h->task		= 2; /* see above */
859	h->function	= 0;
860
861	return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
862}
863
864void ncp_lock_server(struct ncp_server *server)
865{
866	mutex_lock(&server->mutex);
867	if (server->lock)
868		printk(KERN_WARNING "ncp_lock_server: was locked!\n");
869	server->lock = 1;
870}
871
872void ncp_unlock_server(struct ncp_server *server)
873{
874	if (!server->lock) {
875		printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
876		return;
877	}
878	server->lock = 0;
879	mutex_unlock(&server->mutex);
880}