The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/sock.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/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 }

Cache object: 89aff0557183388d3150f0356a9778f3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.