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/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>
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 #ifdef CONFIG_NCPFS_PACKET_SIGNING
33 #include "ncpsign_kernel.h"
36 static int _recv(struct socket *sock, unsigned char *ubuf, int size,
41 struct scm_cookie scm;
43 memset(&scm, 0, sizeof(scm));
50 msg.msg_control = NULL;
53 return sock->ops->recvmsg(sock, &msg, size, flags, &scm);
56 static int _send(struct socket *sock, const void *buff, int len)
60 struct scm_cookie scm;
63 iov.iov_base = (void *) buff;
68 msg.msg_control = NULL;
73 err = scm_send(sock, &msg, &scm);
77 err = sock->ops->sendmsg(sock, &msg, len, &scm);
82 static int do_ncp_rpc_call(struct ncp_server *server, int size,
83 struct ncp_reply_header* reply_buf, int max_reply_size)
88 char *start = server->packet;
89 poll_table wait_table;
90 int init_timeout, max_timeout;
93 int major_timeout_seen;
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));
101 struct ncp_reply_header reply;
103 file = server->ncp_filp;
104 sock = &file->f_dentry->d_inode->u.socket_i;
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;
112 for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) {
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));
124 DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
127 (request.conn_high << 8) + request.conn_low,
129 DDPRINTK(" func: %d\n",
132 result = _send(sock, (void *) start, size);
134 printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result);
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)) {
145 if (timeout > max_timeout) {
147 * This is useful to see if the system is
149 if (acknowledge_seen == 0) {
150 printk(KERN_WARNING "NCP max timeout\n");
152 timeout = max_timeout;
154 timed_out = !schedule_timeout(timeout);
155 poll_freewait(&wait_table);
156 current->state = TASK_RUNNING;
157 if (signal_pending(current)) {
158 result = -ERESTARTSYS;
161 if(wait_table.error) {
162 result = wait_table.error;
168 if (server->m.flags & NCP_MOUNT_SOFT) {
169 printk(KERN_WARNING "NCP server not responding\n");
174 timeout = init_timeout;
175 if (init_timeout < max_timeout)
177 if (!major_timeout_seen) {
178 printk(KERN_WARNING "NCP server not responding\n");
180 major_timeout_seen = 1;
184 poll_freewait(&wait_table);
186 current->state = TASK_RUNNING;
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);
194 if (result == -EAGAIN) {
195 DDPRINTK("ncp_rpc_call: bad select ready\n");
198 if (result == -ECONNREFUSED) {
199 DPRINTK("ncp_rpc_call: server playing coy\n");
202 if (result != -ERESTARTSYS) {
203 printk(KERN_ERR "ncp_rpc_call: recv error = %d\n",
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),
215 timeout = max_timeout;
216 acknowledge_seen = 1;
219 DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
222 (reply.conn_high << 8) + reply.conn_low,
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");
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);
243 DPRINTK("ncp_rpc_call: reply mismatch\n");
247 * we have the correct reply, so read into the correct place and
250 result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT);
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);
263 static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) {
264 poll_table wait_table;
271 file = server->ncp_filp;
272 sock = &file->f_dentry->d_inode->u.socket_i;
276 init_timeout = server->m.time_out * 20;
278 /* hard-mounted volumes have no timeout, except connection close... */
279 if (!(server->m.flags & NCP_MOUNT_SOFT))
280 init_timeout = 0x7FFF0000;
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)) {
298 if(wait_table.error) {
299 return wait_table.error;
302 poll_freewait(&wait_table);
304 current->state = TASK_RUNNING;
306 result = _recv(sock, buffer, len, MSG_DONTWAIT);
308 if (result == -EAGAIN) {
309 DDPRINTK("ncpfs: tcp: bad select ready\n");
315 printk(KERN_ERR "ncpfs: tcp: EOF on socket\n");
319 printk(KERN_ERR "ncpfs: tcp: bug in recvmsg\n");
329 #define NCP_TCP_XMIT_MAGIC (0x446D6454)
330 #define NCP_TCP_XMIT_VERSION (1)
331 #define NCP_TCP_RCVD_MAGIC (0x744E6350)
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)
341 struct scm_cookie scm;
342 __u32 ncptcp_rcvd_hdr[2];
343 __u32 ncptcp_xmit_hdr[4];
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));
350 file = server->ncp_filp;
351 sock = &file->f_dentry->d_inode->u.socket_i;
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);
358 DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
361 (request.conn_high << 8) + request.conn_low,
363 DDPRINTK(" func: %d\n",
366 iov[1].iov_base = (void *) server->packet;
367 iov[1].iov_len = size;
368 iov[0].iov_base = ncptcp_xmit_hdr;
372 msg.msg_control = NULL;
375 msg.msg_flags = MSG_NOSIGNAL;
377 result = scm_send(sock, &msg, &scm);
381 result = sock->ops->sendmsg(sock, &msg, size + 16, &scm);
384 printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
388 result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8);
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]));
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);
401 result = do_tcp_rcv(server, reply_buf, datalen);
404 if (reply_buf->type != NCP_REPLY) {
405 DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type);
408 if (request.type == NCP_ALLOC_SLOT_REQUEST)
410 if (reply_buf->sequence != request.sequence) {
411 printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
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");
423 * We need the server to be locked here, so check!
426 static int ncp_do_request(struct ncp_server *server, int size,
427 void* reply, int max_reply_size)
433 if (server->lock == 0) {
434 printk(KERN_ERR "ncpfs: Server not locked!\n");
437 if (!ncp_conn_valid(server)) {
440 #ifdef CONFIG_NCPFS_PACKET_SIGNING
441 if (server->sign_active)
443 sign_packet(server, &size);
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? */
450 printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n");
455 unsigned long mask, flags;
457 spin_lock_irqsave(¤t->sigmask_lock, flags);
458 old_set = current->blocked;
459 if (current->flags & PF_EXITING)
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);
474 siginitsetinv(¤t->blocked, mask);
475 recalc_sigpending(current);
476 spin_unlock_irqrestore(¤t->sigmask_lock, flags);
481 if (sock->type == SOCK_STREAM)
482 result = do_ncp_tcp_rpc_call(server, size, reply, max_reply_size);
484 result = do_ncp_rpc_call(server, size, reply, max_reply_size);
488 spin_lock_irqsave(¤t->sigmask_lock, flags);
489 current->blocked = old_set;
490 recalc_sigpending(current);
491 spin_unlock_irqrestore(¤t->sigmask_lock, flags);
494 DDPRINTK("do_ncp_rpc_call returned %d\n", result);
497 /* There was a problem with I/O, so the connections is
498 * no longer usable. */
499 ncp_invalidate_conn(server);
504 /* ncp_do_request assures that at least a complete reply header is
505 * received. It assumes that server->current_size contains the ncp
508 int ncp_request2(struct ncp_server *server, int function,
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);
517 h = (struct ncp_request_header *) (server->packet);
518 if (server->has_subfunction != 0) {
519 *(__u16 *) & (h->data[0]) = htons(request_size - 2);
521 h->type = NCP_REQUEST;
523 server->sequence += 1;
524 h->sequence = server->sequence;
525 h->conn_low = (server->connection) & 0xff;
526 h->conn_high = ((server->connection) & 0xff00) >> 8;
528 * The server shouldn't know or care what task is making a
529 * request, so we always use the same task number.
531 h->task = 2; /* (current->pid) & 0xff; */
532 h->function = function;
534 result = ncp_do_request(server, request_size + sizeof(*h), reply, size);
536 DPRINTK("ncp_request_error: %d\n", result);
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);
544 result = reply->completion_code;
547 PPRINTK("ncp_request: completion code=%x\n", result);
552 int ncp_connect(struct ncp_server *server)
554 struct ncp_request_header *h;
557 h = (struct ncp_request_header *) (server->packet);
558 h->type = NCP_ALLOC_SLOT_REQUEST;
560 server->sequence = 0;
561 h->sequence = server->sequence;
564 h->task = 2; /* see above */
567 result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
570 server->sequence = 0;
571 server->connection = h->conn_low + (h->conn_high * 256);
577 int ncp_disconnect(struct ncp_server *server)
579 struct ncp_request_header *h;
581 h = (struct ncp_request_header *) (server->packet);
582 h->type = NCP_DEALLOC_SLOT_REQUEST;
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 */
591 return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
594 void ncp_lock_server(struct ncp_server *server)
598 printk(KERN_WARNING "ncp_lock_server: was locked!\n");
602 void ncp_unlock_server(struct ncp_server *server)
605 printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");