Linux Audio

Check our new training course

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