~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/smbfs/sock.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.