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
_recv(struct socket * sock,unsigned char * ubuf,int size,unsigned flags)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
_send(struct socket * sock,const void * buff,int len)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
do_ncp_rpc_call(struct ncp_server * server,int size,struct ncp_reply_header * reply_buf,int max_reply_size)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
do_tcp_rcv(struct ncp_server * server,void * buffer,size_t len)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
do_ncp_tcp_rpc_call(struct ncp_server * server,int size,struct ncp_reply_header * reply_buf,int max_reply_size)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
ncp_do_request(struct ncp_server * server,int size,void * reply,int max_reply_size)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(¤t->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(¤t->blocked, mask);
475 recalc_sigpending(current);
476 spin_unlock_irqrestore(¤t->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(¤t->sigmask_lock, flags);
489 current->blocked = old_set;
490 recalc_sigpending(current);
491 spin_unlock_irqrestore(¤t->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 */
ncp_request2(struct ncp_server * server,int function,void * rpl,int size)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
ncp_connect(struct ncp_server * server)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
ncp_disconnect(struct ncp_server * server)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
ncp_lock_server(struct ncp_server * server)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
ncp_unlock_server(struct ncp_server * server)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