OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ncpfs/] [sock.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.