This source file includes following definitions.
- _recvfrom
- _sendto
- ncp_wdog_data_ready
- ncp_catch_watchdog
- ncp_dont_catch_watchdog
- ncp_msg_data_ready
- ncp_catch_message
- do_ncp_rpc_call
- ncp_do_request
- ncp_request
- ncp_connect
- ncp_disconnect
- ncp_lock_server
- ncp_unlock_server
1
2
3
4
5
6
7
8
9
10 #include <linux/sched.h>
11 #include <linux/ncp_fs.h>
12 #include <linux/errno.h>
13 #include <linux/socket.h>
14 #include <linux/fcntl.h>
15 #include <linux/stat.h>
16 #include <asm/segment.h>
17 #include <linux/in.h>
18 #include <linux/net.h>
19 #include <linux/mm.h>
20 #include <linux/netdevice.h>
21 #include <linux/ipx.h>
22
23 #include <linux/ncp.h>
24 #include <linux/ncp_fs.h>
25 #include <linux/ncp_fs_sb.h>
26 #include <net/sock.h>
27
28
29 #define _S(nr) (1<<((nr)-1))
30 static int _recvfrom(struct socket *sock, unsigned char *ubuf,
31 int size, int noblock, unsigned flags,
32 struct sockaddr_ipx *sa, int *addr_len)
33 {
34 struct iovec iov;
35 struct msghdr msg;
36
37 iov.iov_base = ubuf;
38 iov.iov_len = size;
39
40 msg.msg_name = (void *)sa;
41 msg.msg_namelen = 0;
42 if (addr_len)
43 msg.msg_namelen = *addr_len;
44 msg.msg_accrights = NULL;
45 msg.msg_iov = &iov;
46 msg.msg_iovlen = 1;
47
48 return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
49 }
50
51 static int _sendto(struct socket *sock, const void *buff,
52 int len, int nonblock, unsigned flags,
53 struct sockaddr_ipx *sa, int addr_len)
54
55 {
56 struct iovec iov;
57 struct msghdr msg;
58
59 iov.iov_base = (void *)buff;
60 iov.iov_len = len;
61
62 msg.msg_name = (void *)sa;
63 msg.msg_namelen = addr_len;
64 msg.msg_accrights = NULL;
65 msg.msg_iov = &iov;
66 msg.msg_iovlen = 1;
67
68 return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
69 }
70
71
72 static void
73 ncp_wdog_data_ready(struct sock *sk, int len)
74 {
75 struct socket *sock = sk->socket;
76
77 if (!sk->dead)
78 {
79 unsigned char packet_buf[2];
80 struct sockaddr_ipx sender;
81 int addr_len = sizeof(struct sockaddr_ipx);
82 int result;
83 unsigned short fs;
84
85 fs = get_fs();
86 set_fs(get_ds());
87
88 result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
89 &sender, &addr_len);
90
91 if ( (result != 2)
92 || (packet_buf[1] != '?')
93
94 )
95 {
96 printk("ncpfs: got strange packet on watchdog "
97 "socket\n");
98 }
99 else
100 {
101 int result;
102 DDPRINTK("ncpfs: got watchdog from:\n");
103 DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
104 " conn:%02X,type:%c\n",
105 htonl(sender.sipx_network),
106 sender.sipx_node[0], sender.sipx_node[1],
107 sender.sipx_node[2], sender.sipx_node[3],
108 sender.sipx_node[4], sender.sipx_node[5],
109 ntohs(sender.sipx_port),
110 packet_buf[0], packet_buf[1]);
111
112 packet_buf[1] = 'Y';
113 result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
114 &sender, sizeof(sender));
115 DDPRINTK("send result: %d\n", result);
116 }
117 set_fs(fs);
118 }
119 }
120
121 int
122 ncp_catch_watchdog(struct ncp_server *server)
123 {
124 struct file *file;
125 struct inode *inode;
126 struct socket *sock;
127 struct sock *sk;
128
129 if ( (server == NULL)
130 || ((file = server->wdog_filp) == NULL)
131 || ((inode = file->f_inode) == NULL)
132 || (!S_ISSOCK(inode->i_mode)))
133 {
134 printk("ncp_catch_watchdog: did not get valid server!\n");
135 server->data_ready = NULL;
136 return -EINVAL;
137 }
138
139 sock = &(inode->u.socket_i);
140
141 if (sock->type != SOCK_DGRAM)
142 {
143 printk("ncp_catch_watchdog: did not get SOCK_DGRAM\n");
144 server->data_ready = NULL;
145 return -EINVAL;
146 }
147
148 sk = (struct sock *)(sock->data);
149
150 if (sk == NULL)
151 {
152 printk("ncp_catch_watchdog: sk == NULL");
153 server->data_ready = NULL;
154 return -EINVAL;
155 }
156
157 DDPRINTK("ncp_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
158 (unsigned int)(sk->data_ready),
159 (unsigned int)(server->data_ready));
160
161 if (sk->data_ready == ncp_wdog_data_ready)
162 {
163 printk("ncp_catch_watchdog: already done\n");
164 return -EINVAL;
165 }
166
167 server->data_ready = sk->data_ready;
168 sk->data_ready = ncp_wdog_data_ready;
169 sk->allocation = GFP_ATOMIC;
170 return 0;
171 }
172
173 int
174 ncp_dont_catch_watchdog(struct ncp_server *server)
175 {
176 struct file *file;
177 struct inode *inode;
178 struct socket *sock;
179 struct sock *sk;
180
181 if ( (server == NULL)
182 || ((file = server->wdog_filp) == NULL)
183 || ((inode = file->f_inode) == NULL)
184 || (!S_ISSOCK(inode->i_mode)))
185 {
186 printk("ncp_dont_catch_watchdog: "
187 "did not get valid server!\n");
188 return -EINVAL;
189 }
190
191 sock = &(inode->u.socket_i);
192
193 if (sock->type != SOCK_DGRAM)
194 {
195 printk("ncp_dont_catch_watchdog: did not get SOCK_DGRAM\n");
196 return -EINVAL;
197 }
198
199 sk = (struct sock *)(sock->data);
200
201 if (sk == NULL)
202 {
203 printk("ncp_dont_catch_watchdog: sk == NULL");
204 return -EINVAL;
205 }
206
207 if (server->data_ready == NULL)
208 {
209 printk("ncp_dont_catch_watchdog: "
210 "server->data_ready == NULL\n");
211 return -EINVAL;
212 }
213
214 if (sk->data_ready != ncp_wdog_data_ready)
215 {
216 printk("ncp_dont_catch_watchdog: "
217 "sk->data_callback != ncp_data_callback\n");
218 return -EINVAL;
219 }
220
221 DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
222 (unsigned int)(sk->data_ready),
223 (unsigned int)(server->data_ready));
224
225 sk->data_ready = server->data_ready;
226 sk->allocation = GFP_KERNEL;
227 server->data_ready = NULL;
228 return 0;
229 }
230
231 static void
232 ncp_msg_data_ready(struct sock *sk, int len)
233 {
234 struct socket *sock = sk->socket;
235
236 if (!sk->dead)
237 {
238 unsigned char packet_buf[2];
239 struct sockaddr_ipx sender;
240 int addr_len = sizeof(struct sockaddr_ipx);
241 int result;
242 unsigned short fs;
243
244 fs = get_fs();
245 set_fs(get_ds());
246
247 result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
248 &sender, &addr_len);
249
250 DPRINTK("ncpfs: got message of size %d from:\n", result);
251 DPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
252 " conn:%02X,type:%c\n",
253 htonl(sender.sipx_network),
254 sender.sipx_node[0], sender.sipx_node[1],
255 sender.sipx_node[2], sender.sipx_node[3],
256 sender.sipx_node[4], sender.sipx_node[5],
257 ntohs(sender.sipx_port),
258 packet_buf[0], packet_buf[1]);
259
260 ncp_trigger_message(sk->protinfo.af_ipx.ncp_server);
261
262 set_fs(fs);
263 }
264 }
265
266 int
267 ncp_catch_message(struct ncp_server *server)
268 {
269 struct file *file;
270 struct inode *inode;
271 struct socket *sock;
272 struct sock *sk;
273
274 if ( (server == NULL)
275 || ((file = server->msg_filp) == NULL)
276 || ((inode = file->f_inode) == NULL)
277 || (!S_ISSOCK(inode->i_mode)))
278 {
279 printk("ncp_catch_message: did not get valid server!\n");
280 return -EINVAL;
281 }
282
283 sock = &(inode->u.socket_i);
284
285 if (sock->type != SOCK_DGRAM)
286 {
287 printk("ncp_catch_message: did not get SOCK_DGRAM\n");
288 return -EINVAL;
289 }
290
291 sk = (struct sock *)(sock->data);
292
293 if (sk == NULL)
294 {
295 printk("ncp_catch_message: sk == NULL");
296 return -EINVAL;
297 }
298
299 DDPRINTK("ncp_catch_message: sk->d_r = %x\n",
300 (unsigned int)(sk->data_ready));
301
302 if (sk->data_ready == ncp_msg_data_ready)
303 {
304 printk("ncp_catch_message: already done\n");
305 return -EINVAL;
306 }
307
308 sk->data_ready = ncp_msg_data_ready;
309 sk->protinfo.af_ipx.ncp_server = server;
310 return 0;
311 }
312
313 #define NCP_SLACK_SPACE 1024
314
315 #define _S(nr) (1<<((nr)-1))
316
317 static int
318 do_ncp_rpc_call(struct ncp_server *server, int size)
319 {
320 struct file *file;
321 struct inode *inode;
322 struct socket *sock;
323 unsigned short fs;
324 int result;
325 char *start = server->packet;
326 select_table wait_table;
327 struct select_table_entry entry;
328 int (*select) (struct inode *, struct file *, int, select_table *);
329 int init_timeout, max_timeout;
330 int timeout;
331 int retrans;
332 int major_timeout_seen;
333 int acknowledge_seen;
334 char *server_name;
335 int n;
336 int addrlen;
337 unsigned long old_mask;
338
339
340 struct ncp_request_header request =
341 *((struct ncp_request_header *)(server->packet));
342
343 struct ncp_reply_header reply;
344
345
346 file = server->ncp_filp;
347 inode = file->f_inode;
348 select = file->f_op->select;
349 sock = &inode->u.socket_i;
350 if (!sock)
351 {
352 printk("ncp_rpc_call: socki_lookup failed\n");
353 return -EBADF;
354 }
355 init_timeout = server->m.time_out;
356 max_timeout = NCP_MAX_RPC_TIMEOUT;
357 retrans = server->m.retry_count;
358 major_timeout_seen = 0;
359 acknowledge_seen = 0;
360 server_name = server->m.server_name;
361 old_mask = current->blocked;
362 current->blocked |= ~(_S(SIGKILL)
363 #if 0
364 | _S(SIGSTOP)
365 #endif
366 | ((server->m.flags & NCP_MOUNT_INTR)
367 ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
368 ? _S(SIGINT) : 0)
369 | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
370 ? _S(SIGQUIT) : 0))
371 : 0));
372 fs = get_fs();
373 set_fs(get_ds());
374 for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
375 {
376 DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
377 htonl(server->m.serv_addr.sipx_network),
378 server->m.serv_addr.sipx_node[0],
379 server->m.serv_addr.sipx_node[1],
380 server->m.serv_addr.sipx_node[2],
381 server->m.serv_addr.sipx_node[3],
382 server->m.serv_addr.sipx_node[4],
383 server->m.serv_addr.sipx_node[5],
384 ntohs(server->m.serv_addr.sipx_port));
385 DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
386 "seq: %d",
387 request.type,
388 (request.conn_high << 8) + request.conn_low,
389 request.sequence);
390 DDPRINTK(" func: %d\n",
391 request.function);
392
393 result = _sendto(sock, (void *) start, size, 0, 0,
394 &(server->m.serv_addr),
395 sizeof(server->m.serv_addr));
396 if (result < 0)
397 {
398 printk("ncp_rpc_call: send error = %d\n", result);
399 break;
400 }
401 re_select:
402 wait_table.nr = 0;
403 wait_table.entry = &entry;
404 current->state = TASK_INTERRUPTIBLE;
405 if ( !select(inode, file, SEL_IN, &wait_table)
406 && !select(inode, file, SEL_IN, NULL))
407 {
408 if (timeout > max_timeout)
409 {
410
411
412
413 if (acknowledge_seen == 0)
414 {
415 printk("NCP max timeout reached on "
416 "%s\n", server_name);
417 }
418 timeout = max_timeout;
419 }
420 current->timeout = jiffies + timeout;
421 schedule();
422 remove_wait_queue(entry.wait_address, &entry.wait);
423 current->state = TASK_RUNNING;
424 if (current->signal & ~current->blocked)
425 {
426 current->timeout = 0;
427 result = -ERESTARTSYS;
428 break;
429 }
430 if (!current->timeout)
431 {
432 if (n < retrans)
433 continue;
434 if (server->m.flags & NCP_MOUNT_SOFT)
435 {
436 printk("NCP server %s not responding, "
437 "timed out\n", server_name);
438 result = -EIO;
439 break;
440 }
441 n = 0;
442 timeout = init_timeout;
443 init_timeout <<= 1;
444 if (!major_timeout_seen)
445 {
446 printk("NCP server %s not responding, "
447 "still trying\n", server_name);
448 }
449 major_timeout_seen = 1;
450 continue;
451 }
452 else
453 current->timeout = 0;
454 }
455 else if (wait_table.nr)
456 remove_wait_queue(entry.wait_address, &entry.wait);
457 current->state = TASK_RUNNING;
458 addrlen = 0;
459
460
461
462
463 result = _recvfrom(sock, (void *)&reply,
464 sizeof(reply), 1, MSG_PEEK,
465 NULL, &addrlen);
466 if (result < 0)
467 {
468 if (result == -EAGAIN)
469 {
470 DPRINTK("ncp_rpc_call: bad select ready\n");
471 goto re_select;
472 }
473 if (result == -ECONNREFUSED)
474 {
475 DPRINTK("ncp_rpc_call: server playing coy\n");
476 goto re_select;
477 }
478 if (result != -ERESTARTSYS)
479 {
480 printk("ncp_rpc_call: recv error = %d\n",
481 -result);
482 }
483 break;
484 }
485 if ( (result == sizeof(reply))
486 && (reply.type == NCP_POSITIVE_ACK))
487 {
488
489 DPRINTK("ncp_rpc_call: got positive acknowledge\n");
490 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
491 NULL, &addrlen);
492 n = 0;
493 timeout = max_timeout;
494 acknowledge_seen = 1;
495 goto re_select;
496 }
497
498 DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
499 "seq: %d\n",
500 reply.type,
501 (reply.conn_high << 8) + reply.conn_low,
502 reply.task,
503 reply.sequence);
504
505 if ( (result >= sizeof(reply))
506 && (reply.type == NCP_REPLY)
507 && ( (request.type == NCP_ALLOC_SLOT_REQUEST)
508 || ( (reply.sequence == request.sequence)
509 && (reply.conn_low == request.conn_low)
510
511 && (reply.conn_high == request.conn_high))))
512 {
513 if (major_timeout_seen)
514 printk("NCP server %s OK\n", server_name);
515 break;
516 }
517
518
519
520
521 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
522 &addrlen);
523
524 DPRINTK("ncp_rpc_call: reply mismatch\n");
525 goto re_select;
526 }
527
528
529
530
531 result = _recvfrom(sock, (void *)start, server->packet_size,
532 1, 0, NULL, &addrlen);
533 if (result < 0)
534 {
535 printk("NCP: notice message: result=%d\n", result);
536 }
537 else if (result < sizeof(struct ncp_reply_header))
538 {
539 printk("NCP: just caught a too small read memory size..., "
540 "email to NET channel\n");
541 printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
542 result = -EIO;
543 }
544
545 current->blocked = old_mask;
546 set_fs(fs);
547 return result;
548 }
549
550
551
552
553
554
555 static int
556 ncp_do_request(struct ncp_server *server, int size)
557 {
558 int result;
559
560 if (server->lock == 0)
561 {
562 printk("ncpfs: Server not locked!\n");
563 return -EIO;
564 }
565
566 if (!ncp_conn_valid(server))
567 {
568 return -EIO;
569 }
570
571 result = do_ncp_rpc_call(server, size);
572
573 DDPRINTK("do_ncp_rpc_call returned %d\n", result);
574
575 if (result < 0)
576 {
577
578
579 ncp_invalidate_conn(server);
580 }
581 return result;
582 }
583
584
585
586
587 int
588 ncp_request(struct ncp_server *server, int function)
589 {
590 struct ncp_request_header *h
591 = (struct ncp_request_header *)(server->packet);
592 struct ncp_reply_header *reply
593 = (struct ncp_reply_header *)(server->packet);
594
595 int request_size = server->current_size
596 - sizeof(struct ncp_request_header);
597
598 int result;
599
600 if (server->has_subfunction != 0)
601 {
602 *(__u16 *)&(h->data[0]) = request_size - 2;
603 }
604
605 h->type = NCP_REQUEST;
606
607 server->sequence += 1;
608 h->sequence = server->sequence;
609 h->conn_low = (server->connection) & 0xff;
610 h->conn_high = ((server->connection) & 0xff00) >> 8;
611 h->task = (current->pid) & 0xff;
612 h->function = function;
613
614 if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
615 {
616 DPRINTK("ncp_request_error: %d\n", result);
617 return result;
618 }
619
620 server->completion = reply->completion_code;
621 server->conn_status = reply->connection_state;
622 server->reply_size = result;
623 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
624
625 result = reply->completion_code;
626
627 if (result != 0)
628 {
629 DPRINTK("ncp_completion_code: %x\n", result);
630 }
631 return result;
632 }
633
634 int
635 ncp_connect(struct ncp_server *server)
636 {
637 struct ncp_request_header *h
638 = (struct ncp_request_header *)(server->packet);
639 int result;
640
641 h->type = NCP_ALLOC_SLOT_REQUEST;
642
643 server->sequence = 0;
644 h->sequence = server->sequence;
645 h->conn_low = 0xff;
646 h->conn_high = 0xff;
647 h->task = (current->pid) & 0xff;
648 h->function = 0;
649
650 if ((result = ncp_do_request(server, sizeof(*h))) < 0)
651 {
652 return result;
653 }
654
655 server->sequence = 0;
656 server->connection = h->conn_low + (h->conn_high * 256);
657 return 0;
658 }
659
660 int
661 ncp_disconnect(struct ncp_server *server)
662 {
663 struct ncp_request_header *h
664 = (struct ncp_request_header *)(server->packet);
665
666 h->type = NCP_DEALLOC_SLOT_REQUEST;
667
668 server->sequence += 1;
669 h->sequence = server->sequence;
670 h->conn_low = (server->connection) & 0xff;
671 h->conn_high = ((server->connection) & 0xff00) >> 8;
672 h->task = (current->pid) & 0xff;
673 h->function = 0;
674
675 return ncp_do_request(server, sizeof(*h));
676 }
677
678 void
679 ncp_lock_server(struct ncp_server *server)
680 {
681 #if 0
682
683 if (server->lock != 0)
684 {
685 DPRINTK("ncpfs: server locked!!!\n");
686 }
687 #endif
688 while (server->lock)
689 sleep_on(&server->wait);
690 server->lock = 1;
691 }
692
693 void
694 ncp_unlock_server(struct ncp_server *server)
695 {
696 if (server->lock != 1)
697 {
698 printk("ncp_unlock_server: was not locked!\n");
699 }
700
701 server->lock = 0;
702 wake_up(&server->wait);
703 }
704