2 * linux/fs/ncpfs/sock.c
4 * Copyright (C) 1992, 1993 Rick Sladkey
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
11 #include <linux/config.h>
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 <asm/uaccess.h>
20 #include <linux/net.h>
22 #include <linux/netdevice.h>
23 #include <linux/signal.h>
26 #include <linux/ipx.h>
27 #include <linux/poll.h>
28 #include <linux/file.h>
30 #include <linux/ncp_fs.h>
32 #include "ncpsign_kernel.h"
34 static int _recv(struct socket *sock, unsigned char *ubuf, int size,
45 msg.msg_control = NULL;
49 return sock_recvmsg(sock, &msg, size, flags);
52 static inline int _send(struct socket *sock, const void *buff, int len)
57 iov.iov_base = (void *) buff;
62 msg.msg_control = NULL;
67 return sock_sendmsg(sock, &msg, len);
70 struct ncp_request_reply {
73 struct ncp_reply_header* reply_buf;
76 enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status;
77 struct iovec* tx_ciov;
80 struct iovec tx_iov[3];
85 void ncp_tcp_data_ready(struct sock *sk, int len) {
86 struct ncp_server *server = sk->sk_user_data;
88 server->data_ready(sk, len);
89 schedule_work(&server->rcv.tq);
92 void ncp_tcp_error_report(struct sock *sk) {
93 struct ncp_server *server = sk->sk_user_data;
95 server->error_report(sk);
96 schedule_work(&server->rcv.tq);
99 void ncp_tcp_write_space(struct sock *sk) {
100 struct ncp_server *server = sk->sk_user_data;
102 /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
104 server->write_space(sk);
105 if (server->tx.creq) {
106 schedule_work(&server->tx.tq);
110 void ncpdgram_timeout_call(unsigned long v) {
111 struct ncp_server *server = (void*)v;
113 schedule_work(&server->timeout_tq);
116 static inline void ncp_finish_request(struct ncp_request_reply *req, int result) {
117 req->result = result;
118 req->status = RQ_DONE;
119 wake_up_all(&req->wq);
122 static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err) {
123 struct ncp_request_reply *req;
125 ncp_invalidate_conn(server);
126 del_timer(&server->timeout_tm);
127 while (!list_empty(&server->tx.requests)) {
128 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
130 list_del_init(&req->req);
131 if (req == aborted) {
132 ncp_finish_request(req, err);
134 ncp_finish_request(req, -EIO);
137 req = server->rcv.creq;
139 server->rcv.creq = NULL;
140 if (req == aborted) {
141 ncp_finish_request(req, err);
143 ncp_finish_request(req, -EIO);
145 server->rcv.ptr = NULL;
146 server->rcv.state = 0;
148 req = server->tx.creq;
150 server->tx.creq = NULL;
151 if (req == aborted) {
152 ncp_finish_request(req, err);
154 ncp_finish_request(req, -EIO);
159 static inline int get_conn_number(struct ncp_reply_header *rp) {
160 return rp->conn_low | (rp->conn_high << 8);
163 static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
164 /* If req is done, we got signal, but we also received answer... */
165 switch (req->status) {
170 list_del_init(&req->req);
171 ncp_finish_request(req, err);
174 __abort_ncp_connection(server, req, err);
179 static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
180 down(&server->rcv.creq_sem);
181 __ncp_abort_request(server, req, err);
182 up(&server->rcv.creq_sem);
185 static inline void __ncptcp_abort(struct ncp_server *server) {
186 __abort_ncp_connection(server, NULL, 0);
189 static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) {
193 /* sock_sendmsg updates iov pointers for us :-( */
194 memcpy(iov, req->tx_ciov, req->tx_iovlen * sizeof(iov[0]));
197 msg.msg_control = NULL;
199 msg.msg_iovlen = req->tx_iovlen;
200 msg.msg_flags = MSG_DONTWAIT;
201 return sock_sendmsg(sock, &msg, req->tx_totallen);
204 static void __ncptcp_try_send(struct ncp_server *server) {
205 struct ncp_request_reply *rq;
208 struct iovec iovc[3];
211 rq = server->tx.creq;
216 /* sock_sendmsg updates iov pointers for us :-( */
217 memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
220 msg.msg_control = NULL;
222 msg.msg_iovlen = rq->tx_iovlen;
223 msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT;
224 result = sock_sendmsg(server->ncp_sock, &msg, rq->tx_totallen);
225 if (result == -EAGAIN) {
229 printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
230 __ncp_abort_request(server, rq, result);
233 if (result >= rq->tx_totallen) {
234 server->rcv.creq = rq;
235 server->tx.creq = NULL;
238 rq->tx_totallen -= result;
240 while (iov->iov_len <= result) {
241 result -= iov->iov_len;
245 iov->iov_base += result;
246 iov->iov_len -= result;
250 static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) {
251 req->status = RQ_INPROGRESS;
252 h->conn_low = server->connection;
253 h->conn_high = server->connection >> 8;
254 h->sequence = ++server->sequence;
257 static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
259 struct ncp_request_header* h;
261 req->tx_ciov = req->tx_iov + 1;
263 h = req->tx_iov[1].iov_base;
264 ncp_init_header(server, req, h);
265 signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
266 req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
267 cpu_to_le32(req->tx_totallen), req->sign);
269 req->tx_ciov[1].iov_base = req->sign;
270 req->tx_ciov[1].iov_len = signlen;
272 req->tx_totallen += signlen;
274 server->rcv.creq = req;
275 server->timeout_last = server->m.time_out;
276 server->timeout_retries = server->m.retry_count;
277 ncpdgram_send(server->ncp_sock, req);
278 mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
281 #define NCP_TCP_XMIT_MAGIC (0x446D6454)
282 #define NCP_TCP_XMIT_VERSION (1)
283 #define NCP_TCP_RCVD_MAGIC (0x744E6350)
285 static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
287 struct ncp_request_header* h;
289 req->tx_ciov = req->tx_iov;
290 h = req->tx_iov[1].iov_base;
291 ncp_init_header(server, req, h);
292 signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
293 req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
294 cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16;
296 req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
297 req->sign[1] = htonl(req->tx_totallen + signlen);
298 req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
299 req->sign[3] = htonl(req->datalen + 8);
300 req->tx_iov[0].iov_base = req->sign;
301 req->tx_iov[0].iov_len = signlen;
303 req->tx_totallen += signlen;
305 server->tx.creq = req;
306 __ncptcp_try_send(server);
309 static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
310 if (server->ncp_sock->type == SOCK_STREAM)
311 ncptcp_start_request(server, req);
313 ncpdgram_start_request(server, req);
316 static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) {
317 down(&server->rcv.creq_sem);
318 if (!ncp_conn_valid(server)) {
319 up(&server->rcv.creq_sem);
320 printk(KERN_ERR "ncpfs: tcp: Server died\n");
323 if (server->tx.creq || server->rcv.creq) {
324 req->status = RQ_QUEUED;
325 list_add_tail(&req->req, &server->tx.requests);
326 up(&server->rcv.creq_sem);
329 __ncp_start_request(server, req);
330 up(&server->rcv.creq_sem);
334 static void __ncp_next_request(struct ncp_server *server) {
335 struct ncp_request_reply *req;
337 server->rcv.creq = NULL;
338 if (list_empty(&server->tx.requests)) {
341 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
342 list_del_init(&req->req);
343 __ncp_start_request(server, req);
346 static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) {
347 if (server->info_sock) {
352 hdr[0] = cpu_to_be32(len + 8);
353 hdr[1] = cpu_to_be32(id);
355 iov[0].iov_base = hdr;
357 iov[1].iov_base = (void *) data;
358 iov[1].iov_len = len;
362 msg.msg_control = NULL;
365 msg.msg_flags = MSG_NOSIGNAL;
367 sock_sendmsg(server->info_sock, &msg, len + 8);
371 static void __ncpdgram_rcv_proc(void *s) {
372 struct ncp_server *server = s;
375 sock = server->ncp_sock;
378 struct ncp_reply_header reply;
381 result = _recv(sock, (void*)&reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
385 if (result >= sizeof(reply)) {
386 struct ncp_request_reply *req;
388 if (reply.type == NCP_WATCHDOG) {
389 unsigned char buf[10];
391 if (server->connection != get_conn_number(&reply)) {
394 result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
396 DPRINTK("recv failed with %d\n", result);
400 DPRINTK("too short (%u) watchdog packet\n", result);
404 DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
408 _send(sock, buf, sizeof(buf));
411 if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
412 result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
416 info_server(server, 0, server->unexpected_packet.data, result);
419 down(&server->rcv.creq_sem);
420 req = server->rcv.creq;
421 if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence &&
422 server->connection == get_conn_number(&reply)))) {
423 if (reply.type == NCP_POSITIVE_ACK) {
424 server->timeout_retries = server->m.retry_count;
425 server->timeout_last = NCP_MAX_RPC_TIMEOUT;
426 mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
427 } else if (reply.type == NCP_REPLY) {
428 result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT);
429 #ifdef CONFIG_NCPFS_PACKET_SIGNING
430 if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
431 if (result < 8 + 8) {
437 hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
438 if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) {
439 printk(KERN_INFO "ncpfs: Signature violation\n");
445 del_timer(&server->timeout_tm);
446 server->rcv.creq = NULL;
447 ncp_finish_request(req, result);
448 __ncp_next_request(server);
449 up(&server->rcv.creq_sem);
453 up(&server->rcv.creq_sem);
456 _recv(sock, (void*)&reply, sizeof(reply), MSG_DONTWAIT);
460 void ncpdgram_rcv_proc(void *s) {
462 struct ncp_server *server = s;
466 __ncpdgram_rcv_proc(server);
470 static void __ncpdgram_timeout_proc(struct ncp_server *server) {
471 /* If timer is pending, we are processing another request... */
472 if (!timer_pending(&server->timeout_tm)) {
473 struct ncp_request_reply* req;
475 req = server->rcv.creq;
479 if (server->m.flags & NCP_MOUNT_SOFT) {
480 if (server->timeout_retries-- == 0) {
481 __ncp_abort_request(server, req, -ETIMEDOUT);
486 ncpdgram_send(server->ncp_sock, req);
487 timeout = server->timeout_last << 1;
488 if (timeout > NCP_MAX_RPC_TIMEOUT) {
489 timeout = NCP_MAX_RPC_TIMEOUT;
491 server->timeout_last = timeout;
492 mod_timer(&server->timeout_tm, jiffies + timeout);
497 void ncpdgram_timeout_proc(void *s) {
499 struct ncp_server *server = s;
503 down(&server->rcv.creq_sem);
504 __ncpdgram_timeout_proc(server);
505 up(&server->rcv.creq_sem);
509 static inline void ncp_init_req(struct ncp_request_reply* req) {
510 init_waitqueue_head(&req->wq);
511 req->status = RQ_IDLE;
514 static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) {
518 result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
520 static unsigned char dummy[1024];
522 if (len > sizeof(dummy)) {
525 result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
531 printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
537 static int __ncptcp_rcv_proc(struct ncp_server *server) {
538 /* We have to check the result, so store the complete header */
541 struct ncp_request_reply *req;
545 while (server->rcv.len) {
546 result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
547 if (result == -EAGAIN) {
551 req = server->rcv.creq;
553 __ncp_abort_request(server, req, -EIO);
555 __ncptcp_abort(server);
558 printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
560 DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
564 if (server->rcv.ptr) {
565 server->rcv.ptr += result;
567 server->rcv.len -= result;
569 switch (server->rcv.state) {
571 if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
572 printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
573 __ncptcp_abort(server);
576 datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
578 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
579 __ncptcp_abort(server);
582 #ifdef CONFIG_NCPFS_PACKET_SIGNING
583 if (server->sign_active) {
585 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
586 __ncptcp_abort(server);
589 server->rcv.buf.len = datalen - 8;
590 server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
592 server->rcv.state = 4;
596 type = ntohs(server->rcv.buf.type);
597 #ifdef CONFIG_NCPFS_PACKET_SIGNING
600 if (type != NCP_REPLY) {
601 if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
602 *(__u16*)(server->unexpected_packet.data) = htons(type);
603 server->unexpected_packet.len = datalen - 8;
605 server->rcv.state = 5;
606 server->rcv.ptr = server->unexpected_packet.data + 2;
607 server->rcv.len = datalen - 10;
610 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
612 server->rcv.state = 2;
614 server->rcv.ptr = NULL;
615 server->rcv.len = datalen - 10;
618 req = server->rcv.creq;
620 DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
623 if (datalen > req->datalen + 8) {
624 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
625 server->rcv.state = 3;
628 req->datalen = datalen - 8;
629 req->reply_buf->type = NCP_REPLY;
630 server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2;
631 server->rcv.len = datalen - 10;
632 server->rcv.state = 1;
634 #ifdef CONFIG_NCPFS_PACKET_SIGNING
636 datalen = server->rcv.buf.len;
637 type = ntohs(server->rcv.buf.type2);
641 req = server->rcv.creq;
642 if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
643 if (req->reply_buf->sequence != server->sequence) {
644 printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
645 __ncp_abort_request(server, req, -EIO);
648 if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) {
649 printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
650 __ncp_abort_request(server, req, -EIO);
654 #ifdef CONFIG_NCPFS_PACKET_SIGNING
655 if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
656 if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
657 printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
658 __ncp_abort_request(server, req, -EIO);
663 ncp_finish_request(req, req->datalen);
665 __ncp_next_request(server);
668 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
669 server->rcv.len = 10;
670 server->rcv.state = 0;
673 ncp_finish_request(server->rcv.creq, -EIO);
676 info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
682 void ncp_tcp_rcv_proc(void *s) {
684 struct ncp_server *server = s;
688 down(&server->rcv.creq_sem);
689 __ncptcp_rcv_proc(server);
690 up(&server->rcv.creq_sem);
695 void ncp_tcp_tx_proc(void *s) {
697 struct ncp_server *server = s;
701 down(&server->rcv.creq_sem);
702 __ncptcp_try_send(server);
703 up(&server->rcv.creq_sem);
708 static int do_ncp_rpc_call(struct ncp_server *server, int size,
709 struct ncp_reply_header* reply_buf, int max_reply_size)
712 struct ncp_request_reply req;
715 req.reply_buf = reply_buf;
716 req.datalen = max_reply_size;
717 req.tx_iov[1].iov_base = (void *) server->packet;
718 req.tx_iov[1].iov_len = size;
720 req.tx_totallen = size;
721 req.tx_type = *(u_int16_t*)server->packet;
723 result = ncp_add_request(server, &req);
727 if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) {
728 ncp_abort_request(server, &req, -EIO);
734 * We need the server to be locked here, so check!
737 static int ncp_do_request(struct ncp_server *server, int size,
738 void* reply, int max_reply_size)
742 if (server->lock == 0) {
743 printk(KERN_ERR "ncpfs: Server not locked!\n");
746 if (!ncp_conn_valid(server)) {
747 printk(KERN_ERR "ncpfs: Connection invalid!\n");
753 unsigned long mask, flags;
755 spin_lock_irqsave(¤t->sighand->siglock, flags);
756 old_set = current->blocked;
757 if (current->flags & PF_EXITING)
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);
772 siginitsetinv(¤t->blocked, mask);
774 spin_unlock_irqrestore(¤t->sighand->siglock, flags);
779 result = do_ncp_rpc_call(server, size, reply, max_reply_size);
783 spin_lock_irqsave(¤t->sighand->siglock, flags);
784 current->blocked = old_set;
786 spin_unlock_irqrestore(¤t->sighand->siglock, flags);
789 DDPRINTK("do_ncp_rpc_call returned %d\n", result);
792 /* There was a problem with I/O, so the connections is
793 * no longer usable. */
794 ncp_invalidate_conn(server);
799 /* ncp_do_request assures that at least a complete reply header is
800 * received. It assumes that server->current_size contains the ncp
803 int ncp_request2(struct ncp_server *server, int function,
806 struct ncp_request_header *h;
807 struct ncp_reply_header* reply = rpl;
810 h = (struct ncp_request_header *) (server->packet);
811 if (server->has_subfunction != 0) {
812 *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
814 h->type = NCP_REQUEST;
816 * The server shouldn't know or care what task is making a
817 * request, so we always use the same task number.
819 h->task = 2; /* (current->pid) & 0xff; */
820 h->function = function;
822 result = ncp_do_request(server, server->current_size, reply, size);
824 DPRINTK("ncp_request_error: %d\n", result);
827 server->completion = reply->completion_code;
828 server->conn_status = reply->connection_state;
829 server->reply_size = result;
830 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
832 result = reply->completion_code;
835 PPRINTK("ncp_request: completion code=%x\n", result);
840 int ncp_connect(struct ncp_server *server)
842 struct ncp_request_header *h;
845 server->connection = 0xFFFF;
846 server->sequence = 255;
848 h = (struct ncp_request_header *) (server->packet);
849 h->type = NCP_ALLOC_SLOT_REQUEST;
850 h->task = 2; /* see above */
853 result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
856 server->connection = h->conn_low + (h->conn_high * 256);
862 int ncp_disconnect(struct ncp_server *server)
864 struct ncp_request_header *h;
866 h = (struct ncp_request_header *) (server->packet);
867 h->type = NCP_DEALLOC_SLOT_REQUEST;
868 h->task = 2; /* see above */
871 return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
874 void ncp_lock_server(struct ncp_server *server)
878 printk(KERN_WARNING "ncp_lock_server: was locked!\n");
882 void ncp_unlock_server(struct ncp_server *server)
885 printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");