This source file includes following definitions.
- _recvfrom
- _sendto
- ncp_wdog_data_ready
- ncp_catch_watchdog
- ncp_dont_catch_watchdog
- 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
97 _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
98 &sender, &addr_len);
99
100 printk("ncpfs: got strange packet on watchdog "
101 "socket\n");
102
103 }
104 else
105 {
106 int result;
107 DDPRINTK("ncpfs: got watchdog from:\n");
108 DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
109 " conn:%02X,type:%c\n",
110 htonl(sender.sipx_network),
111 sender.sipx_node[0], sender.sipx_node[1],
112 sender.sipx_node[2], sender.sipx_node[3],
113 sender.sipx_node[4], sender.sipx_node[5],
114 ntohs(sender.sipx_port),
115 packet_buf[0], packet_buf[1]);
116
117 packet_buf[1] = 'Y';
118 result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
119 &sender, sizeof(sender));
120 DDPRINTK("send result: %d\n", result);
121 }
122 set_fs(fs);
123 }
124 }
125
126
127 int
128 ncp_catch_watchdog(struct ncp_server *server)
129 {
130 struct file *file;
131 struct inode *inode;
132 struct socket *sock;
133 struct sock *sk;
134
135 if ( (server == NULL)
136 || ((file = server->wdog_filp) == NULL)
137 || ((inode = file->f_inode) == NULL)
138 || (!S_ISSOCK(inode->i_mode)))
139 {
140 printk("ncp_catch_watchdog: did not get valid server!\n");
141 server->data_ready = NULL;
142 return -EINVAL;
143 }
144
145 sock = &(inode->u.socket_i);
146
147 if (sock->type != SOCK_DGRAM)
148 {
149 printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
150 server->data_ready = NULL;
151 return -EINVAL;
152 }
153
154 sk = (struct sock *)(sock->data);
155
156 if (sk == NULL)
157 {
158 printk("ncp_catch_watchdog: sk == NULL");
159 server->data_ready = NULL;
160 return -EINVAL;
161 }
162
163 DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n",
164 (unsigned int)(sk->data_ready),
165 (unsigned int)(server->data_ready));
166
167 if (sk->data_ready == ncp_wdog_data_ready)
168 {
169 printk("ncp_catch_watchdog: already done\n");
170 return -EINVAL;
171 }
172
173 server->data_ready = sk->data_ready;
174 sk->data_ready = ncp_wdog_data_ready;
175 sk->allocation = GFP_ATOMIC;
176 return 0;
177 }
178
179 int
180 ncp_dont_catch_watchdog(struct ncp_server *server)
181 {
182 struct file *file;
183 struct inode *inode;
184 struct socket *sock;
185 struct sock *sk;
186
187 if ( (server == NULL)
188 || ((file = server->wdog_filp) == NULL)
189 || ((inode = file->f_inode) == NULL)
190 || (!S_ISSOCK(inode->i_mode)))
191 {
192 printk("ncp_dont_catch_watchdog: "
193 "did not get valid server!\n");
194 return -EINVAL;
195 }
196
197 sock = &(inode->u.socket_i);
198
199 if (sock->type != SOCK_DGRAM)
200 {
201 printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
202 return -EINVAL;
203 }
204
205 sk = (struct sock *)(sock->data);
206
207 if (sk == NULL)
208 {
209 printk("ncp_dont_catch_watchdog: sk == NULL");
210 return -EINVAL;
211 }
212
213 if (server->data_ready == NULL)
214 {
215 printk("ncp_dont_catch_watchdog: "
216 "server->data_ready == NULL\n");
217 return -EINVAL;
218 }
219
220 if (sk->data_ready != ncp_wdog_data_ready)
221 {
222 printk("ncp_dont_catch_watchdog: "
223 "sk->data_callback != ncp_data_callback\n");
224 return -EINVAL;
225 }
226
227 DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
228 (unsigned int)(sk->data_ready),
229 (unsigned int)(server->data_ready));
230
231 sk->data_ready = server->data_ready;
232 sk->allocation = GFP_KERNEL;
233 server->data_ready = NULL;
234 return 0;
235 }
236
237
238
239 #define NCP_SLACK_SPACE 1024
240
241 #define _S(nr) (1<<((nr)-1))
242
243 static int
244 do_ncp_rpc_call(struct ncp_server *server, int size)
245 {
246 struct file *file;
247 struct inode *inode;
248 struct socket *sock;
249 unsigned short fs;
250 int result;
251 char *start = server->packet;
252 select_table wait_table;
253 struct select_table_entry entry;
254 int (*select) (struct inode *, struct file *, int, select_table *);
255 int init_timeout, max_timeout;
256 int timeout;
257 int retrans;
258 int major_timeout_seen;
259 char *server_name;
260 int n;
261 int addrlen;
262 unsigned long old_mask;
263
264
265 struct ncp_request_header request =
266 *((struct ncp_request_header *)(server->packet));
267
268 struct ncp_reply_header reply;
269
270
271 file = server->ncp_filp;
272 inode = file->f_inode;
273 select = file->f_op->select;
274 sock = &inode->u.socket_i;
275 if (!sock)
276 {
277 printk("ncp_rpc_call: socki_lookup failed\n");
278 return -EBADF;
279 }
280 init_timeout = server->m.time_out;
281 max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
282 retrans = server->m.retry_count;
283 major_timeout_seen = 0;
284 server_name = server->m.server_name;
285 old_mask = current->blocked;
286 current->blocked |= ~(_S(SIGKILL)
287 #if 0
288 | _S(SIGSTOP)
289 #endif
290 | ((server->m.flags & NCP_MOUNT_INTR)
291 ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
292 ? _S(SIGINT) : 0)
293 | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
294 ? _S(SIGQUIT) : 0))
295 : 0));
296 fs = get_fs();
297 set_fs(get_ds());
298 for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
299 {
300 DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
301 htonl(server->m.serv_addr.sipx_network),
302 server->m.serv_addr.sipx_node[0],
303 server->m.serv_addr.sipx_node[1],
304 server->m.serv_addr.sipx_node[2],
305 server->m.serv_addr.sipx_node[3],
306 server->m.serv_addr.sipx_node[4],
307 server->m.serv_addr.sipx_node[5],
308 ntohs(server->m.serv_addr.sipx_port));
309 DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
310 "seq: %d",
311 request.type,
312 (request.conn_high << 8) + request.conn_low,
313 request.sequence);
314 DDPRINTK(" func: %d\n",
315 request.function);
316
317 result = _sendto(sock, (void *) start, size, 0, 0,
318 &(server->m.serv_addr),
319 sizeof(server->m.serv_addr));
320 if (result < 0)
321 {
322 printk("ncp_rpc_call: send error = %d\n", result);
323 break;
324 }
325 re_select:
326 wait_table.nr = 0;
327 wait_table.entry = &entry;
328 current->state = TASK_INTERRUPTIBLE;
329 if ( !select(inode, file, SEL_IN, &wait_table)
330 && !select(inode, file, SEL_IN, NULL))
331 {
332 if (timeout > max_timeout)
333 {
334
335
336
337 printk("NCP max timeout reached on %s\n",
338 server_name);
339 timeout = max_timeout;
340 }
341 current->timeout = jiffies + timeout;
342 schedule();
343 remove_wait_queue(entry.wait_address, &entry.wait);
344 current->state = TASK_RUNNING;
345 if (current->signal & ~current->blocked)
346 {
347 current->timeout = 0;
348 result = -ERESTARTSYS;
349 break;
350 }
351 if (!current->timeout)
352 {
353 if (n < retrans)
354 continue;
355 if (server->m.flags & NCP_MOUNT_SOFT)
356 {
357 printk("NCP server %s not responding, "
358 "timed out\n", server_name);
359 result = -EIO;
360 break;
361 }
362 n = 0;
363 timeout = init_timeout;
364 init_timeout <<= 1;
365 if (!major_timeout_seen)
366 {
367 printk("NCP server %s not responding, "
368 "still trying\n", server_name);
369 }
370 major_timeout_seen = 1;
371 continue;
372 }
373 else
374 current->timeout = 0;
375 }
376 else if (wait_table.nr)
377 remove_wait_queue(entry.wait_address, &entry.wait);
378 current->state = TASK_RUNNING;
379 addrlen = 0;
380
381
382
383
384 result = _recvfrom(sock, (void *)&reply,
385 sizeof(reply), 1, MSG_PEEK,
386 NULL, &addrlen);
387 if (result < 0)
388 {
389 if (result == -EAGAIN)
390 {
391 DPRINTK("ncp_rpc_call: bad select ready\n");
392 goto re_select;
393 }
394 if (result == -ECONNREFUSED)
395 {
396 DPRINTK("ncp_rpc_call: server playing coy\n");
397 goto re_select;
398 }
399 if (result != -ERESTARTSYS)
400 {
401 printk("ncp_rpc_call: recv error = %d\n",
402 -result);
403 }
404 break;
405 }
406 if ( (result == sizeof(reply))
407 && (reply.type == NCP_POSITIVE_ACK))
408 {
409
410 DPRINTK("ncp_rpc_call: got positive acknowledge\n");
411 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
412 NULL, &addrlen);
413 goto re_select;
414 }
415
416 DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
417 "seq: %d\n",
418 reply.type,
419 (reply.conn_high << 8) + reply.conn_low,
420 reply.task,
421 reply.sequence);
422
423 if ( (result >= sizeof(reply))
424 && (reply.type == NCP_REPLY)
425 && ( (request.type == NCP_ALLOC_SLOT_REQUEST)
426 || ( (reply.sequence == request.sequence)
427 && (reply.conn_low == request.conn_low)
428
429 && (reply.conn_high == request.conn_high))))
430 {
431 if (major_timeout_seen)
432 printk("NCP server %s OK\n", server_name);
433 break;
434 }
435
436
437
438
439 _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
440 &addrlen);
441 #if 1
442 printk("ncp_rpc_call: reply mismatch\n");
443 #endif
444 goto re_select;
445 }
446
447
448
449
450 result = _recvfrom(sock, (void *)start, server->packet_size,
451 1, 0, NULL, &addrlen);
452 if (result < 0)
453 {
454 printk("NCP: notice message: result=%d\n", result);
455 }
456 else if (result < sizeof(struct ncp_reply_header))
457 {
458 printk("NCP: just caught a too small read memory size..., "
459 "email to NET channel\n");
460 printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
461 result = -EIO;
462 }
463
464 current->blocked = old_mask;
465 set_fs(fs);
466 return result;
467 }
468
469
470
471
472
473
474 static int
475 ncp_do_request(struct ncp_server *server, int size)
476 {
477 if (server->lock == 0)
478 {
479 printk("ncpfs: Server not locked!\n");
480 return -EIO;
481 }
482
483 return do_ncp_rpc_call(server, size);
484 }
485
486
487
488
489 int
490 ncp_request(struct ncp_server *server, int function)
491 {
492 struct ncp_request_header *h
493 = (struct ncp_request_header *)(server->packet);
494 struct ncp_reply_header *reply
495 = (struct ncp_reply_header *)(server->packet);
496
497 int request_size = server->current_size
498 - sizeof(struct ncp_request_header);
499
500 int result;
501
502 if (server->has_subfunction != 0)
503 {
504 *(__u16 *)&(h->data[0]) = request_size - 2;
505 }
506
507 h->type = NCP_REQUEST;
508
509 server->sequence += 1;
510 h->sequence = server->sequence;
511 h->conn_low = (server->connection) & 0xff;
512 h->conn_high = ((server->connection) & 0xff00) >> 8;
513 h->task = (current->pid) & 0xff;
514 h->function = function;
515
516 if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
517 {
518 DPRINTK("ncp_request_error: %d\n", result);
519 return result;
520 }
521
522 server->completion = reply->completion_code;
523 server->conn_status = reply->connection_state;
524 server->reply_size = result;
525 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
526
527 result = reply->completion_code;
528
529 if (result != 0)
530 {
531 DPRINTK("ncp_completion_code: %d\n", result);
532 }
533 return result;
534 }
535
536 int
537 ncp_connect(struct ncp_server *server)
538 {
539 struct ncp_request_header *h
540 = (struct ncp_request_header *)(server->packet);
541 int result;
542
543 h->type = NCP_ALLOC_SLOT_REQUEST;
544
545 server->sequence = 0;
546 h->sequence = server->sequence;
547 h->conn_low = 0xff;
548 h->conn_high = 0xff;
549 h->task = (current->pid) & 0xff;
550 h->function = 0;
551
552 if ((result = ncp_do_request(server, sizeof(*h))) < 0)
553 {
554 return result;
555 }
556
557 server->sequence = 0;
558 server->connection = h->conn_low + (h->conn_high * 256);
559 return 0;
560 }
561
562 int
563 ncp_disconnect(struct ncp_server *server)
564 {
565 struct ncp_request_header *h
566 = (struct ncp_request_header *)(server->packet);
567
568 h->type = NCP_DEALLOC_SLOT_REQUEST;
569
570 server->sequence += 1;
571 h->sequence = server->sequence;
572 h->conn_low = (server->connection) & 0xff;
573 h->conn_high = ((server->connection) & 0xff00) >> 8;
574 h->task = (current->pid) & 0xff;
575 h->function = 0;
576
577 return ncp_do_request(server, sizeof(*h));
578 }
579
580 void
581 ncp_lock_server(struct ncp_server *server)
582 {
583 #if 0
584
585 if (server->lock != 0)
586 {
587 DPRINTK("ncpfs: server locked!!!\n");
588 }
589 #endif
590 while (server->lock)
591 sleep_on(&server->wait);
592 server->lock = 1;
593 }
594
595 void
596 ncp_unlock_server(struct ncp_server *server)
597 {
598 if (server->lock != 1)
599 {
600 printk("ncp_unlock_server: was not locked!\n");
601 }
602
603 server->lock = 0;
604 wake_up(&server->wait);
605 }
606