root/fs/smbfs/sock.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _recvfrom
  2. _send
  3. smb_data_callback
  4. smb_catch_keepalive
  5. smb_dont_catch_keepalive
  6. smb_receive_raw
  7. smb_receive
  8. smb_receive_trans2
  9. server_sock
  10. smb_release
  11. smb_connect
  12. smb_request
  13. smb_trans2_request
  14. smb_request_read_raw
  15. smb_request_write_raw

   1 /*
   2  *  sock.c
   3  *
   4  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/sched.h>
   9 #include <linux/smb_fs.h>
  10 #include <linux/errno.h>
  11 #include <linux/socket.h>
  12 #include <linux/fcntl.h>
  13 #include <linux/stat.h>
  14 #include <asm/segment.h>
  15 #include <linux/in.h>
  16 #include <linux/net.h>
  17 #include <linux/mm.h>
  18 #include <linux/netdevice.h>
  19 #include <net/ip.h>
  20 
  21 #include <linux/smb.h>
  22 #include <linux/smbno.h>
  23 
  24 
  25 #define _S(nr) (1<<((nr)-1))
  26 
  27 static int _recvfrom(struct socket *sock, unsigned char *ubuf, int size, int noblock, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
  28                 struct sockaddr_in *sa, int *addr_len)
  29 {
  30         struct iovec iov;
  31         struct msghdr msg;
  32 
  33         iov.iov_base = ubuf;
  34         iov.iov_len  = size;
  35 
  36         msg.msg_name      = (void *)sa;
  37         msg.msg_namelen   = 0;
  38         if (addr_len)
  39                 msg.msg_namelen = *addr_len;
  40         msg.msg_accrights = NULL;
  41         msg.msg_iov       = &iov;
  42         msg.msg_iovlen    = 1;
  43 
  44         return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
  45 }
  46 
  47 static int _send(struct socket *sock, const void *buff, int len, int nonblock, unsigned flags) {
     /* [previous][next][first][last][top][bottom][index][help] */
  48         struct iovec iov;
  49         struct msghdr msg;
  50 
  51         iov.iov_base = (void *)buff;
  52         iov.iov_len  = len;
  53 
  54         msg.msg_name      = NULL;
  55         msg.msg_namelen   = 0;
  56         msg.msg_accrights = NULL;
  57         msg.msg_iov       = &iov;
  58         msg.msg_iovlen    = 1;
  59 
  60         return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
  61 }
  62 
  63 static void
  64 smb_data_callback(struct sock *sk,int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         struct socket *sock = sk->socket;
  67 
  68         if(!sk->dead)
  69         {
  70                 unsigned char peek_buf[4];
  71                 int result;
  72                 unsigned short fs;
  73 
  74                 fs = get_fs();
  75                 set_fs(get_ds());
  76 
  77                 result = _recvfrom(sock, (void *)peek_buf, 1, 1,
  78                                              MSG_PEEK, NULL, NULL);
  79 
  80                 while ((result != -EAGAIN) && (peek_buf[0] == 0x85)) {
  81 
  82                         /* got SESSION KEEP ALIVE */
  83                         result = _recvfrom(sock, (void *)peek_buf,
  84                                                      4, 1, 0, NULL, NULL);
  85 
  86                         DDPRINTK("smb_data_callback:"
  87                                  " got SESSION KEEP ALIVE\n");
  88 
  89                         if (result == -EAGAIN)
  90                                 break;
  91 
  92                         result = _recvfrom(sock, (void *)peek_buf,
  93                                                      1, 1, MSG_PEEK,
  94                                                      NULL, NULL);
  95 
  96                 }
  97 
  98                 set_fs(fs);
  99 
 100                 if (result != -EAGAIN) {
 101                         wake_up_interruptible(sk->sleep);
 102                 }
 103         }
 104 }
 105 
 106 int
 107 smb_catch_keepalive(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         struct file   *file;
 110         struct inode  *inode;
 111         struct socket *sock;
 112         struct sock   *sk;
 113 
 114         if (   (server == NULL)
 115             || ((file  = server->sock_file) == NULL)
 116             || ((inode = file->f_inode) == NULL)
 117             || (!S_ISSOCK(inode->i_mode))) {
 118 
 119                 printk("smb_catch_keepalive: did not get valid server!\n");
 120                 server->data_ready = NULL;
 121                 return -EINVAL;
 122         }
 123 
 124         sock = &(inode->u.socket_i);
 125 
 126         if (sock->type != SOCK_STREAM) {
 127                 printk("smb_catch_keepalive: did not get SOCK_STREAM\n");
 128                 server->data_ready = NULL;
 129                 return -EINVAL;
 130         }
 131 
 132         sk   = (struct sock *)(sock->data);
 133 
 134         if (sk == NULL) {
 135                 printk("smb_catch_keepalive: sk == NULL");
 136                 server->data_ready = NULL;
 137                 return -EINVAL;
 138         }
 139 
 140         DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n",
 141                  (unsigned int)(sk->data_ready),
 142                  (unsigned int)(server->data_ready));
 143 
 144         if (sk->data_ready == smb_data_callback) {
 145                 printk("smb_catch_keepalive: already done\n");
 146                 return -EINVAL;
 147         }
 148 
 149         server->data_ready = sk->data_ready;
 150         sk->data_ready = smb_data_callback;
 151         return 0;
 152 }
 153                 
 154 int
 155 smb_dont_catch_keepalive(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         struct file   *file;
 158         struct inode  *inode;
 159         struct socket *sock;
 160         struct sock   *sk;
 161 
 162         if (   (server == NULL)
 163             || ((file  = server->sock_file) == NULL)
 164             || ((inode = file->f_inode) == NULL)
 165             || (!S_ISSOCK(inode->i_mode))) {
 166 
 167                 printk("smb_dont_catch_keepalive: "
 168                        "did not get valid server!\n");
 169                 return -EINVAL;
 170         }
 171 
 172         sock = &(inode->u.socket_i);
 173 
 174         if (sock->type != SOCK_STREAM) {
 175                 printk("smb_dont_catch_keepalive: did not get SOCK_STREAM\n");
 176                 return -EINVAL;
 177         }
 178 
 179         sk   = (struct sock *)(sock->data);
 180 
 181         if (sk == NULL) {
 182                 printk("smb_dont_catch_keepalive: sk == NULL");
 183                 return -EINVAL;
 184         }
 185 
 186         if (server->data_ready == NULL) {
 187                 printk("smb_dont_catch_keepalive: "
 188                        "server->data_ready == NULL\n");
 189                 return -EINVAL;
 190         }
 191 
 192         if (sk->data_ready != smb_data_callback) {
 193                 printk("smb_dont_catch_keepalive: "
 194                        "sk->data_callback != smb_data_callback\n");
 195                 return -EINVAL;
 196         }
 197 
 198         DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n",
 199                  (unsigned int)(sk->data_ready),
 200                  (unsigned int)(server->data_ready));
 201 
 202         sk->data_ready = server->data_ready;
 203         server->data_ready = NULL;
 204         return 0;
 205 }
 206 
 207 /*
 208  * smb_receive_raw
 209  * fs points to the correct segment, sock != NULL, target != NULL
 210  * The smb header is only stored if want_header != 0.
 211  */
 212 static int
 213 smb_receive_raw(struct socket *sock, unsigned char *target,
     /* [previous][next][first][last][top][bottom][index][help] */
 214                 int max_raw_length, int want_header)
 215 {
 216         int len, result;
 217         int already_read;
 218         unsigned char peek_buf[4];
 219         unsigned short fs;      /* We fool the kernel to believe
 220                                    we call from user space. */
 221 
 222 
 223  re_recv:
 224 
 225         fs = get_fs();
 226         set_fs(get_ds());
 227         result = _recvfrom(sock, (void *)peek_buf, 4, 0,
 228                                      0, NULL, NULL);
 229         set_fs(fs);
 230 
 231         if (result < 0) {
 232                 DPRINTK("smb_receive_raw: recv error = %d\n", -result);
 233                 return result;
 234         }
 235 
 236         if (result < 4) {
 237                 DPRINTK("smb_receive_raw: got less than 4 bytes\n");
 238                 return -EIO;
 239         }
 240 
 241         switch (peek_buf[0]) {
 242 
 243         case 0x00:
 244         case 0x82:
 245                 break;
 246 
 247         case 0x85:
 248                 DPRINTK("smb_receive_raw: Got SESSION KEEP ALIVE\n");
 249                 goto re_recv;
 250                 
 251         default:
 252                 printk("smb_receive_raw: Invalid packet\n");
 253                 return -EIO;
 254         }
 255 
 256         /* The length in the RFC NB header is the raw data length */
 257         len = smb_len(peek_buf); 
 258         if (len > max_raw_length) { 
 259                 printk("smb_receive_raw: Received length (%d) > max_xmit (%d)!\n", 
 260                        len, max_raw_length);
 261                 return -EIO;
 262         }
 263 
 264         if (want_header != 0) {
 265                 memcpy_tofs(target, peek_buf, 4);
 266                 target += 4;
 267         }
 268 
 269         already_read = 0;
 270 
 271         while (already_read < len) {
 272                 
 273                 result = _recvfrom(sock,
 274                                  (void *)(target+already_read),
 275                                  len - already_read, 0, 0,
 276                                  NULL, NULL);
 277    
 278                 if (result < 0) {
 279                         printk("smb_receive_raw: recvfrom error = %d\n",
 280                                -result);
 281                         return result;
 282                 }
 283 
 284                 already_read += result;
 285         }
 286         return already_read;
 287 }
 288 
 289 /*
 290  * smb_receive
 291  * fs points to the correct segment, server != NULL, sock!=NULL
 292  */
 293 static int
 294 smb_receive(struct smb_server *server, struct socket *sock)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         int result;
 297 
 298         result = smb_receive_raw(sock, server->packet,
 299                                  server->max_xmit - 4, /* max_xmit in server
 300                                                           includes NB header */
 301                                  1); /* We want the header */
 302 
 303         if (result < 0) {
 304                 printk("smb_receive: receive error: %d\n", result);
 305                 return result;
 306         }
 307 
 308         server->rcls = *((unsigned char *)(server->packet+9));
 309         server->err  = *((unsigned short *)(server->packet+11));
 310 
 311         if (server->rcls != 0) {
 312                 DPRINTK("smb_receive: rcls=%d, err=%d\n",
 313                         server->rcls, server->err);
 314         }
 315 
 316         return result;
 317 }
 318 
 319 
 320 /*
 321  * smb_receive's preconditions also apply here.
 322  */
 323 static int
 324 smb_receive_trans2(struct smb_server *server, struct socket *sock,
     /* [previous][next][first][last][top][bottom][index][help] */
 325                    int *data_len, int *param_len,
 326                    char **data, char **param)
 327 {
 328         int total_data=0;
 329         int total_param=0;
 330         int result;
 331         unsigned char *inbuf = server->packet;
 332 
 333         *data_len = *param_len = 0;
 334 
 335         DDPRINTK("smb_receive_trans2: enter\n");
 336         
 337         if ((result = smb_receive(server, sock)) < 0) {
 338                 return result;
 339         }
 340 
 341         if (server->rcls != 0) {
 342                 return result;
 343         }
 344 
 345         /* parse out the lengths */
 346         total_data = WVAL(inbuf,smb_tdrcnt);
 347         total_param = WVAL(inbuf,smb_tprcnt);
 348 
 349         if (   (total_data  > TRANS2_MAX_TRANSFER)
 350             || (total_param > TRANS2_MAX_TRANSFER)) {
 351                 printk("smb_receive_trans2: data/param too long\n");
 352                 return -EIO;
 353         }
 354 
 355         /* allocate it */
 356         if ((*data  = smb_kmalloc(total_data, GFP_KERNEL)) == NULL) {
 357                 printk("smb_receive_trans2: could not alloc data area\n");
 358                 return -ENOMEM;
 359         }
 360 
 361         if ((*param = smb_kmalloc(total_param, GFP_KERNEL)) == NULL) {
 362                 printk("smb_receive_trans2: could not alloc param area\n");
 363                 smb_kfree_s(*data, total_data);
 364                 return -ENOMEM;
 365         }
 366 
 367         DDPRINTK("smb_rec_trans2: total_data/param: %d/%d\n",
 368                  total_data, total_param);
 369 
 370         while (1)
 371         {
 372                 if (WVAL(inbuf,smb_prdisp)+WVAL(inbuf, smb_prcnt)
 373                     > total_param) {
 374                         printk("smb_receive_trans2: invalid parameters\n");
 375                         result = -EIO;
 376                         goto fail;
 377                 }
 378                 memcpy(*param + WVAL(inbuf,smb_prdisp),
 379                        smb_base(inbuf) + WVAL(inbuf,smb_proff),
 380                        WVAL(inbuf,smb_prcnt));
 381                 *param_len += WVAL(inbuf,smb_prcnt);
 382 
 383 
 384                 if (WVAL(inbuf,smb_drdisp)+WVAL(inbuf, smb_drcnt)>total_data) {
 385                         printk("smb_receive_trans2: invalid data block\n");
 386                         result = -EIO;
 387                         goto fail;
 388                 }
 389                 memcpy(*data + WVAL(inbuf,smb_drdisp),
 390                        smb_base(inbuf) + WVAL(inbuf,smb_droff),
 391                        WVAL(inbuf,smb_drcnt));
 392                 *data_len += WVAL(inbuf,smb_drcnt);
 393 
 394                 DDPRINTK("smb_rec_trans2: drcnt/prcnt: %d/%d\n",
 395                          WVAL(inbuf, smb_drcnt), WVAL(inbuf, smb_prcnt));
 396 
 397                 /* parse out the total lengths again - they can shrink! */
 398 
 399                 if (   (WVAL(inbuf,smb_tdrcnt) > total_data)
 400                     || (WVAL(inbuf,smb_tprcnt) > total_param)) {
 401                         printk("smb_receive_trans2: data/params grew!\n");
 402                         result = -EIO;
 403                         goto fail;
 404                 }
 405 
 406                 total_data = WVAL(inbuf,smb_tdrcnt);
 407                 total_param = WVAL(inbuf,smb_tprcnt);
 408 
 409                 if (total_data <= *data_len && total_param <= *param_len)
 410                         break;
 411 
 412                 if ((result = smb_receive(server, sock)) < 0) {
 413                         goto fail;
 414                 }
 415                 if (server->rcls != 0) {
 416                         result = -EIO;
 417                         goto fail;
 418                 }
 419         }
 420 
 421         DDPRINTK("smb_receive_trans2: normal exit\n");
 422 
 423         return 0;
 424 
 425  fail:
 426         DPRINTK("smb_receive_trans2: failed exit\n");
 427 
 428         smb_kfree_s(*param, 0); *param = NULL;
 429         smb_kfree_s(*data, 0);  *data = NULL;
 430         return result;
 431 }
 432 
 433 static inline struct socket *
 434 server_sock(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436         struct file *file;
 437         struct inode *inode;
 438 
 439         if (server == NULL)
 440                 return NULL;
 441         if ((file = server->sock_file) == NULL)
 442                 return NULL;
 443         if ((inode = file->f_inode) == NULL)
 444                 return NULL;
 445         return &(inode->u.socket_i);
 446 }
 447 
 448 int
 449 smb_release(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451         struct socket *sock = server_sock(server);
 452         int result;
 453 
 454         if (sock == NULL)
 455                 return -EINVAL;
 456 
 457         result = sock->ops->release(sock, NULL);
 458         DPRINTK("smb_release: sock->ops->release = %d\n", result);
 459 
 460         /* inet_release does not set sock->state.  Maybe someone is
 461            confused about sock->state being SS_CONNECTED while there
 462            is nothing behind it, so I set it to SS_UNCONNECTED.*/
 463         sock->state = SS_UNCONNECTED;
 464 
 465         result = sock->ops->create(sock, 0);
 466         DPRINTK("smb_release: sock->ops->create = %d\n", result);
 467         return result;
 468 }
 469 
 470 int
 471 smb_connect(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 472 {
 473         struct socket *sock = server_sock(server);
 474         if (sock == NULL)
 475                 return -EINVAL;
 476         if (sock->state != SS_UNCONNECTED) {
 477                 DPRINTK("smb_connect: socket is not unconnected: %d\n",
 478                         sock->state);
 479         }
 480         return sock->ops->connect(sock, (struct sockaddr *)&(server->m.addr),
 481                                   sizeof(struct sockaddr_in), 0);
 482 }
 483         
 484 /*****************************************************************************/
 485 /*                                                                           */
 486 /*  This routine was once taken from nfs, which is for udp. Here TCP does     */
 487 /*  most of the ugly stuff for us (thanks, Alan!)                            */
 488 /*                                                                           */
 489 /*****************************************************************************/
 490 int
 491 smb_request(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493         unsigned long old_mask;
 494         unsigned short fs;      /* We fool the kernel to believe
 495                                    we call from user space. */
 496         int len, result, result2;
 497 
 498         struct socket *sock = server_sock(server);
 499         unsigned char *buffer = (server == NULL) ? NULL : server->packet;
 500 
 501         if ((sock == NULL) || (buffer == NULL)) {
 502                 printk("smb_request: Bad server!\n");
 503                 return -EBADF;
 504         }
 505 
 506         if (server->state != CONN_VALID)
 507                 return -EIO;
 508                 
 509         if ((result = smb_dont_catch_keepalive(server)) != 0) {
 510                 server->state = CONN_INVALID;
 511                 smb_invalidate_all_inodes(server);
 512                 return result;
 513         }
 514 
 515         len = smb_len(buffer) + 4;
 516 
 517         DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
 518 
 519         old_mask = current->blocked;
 520         current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
 521         fs = get_fs();
 522         set_fs(get_ds());
 523 
 524         result = _send(sock, (void *)buffer, len, 0, 0);
 525         if (result < 0) {
 526                 printk("smb_request: send error = %d\n", result);
 527         }
 528         else {
 529                 result = smb_receive(server, sock);
 530         }
 531 
 532         /* read/write errors are handled by errno */
 533         current->signal &= ~_S(SIGPIPE);
 534 
 535         current->blocked = old_mask;
 536         set_fs(fs);
 537 
 538         if ((result2 = smb_catch_keepalive(server)) < 0) {
 539                 result = result2;
 540         }
 541 
 542         if (result < 0) {
 543                 server->state = CONN_INVALID;
 544                 smb_invalidate_all_inodes(server);
 545         }
 546         
 547         DDPRINTK("smb_request: result = %d\n", result);
 548 
 549         return result;
 550 }
 551 
 552 /*
 553  * This is not really a trans2 request, we assume that you only have
 554  * one packet to send.
 555  */ 
 556 int
 557 smb_trans2_request(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 558                    int *data_len, int *param_len,
 559                    char **data, char **param)
 560 {
 561         unsigned long old_mask;
 562         unsigned short fs;      /* We fool the kernel to believe
 563                                    we call from user space. */
 564         int len, result, result2;
 565 
 566         struct socket *sock = server_sock(server);
 567         unsigned char *buffer = (server == NULL) ? NULL : server->packet;
 568 
 569         if ((sock == NULL) || (buffer == NULL)) {
 570                 printk("smb_trans2_request: Bad server!\n");
 571                 return -EBADF;
 572         }
 573 
 574         if (server->state != CONN_VALID)
 575                 return -EIO;
 576                 
 577         if ((result = smb_dont_catch_keepalive(server)) != 0) {
 578                 server->state = CONN_INVALID;
 579                 smb_invalidate_all_inodes(server);
 580                 return result;
 581         }
 582 
 583         len = smb_len(buffer) + 4;
 584 
 585         old_mask = current->blocked;
 586         current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
 587         fs = get_fs();
 588         set_fs(get_ds());
 589 
 590         DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
 591 
 592         result = _send(sock, (void *)buffer, len, 0, 0);
 593         if (result < 0) {
 594                 printk("smb_trans2_request: send error = %d\n", result);
 595         }
 596         else {
 597                 result = smb_receive_trans2(server, sock,
 598                                             data_len, param_len,
 599                                             data, param);
 600         }
 601 
 602         /* read/write errors are handled by errno */
 603         current->signal &= ~_S(SIGPIPE);
 604 
 605         current->blocked = old_mask;
 606         set_fs(fs);
 607 
 608         if ((result2 = smb_catch_keepalive(server)) < 0) {
 609                 result = result2;
 610         }
 611 
 612         if (result < 0) {
 613                 server->state = CONN_INVALID;
 614                 smb_invalidate_all_inodes(server);
 615         }
 616         
 617         DDPRINTK("smb_trans2_request: result = %d\n", result);
 618 
 619         return result;
 620 }
 621 
 622 /* target must be in user space */
 623 int
 624 smb_request_read_raw(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 625                      unsigned char *target, int max_len)
 626 {
 627         unsigned long old_mask;
 628         int len, result, result2;
 629         unsigned short fs;      /* We fool the kernel to believe
 630                                    we call from user space. */
 631 
 632         struct socket *sock = server_sock(server);
 633         unsigned char *buffer = (server == NULL) ? NULL : server->packet;
 634 
 635         if ((sock == NULL) || (buffer == NULL)) {
 636                 printk("smb_request_read_raw: Bad server!\n");
 637                 return -EBADF;
 638         }
 639 
 640         if (server->state != CONN_VALID)
 641                 return -EIO;
 642                 
 643         if ((result = smb_dont_catch_keepalive(server)) != 0) {
 644                 server->state = CONN_INVALID;
 645                 smb_invalidate_all_inodes(server);
 646                 return result;
 647         }
 648 
 649         len = smb_len(buffer) + 4;
 650 
 651         old_mask = current->blocked;
 652         current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
 653         fs = get_fs();
 654         set_fs(get_ds());
 655 
 656         DPRINTK("smb_request_read_raw: len = %d cmd = 0x%X\n",
 657                 len, buffer[8]);
 658         DPRINTK("smb_request_read_raw: target=%X, max_len=%d\n",
 659                 (unsigned int)target, max_len);
 660         DPRINTK("smb_request_read_raw: buffer=%X, sock=%X\n",
 661                 (unsigned int)buffer, (unsigned int)sock);
 662 
 663         result = _send(sock, (void *)buffer, len, 0, 0);
 664 
 665         DPRINTK("smb_request_read_raw: send returned %d\n", result);
 666 
 667         set_fs(fs);             /* We recv into user space */
 668 
 669         if (result < 0) {
 670                 printk("smb_request_read_raw: send error = %d\n", result);
 671         }
 672         else {
 673                 result = smb_receive_raw(sock, target, max_len, 0);
 674         }
 675 
 676         /* read/write errors are handled by errno */
 677         current->signal &= ~_S(SIGPIPE);
 678         current->blocked = old_mask;
 679 
 680         if ((result2 = smb_catch_keepalive(server)) < 0) {
 681                 result = result2;
 682         }
 683 
 684         if (result < 0) {
 685                 server->state = CONN_INVALID;
 686                 smb_invalidate_all_inodes(server);
 687         }
 688         
 689         DPRINTK("smb_request_read_raw: result = %d\n", result);
 690 
 691         return result;
 692 }
 693 
 694 /* Source must be in user space. smb_request_write_raw assumes that
 695  * the request SMBwriteBraw has been completed successfully, so that
 696  * we can send the raw data now.  */
 697 int
 698 smb_request_write_raw(struct smb_server *server,
     /* [previous][next][first][last][top][bottom][index][help] */
 699                       unsigned const char *source, int length)
 700 {
 701         unsigned long old_mask;
 702         int result, result2;
 703         unsigned short fs;      /* We fool the kernel to believe
 704                                    we call from user space. */
 705         byte nb_header[4];
 706 
 707         struct socket *sock = server_sock(server);
 708         unsigned char *buffer = (server == NULL) ? NULL : server->packet;
 709 
 710         if ((sock == NULL) || (buffer == NULL)) {
 711                 printk("smb_request_write_raw: Bad server!\n");
 712                 return -EBADF;
 713         }
 714 
 715         if (server->state != CONN_VALID)
 716                 return -EIO;
 717                 
 718         if ((result = smb_dont_catch_keepalive(server)) != 0) {
 719                 server->state = CONN_INVALID;
 720                 smb_invalidate_all_inodes(server);
 721                 return result;
 722         }
 723 
 724         old_mask = current->blocked;
 725         current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
 726         fs = get_fs();
 727         set_fs(get_ds());
 728 
 729         smb_encode_smb_length(nb_header, length);
 730 
 731         result = _send(sock, (void *)nb_header, 4, 0, 0);
 732 
 733         if (result == 4) {
 734                 set_fs(fs);     /* source is in user-land */
 735                 result = _send(sock, (void *)source, length, 0, 0);
 736                 set_fs(get_ds());
 737         } else {
 738                 result = -EIO;
 739         }
 740 
 741         DPRINTK("smb_request_write_raw: send returned %d\n", result);
 742 
 743         if (result == length) {
 744                 result = smb_receive(server, sock);
 745         } else {
 746                 result = -EIO;
 747         }
 748 
 749         /* read/write errors are handled by errno */
 750         current->signal &= ~_S(SIGPIPE);
 751         current->blocked = old_mask;
 752         set_fs(fs);
 753 
 754         if ((result2 = smb_catch_keepalive(server)) < 0) {
 755                 result = result2;
 756         }
 757 
 758         if (result < 0) {
 759                 server->state = CONN_INVALID;
 760                 smb_invalidate_all_inodes(server);
 761         }
 762 
 763         if (result > 0) {
 764                 result = length;
 765         }
 766         
 767         DPRINTK("smb_request_write_raw: result = %d\n", result);
 768 
 769         return result;
 770 }
 771 
 772 /*
 773  * Overrides for Emacs so that we follow Linus's tabbing style.
 774  * Emacs will notice this stuff at the end of the file and automatically
 775  * adjust the settings for this buffer only.  This must remain at the end
 776  * of the file.
 777  * ---------------------------------------------------------------------------
 778  * Local variables:
 779  * c-indent-level: 8
 780  * c-brace-imaginary-offset: 0
 781  * c-brace-offset: -8
 782  * c-argdecl-indent: 8
 783  * c-label-offset: -8
 784  * c-continued-statement-offset: 8
 785  * c-continued-brace-offset: 0
 786  * End:
 787  */

/* [previous][next][first][last][top][bottom][index][help] */