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 char *server_name;
334 int n;
335 int addrlen;
336 unsigned long old_mask;
337
338
339 struct ncp_request_header request =
340 *((struct ncp_request_header *)(server->packet));
341
342 struct ncp_reply_header reply;
343
344
345 file = server->ncp_filp;
346 inode = file->f_inode;
347 select = file->f_op->select;
348 sock = &inode->u.socket_i;
349 if (!sock)
350 {
351 printk("ncp_rpc_call: socki_lookup failed\n");
352 return -EBADF;
353 }
354 init_timeout = server->m.time_out;
355 max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
356 retrans = server->m.retry_count;
357 major_timeout_seen = 0;
358 server_name = server->m.server_name;
359 old_mask = current->blocked;
360 current->blocked |= ~(_S(SIGKILL)
361 #if 0
362 | _S(SIGSTOP)
363 #endif
364 | ((server->m.flags & NCP_MOUNT_INTR)
365 ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
366 ? _S(SIGINT) : 0)
367 | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
368 ? _S(SIGQUIT) : 0))
369 : 0));
370 fs = get_fs();
371 set_fs(get_ds());
372 for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
373 {
374 DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
375 htonl(server->m.serv_addr.sipx_network),
376 server->m.serv_addr.sipx_node[0],
377 server->m.serv_addr.sipx_node[1],
378 server->m.serv_addr.sipx_node[2],
379 server->m.serv_addr.sipx_node[3],
380 server->m.serv_addr.sipx_node[4],
381 server->m.serv_addr.sipx_node[5],
382 ntohs(server->m.serv_addr.sipx_port));
383 DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
384 "seq: %d",
385 request.type,
386 (request.conn_high << 8) + request.conn_low,
387 request.sequence);
388 DDPRINTK(" func: %d\n",
389 request.function);
390
391 result = _sendto(sock, (void *) start, size, 0, 0,
392 &(server->m.serv_addr),
393 sizeof(server->m.serv_addr));
394 if (result < 0)
395 {
396 printk("ncp_rpc_call: send error = %d\n", result);
397 break;
398 }
399 re_select:
400 wait_table.nr = 0;
401 wait_table.entry = &entry;
402 current->state = TASK_INTERRUPTIBLE;
403 if ( !select(inode, file, SEL_IN, &wait_table)
404 && !select(inode, file, SEL_IN, NULL))
405 {
406 if (timeout > max_timeout)
407 {
408
409
410
411 printk("NCP max timeout reached on %s\n",
412 server_name);
413 timeout = max_timeout;
414 }
415 current->timeout = jiffies + timeout;
416 schedule();
417 remove_wait_queue(entry.wait_address, &entry.wait);
418 current->state = TASK_RUNNING;
419 if (current->signal & ~current->blocked)
420 {
421 current->timeout = 0;
422 result = -ERESTARTSYS;
423 break;
424 }
425 if (!current->timeout)
426 {
427 if (n < retrans)
428 continue;
429 if (server->m.flags & NCP_MOUNT_SOFT)
430 {
431 printk("NCP server %s not responding, "
432 "timed out\n", server_name);
433 result = -EIO;
434 break;
435 }
436 n = 0;
437 timeout = init_timeout;
438 init_timeout <<= 1;
439 if (!major_timeout_seen)
440 {
441 printk("NCP server %s not responding, "
442 "still trying\n", server_name);
443 }
444 major_timeout_seen = 1;
445 continue;
446 }
447 else
448 current->timeout = 0;
449 }
450 else if (wait_table.nr)
451 remove_wait_queue(entry.wait_address, &entry.wait);
452 current->state = TASK_RUNNING;
453 addrlen = 0;
454
455
456
457
458 result = _recvfrom(sock, (void *)&reply,
459 sizeof(reply), 1, MSG_PEEK,
460 NULL, &addrlen);
461 if (result < 0)
462 {
463 if (result == -EAGAIN)
464 {
465 DPRINTK("ncp_rpc_call: bad select ready\n");
466 goto re_select;
467 }
468 if (result == -ECONNREFUSED)
469 {
470 DPRINTK("ncp_rpc_call: server playing coy\n");
471 goto re_select;
472 }
473 if (result != -ERESTARTSYS)
474 {
475 printk("ncp_rpc_call: recv error = %d\n",
476 -result);
477 }
478 break;
479 }
480 if ( (result == sizeof(reply))
481 && (reply.type == NCP_POSITIVE_ACK))
482 {
483
484 DPRINTK("ncp_rpc_call: got positive acknowledge\n");
485 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
486 NULL, &addrlen);
487 goto re_select;
488 }
489
490 DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
491 "seq: %d\n",
492 reply.type,
493 (reply.conn_high << 8) + reply.conn_low,
494 reply.task,
495 reply.sequence);
496
497 if ( (result >= sizeof(reply))
498 && (reply.type == NCP_REPLY)
499 && ( (request.type == NCP_ALLOC_SLOT_REQUEST)
500 || ( (reply.sequence == request.sequence)
501 && (reply.conn_low == request.conn_low)
502
503 && (reply.conn_high == request.conn_high))))
504 {
505 if (major_timeout_seen)
506 printk("NCP server %s OK\n", server_name);
507 break;
508 }
509
510
511
512
513 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
514 &addrlen);
515
516 DPRINTK("ncp_rpc_call: reply mismatch\n");
517 goto re_select;
518 }
519
520
521
522
523 result = _recvfrom(sock, (void *)start, server->packet_size,
524 1, 0, NULL, &addrlen);
525 if (result < 0)
526 {
527 printk("NCP: notice message: result=%d\n", result);
528 }
529 else if (result < sizeof(struct ncp_reply_header))
530 {
531 printk("NCP: just caught a too small read memory size..., "
532 "email to NET channel\n");
533 printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
534 result = -EIO;
535 }
536
537 current->blocked = old_mask;
538 set_fs(fs);
539 return result;
540 }
541
542
543
544
545
546
547 static int
548 ncp_do_request(struct ncp_server *server, int size)
549 {
550 int result;
551
552 if (server->lock == 0)
553 {
554 printk("ncpfs: Server not locked!\n");
555 return -EIO;
556 }
557
558 if (!ncp_conn_valid(server))
559 {
560 return -EIO;
561 }
562
563 result = do_ncp_rpc_call(server, size);
564
565 DDPRINTK("do_ncp_rpc_call returned %d\n", result);
566
567 if (result < 0)
568 {
569
570
571 ncp_invalidate_conn(server);
572 }
573 return result;
574 }
575
576
577
578
579 int
580 ncp_request(struct ncp_server *server, int function)
581 {
582 struct ncp_request_header *h
583 = (struct ncp_request_header *)(server->packet);
584 struct ncp_reply_header *reply
585 = (struct ncp_reply_header *)(server->packet);
586
587 int request_size = server->current_size
588 - sizeof(struct ncp_request_header);
589
590 int result;
591
592 if (server->has_subfunction != 0)
593 {
594 *(__u16 *)&(h->data[0]) = request_size - 2;
595 }
596
597 h->type = NCP_REQUEST;
598
599 server->sequence += 1;
600 h->sequence = server->sequence;
601 h->conn_low = (server->connection) & 0xff;
602 h->conn_high = ((server->connection) & 0xff00) >> 8;
603 h->task = (current->pid) & 0xff;
604 h->function = function;
605
606 if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
607 {
608 DPRINTK("ncp_request_error: %d\n", result);
609 return result;
610 }
611
612 server->completion = reply->completion_code;
613 server->conn_status = reply->connection_state;
614 server->reply_size = result;
615 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
616
617 result = reply->completion_code;
618
619 if (result != 0)
620 {
621 DPRINTK("ncp_completion_code: %x\n", result);
622 }
623 return result;
624 }
625
626 int
627 ncp_connect(struct ncp_server *server)
628 {
629 struct ncp_request_header *h
630 = (struct ncp_request_header *)(server->packet);
631 int result;
632
633 h->type = NCP_ALLOC_SLOT_REQUEST;
634
635 server->sequence = 0;
636 h->sequence = server->sequence;
637 h->conn_low = 0xff;
638 h->conn_high = 0xff;
639 h->task = (current->pid) & 0xff;
640 h->function = 0;
641
642 if ((result = ncp_do_request(server, sizeof(*h))) < 0)
643 {
644 return result;
645 }
646
647 server->sequence = 0;
648 server->connection = h->conn_low + (h->conn_high * 256);
649 return 0;
650 }
651
652 int
653 ncp_disconnect(struct ncp_server *server)
654 {
655 struct ncp_request_header *h
656 = (struct ncp_request_header *)(server->packet);
657
658 h->type = NCP_DEALLOC_SLOT_REQUEST;
659
660 server->sequence += 1;
661 h->sequence = server->sequence;
662 h->conn_low = (server->connection) & 0xff;
663 h->conn_high = ((server->connection) & 0xff00) >> 8;
664 h->task = (current->pid) & 0xff;
665 h->function = 0;
666
667 return ncp_do_request(server, sizeof(*h));
668 }
669
670 void
671 ncp_lock_server(struct ncp_server *server)
672 {
673 #if 0
674
675 if (server->lock != 0)
676 {
677 DPRINTK("ncpfs: server locked!!!\n");
678 }
679 #endif
680 while (server->lock)
681 sleep_on(&server->wait);
682 server->lock = 1;
683 }
684
685 void
686 ncp_unlock_server(struct ncp_server *server)
687 {
688 if (server->lock != 1)
689 {
690 printk("ncp_unlock_server: was not locked!\n");
691 }
692
693 server->lock = 0;
694 wake_up(&server->wait);
695 }
696