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