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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [smbfs/] [sock.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  sock.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5
 *  Copyright (C) 1997 by Volker Lendecke
6
 *
7
 *  Please add a note about your changes to smbfs in the ChangeLog file.
8
 */
9
 
10
#include <linux/sched.h>
11
#include <linux/errno.h>
12
#include <linux/socket.h>
13
#include <linux/fcntl.h>
14
#include <linux/file.h>
15
#include <linux/poll.h>
16
#include <linux/in.h>
17
#include <linux/net.h>
18
#include <linux/mm.h>
19
#include <linux/netdevice.h>
20
#include <linux/smp_lock.h>
21
#include <net/scm.h>
22
#include <net/ip.h>
23
 
24
#include <linux/smb_fs.h>
25
#include <linux/smb.h>
26
#include <linux/smbno.h>
27
 
28
#include <asm/uaccess.h>
29
 
30
#include "smb_debug.h"
31
#include "proto.h"
32
 
33
 
34
static int
35
_recvfrom(struct socket *socket, unsigned char *ubuf, int size,
36
          unsigned flags)
37
{
38
        struct iovec iov;
39
        struct msghdr msg;
40
        struct scm_cookie scm;
41
 
42
        msg.msg_name = NULL;
43
        msg.msg_namelen = 0;
44
        msg.msg_iov = &iov;
45
        msg.msg_iovlen = 1;
46
        msg.msg_control = NULL;
47
        iov.iov_base = ubuf;
48
        iov.iov_len = size;
49
 
50
        memset(&scm, 0,sizeof(scm));
51
        size=socket->ops->recvmsg(socket, &msg, size, flags, &scm);
52
        if(size>=0)
53
                scm_recv(socket,&msg,&scm,flags);
54
        return size;
55
}
56
 
57
static int
58
_send(struct socket *socket, const void *buff, int len)
59
{
60
        struct iovec iov;
61
        struct msghdr msg;
62
        struct scm_cookie scm;
63
        int err;
64
 
65
        msg.msg_name = NULL;
66
        msg.msg_namelen = 0;
67
        msg.msg_iov = &iov;
68
        msg.msg_iovlen = 1;
69
        msg.msg_control = NULL;
70
        msg.msg_controllen = 0;
71
 
72
        iov.iov_base = (void *)buff;
73
        iov.iov_len = len;
74
 
75
        msg.msg_flags = 0;
76
 
77
        err = scm_send(socket, &msg, &scm);
78
        if (err >= 0)
79
        {
80
                err = socket->ops->sendmsg(socket, &msg, len, &scm);
81
                scm_destroy(&scm);
82
        }
83
        return err;
84
}
85
 
86
struct data_callback {
87
        struct tq_struct cb;
88
        struct sock *sk;
89
};
90
/*
91
 * N.B. What happens if we're in here when the socket closes??
92
 */
93
static void
94
found_data(struct sock *sk)
95
{
96
        /*
97
         * FIXME: copied from sock_def_readable, it should be a call to
98
         * server->data_ready() -- manfreds@colorfullife.com
99
         */
100
        read_lock(&sk->callback_lock);
101
        if(!sk->dead) {
102
                wake_up_interruptible(sk->sleep);
103
                sock_wake_async(sk->socket,1,POLL_IN);
104
        }
105
        read_unlock(&sk->callback_lock);
106
}
107
 
108
static void
109
smb_data_callback(void* ptr)
110
{
111
        struct data_callback* job=ptr;
112
        struct socket *socket = job->sk->socket;
113
        unsigned char peek_buf[4];
114
        int result = 0;
115
        mm_segment_t fs;
116
        int count = 100;   /* this is a lot, we should have some data waiting */
117
        int found = 0;
118
 
119
        fs = get_fs();
120
        set_fs(get_ds());
121
 
122
        lock_kernel();
123
        while (count-- > 0) {
124
                peek_buf[0] = 0;
125
 
126
                result = -EIO;
127
                if (job->sk->dead) {
128
                        PARANOIA("sock dead!\n");
129
                        break;
130
                }
131
 
132
                result = _recvfrom(socket, (void *) peek_buf, 1,
133
                                   MSG_PEEK | MSG_DONTWAIT);
134
                if (result < 0)
135
                        break;
136
                if (peek_buf[0] != 0x85)
137
                        break;
138
 
139
                /* got SESSION KEEP ALIVE */
140
                result = _recvfrom(socket, (void *) peek_buf, 4,
141
                                   MSG_DONTWAIT);
142
 
143
                DEBUG1("got SESSION KEEPALIVE\n");
144
 
145
                if (result < 0)
146
                        break;
147
                found = 1;
148
        }
149
        unlock_kernel();
150
        set_fs(fs);
151
 
152
        DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
153
        if (found)
154
                found_data(job->sk);
155
        smb_kfree(ptr);
156
}
157
 
158
static void
159
smb_data_ready(struct sock *sk, int len)
160
{
161
        struct data_callback* job;
162
        job = smb_kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
163
        if(job == 0) {
164
                printk("smb_data_ready: lost SESSION KEEPALIVE due to OOM.\n");
165
                found_data(sk);
166
                return;
167
        }
168
        INIT_LIST_HEAD(&job->cb.list);
169
        job->cb.sync = 0;
170
        job->cb.routine = smb_data_callback;
171
        job->cb.data = job;
172
        job->sk = sk;
173
        schedule_task(&job->cb);
174
}
175
 
176
int
177
smb_valid_socket(struct inode * inode)
178
{
179
        return (inode && S_ISSOCK(inode->i_mode) &&
180
                inode->u.socket_i.type == SOCK_STREAM);
181
}
182
 
183
static struct socket *
184
server_sock(struct smb_sb_info *server)
185
{
186
        struct file *file;
187
 
188
        if (server && (file = server->sock_file))
189
        {
190
#ifdef SMBFS_PARANOIA
191
                if (!smb_valid_socket(file->f_dentry->d_inode))
192
                        PARANOIA("bad socket!\n");
193
#endif
194
                return &file->f_dentry->d_inode->u.socket_i;
195
        }
196
        return NULL;
197
}
198
 
199
int
200
smb_catch_keepalive(struct smb_sb_info *server)
201
{
202
        struct socket *socket;
203
        struct sock *sk;
204
        void *data_ready;
205
        int error;
206
 
207
        error = -EINVAL;
208
        socket = server_sock(server);
209
        if (!socket)
210
        {
211
                printk(KERN_DEBUG "smb_catch_keepalive: did not get valid server!\n");
212
                server->data_ready = NULL;
213
                goto out;
214
        }
215
 
216
        sk = socket->sk;
217
        if (sk == NULL)
218
        {
219
                DEBUG1("sk == NULL");
220
                server->data_ready = NULL;
221
                goto out;
222
        }
223
        DEBUG1("sk->d_r = %x, server->d_r = %x\n",
224
                 (unsigned int) (sk->data_ready),
225
                 (unsigned int) (server->data_ready));
226
 
227
        /*
228
         * Install the callback atomically to avoid races ...
229
         */
230
        data_ready = xchg(&sk->data_ready, smb_data_ready);
231
        if (data_ready != smb_data_ready) {
232
                server->data_ready = data_ready;
233
                error = 0;
234
        } else
235
                printk(KERN_ERR "smb_catch_keepalive: already done\n");
236
out:
237
        return error;
238
}
239
 
240
int
241
smb_dont_catch_keepalive(struct smb_sb_info *server)
242
{
243
        struct socket *socket;
244
        struct sock *sk;
245
        void * data_ready;
246
        int error;
247
 
248
        error = -EINVAL;
249
        socket = server_sock(server);
250
        if (!socket)
251
        {
252
                printk(KERN_DEBUG "smb_dont_catch_keepalive: did not get valid server!\n");
253
                goto out;
254
        }
255
 
256
        sk = socket->sk;
257
        if (sk == NULL)
258
        {
259
                DEBUG1("sk == NULL");
260
                goto out;
261
        }
262
 
263
        /* Is this really an error?? */
264
        if (server->data_ready == NULL)
265
        {
266
                printk(KERN_DEBUG "smb_dont_catch_keepalive: "
267
                       "server->data_ready == NULL\n");
268
                goto out;
269
        }
270
        DEBUG1("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n",
271
               (unsigned int) (sk->data_ready),
272
               (unsigned int) (server->data_ready));
273
 
274
        /*
275
         * Restore the original callback atomically to avoid races ...
276
         */
277
        data_ready = xchg(&sk->data_ready, server->data_ready);
278
        server->data_ready = NULL;
279
        if (data_ready != smb_data_ready)
280
        {
281
                printk(KERN_ERR "smb_dont_catch_keepalive: "
282
                       "sk->data_ready != smb_data_ready\n");
283
        }
284
        error = 0;
285
out:
286
        return error;
287
}
288
 
289
/*
290
 * Called with the server locked.
291
 */
292
void
293
smb_close_socket(struct smb_sb_info *server)
294
{
295
        struct file * file = server->sock_file;
296
 
297
        if (file)
298
        {
299
                VERBOSE("closing socket %p\n", server_sock(server));
300
#ifdef SMBFS_PARANOIA
301
                if (server_sock(server)->sk->data_ready == smb_data_ready)
302
                        PARANOIA("still catching keepalives!\n");
303
#endif
304
                server->sock_file = NULL;
305
                fput(file);
306
        }
307
}
308
 
309
/*
310
 * Poll the server->socket to allow receives to time out.
311
 * returns 0 when ok to continue, <0 on errors.
312
 */
313
static int
314
smb_receive_poll(struct smb_sb_info *server)
315
{
316
        struct file *file = server->sock_file;
317
        poll_table wait_table;
318
        int result = 0;
319
        int timeout = server->mnt->timeo * HZ;
320
        int mask;
321
 
322
        for (;;) {
323
                poll_initwait(&wait_table);
324
                set_current_state(TASK_INTERRUPTIBLE);
325
 
326
                mask = file->f_op->poll(file, &wait_table);
327
                if (mask & POLLIN) {
328
                        poll_freewait(&wait_table);
329
                        current->state = TASK_RUNNING;
330
                        break;
331
                }
332
 
333
                timeout = schedule_timeout(timeout);
334
                poll_freewait(&wait_table);
335
                set_current_state(TASK_RUNNING);
336
 
337
                if (wait_table.error) {
338
                        result = wait_table.error;
339
                        break;
340
                }
341
 
342
                if (signal_pending(current)) {
343
                        /* we got a signal (which?) tell the caller to
344
                           try again (on all signals?). */
345
                        DEBUG1("got signal_pending()\n");
346
                        result = -ERESTARTSYS;
347
                        break;
348
                }
349
                if (!timeout) {
350
                        printk(KERN_WARNING "SMB server not responding\n");
351
                        result = -EIO;
352
                        break;
353
                }
354
        }
355
        return result;
356
}
357
 
358
static int
359
smb_send_raw(struct socket *socket, unsigned char *source, int length)
360
{
361
        int result;
362
        int already_sent = 0;
363
 
364
        while (already_sent < length)
365
        {
366
                result = _send(socket,
367
                               (void *) (source + already_sent),
368
                               length - already_sent);
369
 
370
                if (result == 0)
371
                {
372
                        return -EIO;
373
                }
374
                if (result < 0)
375
                {
376
                        DEBUG1("smb_send_raw: sendto error = %d\n", -result);
377
                        return result;
378
                }
379
                already_sent += result;
380
        }
381
        return already_sent;
382
}
383
 
384
static int
385
smb_receive_raw(struct smb_sb_info *server, unsigned char *target, int length)
386
{
387
        int result;
388
        int already_read = 0;
389
        struct socket *socket = server_sock(server);
390
 
391
        while (already_read < length)
392
        {
393
                result = smb_receive_poll(server);
394
                if (result < 0) {
395
                        DEBUG1("poll error = %d\n", -result);
396
                        return result;
397
                }
398
                result = _recvfrom(socket,
399
                                   (void *) (target + already_read),
400
                                   length - already_read, 0);
401
 
402
                if (result == 0)
403
                {
404
                        return -EIO;
405
                }
406
                if (result < 0)
407
                {
408
                        DEBUG1("recvfrom error = %d\n", -result);
409
                        return result;
410
                }
411
                already_read += result;
412
        }
413
        return already_read;
414
}
415
 
416
static int
417
smb_get_length(struct smb_sb_info *server, unsigned char *header)
418
{
419
        int result;
420
        unsigned char peek_buf[4];
421
        mm_segment_t fs;
422
 
423
      re_recv:
424
        fs = get_fs();
425
        set_fs(get_ds());
426
        result = smb_receive_raw(server, peek_buf, 4);
427
        set_fs(fs);
428
 
429
        if (result < 0)
430
        {
431
                PARANOIA("recv error = %d\n", -result);
432
                return result;
433
        }
434
        switch (peek_buf[0])
435
        {
436
        case 0x00:
437
        case 0x82:
438
                break;
439
 
440
        case 0x85:
441
                DEBUG1("Got SESSION KEEP ALIVE\n");
442
                goto re_recv;
443
 
444
        default:
445
                PARANOIA("Invalid NBT packet, code=%x\n", peek_buf[0]);
446
                return -EIO;
447
        }
448
 
449
        if (header != NULL)
450
        {
451
                memcpy(header, peek_buf, 4);
452
        }
453
        /* The length in the RFC NB header is the raw data length */
454
        return smb_len(peek_buf);
455
}
456
 
457
/*
458
 * Since we allocate memory in increments of PAGE_SIZE,
459
 * round up the packet length to the next multiple.
460
 */
461
int
462
smb_round_length(int len)
463
{
464
        return (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
465
}
466
 
467
/*
468
 * smb_receive
469
 * fs points to the correct segment
470
 */
471
static int
472
smb_receive(struct smb_sb_info *server)
473
{
474
        unsigned char * packet = server->packet;
475
        int len, result;
476
        unsigned char peek_buf[4];
477
 
478
        result = smb_get_length(server, peek_buf);
479
        if (result < 0)
480
                goto out;
481
        len = result;
482
        /*
483
         * Some servers do not respect our max_xmit and send
484
         * larger packets.  Try to allocate a new packet,
485
         * but don't free the old one unless we succeed.
486
         */
487
        if (len + 4 > server->packet_size)
488
        {
489
                int new_len = smb_round_length(len + 4);
490
 
491
                result = -ENOMEM;
492
                packet = smb_vmalloc(new_len);
493
                if (packet == NULL)
494
                        goto out;
495
                smb_vfree(server->packet);
496
                server->packet = packet;
497
                server->packet_size = new_len;
498
        }
499
        memcpy(packet, peek_buf, 4);
500
        result = smb_receive_raw(server, packet + 4, len);
501
        if (result < 0)
502
        {
503
                VERBOSE("receive error: %d\n", result);
504
                goto out;
505
        }
506
        server->rcls = *(packet + smb_rcls);
507
        server->err  = WVAL(packet, smb_err);
508
 
509
#ifdef SMBFS_DEBUG_VERBOSE
510
        if (server->rcls != 0)
511
                VERBOSE("rcls=%d, err=%d\n", server->rcls, server->err);
512
#endif
513
out:
514
        return result;
515
}
516
 
517
/*
518
 * This routine checks first for "fast track" processing, as most
519
 * packets won't need to be copied. Otherwise, it allocates a new
520
 * packet to hold the incoming data.
521
 *
522
 * Note that the final server packet must be the larger of the two;
523
 * server packets aren't allowed to shrink.
524
 */
525
static int
526
smb_receive_trans2(struct smb_sb_info *server,
527
                   int *ldata, unsigned char **data,
528
                   int *lparm, unsigned char **parm)
529
{
530
        unsigned char *inbuf, *base, *rcv_buf = NULL;
531
        unsigned int parm_disp, parm_offset, parm_count, parm_tot, parm_len = 0;
532
        unsigned int data_disp, data_offset, data_count, data_tot, data_len = 0;
533
        unsigned int total_p = 0, total_d = 0, buf_len = 0;
534
        int result;
535
 
536
        while (1) {
537
                result = smb_receive(server);
538
                if (result < 0)
539
                        goto out;
540
                inbuf = server->packet;
541
                if (server->rcls != 0) {
542
                        *parm = *data = inbuf;
543
                        *ldata = *lparm = 0;
544
                        goto out;
545
                }
546
                /*
547
                 * Extract the control data from the packet.
548
                 */
549
                data_tot    = WVAL(inbuf, smb_tdrcnt);
550
                parm_tot    = WVAL(inbuf, smb_tprcnt);
551
                parm_disp   = WVAL(inbuf, smb_prdisp);
552
                parm_offset = WVAL(inbuf, smb_proff);
553
                parm_count  = WVAL(inbuf, smb_prcnt);
554
                data_disp   = WVAL(inbuf, smb_drdisp);
555
                data_offset = WVAL(inbuf, smb_droff);
556
                data_count  = WVAL(inbuf, smb_drcnt);
557
                base = smb_base(inbuf);
558
 
559
                /*
560
                 * Assume success and increment lengths.
561
                 */
562
                parm_len += parm_count;
563
                data_len += data_count;
564
 
565
                if (!rcv_buf) {
566
                        /*
567
                         * Check for fast track processing ... just this packet.
568
                         */
569
                        if (parm_count == parm_tot && data_count == data_tot) {
570
                                VERBOSE("fast track, parm=%u %u %u, data=%u %u %u\n",
571
                                        parm_disp, parm_offset, parm_count,
572
                                        data_disp, data_offset, data_count);
573
                                *parm  = base + parm_offset;
574
                                *data  = base + data_offset;
575
                                goto success;
576
                        }
577
 
578
                        /*
579
                         * Save the total parameter and data length.
580
                         */
581
                        total_d = data_tot;
582
                        total_p = parm_tot;
583
 
584
                        buf_len = total_d + total_p;
585
                        if (server->packet_size > buf_len)
586
                                buf_len = server->packet_size;
587
                        buf_len = smb_round_length(buf_len);
588
                        if (buf_len > SMB_MAX_PACKET_SIZE)
589
                                goto out_too_long;
590
 
591
                        rcv_buf = smb_vmalloc(buf_len);
592
                        if (!rcv_buf)
593
                                goto out_no_mem;
594
                        *parm = rcv_buf;
595
                        *data = rcv_buf + total_p;
596
                } else if (data_tot > total_d || parm_tot > total_p)
597
                        goto out_data_grew;
598
 
599
                if (parm_disp + parm_count > total_p)
600
                        goto out_bad_parm;
601
                if (data_disp + data_count > total_d)
602
                        goto out_bad_data;
603
                memcpy(*parm + parm_disp, base + parm_offset, parm_count);
604
                memcpy(*data + data_disp, base + data_offset, data_count);
605
 
606
                PARANOIA("copied, parm=%u of %u, data=%u of %u\n",
607
                         parm_len, parm_tot, data_len, data_tot);
608
 
609
                /*
610
                 * Check whether we've received all of the data. Note that
611
                 * we use the packet totals -- total lengths might shrink!
612
                 */
613
                if (data_len >= data_tot && parm_len >= parm_tot)
614
                        break;
615
        }
616
 
617
        /*
618
         * Install the new packet.  Note that it's possible, though
619
         * unlikely, that the new packet could be smaller than the
620
         * old one, in which case we just copy the data.
621
         */
622
        inbuf = server->packet;
623
        if (buf_len >= server->packet_size) {
624
                server->packet_size = buf_len;
625
                server->packet = rcv_buf;
626
                rcv_buf = inbuf;
627
        } else {
628
                PARANOIA("copying data, old size=%d, new size=%u\n",
629
                         server->packet_size, buf_len);
630
                memcpy(inbuf, rcv_buf, parm_len + data_len);
631
        }
632
 
633
success:
634
        *ldata = data_len;
635
        *lparm = parm_len;
636
out:
637
        if (rcv_buf)
638
                smb_vfree(rcv_buf);
639
        return result;
640
 
641
out_no_mem:
642
        PARANOIA("couldn't allocate data area\n");
643
        result = -ENOMEM;
644
        goto out;
645
out_too_long:
646
        printk(KERN_ERR "smb_receive_trans2: data/param too long, data=%d, parm=%d\n",
647
                data_tot, parm_tot);
648
        goto out_error;
649
out_data_grew:
650
        printk(KERN_ERR "smb_receive_trans2: data/params grew!\n");
651
        goto out_error;
652
out_bad_parm:
653
        printk(KERN_ERR "smb_receive_trans2: invalid parms, disp=%d, cnt=%d, tot=%d\n",
654
                parm_disp, parm_count, parm_tot);
655
        goto out_error;
656
out_bad_data:
657
        printk(KERN_ERR "smb_receive_trans2: invalid data, disp=%d, cnt=%d, tot=%d\n",
658
                data_disp, data_count, data_tot);
659
out_error:
660
        result = -EIO;
661
        goto out;
662
}
663
 
664
/*
665
 * Called with the server locked
666
 */
667
int
668
smb_request(struct smb_sb_info *server)
669
{
670
        unsigned long flags, sigpipe;
671
        mm_segment_t fs;
672
        sigset_t old_set;
673
        int len, result;
674
        unsigned char *buffer;
675
 
676
        result = -EBADF;
677
        buffer = server->packet;
678
        if (!buffer)
679
                goto bad_no_packet;
680
 
681
        result = -EIO;
682
        if (server->state != CONN_VALID)
683
                goto bad_no_conn;
684
 
685
        if ((result = smb_dont_catch_keepalive(server)) != 0)
686
                goto bad_conn;
687
 
688
        len = smb_len(buffer) + 4;
689
        DEBUG1("len = %d cmd = 0x%X\n", len, buffer[8]);
690
 
691
        spin_lock_irqsave(&current->sigmask_lock, flags);
692
        sigpipe = sigismember(&current->pending.signal, SIGPIPE);
693
        old_set = current->blocked;
694
        siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
695
        recalc_sigpending(current);
696
        spin_unlock_irqrestore(&current->sigmask_lock, flags);
697
 
698
        fs = get_fs();
699
        set_fs(get_ds());
700
 
701
        result = smb_send_raw(server_sock(server), (void *) buffer, len);
702
        if (result > 0)
703
        {
704
                result = smb_receive(server);
705
        }
706
 
707
        /* read/write errors are handled by errno */
708
        spin_lock_irqsave(&current->sigmask_lock, flags);
709
        if (result == -EPIPE && !sigpipe)
710
                sigdelset(&current->pending.signal, SIGPIPE);
711
        current->blocked = old_set;
712
        recalc_sigpending(current);
713
        spin_unlock_irqrestore(&current->sigmask_lock, flags);
714
 
715
        set_fs(fs);
716
 
717
        if (result >= 0)
718
        {
719
                int result2 = smb_catch_keepalive(server);
720
                if (result2 < 0)
721
                {
722
                        printk(KERN_ERR "smb_request: catch keepalive failed\n");
723
                        result = result2;
724
                }
725
        }
726
        if (result < 0)
727
                goto bad_conn;
728
        /*
729
         * Check for fatal server errors ...
730
         */
731
        if (server->rcls) {
732
                int error = smb_errno(server);
733
                if (error == -EBADSLT) {
734
                        printk(KERN_ERR "smb_request: tree ID invalid\n");
735
                        result = error;
736
                        goto bad_conn;
737
                }
738
        }
739
 
740
out:
741
        DEBUG1("result = %d\n", result);
742
        return result;
743
 
744
bad_conn:
745
        PARANOIA("result %d, setting invalid\n", result);
746
        server->state = CONN_INVALID;
747
        smb_invalidate_inodes(server);
748
        goto out;
749
bad_no_packet:
750
        printk(KERN_ERR "smb_request: no packet!\n");
751
        goto out;
752
bad_no_conn:
753
        printk(KERN_ERR "smb_request: connection %d not valid!\n",
754
               server->state);
755
        goto out;
756
}
757
 
758
#define ROUND_UP(x) (((x)+3) & ~3)
759
static int
760
smb_send_trans2(struct smb_sb_info *server, __u16 trans2_command,
761
                int ldata, unsigned char *data,
762
                int lparam, unsigned char *param)
763
{
764
        struct socket *sock = server_sock(server);
765
        struct scm_cookie scm;
766
        int err;
767
        int mparam, mdata;
768
 
769
        /* I know the following is very ugly, but I want to build the
770
           smb packet as efficiently as possible. */
771
 
772
        const int smb_parameters = 15;
773
        const int oparam =
774
                ROUND_UP(SMB_HEADER_LEN + 2 * smb_parameters + 2 + 3);
775
        const int odata =
776
                ROUND_UP(oparam + lparam);
777
        const int bcc =
778
                odata + ldata - (SMB_HEADER_LEN + 2 * smb_parameters + 2);
779
        const int packet_length =
780
                SMB_HEADER_LEN + 2 * smb_parameters + bcc + 2;
781
 
782
        unsigned char padding[4] =
783
        {0,};
784
        char *p;
785
 
786
        struct iovec iov[4];
787
        struct msghdr msg;
788
 
789
        /* FIXME! this test needs to include SMB overhead too, I think ... */
790
        if ((bcc + oparam) > server->opt.max_xmit)
791
                return -ENOMEM;
792
        p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc);
793
 
794
        /*
795
         * max parameters + max data + max setup == max_xmit to make NT4 happy
796
         * and not abort the transfer or split into multiple responses.
797
         *
798
         * -100 is to make room for headers, which OS/2 seems to include in the
799
         * size calculation while NT4 does not?
800
         */
801
        mparam = SMB_TRANS2_MAX_PARAM;
802
        mdata = server->opt.max_xmit - mparam - 100;
803
        if (mdata < 1024) {
804
                mdata = 1024;
805
                mparam = 20;
806
        }
807
 
808
        WSET(server->packet, smb_tpscnt, lparam);
809
        WSET(server->packet, smb_tdscnt, ldata);
810
        WSET(server->packet, smb_mprcnt, mparam);
811
        WSET(server->packet, smb_mdrcnt, mdata);
812
        WSET(server->packet, smb_msrcnt, 0);    /* max setup always 0 ? */
813
        WSET(server->packet, smb_flags, 0);
814
        DSET(server->packet, smb_timeout, 0);
815
        WSET(server->packet, smb_pscnt, lparam);
816
        WSET(server->packet, smb_psoff, oparam - 4);
817
        WSET(server->packet, smb_dscnt, ldata);
818
        WSET(server->packet, smb_dsoff, odata - 4);
819
        WSET(server->packet, smb_suwcnt, 1);
820
        WSET(server->packet, smb_setup0, trans2_command);
821
        *p++ = 0;                /* null smb_name for trans2 */
822
        *p++ = 'D';             /* this was added because OS/2 does it */
823
        *p++ = ' ';
824
 
825
 
826
        msg.msg_name = NULL;
827
        msg.msg_namelen = 0;
828
        msg.msg_control = NULL;
829
        msg.msg_controllen = 0;
830
        msg.msg_iov = iov;
831
        msg.msg_iovlen = 4;
832
        msg.msg_flags = 0;
833
 
834
        iov[0].iov_base = (void *) server->packet;
835
        iov[0].iov_len = oparam;
836
        iov[1].iov_base = (param == NULL) ? padding : param;
837
        iov[1].iov_len = lparam;
838
        iov[2].iov_base = padding;
839
        iov[2].iov_len = odata - oparam - lparam;
840
        iov[3].iov_base = (data == NULL) ? padding : data;
841
        iov[3].iov_len = ldata;
842
 
843
        err = scm_send(sock, &msg, &scm);
844
        if (err >= 0) {
845
                err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
846
                scm_destroy(&scm);
847
        }
848
        return err;
849
}
850
 
851
/*
852
 * This is not really a trans2 request, we assume that you only have
853
 * one packet to send.
854
 */
855
int
856
smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
857
                   int ldata, unsigned char *data,
858
                   int lparam, unsigned char *param,
859
                   int *lrdata, unsigned char **rdata,
860
                   int *lrparam, unsigned char **rparam)
