• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/fs/smbfs/
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