at v2.6.21 21 kB view raw
1/* 2 * request.c 3 * 4 * Copyright (C) 2001 by Urban Widmark 5 * 6 * Please add a note about your changes to smbfs in the ChangeLog file. 7 */ 8 9#include <linux/types.h> 10#include <linux/fs.h> 11#include <linux/slab.h> 12#include <linux/net.h> 13 14#include <linux/smb_fs.h> 15#include <linux/smbno.h> 16#include <linux/smb_mount.h> 17 18#include "smb_debug.h" 19#include "request.h" 20#include "proto.h" 21 22/* #define SMB_SLAB_DEBUG (SLAB_RED_ZONE | SLAB_POISON) */ 23#define SMB_SLAB_DEBUG 0 24 25#define ROUND_UP(x) (((x)+3) & ~3) 26 27/* cache for request structures */ 28static struct kmem_cache *req_cachep; 29 30static int smb_request_send_req(struct smb_request *req); 31 32/* 33 /proc/slabinfo: 34 name, active, num, objsize, active_slabs, num_slaps, #pages 35*/ 36 37 38int smb_init_request_cache(void) 39{ 40 req_cachep = kmem_cache_create("smb_request", 41 sizeof(struct smb_request), 0, 42 SMB_SLAB_DEBUG | SLAB_HWCACHE_ALIGN, 43 NULL, NULL); 44 if (req_cachep == NULL) 45 return -ENOMEM; 46 47 return 0; 48} 49 50void smb_destroy_request_cache(void) 51{ 52 kmem_cache_destroy(req_cachep); 53} 54 55/* 56 * Allocate and initialise a request structure 57 */ 58static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server, 59 int bufsize) 60{ 61 struct smb_request *req; 62 unsigned char *buf = NULL; 63 64 req = kmem_cache_zalloc(req_cachep, GFP_KERNEL); 65 VERBOSE("allocating request: %p\n", req); 66 if (!req) 67 goto out; 68 69 if (bufsize > 0) { 70 buf = kmalloc(bufsize, GFP_NOFS); 71 if (!buf) { 72 kmem_cache_free(req_cachep, req); 73 return NULL; 74 } 75 } 76 77 req->rq_buffer = buf; 78 req->rq_bufsize = bufsize; 79 req->rq_server = server; 80 init_waitqueue_head(&req->rq_wait); 81 INIT_LIST_HEAD(&req->rq_queue); 82 atomic_set(&req->rq_count, 1); 83 84out: 85 return req; 86} 87 88struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize) 89{ 90 struct smb_request *req = NULL; 91 92 for (;;) { 93 atomic_inc(&server->nr_requests); 94 if (atomic_read(&server->nr_requests) <= MAX_REQUEST_HARD) { 95 req = smb_do_alloc_request(server, bufsize); 96 if (req != NULL) 97 break; 98 } 99 100#if 0 101 /* 102 * Try to free up at least one request in order to stay 103 * below the hard limit 104 */ 105 if (nfs_try_to_free_pages(server)) 106 continue; 107 108 if (signalled() && (server->flags & NFS_MOUNT_INTR)) 109 return ERR_PTR(-ERESTARTSYS); 110 current->policy = SCHED_YIELD; 111 schedule(); 112#else 113 /* FIXME: we want something like nfs does above, but that 114 requires changes to all callers and can wait. */ 115 break; 116#endif 117 } 118 return req; 119} 120 121static void smb_free_request(struct smb_request *req) 122{ 123 atomic_dec(&req->rq_server->nr_requests); 124 if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC)) 125 kfree(req->rq_buffer); 126 kfree(req->rq_trans2buffer); 127 kmem_cache_free(req_cachep, req); 128} 129 130/* 131 * What prevents a rget to race with a rput? The count must never drop to zero 132 * while it is in use. Only rput if it is ok that it is free'd. 133 */ 134static void smb_rget(struct smb_request *req) 135{ 136 atomic_inc(&req->rq_count); 137} 138void smb_rput(struct smb_request *req) 139{ 140 if (atomic_dec_and_test(&req->rq_count)) { 141 list_del_init(&req->rq_queue); 142 smb_free_request(req); 143 } 144} 145 146/* setup to receive the data part of the SMB */ 147static int smb_setup_bcc(struct smb_request *req) 148{ 149 int result = 0; 150 req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd; 151 152 if (req->rq_rlen > req->rq_bufsize) { 153 PARANOIA("Packet too large %d > %d\n", 154 req->rq_rlen, req->rq_bufsize); 155 return -ENOBUFS; 156 } 157 158 req->rq_iov[0].iov_base = req->rq_buffer; 159 req->rq_iov[0].iov_len = req->rq_rlen; 160 req->rq_iovlen = 1; 161 162 return result; 163} 164 165/* 166 * Prepare a "normal" request structure. 167 */ 168static int smb_setup_request(struct smb_request *req) 169{ 170 int len = smb_len(req->rq_header) + 4; 171 req->rq_slen = len; 172 173 /* if we expect a data part in the reply we set the iov's to read it */ 174 if (req->rq_resp_bcc) 175 req->rq_setup_read = smb_setup_bcc; 176 177 /* This tries to support re-using the same request */ 178 req->rq_bytes_sent = 0; 179 req->rq_rcls = 0; 180 req->rq_err = 0; 181 req->rq_errno = 0; 182 req->rq_fragment = 0; 183 kfree(req->rq_trans2buffer); 184 req->rq_trans2buffer = NULL; 185 186 return 0; 187} 188 189/* 190 * Prepare a transaction2 request structure 191 */ 192static int smb_setup_trans2request(struct smb_request *req) 193{ 194 struct smb_sb_info *server = req->rq_server; 195 int mparam, mdata; 196 static unsigned char padding[4]; 197 198 /* I know the following is very ugly, but I want to build the 199 smb packet as efficiently as possible. */ 200 201 const int smb_parameters = 15; 202 const int header = SMB_HEADER_LEN + 2 * smb_parameters + 2; 203 const int oparam = ROUND_UP(header + 3); 204 const int odata = ROUND_UP(oparam + req->rq_lparm); 205 const int bcc = (req->rq_data ? odata + req->rq_ldata : 206 oparam + req->rq_lparm) - header; 207 208 if ((bcc + oparam) > server->opt.max_xmit) 209 return -ENOMEM; 210 smb_setup_header(req, SMBtrans2, smb_parameters, bcc); 211 212 /* 213 * max parameters + max data + max setup == bufsize to make NT4 happy 214 * and not abort the transfer or split into multiple responses. It also 215 * makes smbfs happy as handling packets larger than the buffer size 216 * is extra work. 217 * 218 * OS/2 is probably going to hate me for this ... 219 */ 220 mparam = SMB_TRANS2_MAX_PARAM; 221 mdata = req->rq_bufsize - mparam; 222 223 mdata = server->opt.max_xmit - mparam - 100; 224 if (mdata < 1024) { 225 mdata = 1024; 226 mparam = 20; 227 } 228 229#if 0 230 /* NT/win2k has ~4k max_xmit, so with this we request more than it wants 231 to return as one SMB. Useful for testing the fragmented trans2 232 handling. */ 233 mdata = 8192; 234#endif 235 236 WSET(req->rq_header, smb_tpscnt, req->rq_lparm); 237 WSET(req->rq_header, smb_tdscnt, req->rq_ldata); 238 WSET(req->rq_header, smb_mprcnt, mparam); 239 WSET(req->rq_header, smb_mdrcnt, mdata); 240 WSET(req->rq_header, smb_msrcnt, 0); /* max setup always 0 ? */ 241 WSET(req->rq_header, smb_flags, 0); 242 DSET(req->rq_header, smb_timeout, 0); 243 WSET(req->rq_header, smb_pscnt, req->rq_lparm); 244 WSET(req->rq_header, smb_psoff, oparam - 4); 245 WSET(req->rq_header, smb_dscnt, req->rq_ldata); 246 WSET(req->rq_header, smb_dsoff, req->rq_data ? odata - 4 : 0); 247 *(req->rq_header + smb_suwcnt) = 0x01; /* setup count */ 248 *(req->rq_header + smb_suwcnt + 1) = 0x00; /* reserved */ 249 WSET(req->rq_header, smb_setup0, req->rq_trans2_command); 250 251 req->rq_iovlen = 2; 252 req->rq_iov[0].iov_base = (void *) req->rq_header; 253 req->rq_iov[0].iov_len = oparam; 254 req->rq_iov[1].iov_base = (req->rq_parm==NULL) ? padding : req->rq_parm; 255 req->rq_iov[1].iov_len = req->rq_lparm; 256 req->rq_slen = oparam + req->rq_lparm; 257 258 if (req->rq_data) { 259 req->rq_iovlen += 2; 260 req->rq_iov[2].iov_base = padding; 261 req->rq_iov[2].iov_len = odata - oparam - req->rq_lparm; 262 req->rq_iov[3].iov_base = req->rq_data; 263 req->rq_iov[3].iov_len = req->rq_ldata; 264 req->rq_slen = odata + req->rq_ldata; 265 } 266 267 /* always a data part for trans2 replies */ 268 req->rq_setup_read = smb_setup_bcc; 269 270 return 0; 271} 272 273/* 274 * Add a request and tell smbiod to process it 275 */ 276int smb_add_request(struct smb_request *req) 277{ 278 long timeleft; 279 struct smb_sb_info *server = req->rq_server; 280 int result = 0; 281 282 smb_setup_request(req); 283 if (req->rq_trans2_command) { 284 if (req->rq_buffer == NULL) { 285 PARANOIA("trans2 attempted without response buffer!\n"); 286 return -EIO; 287 } 288 result = smb_setup_trans2request(req); 289 } 290 if (result < 0) 291 return result; 292 293#ifdef SMB_DEBUG_PACKET_SIZE 294 add_xmit_stats(req); 295#endif 296 297 /* add 'req' to the queue of requests */ 298 if (smb_lock_server_interruptible(server)) 299 return -EINTR; 300 301 /* 302 * Try to send the request as the process. If that fails we queue the 303 * request and let smbiod send it later. 304 */ 305 306 /* FIXME: each server has a number on the maximum number of parallel 307 requests. 10, 50 or so. We should not allow more requests to be 308 active. */ 309 if (server->mid > 0xf000) 310 server->mid = 0; 311 req->rq_mid = server->mid++; 312 WSET(req->rq_header, smb_mid, req->rq_mid); 313 314 result = 0; 315 if (server->state == CONN_VALID) { 316 if (list_empty(&server->xmitq)) 317 result = smb_request_send_req(req); 318 if (result < 0) { 319 /* Connection lost? */ 320 server->conn_error = result; 321 server->state = CONN_INVALID; 322 } 323 } 324 if (result != 1) 325 list_add_tail(&req->rq_queue, &server->xmitq); 326 smb_rget(req); 327 328 if (server->state != CONN_VALID) 329 smbiod_retry(server); 330 331 smb_unlock_server(server); 332 333 smbiod_wake_up(); 334 335 timeleft = wait_event_interruptible_timeout(req->rq_wait, 336 req->rq_flags & SMB_REQ_RECEIVED, 30*HZ); 337 if (!timeleft || signal_pending(current)) { 338 /* 339 * On timeout or on interrupt we want to try and remove the 340 * request from the recvq/xmitq. 341 * First check if the request is still part of a queue. (May 342 * have been removed by some error condition) 343 */ 344 smb_lock_server(server); 345 if (!list_empty(&req->rq_queue)) { 346 list_del_init(&req->rq_queue); 347 smb_rput(req); 348 } 349 smb_unlock_server(server); 350 } 351 352 if (!timeleft) { 353 PARANOIA("request [%p, mid=%d] timed out!\n", 354 req, req->rq_mid); 355 VERBOSE("smb_com: %02x\n", *(req->rq_header + smb_com)); 356 VERBOSE("smb_rcls: %02x\n", *(req->rq_header + smb_rcls)); 357 VERBOSE("smb_flg: %02x\n", *(req->rq_header + smb_flg)); 358 VERBOSE("smb_tid: %04x\n", WVAL(req->rq_header, smb_tid)); 359 VERBOSE("smb_pid: %04x\n", WVAL(req->rq_header, smb_pid)); 360 VERBOSE("smb_uid: %04x\n", WVAL(req->rq_header, smb_uid)); 361 VERBOSE("smb_mid: %04x\n", WVAL(req->rq_header, smb_mid)); 362 VERBOSE("smb_wct: %02x\n", *(req->rq_header + smb_wct)); 363 364 req->rq_rcls = ERRSRV; 365 req->rq_err = ERRtimeout; 366 367 /* Just in case it was "stuck" */ 368 smbiod_wake_up(); 369 } 370 VERBOSE("woke up, rcls=%d\n", req->rq_rcls); 371 372 if (req->rq_rcls != 0) 373 req->rq_errno = smb_errno(req); 374 if (signal_pending(current)) 375 req->rq_errno = -ERESTARTSYS; 376 return req->rq_errno; 377} 378 379/* 380 * Send a request and place it on the recvq if successfully sent. 381 * Must be called with the server lock held. 382 */ 383static int smb_request_send_req(struct smb_request *req) 384{ 385 struct smb_sb_info *server = req->rq_server; 386 int result; 387 388 if (req->rq_bytes_sent == 0) { 389 WSET(req->rq_header, smb_tid, server->opt.tid); 390 WSET(req->rq_header, smb_pid, 1); 391 WSET(req->rq_header, smb_uid, server->opt.server_uid); 392 } 393 394 result = smb_send_request(req); 395 if (result < 0 && result != -EAGAIN) 396 goto out; 397 398 result = 0; 399 if (!(req->rq_flags & SMB_REQ_TRANSMITTED)) 400 goto out; 401 402 list_move_tail(&req->rq_queue, &server->recvq); 403 result = 1; 404out: 405 return result; 406} 407 408/* 409 * Sends one request for this server. (smbiod) 410 * Must be called with the server lock held. 411 * Returns: <0 on error 412 * 0 if no request could be completely sent 413 * 1 if all data for one request was sent 414 */ 415int smb_request_send_server(struct smb_sb_info *server) 416{ 417 struct list_head *head; 418 struct smb_request *req; 419 int result; 420 421 if (server->state != CONN_VALID) 422 return 0; 423 424 /* dequeue first request, if any */ 425 req = NULL; 426 head = server->xmitq.next; 427 if (head != &server->xmitq) { 428 req = list_entry(head, struct smb_request, rq_queue); 429 } 430 if (!req) 431 return 0; 432 433 result = smb_request_send_req(req); 434 if (result < 0) { 435 server->conn_error = result; 436 list_move(&req->rq_queue, &server->xmitq); 437 result = -EIO; 438 goto out; 439 } 440 441out: 442 return result; 443} 444 445/* 446 * Try to find a request matching this "mid". Typically the first entry will 447 * be the matching one. 448 */ 449static struct smb_request *find_request(struct smb_sb_info *server, int mid) 450{ 451 struct list_head *tmp; 452 struct smb_request *req = NULL; 453 454 list_for_each(tmp, &server->recvq) { 455 req = list_entry(tmp, struct smb_request, rq_queue); 456 if (req->rq_mid == mid) { 457 break; 458 } 459 req = NULL; 460 } 461 462 if (!req) { 463 VERBOSE("received reply with mid %d but no request!\n", 464 WVAL(server->header, smb_mid)); 465 server->rstate = SMB_RECV_DROP; 466 } 467 468 return req; 469} 470 471/* 472 * Called when we have read the smb header and believe this is a response. 473 */ 474static int smb_init_request(struct smb_sb_info *server, struct smb_request *req) 475{ 476 int hdrlen, wct; 477 478 memcpy(req->rq_header, server->header, SMB_HEADER_LEN); 479 480 wct = *(req->rq_header + smb_wct); 481 if (wct > 20) { 482 PARANOIA("wct too large, %d > 20\n", wct); 483 server->rstate = SMB_RECV_DROP; 484 return 0; 485 } 486 487 req->rq_resp_wct = wct; 488 hdrlen = SMB_HEADER_LEN + wct*2 + 2; 489 VERBOSE("header length: %d smb_wct: %2d\n", hdrlen, wct); 490 491 req->rq_bytes_recvd = SMB_HEADER_LEN; 492 req->rq_rlen = hdrlen; 493 req->rq_iov[0].iov_base = req->rq_header; 494 req->rq_iov[0].iov_len = hdrlen; 495 req->rq_iovlen = 1; 496 server->rstate = SMB_RECV_PARAM; 497 498#ifdef SMB_DEBUG_PACKET_SIZE 499 add_recv_stats(smb_len(server->header)); 500#endif 501 return 0; 502} 503 504/* 505 * Reads the SMB parameters 506 */ 507static int smb_recv_param(struct smb_sb_info *server, struct smb_request *req) 508{ 509 int result; 510 511 result = smb_receive(server, req); 512 if (result < 0) 513 return result; 514 if (req->rq_bytes_recvd < req->rq_rlen) 515 return 0; 516 517 VERBOSE("result: %d smb_bcc: %04x\n", result, 518 WVAL(req->rq_header, SMB_HEADER_LEN + 519 (*(req->rq_header + smb_wct) * 2))); 520 521 result = 0; 522 req->rq_iov[0].iov_base = NULL; 523 req->rq_rlen = 0; 524 if (req->rq_callback) 525 req->rq_callback(req); 526 else if (req->rq_setup_read) 527 result = req->rq_setup_read(req); 528 if (result < 0) { 529 server->rstate = SMB_RECV_DROP; 530 return result; 531 } 532 533 server->rstate = req->rq_rlen > 0 ? SMB_RECV_DATA : SMB_RECV_END; 534 535 req->rq_bytes_recvd = 0; // recvd out of the iov 536 537 VERBOSE("rlen: %d\n", req->rq_rlen); 538 if (req->rq_rlen < 0) { 539 PARANOIA("Parameters read beyond end of packet!\n"); 540 server->rstate = SMB_RECV_END; 541 return -EIO; 542 } 543 return 0; 544} 545 546/* 547 * Reads the SMB data 548 */ 549static int smb_recv_data(struct smb_sb_info *server, struct smb_request *req) 550{ 551 int result; 552 553 result = smb_receive(server, req); 554 if (result < 0) 555 goto out; 556 if (req->rq_bytes_recvd < req->rq_rlen) 557 goto out; 558 server->rstate = SMB_RECV_END; 559out: 560 VERBOSE("result: %d\n", result); 561 return result; 562} 563 564/* 565 * Receive a transaction2 response 566 * Return: 0 if the response has been fully read 567 * 1 if there are further "fragments" to read 568 * <0 if there is an error 569 */ 570static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req) 571{ 572 unsigned char *inbuf; 573 unsigned int parm_disp, parm_offset, parm_count, parm_tot; 574 unsigned int data_disp, data_offset, data_count, data_tot; 575 int hdrlen = SMB_HEADER_LEN + req->rq_resp_wct*2 - 2; 576 577 VERBOSE("handling trans2\n"); 578 579 inbuf = req->rq_header; 580 data_tot = WVAL(inbuf, smb_tdrcnt); 581 parm_tot = WVAL(inbuf, smb_tprcnt); 582 parm_disp = WVAL(inbuf, smb_prdisp); 583 parm_offset = WVAL(inbuf, smb_proff); 584 parm_count = WVAL(inbuf, smb_prcnt); 585 data_disp = WVAL(inbuf, smb_drdisp); 586 data_offset = WVAL(inbuf, smb_droff); 587 data_count = WVAL(inbuf, smb_drcnt); 588 589 /* Modify offset for the split header/buffer we use */ 590 if (data_count || data_offset) { 591 if (unlikely(data_offset < hdrlen)) 592 goto out_bad_data; 593 else 594 data_offset -= hdrlen; 595 } 596 if (parm_count || parm_offset) { 597 if (unlikely(parm_offset < hdrlen)) 598 goto out_bad_parm; 599 else 600 parm_offset -= hdrlen; 601 } 602 603 if (parm_count == parm_tot && data_count == data_tot) { 604 /* 605 * This packet has all the trans2 data. 606 * 607 * We setup the request so that this will be the common 608 * case. It may be a server error to not return a 609 * response that fits. 610 */ 611 VERBOSE("single trans2 response " 612 "dcnt=%u, pcnt=%u, doff=%u, poff=%u\n", 613 data_count, parm_count, 614 data_offset, parm_offset); 615 req->rq_ldata = data_count; 616 req->rq_lparm = parm_count; 617 req->rq_data = req->rq_buffer + data_offset; 618 req->rq_parm = req->rq_buffer + parm_offset; 619 if (unlikely(parm_offset + parm_count > req->rq_rlen)) 620 goto out_bad_parm; 621 if (unlikely(data_offset + data_count > req->rq_rlen)) 622 goto out_bad_data; 623 return 0; 624 } 625 626 VERBOSE("multi trans2 response " 627 "frag=%d, dcnt=%u, pcnt=%u, doff=%u, poff=%u\n", 628 req->rq_fragment, 629 data_count, parm_count, 630 data_offset, parm_offset); 631 632 if (!req->rq_fragment) { 633 int buf_len; 634 635 /* We got the first trans2 fragment */ 636 req->rq_fragment = 1; 637 req->rq_total_data = data_tot; 638 req->rq_total_parm = parm_tot; 639 req->rq_ldata = 0; 640 req->rq_lparm = 0; 641 642 buf_len = data_tot + parm_tot; 643 if (buf_len > SMB_MAX_PACKET_SIZE) 644 goto out_too_long; 645 646 req->rq_trans2bufsize = buf_len; 647 req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS); 648 if (!req->rq_trans2buffer) 649 goto out_no_mem; 650 651 req->rq_parm = req->rq_trans2buffer; 652 req->rq_data = req->rq_trans2buffer + parm_tot; 653 } else if (unlikely(req->rq_total_data < data_tot || 654 req->rq_total_parm < parm_tot)) 655 goto out_data_grew; 656 657 if (unlikely(parm_disp + parm_count > req->rq_total_parm || 658 parm_offset + parm_count > req->rq_rlen)) 659 goto out_bad_parm; 660 if (unlikely(data_disp + data_count > req->rq_total_data || 661 data_offset + data_count > req->rq_rlen)) 662 goto out_bad_data; 663 664 inbuf = req->rq_buffer; 665 memcpy(req->rq_parm + parm_disp, inbuf + parm_offset, parm_count); 666 memcpy(req->rq_data + data_disp, inbuf + data_offset, data_count); 667 668 req->rq_ldata += data_count; 669 req->rq_lparm += parm_count; 670 671 /* 672 * Check whether we've received all of the data. Note that 673 * we use the packet totals -- total lengths might shrink! 674 */ 675 if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot) { 676 req->rq_ldata = data_tot; 677 req->rq_lparm = parm_tot; 678 return 0; 679 } 680 return 1; 681 682out_too_long: 683 printk(KERN_ERR "smb_trans2: data/param too long, data=%u, parm=%u\n", 684 data_tot, parm_tot); 685 goto out_EIO; 686out_no_mem: 687 printk(KERN_ERR "smb_trans2: couldn't allocate data area of %d bytes\n", 688 req->rq_trans2bufsize); 689 req->rq_errno = -ENOMEM; 690 goto out; 691out_data_grew: 692 printk(KERN_ERR "smb_trans2: data/params grew!\n"); 693 goto out_EIO; 694out_bad_parm: 695 printk(KERN_ERR "smb_trans2: invalid parms, disp=%u, cnt=%u, tot=%u, ofs=%u\n", 696 parm_disp, parm_count, parm_tot, parm_offset); 697 goto out_EIO; 698out_bad_data: 699 printk(KERN_ERR "smb_trans2: invalid data, disp=%u, cnt=%u, tot=%u, ofs=%u\n", 700 data_disp, data_count, data_tot, data_offset); 701out_EIO: 702 req->rq_errno = -EIO; 703out: 704 return req->rq_errno; 705} 706 707/* 708 * State machine for receiving responses. We handle the fact that we can't 709 * read the full response in one try by having states telling us how much we 710 * have read. 711 * 712 * Must be called with the server lock held (only called from smbiod). 713 * 714 * Return: <0 on error 715 */ 716int smb_request_recv(struct smb_sb_info *server) 717{ 718 struct smb_request *req = NULL; 719 int result = 0; 720 721 if (smb_recv_available(server) <= 0) 722 return 0; 723 724 VERBOSE("state: %d\n", server->rstate); 725 switch (server->rstate) { 726 case SMB_RECV_DROP: 727 result = smb_receive_drop(server); 728 if (result < 0) 729 break; 730 if (server->rstate == SMB_RECV_DROP) 731 break; 732 server->rstate = SMB_RECV_START; 733 /* fallthrough */ 734 case SMB_RECV_START: 735 server->smb_read = 0; 736 server->rstate = SMB_RECV_HEADER; 737 /* fallthrough */ 738 case SMB_RECV_HEADER: 739 result = smb_receive_header(server); 740 if (result < 0) 741 break; 742 if (server->rstate == SMB_RECV_HEADER) 743 break; 744 if (! (*(server->header + smb_flg) & SMB_FLAGS_REPLY) ) { 745 server->rstate = SMB_RECV_REQUEST; 746 break; 747 } 748 if (server->rstate != SMB_RECV_HCOMPLETE) 749 break; 750 /* fallthrough */ 751 case SMB_RECV_HCOMPLETE: 752 req = find_request(server, WVAL(server->header, smb_mid)); 753 if (!req) 754 break; 755 smb_init_request(server, req); 756 req->rq_rcls = *(req->rq_header + smb_rcls); 757 req->rq_err = WVAL(req->rq_header, smb_err); 758 if (server->rstate != SMB_RECV_PARAM) 759 break; 760 /* fallthrough */ 761 case SMB_RECV_PARAM: 762 if (!req) 763 req = find_request(server,WVAL(server->header,smb_mid)); 764 if (!req) 765 break; 766 result = smb_recv_param(server, req); 767 if (result < 0) 768 break; 769 if (server->rstate != SMB_RECV_DATA) 770 break; 771 /* fallthrough */ 772 case SMB_RECV_DATA: 773 if (!req) 774 req = find_request(server,WVAL(server->header,smb_mid)); 775 if (!req) 776 break; 777 result = smb_recv_data(server, req); 778 if (result < 0) 779 break; 780 break; 781 782 /* We should never be called with any of these states */ 783 case SMB_RECV_END: 784 case SMB_RECV_REQUEST: 785 BUG(); 786 } 787 788 if (result < 0) { 789 /* We saw an error */ 790 return result; 791 } 792 793 if (server->rstate != SMB_RECV_END) 794 return 0; 795 796 result = 0; 797 if (req->rq_trans2_command && req->rq_rcls == SUCCESS) 798 result = smb_recv_trans2(server, req); 799 800 /* 801 * Response completely read. Drop any extra bytes sent by the server. 802 * (Yes, servers sometimes add extra bytes to responses) 803 */ 804 VERBOSE("smb_len: %d smb_read: %d\n", 805 server->smb_len, server->smb_read); 806 if (server->smb_read < server->smb_len) 807 smb_receive_drop(server); 808 809 server->rstate = SMB_RECV_START; 810 811 if (!result) { 812 list_del_init(&req->rq_queue); 813 req->rq_flags |= SMB_REQ_RECEIVED; 814 smb_rput(req); 815 wake_up_interruptible(&req->rq_wait); 816 } 817 return 0; 818}