861
{
862
        sigset_t old_set;
863
        unsigned long flags, sigpipe;
864
        mm_segment_t fs;
865
        int result;
866
 
867
        DEBUG1("com=%d, ld=%d, lp=%d\n", trans2_command, ldata, lparam);
868
 
869
        /*
870
         * These are initialized in smb_request_ok, but not here??
871
         */
872
        server->rcls = 0;
873
        server->err = 0;
874
 
875
        result = -EIO;
876
        if (server->state != CONN_VALID)
877
                goto out;
878
 
879
        if ((result = smb_dont_catch_keepalive(server)) != 0)
880
                goto bad_conn;
881
 
882
        spin_lock_irqsave(&current->sigmask_lock, flags);
883
        sigpipe = sigismember(&current->pending.signal, SIGPIPE);
884
        old_set = current->blocked;
885
        siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
886
        recalc_sigpending(current);
887
        spin_unlock_irqrestore(&current->sigmask_lock, flags);
888
 
889
        fs = get_fs();
890
        set_fs(get_ds());
891
 
892
        result = smb_send_trans2(server, trans2_command,
893
                                 ldata, data, lparam, param);
894
        if (result >= 0)
895
        {
896
                result = smb_receive_trans2(server,
897
                                            lrdata, rdata, lrparam, rparam);
898
        }
899
 
900
        /* read/write errors are handled by errno */
901
        spin_lock_irqsave(&current->sigmask_lock, flags);
902
        if (result == -EPIPE && !sigpipe)
903
                sigdelset(&current->pending.signal, SIGPIPE);
904
        current->blocked = old_set;
905
        recalc_sigpending(current);
906
        spin_unlock_irqrestore(&current->sigmask_lock, flags);
907
 
908
        set_fs(fs);
909
 
910
        if (result >= 0)
911
        {
912
                int result2 = smb_catch_keepalive(server);
913
                if (result2 < 0)
914
                {
915
                        result = result2;
916
                }
917
        }
918
        if (result < 0)
919
                goto bad_conn;
920
        /*
921
         * Check for fatal server errors ...
922
         */
923
        if (server->rcls) {
924
                int error = smb_errno(server);
925
                if (error == -EBADSLT) {
926
                        printk(KERN_ERR "smb_request: tree ID invalid\n");
927
                        result = error;
928
                        goto bad_conn;
929
                }
930
        }
931
 
932
out:
933
        return result;
934
 
935
bad_conn:
936
        PARANOIA("result=%d, setting invalid\n", result);
937
        server->state = CONN_INVALID;
938
        smb_invalidate_inodes(server);
939
        goto out;
940
}

powered by: WebSVN 2.1.0

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