File: /usr/src/linux/fs/ncpfs/sock.c

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     #include <linux/config.h>
12     
13     #include <linux/sched.h>
14     #include <linux/errno.h>
15     #include <linux/socket.h>
16     #include <linux/fcntl.h>
17     #include <linux/stat.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 <net/scm.h>
25     #include <net/sock.h>
26     #include <linux/ipx.h>
27     #include <linux/poll.h>
28     #include <linux/file.h>
29     
30     #include <linux/ncp_fs.h>
31     
32     #ifdef CONFIG_NCPFS_PACKET_SIGNING
33     #include "ncpsign_kernel.h"
34     #endif
35     
36     static int _recv(struct socket *sock, unsigned char *ubuf, int size,
37     		 unsigned flags)
38     {
39     	struct iovec iov;
40     	struct msghdr msg;
41     	struct scm_cookie scm;
42     
43     	memset(&scm, 0, sizeof(scm));
44     
45     	iov.iov_base = ubuf;
46     	iov.iov_len = size;
47     
48     	msg.msg_name = NULL;
49     	msg.msg_namelen = 0;
50     	msg.msg_control = NULL;
51     	msg.msg_iov = &iov;
52     	msg.msg_iovlen = 1;
53     	return sock->ops->recvmsg(sock, &msg, size, flags, &scm);
54     }
55     
56     static int _send(struct socket *sock, const void *buff, int len)
57     {
58     	struct iovec iov;
59     	struct msghdr msg;
60     	struct scm_cookie scm;
61     	int err;
62     
63     	iov.iov_base = (void *) buff;
64     	iov.iov_len = len;
65     
66     	msg.msg_name = NULL;
67     	msg.msg_namelen = 0;
68     	msg.msg_control = NULL;
69     	msg.msg_iov = &iov;
70     	msg.msg_iovlen = 1;
71     	msg.msg_flags = 0;
72     
73     	err = scm_send(sock, &msg, &scm);
74     	if (err < 0) {
75     		return err;
76     	}
77     	err = sock->ops->sendmsg(sock, &msg, len, &scm);
78     	scm_destroy(&scm);
79     	return err;
80     }
81     
82     static int do_ncp_rpc_call(struct ncp_server *server, int size,
83     		struct ncp_reply_header* reply_buf, int max_reply_size)
84     {
85     	struct file *file;
86     	struct socket *sock;
87     	int result;
88     	char *start = server->packet;
89     	poll_table wait_table;
90     	int init_timeout, max_timeout;
91     	int timeout;
92     	int retrans;
93     	int major_timeout_seen;
94     	int acknowledge_seen;
95     	int n;
96     
97     	/* We have to check the result, so store the complete header */
98     	struct ncp_request_header request =
99     	*((struct ncp_request_header *) (server->packet));
100     
101     	struct ncp_reply_header reply;
102     
103     	file = server->ncp_filp;
104     	sock = &file->f_dentry->d_inode->u.socket_i;
105     
106     	init_timeout = server->m.time_out;
107     	max_timeout = NCP_MAX_RPC_TIMEOUT;
108     	retrans = server->m.retry_count;
109     	major_timeout_seen = 0;
110     	acknowledge_seen = 0;
111     
112     	for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) {
113     		/*
114     		DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
115     			 htonl(server->m.serv_addr.sipx_network),
116     			 server->m.serv_addr.sipx_node[0],
117     			 server->m.serv_addr.sipx_node[1],
118     			 server->m.serv_addr.sipx_node[2],
119     			 server->m.serv_addr.sipx_node[3],
120     			 server->m.serv_addr.sipx_node[4],
121     			 server->m.serv_addr.sipx_node[5],
122     			 ntohs(server->m.serv_addr.sipx_port));
123     		*/
124     		DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
125     			 "seq: %d",
126     			 request.type,
127     			 (request.conn_high << 8) + request.conn_low,
128     			 request.sequence);
129     		DDPRINTK(" func: %d\n",
130     			 request.function);
131     
132     		result = _send(sock, (void *) start, size);
133     		if (result < 0) {
134     			printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result);
135     			break;
136     		}
137     	      re_select:
138     		poll_initwait(&wait_table);
139     		/* mb() is not necessary because ->poll() will serialize
140     		   instructions adding the wait_table waitqueues in the
141     		   waitqueue-head before going to calculate the mask-retval. */
142     		__set_current_state(TASK_INTERRUPTIBLE);
143     		if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) {
144     			int timed_out;
145     			if (timeout > max_timeout) {
146     				/* JEJB/JSP 2/7/94
147     				 * This is useful to see if the system is
148     				 * hanging */
149     				if (acknowledge_seen == 0) {
150     					printk(KERN_WARNING "NCP max timeout\n");
151     				}
152     				timeout = max_timeout;
153     			}
154     			timed_out = !schedule_timeout(timeout);
155     			poll_freewait(&wait_table);
156     			current->state = TASK_RUNNING;
157     			if (signal_pending(current)) {
158     				result = -ERESTARTSYS;
159     				break;
160     			}
161     			if(wait_table.error) {
162     				result = wait_table.error;
163     				break;
164     			}
165     			if (timed_out) {
166     				if (n < retrans)
167     					continue;
168     				if (server->m.flags & NCP_MOUNT_SOFT) {
169     					printk(KERN_WARNING "NCP server not responding\n");
170     					result = -EIO;
171     					break;
172     				}
173     				n = 0;
174     				timeout = init_timeout;
175     				if (init_timeout < max_timeout)
176     					init_timeout <<= 1;
177     				if (!major_timeout_seen) {
178     					printk(KERN_WARNING "NCP server not responding\n");
179     				}
180     				major_timeout_seen = 1;
181     				continue;
182     			}
183     		} else {
184     			poll_freewait(&wait_table);
185     		}
186     		current->state = TASK_RUNNING;
187     
188     		/* Get the header from the next packet using a peek, so keep it
189     		 * on the recv queue.  If it is wrong, it will be some reply
190     		 * we don't now need, so discard it */
191     		result = _recv(sock, (void *) &reply, sizeof(reply),
192     			       MSG_PEEK | MSG_DONTWAIT);
193     		if (result < 0) {
194     			if (result == -EAGAIN) {
195     				DDPRINTK("ncp_rpc_call: bad select ready\n");
196     				goto re_select;
197     			}
198     			if (result == -ECONNREFUSED) {
199     				DPRINTK("ncp_rpc_call: server playing coy\n");
200     				goto re_select;
201     			}
202     			if (result != -ERESTARTSYS) {
203     				printk(KERN_ERR "ncp_rpc_call: recv error = %d\n",
204     				       -result);
205     			}
206     			break;
207     		}
208     		if ((result == sizeof(reply))
209     		    && (reply.type == NCP_POSITIVE_ACK)) {
210     			/* Throw away the packet */
211     			DPRINTK("ncp_rpc_call: got positive acknowledge\n");
212     			_recv(sock, (void *) &reply, sizeof(reply),
213     			      MSG_DONTWAIT);
214     			n = 0;
215     			timeout = max_timeout;
216     			acknowledge_seen = 1;
217     			goto re_select;
218     		}
219     		DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
220     			 "seq: %d\n",
221     			 reply.type,
222     			 (reply.conn_high << 8) + reply.conn_low,
223     			 reply.task,
224     			 reply.sequence);
225     
226     		if ((result >= sizeof(reply))
227     		    && (reply.type == NCP_REPLY)
228     		    && ((request.type == NCP_ALLOC_SLOT_REQUEST)
229     			|| ((reply.sequence == request.sequence)
230     			    && (reply.conn_low == request.conn_low)
231     /* seem to get wrong task from NW311 && (reply.task      == request.task) */
232     			    && (reply.conn_high == request.conn_high)))) {
233     			if (major_timeout_seen)
234     				printk(KERN_NOTICE "NCP server OK\n");
235     			break;
236     		}
237     		/* JEJB/JSP 2/7/94
238     		 * we have xid mismatch, so discard the packet and start
239     		 * again.  What a hack! but I can't call recvfrom with
240     		 * a null buffer yet. */
241     		_recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT);
242     
243     		DPRINTK("ncp_rpc_call: reply mismatch\n");
244     		goto re_select;
245     	}
246     	/* 
247     	 * we have the correct reply, so read into the correct place and
248     	 * return it
249     	 */
250     	result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT);
251     	if (result < 0) {
252     		printk(KERN_WARNING "NCP: notice message: result=%d\n", result);
253     	} else if (result < sizeof(struct ncp_reply_header)) {
254     		printk(KERN_ERR "NCP: just caught a too small read memory size..., "
255     		       "email to NET channel\n");
256     		printk(KERN_ERR "NCP: result=%d\n", result);
257     		result = -EIO;
258     	}
259     
260     	return result;
261     }
262     
263     static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) {
264     	poll_table wait_table;
265     	struct file *file;
266     	struct socket *sock;
267     	int init_timeout;
268     	size_t dataread;
269     	int result = 0;
270     	
271     	file = server->ncp_filp;
272     	sock = &file->f_dentry->d_inode->u.socket_i;
273     	
274     	dataread = 0;
275     
276     	init_timeout = server->m.time_out * 20;
277     	
278     	/* hard-mounted volumes have no timeout, except connection close... */
279     	if (!(server->m.flags & NCP_MOUNT_SOFT))
280     		init_timeout = 0x7FFF0000;
281     
282     	while (len) {
283     		poll_initwait(&wait_table);
284     		/* mb() is not necessary because ->poll() will serialize
285     		   instructions adding the wait_table waitqueues in the
286     		   waitqueue-head before going to calculate the mask-retval. */
287     		__set_current_state(TASK_INTERRUPTIBLE);
288     		if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) {
289     			init_timeout = schedule_timeout(init_timeout);
290     			poll_freewait(&wait_table);
291     			current->state = TASK_RUNNING;
292     			if (signal_pending(current)) {
293     				return -ERESTARTSYS;
294     			}
295     			if (!init_timeout) {
296     				return -EIO;
297     			}
298     			if(wait_table.error) {
299     				return wait_table.error;
300     			}
301     		} else {
302     			poll_freewait(&wait_table);
303     		}
304     		current->state = TASK_RUNNING;
305     
306     		result = _recv(sock, buffer, len, MSG_DONTWAIT);
307     		if (result < 0) {
308     			if (result == -EAGAIN) {
309     				DDPRINTK("ncpfs: tcp: bad select ready\n");
310     				continue;
311     			}
312     			return result;
313     		}
314     		if (result == 0) {
315     			printk(KERN_ERR "ncpfs: tcp: EOF on socket\n");
316     			return -EIO;
317     		}
318     		if (result > len) {
319     			printk(KERN_ERR "ncpfs: tcp: bug in recvmsg\n");
320     			return -EIO;			
321     		}
322     		dataread += result;
323     		buffer += result;
324     		len -= result;
325     	}
326     	return 0;
327     }	
328     
329     #define NCP_TCP_XMIT_MAGIC	(0x446D6454)
330     #define NCP_TCP_XMIT_VERSION	(1)
331     #define NCP_TCP_RCVD_MAGIC	(0x744E6350)
332     
333     static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
334     		struct ncp_reply_header* reply_buf, int max_reply_size)
335     {
336     	struct file *file;
337     	struct socket *sock;
338     	int result;
339     	struct iovec iov[2];
340     	struct msghdr msg;
341     	struct scm_cookie scm;
342     	__u32 ncptcp_rcvd_hdr[2];
343     	__u32 ncptcp_xmit_hdr[4];
344     	int   datalen;
345     
346     	/* We have to check the result, so store the complete header */
347     	struct ncp_request_header request =
348     	*((struct ncp_request_header *) (server->packet));
349     
350     	file = server->ncp_filp;
351     	sock = &file->f_dentry->d_inode->u.socket_i;
352     	
353     	ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC);
354     	ncptcp_xmit_hdr[1] = htonl(size + 16);
355     	ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION);
356     	ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8);
357     
358     	DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
359     		 "seq: %d",
360     		 request.type,
361     		 (request.conn_high << 8) + request.conn_low,
362     		 request.sequence);
363     	DDPRINTK(" func: %d\n",
364     		 request.function);
365     
366     	iov[1].iov_base = (void *) server->packet;
367     	iov[1].iov_len = size;
368     	iov[0].iov_base = ncptcp_xmit_hdr;
369     	iov[0].iov_len = 16;
370     	msg.msg_name = NULL;
371     	msg.msg_namelen = 0;
372     	msg.msg_control = NULL;
373     	msg.msg_iov = iov;
374     	msg.msg_iovlen = 2;
375     	msg.msg_flags = MSG_NOSIGNAL;
376     
377     	result = scm_send(sock, &msg, &scm);
378     	if (result < 0) {
379     		return result;
380     	}
381     	result = sock->ops->sendmsg(sock, &msg, size + 16, &scm);
382     	scm_destroy(&scm);
383     	if (result < 0) {
384     		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
385     		return result;
386     	}
387     rstrcv:
388     	result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8);
389     	if (result)
390     		return result;
391     	if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) {
392     		printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0]));
393     		return -EIO;
394     	}
395     	datalen = ntohl(ncptcp_rcvd_hdr[1]);
396     	if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) {
397     		printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
398     		return -EIO;
399     	}
400     	datalen -= 8;
401     	result = do_tcp_rcv(server, reply_buf, datalen);
402     	if (result)
403     		return result;
404     	if (reply_buf->type != NCP_REPLY) {
405     		DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type);
406     		goto rstrcv;
407     	}
408     	if (request.type == NCP_ALLOC_SLOT_REQUEST)
409     		return datalen;
410     	if (reply_buf->sequence != request.sequence) {
411     		printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
412     		return -EIO;
413     	}
414     	if ((reply_buf->conn_low != request.conn_low) ||
415     	    (reply_buf->conn_high != request.conn_high)) {
416     		printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
417     		return -EIO;
418     	}
419     	return datalen;
420     }
421     
422     /*
423      * We need the server to be locked here, so check!
424      */
425     
426     static int ncp_do_request(struct ncp_server *server, int size,
427     		void* reply, int max_reply_size)
428     {
429     	struct file *file;
430     	struct socket *sock;
431     	int result;
432     
433     	if (server->lock == 0) {
434     		printk(KERN_ERR "ncpfs: Server not locked!\n");
435     		return -EIO;
436     	}
437     	if (!ncp_conn_valid(server)) {
438     		return -EIO;
439     	}
440     #ifdef CONFIG_NCPFS_PACKET_SIGNING
441     	if (server->sign_active)
442     	{
443     		sign_packet(server, &size);
444     	}
445     #endif /* CONFIG_NCPFS_PACKET_SIGNING */
446     	file = server->ncp_filp;
447     	sock = &file->f_dentry->d_inode->u.socket_i;
448     	/* N.B. this isn't needed ... check socket type? */
449     	if (!sock) {
450     		printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n");
451     		result = -EBADF;
452     	} else {
453     		mm_segment_t fs;
454     		sigset_t old_set;
455     		unsigned long mask, flags;
456     
457     		spin_lock_irqsave(&current->sigmask_lock, flags);
458     		old_set = current->blocked;
459     		if (current->flags & PF_EXITING)
460     			mask = 0;
461     		else
462     			mask = sigmask(SIGKILL);
463     		if (server->m.flags & NCP_MOUNT_INTR) {
464     			/* FIXME: This doesn't seem right at all.  So, like,
465     			   we can't handle SIGINT and get whatever to stop?
466     			   What if we've blocked it ourselves?  What about
467     			   alarms?  Why, in fact, are we mucking with the
468     			   sigmask at all? -- r~ */
469     			if (current->sig->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
470     				mask |= sigmask(SIGINT);
471     			if (current->sig->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
472     				mask |= sigmask(SIGQUIT);
473     		}
474     		siginitsetinv(&current->blocked, mask);
475     		recalc_sigpending(current);
476     		spin_unlock_irqrestore(&current->sigmask_lock, flags);
477     		
478     		fs = get_fs();
479     		set_fs(get_ds());
480     
481     		if (sock->type == SOCK_STREAM)
482     			result = do_ncp_tcp_rpc_call(server, size, reply, max_reply_size);
483     		else
484     			result = do_ncp_rpc_call(server, size, reply, max_reply_size);
485     
486     		set_fs(fs);
487     
488     		spin_lock_irqsave(&current->sigmask_lock, flags);
489     		current->blocked = old_set;
490     		recalc_sigpending(current);
491     		spin_unlock_irqrestore(&current->sigmask_lock, flags);
492     	}
493     
494     	DDPRINTK("do_ncp_rpc_call returned %d\n", result);
495     
496     	if (result < 0) {
497     		/* There was a problem with I/O, so the connections is
498     		 * no longer usable. */
499     		ncp_invalidate_conn(server);
500     	}
501     	return result;
502     }
503     
504     /* ncp_do_request assures that at least a complete reply header is
505      * received. It assumes that server->current_size contains the ncp
506      * request size
507      */
508     int ncp_request2(struct ncp_server *server, int function, 
509     		void* rpl, int size)
510     {
511     	struct ncp_request_header *h;
512     	struct ncp_reply_header* reply = rpl;
513     	int request_size = server->current_size
514     			 - sizeof(struct ncp_request_header);
515     	int result;
516     
517     	h = (struct ncp_request_header *) (server->packet);
518     	if (server->has_subfunction != 0) {
519     		*(__u16 *) & (h->data[0]) = htons(request_size - 2);
520     	}
521     	h->type = NCP_REQUEST;
522     
523     	server->sequence += 1;
524     	h->sequence = server->sequence;
525     	h->conn_low = (server->connection) & 0xff;
526     	h->conn_high = ((server->connection) & 0xff00) >> 8;
527     	/*
528     	 * The server shouldn't know or care what task is making a
529     	 * request, so we always use the same task number.
530     	 */
531     	h->task = 2; /* (current->pid) & 0xff; */
532     	h->function = function;
533     
534     	result = ncp_do_request(server, request_size + sizeof(*h), reply, size);
535     	if (result < 0) {
536     		DPRINTK("ncp_request_error: %d\n", result);
537     		goto out;
538     	}
539     	server->completion = reply->completion_code;
540     	server->conn_status = reply->connection_state;
541     	server->reply_size = result;
542     	server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
543     
544     	result = reply->completion_code;
545     
546     	if (result != 0)
547     		PPRINTK("ncp_request: completion code=%x\n", result);
548     out:
549     	return result;
550     }
551     
552     int ncp_connect(struct ncp_server *server)
553     {
554     	struct ncp_request_header *h;
555     	int result;
556     
557     	h = (struct ncp_request_header *) (server->packet);
558     	h->type = NCP_ALLOC_SLOT_REQUEST;
559     
560     	server->sequence = 0;
561     	h->sequence	= server->sequence;
562     	h->conn_low	= 0xff;
563     	h->conn_high	= 0xff;
564     	h->task		= 2; /* see above */
565     	h->function	= 0;
566     
567     	result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
568     	if (result < 0)
569     		goto out;
570     	server->sequence = 0;
571     	server->connection = h->conn_low + (h->conn_high * 256);
572     	result = 0;
573     out:
574     	return result;
575     }
576     
577     int ncp_disconnect(struct ncp_server *server)
578     {
579     	struct ncp_request_header *h;
580     
581     	h = (struct ncp_request_header *) (server->packet);
582     	h->type = NCP_DEALLOC_SLOT_REQUEST;
583     
584     	server->sequence += 1;
585     	h->sequence	= server->sequence;
586     	h->conn_low	= (server->connection) & 0xff;
587     	h->conn_high	= ((server->connection) & 0xff00) >> 8;
588     	h->task		= 2; /* see above */
589     	h->function	= 0;
590     
591     	return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
592     }
593     
594     void ncp_lock_server(struct ncp_server *server)
595     {
596     	down(&server->sem);
597     	if (server->lock)
598     		printk(KERN_WARNING "ncp_lock_server: was locked!\n");
599     	server->lock = 1;
600     }
601     
602     void ncp_unlock_server(struct ncp_server *server)
603     {
604     	if (!server->lock) {
605     		printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
606     		return;
607     	}
608     	server->lock = 0;
609     	up(&server->sem);
610     }
611