diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 743 |
1 files changed, 513 insertions, 230 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 40470b9d5477..e568cc47a7f9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/connect.c | 2 | * fs/cifs/connect.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2002,2004 | 4 | * Copyright (C) International Business Machines Corp., 2002,2005 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/mempool.h> | 30 | #include <linux/mempool.h> |
31 | #include <linux/delay.h> | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
33 | #include "cifspdu.h" | 34 | #include "cifspdu.h" |
@@ -72,6 +73,7 @@ struct smb_vol { | |||
72 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 73 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
73 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 74 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
74 | unsigned direct_io:1; | 75 | unsigned direct_io:1; |
76 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ | ||
75 | unsigned int rsize; | 77 | unsigned int rsize; |
76 | unsigned int wsize; | 78 | unsigned int wsize; |
77 | unsigned int sockopt; | 79 | unsigned int sockopt; |
@@ -114,7 +116,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
114 | spin_unlock(&GlobalMid_Lock); | 116 | spin_unlock(&GlobalMid_Lock); |
115 | server->maxBuf = 0; | 117 | server->maxBuf = 0; |
116 | 118 | ||
117 | cFYI(1, ("Reconnecting tcp session ")); | 119 | cFYI(1, ("Reconnecting tcp session")); |
118 | 120 | ||
119 | /* before reconnecting the tcp session, mark the smb session (uid) | 121 | /* before reconnecting the tcp session, mark the smb session (uid) |
120 | and the tid bad so they are not used until reconnected */ | 122 | and the tid bad so they are not used until reconnected */ |
@@ -155,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
155 | qhead); | 157 | qhead); |
156 | if(mid_entry) { | 158 | if(mid_entry) { |
157 | if(mid_entry->midState == MID_REQUEST_SUBMITTED) { | 159 | if(mid_entry->midState == MID_REQUEST_SUBMITTED) { |
158 | /* Mark other intransit requests as needing retry so | 160 | /* Mark other intransit requests as needing |
159 | we do not immediately mark the session bad again | 161 | retry so we do not immediately mark the |
160 | (ie after we reconnect below) as they timeout too */ | 162 | session bad again (ie after we reconnect |
163 | below) as they timeout too */ | ||
161 | mid_entry->midState = MID_RETRY_NEEDED; | 164 | mid_entry->midState = MID_RETRY_NEEDED; |
162 | } | 165 | } |
163 | } | 166 | } |
@@ -175,14 +178,14 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
175 | server->workstation_RFC1001_name); | 178 | server->workstation_RFC1001_name); |
176 | } | 179 | } |
177 | if(rc) { | 180 | if(rc) { |
178 | set_current_state(TASK_INTERRUPTIBLE); | 181 | msleep(3000); |
179 | schedule_timeout(3 * HZ); | ||
180 | } else { | 182 | } else { |
181 | atomic_inc(&tcpSesReconnectCount); | 183 | atomic_inc(&tcpSesReconnectCount); |
182 | spin_lock(&GlobalMid_Lock); | 184 | spin_lock(&GlobalMid_Lock); |
183 | if(server->tcpStatus != CifsExiting) | 185 | if(server->tcpStatus != CifsExiting) |
184 | server->tcpStatus = CifsGood; | 186 | server->tcpStatus = CifsGood; |
185 | spin_unlock(&GlobalMid_Lock); | 187 | server->sequence_number = 0; |
188 | spin_unlock(&GlobalMid_Lock); | ||
186 | /* atomic_set(&server->inFlight,0);*/ | 189 | /* atomic_set(&server->inFlight,0);*/ |
187 | wake_up(&server->response_q); | 190 | wake_up(&server->response_q); |
188 | } | 191 | } |
@@ -190,12 +193,129 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
190 | return rc; | 193 | return rc; |
191 | } | 194 | } |
192 | 195 | ||
196 | /* | ||
197 | return codes: | ||
198 | 0 not a transact2, or all data present | ||
199 | >0 transact2 with that much data missing | ||
200 | -EINVAL = invalid transact2 | ||
201 | |||
202 | */ | ||
203 | static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize) | ||
204 | { | ||
205 | struct smb_t2_rsp * pSMBt; | ||
206 | int total_data_size; | ||
207 | int data_in_this_rsp; | ||
208 | int remaining; | ||
209 | |||
210 | if(pSMB->Command != SMB_COM_TRANSACTION2) | ||
211 | return 0; | ||
212 | |||
213 | /* check for plausible wct, bcc and t2 data and parm sizes */ | ||
214 | /* check for parm and data offset going beyond end of smb */ | ||
215 | if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ | ||
216 | cFYI(1,("invalid transact2 word count")); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | pSMBt = (struct smb_t2_rsp *)pSMB; | ||
221 | |||
222 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | ||
223 | data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount); | ||
224 | |||
225 | remaining = total_data_size - data_in_this_rsp; | ||
226 | |||
227 | if(remaining == 0) | ||
228 | return 0; | ||
229 | else if(remaining < 0) { | ||
230 | cFYI(1,("total data %d smaller than data in frame %d", | ||
231 | total_data_size, data_in_this_rsp)); | ||
232 | return -EINVAL; | ||
233 | } else { | ||
234 | cFYI(1,("missing %d bytes from transact2, check next response", | ||
235 | remaining)); | ||
236 | if(total_data_size > maxBufSize) { | ||
237 | cERROR(1,("TotalDataSize %d is over maximum buffer %d", | ||
238 | total_data_size,maxBufSize)); | ||
239 | return -EINVAL; | ||
240 | } | ||
241 | return remaining; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) | ||
246 | { | ||
247 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; | ||
248 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | ||
249 | int total_data_size; | ||
250 | int total_in_buf; | ||
251 | int remaining; | ||
252 | int total_in_buf2; | ||
253 | char * data_area_of_target; | ||
254 | char * data_area_of_buf2; | ||
255 | __u16 byte_count; | ||
256 | |||
257 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | ||
258 | |||
259 | if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) { | ||
260 | cFYI(1,("total data sizes of primary and secondary t2 differ")); | ||
261 | } | ||
262 | |||
263 | total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount); | ||
264 | |||
265 | remaining = total_data_size - total_in_buf; | ||
266 | |||
267 | if(remaining < 0) | ||
268 | return -EINVAL; | ||
269 | |||
270 | if(remaining == 0) /* nothing to do, ignore */ | ||
271 | return 0; | ||
272 | |||
273 | total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount); | ||
274 | if(remaining < total_in_buf2) { | ||
275 | cFYI(1,("transact2 2nd response contains too much data")); | ||
276 | } | ||
277 | |||
278 | /* find end of first SMB data area */ | ||
279 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + | ||
280 | le16_to_cpu(pSMBt->t2_rsp.DataOffset); | ||
281 | /* validate target area */ | ||
282 | |||
283 | data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol + | ||
284 | le16_to_cpu(pSMB2->t2_rsp.DataOffset); | ||
285 | |||
286 | data_area_of_target += total_in_buf; | ||
287 | |||
288 | /* copy second buffer into end of first buffer */ | ||
289 | memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2); | ||
290 | total_in_buf += total_in_buf2; | ||
291 | pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); | ||
292 | byte_count = le16_to_cpu(BCC_LE(pTargetSMB)); | ||
293 | byte_count += total_in_buf2; | ||
294 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | ||
295 | |||
296 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | ||
297 | byte_count += total_in_buf2; | ||
298 | |||
299 | /* BB also add check that we are not beyond maximum buffer size */ | ||
300 | |||
301 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | ||
302 | |||
303 | if(remaining == total_in_buf2) { | ||
304 | cFYI(1,("found the last secondary response")); | ||
305 | return 0; /* we are done */ | ||
306 | } else /* more responses to go */ | ||
307 | return 1; | ||
308 | |||
309 | } | ||
310 | |||
193 | static int | 311 | static int |
194 | cifs_demultiplex_thread(struct TCP_Server_Info *server) | 312 | cifs_demultiplex_thread(struct TCP_Server_Info *server) |
195 | { | 313 | { |
196 | int length; | 314 | int length; |
197 | unsigned int pdu_length, total_read; | 315 | unsigned int pdu_length, total_read; |
198 | struct smb_hdr *smb_buffer = NULL; | 316 | struct smb_hdr *smb_buffer = NULL; |
317 | struct smb_hdr *bigbuf = NULL; | ||
318 | struct smb_hdr *smallbuf = NULL; | ||
199 | struct msghdr smb_msg; | 319 | struct msghdr smb_msg; |
200 | struct kvec iov; | 320 | struct kvec iov; |
201 | struct socket *csocket = server->ssocket; | 321 | struct socket *csocket = server->ssocket; |
@@ -204,6 +324,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
204 | struct task_struct *task_to_wake = NULL; | 324 | struct task_struct *task_to_wake = NULL; |
205 | struct mid_q_entry *mid_entry; | 325 | struct mid_q_entry *mid_entry; |
206 | char *temp; | 326 | char *temp; |
327 | int isLargeBuf = FALSE; | ||
328 | int isMultiRsp; | ||
329 | int reconnect; | ||
207 | 330 | ||
208 | daemonize("cifsd"); | 331 | daemonize("cifsd"); |
209 | allow_signal(SIGKILL); | 332 | allow_signal(SIGKILL); |
@@ -221,17 +344,34 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
221 | } | 344 | } |
222 | 345 | ||
223 | while (server->tcpStatus != CifsExiting) { | 346 | while (server->tcpStatus != CifsExiting) { |
224 | if (smb_buffer == NULL) | 347 | if (bigbuf == NULL) { |
225 | smb_buffer = cifs_buf_get(); | 348 | bigbuf = cifs_buf_get(); |
226 | else | 349 | if(bigbuf == NULL) { |
227 | memset(smb_buffer, 0, sizeof (struct smb_hdr)); | 350 | cERROR(1,("No memory for large SMB response")); |
228 | 351 | msleep(3000); | |
229 | if (smb_buffer == NULL) { | 352 | /* retry will check if exiting */ |
230 | cERROR(1,("Can not get memory for SMB response")); | 353 | continue; |
231 | set_current_state(TASK_INTERRUPTIBLE); | 354 | } |
232 | schedule_timeout(HZ * 3); /* give system time to free memory */ | 355 | } else if(isLargeBuf) { |
233 | continue; | 356 | /* we are reusing a dirtry large buf, clear its start */ |
357 | memset(bigbuf, 0, sizeof (struct smb_hdr)); | ||
234 | } | 358 | } |
359 | |||
360 | if (smallbuf == NULL) { | ||
361 | smallbuf = cifs_small_buf_get(); | ||
362 | if(smallbuf == NULL) { | ||
363 | cERROR(1,("No memory for SMB response")); | ||
364 | msleep(1000); | ||
365 | /* retry will check if exiting */ | ||
366 | continue; | ||
367 | } | ||
368 | /* beginning of smb buffer is cleared in our buf_get */ | ||
369 | } else /* if existing small buf clear beginning */ | ||
370 | memset(smallbuf, 0, sizeof (struct smb_hdr)); | ||
371 | |||
372 | isLargeBuf = FALSE; | ||
373 | isMultiRsp = FALSE; | ||
374 | smb_buffer = smallbuf; | ||
235 | iov.iov_base = smb_buffer; | 375 | iov.iov_base = smb_buffer; |
236 | iov.iov_len = 4; | 376 | iov.iov_len = 4; |
237 | smb_msg.msg_control = NULL; | 377 | smb_msg.msg_control = NULL; |
@@ -243,176 +383,257 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
243 | if(server->tcpStatus == CifsExiting) { | 383 | if(server->tcpStatus == CifsExiting) { |
244 | break; | 384 | break; |
245 | } else if (server->tcpStatus == CifsNeedReconnect) { | 385 | } else if (server->tcpStatus == CifsNeedReconnect) { |
246 | cFYI(1,("Reconnecting after server stopped responding")); | 386 | cFYI(1,("Reconnect after server stopped responding")); |
247 | cifs_reconnect(server); | 387 | cifs_reconnect(server); |
248 | cFYI(1,("call to reconnect done")); | 388 | cFYI(1,("call to reconnect done")); |
249 | csocket = server->ssocket; | 389 | csocket = server->ssocket; |
250 | continue; | 390 | continue; |
251 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { | 391 | } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { |
252 | set_current_state(TASK_INTERRUPTIBLE); | 392 | msleep(1); /* minimum sleep to prevent looping |
253 | schedule_timeout(1); /* minimum sleep to prevent looping | ||
254 | allowing socket to clear and app threads to set | 393 | allowing socket to clear and app threads to set |
255 | tcpStatus CifsNeedReconnect if server hung */ | 394 | tcpStatus CifsNeedReconnect if server hung */ |
256 | continue; | 395 | continue; |
257 | } else if (length <= 0) { | 396 | } else if (length <= 0) { |
258 | if(server->tcpStatus == CifsNew) { | 397 | if(server->tcpStatus == CifsNew) { |
259 | cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); | 398 | cFYI(1,("tcp session abend after SMBnegprot")); |
260 | /* some servers kill tcp session rather than returning | 399 | /* some servers kill the TCP session rather than |
261 | smb negprot error in which case reconnecting here is | 400 | returning an SMB negprot error, in which |
262 | not going to help - return error to mount */ | 401 | case reconnecting here is not going to help, |
402 | and so simply return error to mount */ | ||
263 | break; | 403 | break; |
264 | } | 404 | } |
265 | if(length == -EINTR) { | 405 | if(length == -EINTR) { |
266 | cFYI(1,("cifsd thread killed")); | 406 | cFYI(1,("cifsd thread killed")); |
267 | break; | 407 | break; |
268 | } | 408 | } |
269 | cFYI(1,("Reconnecting after unexpected peek error %d",length)); | 409 | cFYI(1,("Reconnect after unexpected peek error %d", |
410 | length)); | ||
270 | cifs_reconnect(server); | 411 | cifs_reconnect(server); |
271 | csocket = server->ssocket; | 412 | csocket = server->ssocket; |
272 | wake_up(&server->response_q); | 413 | wake_up(&server->response_q); |
273 | continue; | 414 | continue; |
274 | } else if (length > 3) { | 415 | } else if (length < 4) { |
275 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 416 | cFYI(1, |
276 | /* Only read pdu_length after below checks for too short (due | 417 | ("Frame under four bytes received (%d bytes long)", |
277 | to e.g. int overflow) and too long ie beyond end of buf */ | 418 | length)); |
278 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); | 419 | cifs_reconnect(server); |
279 | 420 | csocket = server->ssocket; | |
280 | temp = (char *) smb_buffer; | 421 | wake_up(&server->response_q); |
281 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | 422 | continue; |
282 | cFYI(0,("Received 4 byte keep alive packet")); | 423 | } |
283 | } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { | ||
284 | cFYI(1,("Good RFC 1002 session rsp")); | ||
285 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | ||
286 | /* we get this from Windows 98 instead of error on SMB negprot response */ | ||
287 | cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); | ||
288 | if(server->tcpStatus == CifsNew) { | ||
289 | /* if nack on negprot (rather than | ||
290 | ret of smb negprot error) reconnecting | ||
291 | not going to help, ret error to mount */ | ||
292 | break; | ||
293 | } else { | ||
294 | /* give server a second to | ||
295 | clean up before reconnect attempt */ | ||
296 | set_current_state(TASK_INTERRUPTIBLE); | ||
297 | schedule_timeout(HZ); | ||
298 | /* always try 445 first on reconnect | ||
299 | since we get NACK on some if we ever | ||
300 | connected to port 139 (the NACK is | ||
301 | since we do not begin with RFC1001 | ||
302 | session initialize frame) */ | ||
303 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); | ||
304 | cifs_reconnect(server); | ||
305 | csocket = server->ssocket; | ||
306 | wake_up(&server->response_q); | ||
307 | continue; | ||
308 | } | ||
309 | } else if (temp[0] != (char) 0) { | ||
310 | cERROR(1,("Unknown RFC 1002 frame")); | ||
311 | cifs_dump_mem(" Received Data: ", temp, length); | ||
312 | cifs_reconnect(server); | ||
313 | csocket = server->ssocket; | ||
314 | continue; | ||
315 | } else { | ||
316 | if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | ||
317 | || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | ||
318 | cERROR(1, | ||
319 | ("Invalid size SMB length %d and pdu_length %d", | ||
320 | length, pdu_length+4)); | ||
321 | cifs_reconnect(server); | ||
322 | csocket = server->ssocket; | ||
323 | wake_up(&server->response_q); | ||
324 | continue; | ||
325 | } else { /* length ok */ | ||
326 | length = 0; | ||
327 | iov.iov_base = 4 + (char *)smb_buffer; | ||
328 | iov.iov_len = pdu_length; | ||
329 | for (total_read = 0; | ||
330 | total_read < pdu_length; | ||
331 | total_read += length) { | ||
332 | length = kernel_recvmsg(csocket, &smb_msg, | ||
333 | &iov, 1, | ||
334 | pdu_length - total_read, 0); | ||
335 | if (length == 0) { | ||
336 | cERROR(1, | ||
337 | ("Zero length receive when expecting %d ", | ||
338 | pdu_length - total_read)); | ||
339 | cifs_reconnect(server); | ||
340 | csocket = server->ssocket; | ||
341 | wake_up(&server->response_q); | ||
342 | continue; | ||
343 | } | ||
344 | } | ||
345 | length += 4; /* account for rfc1002 hdr */ | ||
346 | } | ||
347 | 424 | ||
348 | dump_smb(smb_buffer, length); | 425 | /* the right amount was read from socket - 4 bytes */ |
349 | if (checkSMB | ||
350 | (smb_buffer, smb_buffer->Mid, total_read+4)) { | ||
351 | cERROR(1, ("Bad SMB Received ")); | ||
352 | continue; | ||
353 | } | ||
354 | 426 | ||
355 | task_to_wake = NULL; | 427 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
356 | spin_lock(&GlobalMid_Lock); | 428 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); |
357 | list_for_each(tmp, &server->pending_mid_q) { | ||
358 | mid_entry = list_entry(tmp, struct | ||
359 | mid_q_entry, | ||
360 | qhead); | ||
361 | 429 | ||
362 | if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) { | 430 | temp = (char *) smb_buffer; |
363 | cFYI(1, | 431 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { |
364 | (" Mid 0x%x matched - waking up ",mid_entry->mid)); | 432 | continue; |
365 | task_to_wake = mid_entry->tsk; | 433 | } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { |
366 | mid_entry->resp_buf = | 434 | cFYI(1,("Good RFC 1002 session rsp")); |
367 | smb_buffer; | 435 | continue; |
368 | mid_entry->midState = | 436 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
369 | MID_RESPONSE_RECEIVED; | 437 | /* we get this from Windows 98 instead of |
370 | } | 438 | an error on SMB negprot response */ |
371 | } | 439 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", |
372 | spin_unlock(&GlobalMid_Lock); | 440 | temp[4])); |
373 | if (task_to_wake) { | 441 | if(server->tcpStatus == CifsNew) { |
374 | smb_buffer = NULL; /* will be freed by users thread after he is done */ | 442 | /* if nack on negprot (rather than |
375 | wake_up_process(task_to_wake); | 443 | ret of smb negprot error) reconnecting |
376 | } else if (is_valid_oplock_break(smb_buffer) == FALSE) { | 444 | not going to help, ret error to mount */ |
377 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 445 | break; |
378 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | 446 | } else { |
379 | } | 447 | /* give server a second to |
448 | clean up before reconnect attempt */ | ||
449 | msleep(1000); | ||
450 | /* always try 445 first on reconnect | ||
451 | since we get NACK on some if we ever | ||
452 | connected to port 139 (the NACK is | ||
453 | since we do not begin with RFC1001 | ||
454 | session initialize frame) */ | ||
455 | server->addr.sockAddr.sin_port = | ||
456 | htons(CIFS_PORT); | ||
457 | cifs_reconnect(server); | ||
458 | csocket = server->ssocket; | ||
459 | wake_up(&server->response_q); | ||
460 | continue; | ||
380 | } | 461 | } |
381 | } else { | 462 | } else if (temp[0] != (char) 0) { |
382 | cFYI(1, | 463 | cERROR(1,("Unknown RFC 1002 frame")); |
383 | ("Frame less than four bytes received %d bytes long.", | 464 | cifs_dump_mem(" Received Data: ", temp, length); |
384 | length)); | 465 | cifs_reconnect(server); |
466 | csocket = server->ssocket; | ||
467 | continue; | ||
468 | } | ||
469 | |||
470 | /* else we have an SMB response */ | ||
471 | if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | ||
472 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | ||
473 | cERROR(1, ("Invalid size SMB length %d pdu_length %d", | ||
474 | length, pdu_length+4)); | ||
385 | cifs_reconnect(server); | 475 | cifs_reconnect(server); |
386 | csocket = server->ssocket; | 476 | csocket = server->ssocket; |
387 | wake_up(&server->response_q); | 477 | wake_up(&server->response_q); |
388 | continue; | 478 | continue; |
479 | } | ||
480 | |||
481 | /* else length ok */ | ||
482 | reconnect = 0; | ||
483 | |||
484 | if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { | ||
485 | isLargeBuf = TRUE; | ||
486 | memcpy(bigbuf, smallbuf, 4); | ||
487 | smb_buffer = bigbuf; | ||
389 | } | 488 | } |
390 | } | 489 | length = 0; |
490 | iov.iov_base = 4 + (char *)smb_buffer; | ||
491 | iov.iov_len = pdu_length; | ||
492 | for (total_read = 0; total_read < pdu_length; | ||
493 | total_read += length) { | ||
494 | length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, | ||
495 | pdu_length - total_read, 0); | ||
496 | if((server->tcpStatus == CifsExiting) || | ||
497 | (length == -EINTR)) { | ||
498 | /* then will exit */ | ||
499 | reconnect = 2; | ||
500 | break; | ||
501 | } else if (server->tcpStatus == CifsNeedReconnect) { | ||
502 | cifs_reconnect(server); | ||
503 | csocket = server->ssocket; | ||
504 | /* Reconnect wakes up rspns q */ | ||
505 | /* Now we will reread sock */ | ||
506 | reconnect = 1; | ||
507 | break; | ||
508 | } else if ((length == -ERESTARTSYS) || | ||
509 | (length == -EAGAIN)) { | ||
510 | msleep(1); /* minimum sleep to prevent looping, | ||
511 | allowing socket to clear and app | ||
512 | threads to set tcpStatus | ||
513 | CifsNeedReconnect if server hung*/ | ||
514 | continue; | ||
515 | } else if (length <= 0) { | ||
516 | cERROR(1,("Received no data, expecting %d", | ||
517 | pdu_length - total_read)); | ||
518 | cifs_reconnect(server); | ||
519 | csocket = server->ssocket; | ||
520 | reconnect = 1; | ||
521 | break; | ||
522 | } | ||
523 | } | ||
524 | if(reconnect == 2) | ||
525 | break; | ||
526 | else if(reconnect == 1) | ||
527 | continue; | ||
528 | |||
529 | length += 4; /* account for rfc1002 hdr */ | ||
530 | |||
531 | |||
532 | dump_smb(smb_buffer, length); | ||
533 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { | ||
534 | cERROR(1, ("Bad SMB Received ")); | ||
535 | continue; | ||
536 | } | ||
537 | |||
538 | |||
539 | task_to_wake = NULL; | ||
540 | spin_lock(&GlobalMid_Lock); | ||
541 | list_for_each(tmp, &server->pending_mid_q) { | ||
542 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | ||
543 | |||
544 | if ((mid_entry->mid == smb_buffer->Mid) && | ||
545 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | ||
546 | (mid_entry->command == smb_buffer->Command)) { | ||
547 | if(check2ndT2(smb_buffer,server->maxBuf) > 0) { | ||
548 | /* We have a multipart transact2 resp */ | ||
549 | isMultiRsp = TRUE; | ||
550 | if(mid_entry->resp_buf) { | ||
551 | /* merge response - fix up 1st*/ | ||
552 | if(coalesce_t2(smb_buffer, | ||
553 | mid_entry->resp_buf)) { | ||
554 | break; | ||
555 | } else { | ||
556 | /* all parts received */ | ||
557 | goto multi_t2_fnd; | ||
558 | } | ||
559 | } else { | ||
560 | if(!isLargeBuf) { | ||
561 | cERROR(1,("1st trans2 resp needs bigbuf")); | ||
562 | /* BB maybe we can fix this up, switch | ||
563 | to already allocated large buffer? */ | ||
564 | } else { | ||
565 | /* Have first buffer */ | ||
566 | mid_entry->resp_buf = | ||
567 | smb_buffer; | ||
568 | mid_entry->largeBuf = 1; | ||
569 | bigbuf = NULL; | ||
570 | } | ||
571 | } | ||
572 | break; | ||
573 | } | ||
574 | mid_entry->resp_buf = smb_buffer; | ||
575 | if(isLargeBuf) | ||
576 | mid_entry->largeBuf = 1; | ||
577 | else | ||
578 | mid_entry->largeBuf = 0; | ||
579 | multi_t2_fnd: | ||
580 | task_to_wake = mid_entry->tsk; | ||
581 | mid_entry->midState = MID_RESPONSE_RECEIVED; | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | spin_unlock(&GlobalMid_Lock); | ||
586 | if (task_to_wake) { | ||
587 | /* Was previous buf put in mpx struct for multi-rsp? */ | ||
588 | if(!isMultiRsp) { | ||
589 | /* smb buffer will be freed by user thread */ | ||
590 | if(isLargeBuf) { | ||
591 | bigbuf = NULL; | ||
592 | } else | ||
593 | smallbuf = NULL; | ||
594 | } | ||
595 | wake_up_process(task_to_wake); | ||
596 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) | ||
597 | && (isMultiRsp == FALSE)) { | ||
598 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | ||
599 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | ||
600 | } | ||
601 | } /* end while !EXITING */ | ||
602 | |||
391 | spin_lock(&GlobalMid_Lock); | 603 | spin_lock(&GlobalMid_Lock); |
392 | server->tcpStatus = CifsExiting; | 604 | server->tcpStatus = CifsExiting; |
393 | server->tsk = NULL; | 605 | server->tsk = NULL; |
394 | atomic_set(&server->inFlight, 0); | 606 | /* check if we have blocked requests that need to free */ |
607 | /* Note that cifs_max_pending is normally 50, but | ||
608 | can be set at module install time to as little as two */ | ||
609 | if(atomic_read(&server->inFlight) >= cifs_max_pending) | ||
610 | atomic_set(&server->inFlight, cifs_max_pending - 1); | ||
611 | /* We do not want to set the max_pending too low or we | ||
612 | could end up with the counter going negative */ | ||
395 | spin_unlock(&GlobalMid_Lock); | 613 | spin_unlock(&GlobalMid_Lock); |
396 | /* Although there should not be any requests blocked on | 614 | /* Although there should not be any requests blocked on |
397 | this queue it can not hurt to be paranoid and try to wake up requests | 615 | this queue it can not hurt to be paranoid and try to wake up requests |
398 | that may haven been blocked when more than 50 at time were on the wire | 616 | that may haven been blocked when more than 50 at time were on the wire |
399 | to the same server - they now will see the session is in exit state | 617 | to the same server - they now will see the session is in exit state |
400 | and get out of SendReceive. */ | 618 | and get out of SendReceive. */ |
401 | wake_up_all(&server->request_q); | 619 | wake_up_all(&server->request_q); |
402 | /* give those requests time to exit */ | 620 | /* give those requests time to exit */ |
403 | set_current_state(TASK_INTERRUPTIBLE); | 621 | msleep(125); |
404 | schedule_timeout(HZ/8); | 622 | |
405 | |||
406 | if(server->ssocket) { | 623 | if(server->ssocket) { |
407 | sock_release(csocket); | 624 | sock_release(csocket); |
408 | server->ssocket = NULL; | 625 | server->ssocket = NULL; |
409 | } | 626 | } |
410 | if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ | 627 | /* buffer usuallly freed in free_mid - need to free it here on exit */ |
411 | cifs_buf_release(smb_buffer); | 628 | if (bigbuf != NULL) |
629 | cifs_buf_release(bigbuf); | ||
630 | if (smallbuf != NULL) | ||
631 | cifs_small_buf_release(smallbuf); | ||
412 | 632 | ||
413 | read_lock(&GlobalSMBSeslock); | 633 | read_lock(&GlobalSMBSeslock); |
414 | if (list_empty(&server->pending_mid_q)) { | 634 | if (list_empty(&server->pending_mid_q)) { |
415 | /* loop through server session structures attached to this and mark them dead */ | 635 | /* loop through server session structures attached to this and |
636 | mark them dead */ | ||
416 | list_for_each(tmp, &GlobalSMBSessionList) { | 637 | list_for_each(tmp, &GlobalSMBSessionList) { |
417 | ses = | 638 | ses = |
418 | list_entry(tmp, struct cifsSesInfo, | 639 | list_entry(tmp, struct cifsSesInfo, |
@@ -424,12 +645,23 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
424 | } | 645 | } |
425 | read_unlock(&GlobalSMBSeslock); | 646 | read_unlock(&GlobalSMBSeslock); |
426 | } else { | 647 | } else { |
648 | /* although we can not zero the server struct pointer yet, | ||
649 | since there are active requests which may depnd on them, | ||
650 | mark the corresponding SMB sessions as exiting too */ | ||
651 | list_for_each(tmp, &GlobalSMBSessionList) { | ||
652 | ses = list_entry(tmp, struct cifsSesInfo, | ||
653 | cifsSessionList); | ||
654 | if (ses->server == server) { | ||
655 | ses->status = CifsExiting; | ||
656 | } | ||
657 | } | ||
658 | |||
427 | spin_lock(&GlobalMid_Lock); | 659 | spin_lock(&GlobalMid_Lock); |
428 | list_for_each(tmp, &server->pending_mid_q) { | 660 | list_for_each(tmp, &server->pending_mid_q) { |
429 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 661 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
430 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | 662 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { |
431 | cFYI(1, | 663 | cFYI(1, |
432 | (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); | 664 | ("Clearing Mid 0x%x - waking up ",mid_entry->mid)); |
433 | task_to_wake = mid_entry->tsk; | 665 | task_to_wake = mid_entry->tsk; |
434 | if(task_to_wake) { | 666 | if(task_to_wake) { |
435 | wake_up_process(task_to_wake); | 667 | wake_up_process(task_to_wake); |
@@ -438,47 +670,51 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
438 | } | 670 | } |
439 | spin_unlock(&GlobalMid_Lock); | 671 | spin_unlock(&GlobalMid_Lock); |
440 | read_unlock(&GlobalSMBSeslock); | 672 | read_unlock(&GlobalSMBSeslock); |
441 | set_current_state(TASK_INTERRUPTIBLE); | ||
442 | /* 1/8th of sec is more than enough time for them to exit */ | 673 | /* 1/8th of sec is more than enough time for them to exit */ |
443 | schedule_timeout(HZ/8); | 674 | msleep(125); |
444 | } | 675 | } |
445 | 676 | ||
446 | if (list_empty(&server->pending_mid_q)) { | 677 | if (list_empty(&server->pending_mid_q)) { |
447 | /* mpx threads have not exited yet give them | 678 | /* mpx threads have not exited yet give them |
448 | at least the smb send timeout time for long ops */ | 679 | at least the smb send timeout time for long ops */ |
680 | /* due to delays on oplock break requests, we need | ||
681 | to wait at least 45 seconds before giving up | ||
682 | on a request getting a response and going ahead | ||
683 | and killing cifsd */ | ||
449 | cFYI(1, ("Wait for exit from demultiplex thread")); | 684 | cFYI(1, ("Wait for exit from demultiplex thread")); |
450 | set_current_state(TASK_INTERRUPTIBLE); | 685 | msleep(46000); |
451 | schedule_timeout(46 * HZ); | ||
452 | /* if threads still have not exited they are probably never | 686 | /* if threads still have not exited they are probably never |
453 | coming home not much else we can do but free the memory */ | 687 | coming home not much else we can do but free the memory */ |
454 | } | 688 | } |
455 | kfree(server); | ||
456 | 689 | ||
457 | write_lock(&GlobalSMBSeslock); | 690 | write_lock(&GlobalSMBSeslock); |
458 | atomic_dec(&tcpSesAllocCount); | 691 | atomic_dec(&tcpSesAllocCount); |
459 | length = tcpSesAllocCount.counter; | 692 | length = tcpSesAllocCount.counter; |
693 | |||
694 | /* last chance to mark ses pointers invalid | ||
695 | if there are any pointing to this (e.g | ||
696 | if a crazy root user tried to kill cifsd | ||
697 | kernel thread explicitly this might happen) */ | ||
698 | list_for_each(tmp, &GlobalSMBSessionList) { | ||
699 | ses = list_entry(tmp, struct cifsSesInfo, | ||
700 | cifsSessionList); | ||
701 | if (ses->server == server) { | ||
702 | ses->server = NULL; | ||
703 | } | ||
704 | } | ||
460 | write_unlock(&GlobalSMBSeslock); | 705 | write_unlock(&GlobalSMBSeslock); |
706 | |||
707 | kfree(server); | ||
461 | if(length > 0) { | 708 | if(length > 0) { |
462 | mempool_resize(cifs_req_poolp, | 709 | mempool_resize(cifs_req_poolp, |
463 | length + cifs_min_rcv, | 710 | length + cifs_min_rcv, |
464 | GFP_KERNEL); | 711 | GFP_KERNEL); |
465 | } | 712 | } |
466 | 713 | ||
467 | set_current_state(TASK_INTERRUPTIBLE); | 714 | msleep(250); |
468 | schedule_timeout(HZ/4); | ||
469 | return 0; | 715 | return 0; |
470 | } | 716 | } |
471 | 717 | ||
472 | static void * | ||
473 | cifs_kcalloc(size_t size, unsigned int __nocast type) | ||
474 | { | ||
475 | void *addr; | ||
476 | addr = kmalloc(size, type); | ||
477 | if (addr) | ||
478 | memset(addr, 0, size); | ||
479 | return addr; | ||
480 | } | ||
481 | |||
482 | static int | 718 | static int |
483 | cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | 719 | cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) |
484 | { | 720 | { |
@@ -495,7 +731,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
495 | /* does not have to be a perfect mapping since the field is | 731 | /* does not have to be a perfect mapping since the field is |
496 | informational, only used for servers that do not support | 732 | informational, only used for servers that do not support |
497 | port 445 and it can be overridden at mount time */ | 733 | port 445 and it can be overridden at mount time */ |
498 | vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); | 734 | vol->source_rfc1001_name[i] = |
735 | toupper(system_utsname.nodename[i]); | ||
499 | } | 736 | } |
500 | vol->source_rfc1001_name[15] = 0; | 737 | vol->source_rfc1001_name[15] = 0; |
501 | 738 | ||
@@ -570,14 +807,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
570 | /* NB: password legally can have multiple commas and | 807 | /* NB: password legally can have multiple commas and |
571 | the only illegal character in a password is null */ | 808 | the only illegal character in a password is null */ |
572 | 809 | ||
573 | if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { | 810 | if ((value[temp_len] == 0) && |
811 | (value[temp_len+1] == separator[0])) { | ||
574 | /* reinsert comma */ | 812 | /* reinsert comma */ |
575 | value[temp_len] = separator[0]; | 813 | value[temp_len] = separator[0]; |
576 | temp_len+=2; /* move after the second comma */ | 814 | temp_len+=2; /* move after the second comma */ |
577 | while(value[temp_len] != 0) { | 815 | while(value[temp_len] != 0) { |
578 | if (value[temp_len] == separator[0]) { | 816 | if (value[temp_len] == separator[0]) { |
579 | if (value[temp_len+1] == separator[0]) { | 817 | if (value[temp_len+1] == |
580 | temp_len++; /* skip second comma */ | 818 | separator[0]) { |
819 | /* skip second comma */ | ||
820 | temp_len++; | ||
581 | } else { | 821 | } else { |
582 | /* single comma indicating start | 822 | /* single comma indicating start |
583 | of next parm */ | 823 | of next parm */ |
@@ -596,17 +836,26 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
596 | /* go from value to value + temp_len condensing | 836 | /* go from value to value + temp_len condensing |
597 | double commas to singles. Note that this ends up | 837 | double commas to singles. Note that this ends up |
598 | allocating a few bytes too many, which is ok */ | 838 | allocating a few bytes too many, which is ok */ |
599 | vol->password = cifs_kcalloc(temp_len, GFP_KERNEL); | 839 | vol->password = kcalloc(1, temp_len, GFP_KERNEL); |
840 | if(vol->password == NULL) { | ||
841 | printk("CIFS: no memory for pass\n"); | ||
842 | return 1; | ||
843 | } | ||
600 | for(i=0,j=0;i<temp_len;i++,j++) { | 844 | for(i=0,j=0;i<temp_len;i++,j++) { |
601 | vol->password[j] = value[i]; | 845 | vol->password[j] = value[i]; |
602 | if(value[i] == separator[0] && value[i+1] == separator[0]) { | 846 | if(value[i] == separator[0] |
847 | && value[i+1] == separator[0]) { | ||
603 | /* skip second comma */ | 848 | /* skip second comma */ |
604 | i++; | 849 | i++; |
605 | } | 850 | } |
606 | } | 851 | } |
607 | vol->password[j] = 0; | 852 | vol->password[j] = 0; |
608 | } else { | 853 | } else { |
609 | vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL); | 854 | vol->password = kcalloc(1, temp_len+1, GFP_KERNEL); |
855 | if(vol->password == NULL) { | ||
856 | printk("CIFS: no memory for pass\n"); | ||
857 | return 1; | ||
858 | } | ||
610 | strcpy(vol->password, value); | 859 | strcpy(vol->password, value); |
611 | } | 860 | } |
612 | } else if (strnicmp(data, "ip", 2) == 0) { | 861 | } else if (strnicmp(data, "ip", 2) == 0) { |
@@ -770,6 +1019,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
770 | vol->noperm = 0; | 1019 | vol->noperm = 0; |
771 | } else if (strnicmp(data, "noperm", 6) == 0) { | 1020 | } else if (strnicmp(data, "noperm", 6) == 0) { |
772 | vol->noperm = 1; | 1021 | vol->noperm = 1; |
1022 | } else if (strnicmp(data, "mapchars", 8) == 0) { | ||
1023 | vol->remap = 1; | ||
1024 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | ||
1025 | vol->remap = 0; | ||
773 | } else if (strnicmp(data, "setuids", 7) == 0) { | 1026 | } else if (strnicmp(data, "setuids", 7) == 0) { |
774 | vol->setuids = 1; | 1027 | vol->setuids = 1; |
775 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1028 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
@@ -918,14 +1171,15 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) | |||
918 | 1171 | ||
919 | int | 1172 | int |
920 | connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1173 | connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, |
921 | const char *old_path, const struct nls_table *nls_codepage) | 1174 | const char *old_path, const struct nls_table *nls_codepage, |
1175 | int remap) | ||
922 | { | 1176 | { |
923 | unsigned char *referrals = NULL; | 1177 | unsigned char *referrals = NULL; |
924 | unsigned int num_referrals; | 1178 | unsigned int num_referrals; |
925 | int rc = 0; | 1179 | int rc = 0; |
926 | 1180 | ||
927 | rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, | 1181 | rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, |
928 | &num_referrals, &referrals); | 1182 | &num_referrals, &referrals, remap); |
929 | 1183 | ||
930 | /* BB Add in code to: if valid refrl, if not ip address contact | 1184 | /* BB Add in code to: if valid refrl, if not ip address contact |
931 | the helper that resolves tcp names, mount to it, try to | 1185 | the helper that resolves tcp names, mount to it, try to |
@@ -940,7 +1194,8 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | |||
940 | int | 1194 | int |
941 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | 1195 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, |
942 | const char *old_path, const struct nls_table *nls_codepage, | 1196 | const char *old_path, const struct nls_table *nls_codepage, |
943 | unsigned int *pnum_referrals, unsigned char ** preferrals) | 1197 | unsigned int *pnum_referrals, |
1198 | unsigned char ** preferrals, int remap) | ||
944 | { | 1199 | { |
945 | char *temp_unc; | 1200 | char *temp_unc; |
946 | int rc = 0; | 1201 | int rc = 0; |
@@ -965,7 +1220,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, | |||
965 | } | 1220 | } |
966 | if (rc == 0) | 1221 | if (rc == 0) |
967 | rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, | 1222 | rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, |
968 | pnum_referrals, nls_codepage); | 1223 | pnum_referrals, nls_codepage, remap); |
969 | 1224 | ||
970 | return rc; | 1225 | return rc; |
971 | } | 1226 | } |
@@ -1062,7 +1317,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1062 | sessinit is sent but no second negprot */ | 1317 | sessinit is sent but no second negprot */ |
1063 | struct rfc1002_session_packet * ses_init_buf; | 1318 | struct rfc1002_session_packet * ses_init_buf; |
1064 | struct smb_hdr * smb_buf; | 1319 | struct smb_hdr * smb_buf; |
1065 | ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); | 1320 | ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); |
1066 | if(ses_init_buf) { | 1321 | if(ses_init_buf) { |
1067 | ses_init_buf->trailer.session_req.called_len = 32; | 1322 | ses_init_buf->trailer.session_req.called_len = 32; |
1068 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | 1323 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, |
@@ -1352,6 +1607,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1352 | } else | 1607 | } else |
1353 | rc = 0; | 1608 | rc = 0; |
1354 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1609 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
1610 | srvTcp->sequence_number = 0; | ||
1355 | } | 1611 | } |
1356 | } | 1612 | } |
1357 | 1613 | ||
@@ -1419,6 +1675,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1419 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; | 1675 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; |
1420 | if(volume_info.server_ino) | 1676 | if(volume_info.server_ino) |
1421 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; | 1677 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; |
1678 | if(volume_info.remap) | ||
1679 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
1422 | if(volume_info.no_xattr) | 1680 | if(volume_info.no_xattr) |
1423 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 1681 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
1424 | if(volume_info.direct_io) { | 1682 | if(volume_info.direct_io) { |
@@ -1447,11 +1705,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1447 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) | 1705 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) |
1448 | && (strchr(volume_info.UNC + 3, '/') == | 1706 | && (strchr(volume_info.UNC + 3, '/') == |
1449 | NULL)) { | 1707 | NULL)) { |
1450 | rc = connect_to_dfs_path(xid, | 1708 | rc = connect_to_dfs_path(xid, pSesInfo, |
1451 | pSesInfo, | 1709 | "", cifs_sb->local_nls, |
1452 | "", | 1710 | cifs_sb->mnt_cifs_flags & |
1453 | cifs_sb-> | 1711 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1454 | local_nls); | ||
1455 | if(volume_info.UNC) | 1712 | if(volume_info.UNC) |
1456 | kfree(volume_info.UNC); | 1713 | kfree(volume_info.UNC); |
1457 | FreeXid(xid); | 1714 | FreeXid(xid); |
@@ -1514,10 +1771,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1514 | tcon->ses = pSesInfo; | 1771 | tcon->ses = pSesInfo; |
1515 | 1772 | ||
1516 | /* do not care if following two calls succeed - informational only */ | 1773 | /* do not care if following two calls succeed - informational only */ |
1517 | CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); | 1774 | CIFSSMBQFSDeviceInfo(xid, tcon); |
1518 | CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); | 1775 | CIFSSMBQFSAttributeInfo(xid, tcon); |
1519 | if (tcon->ses->capabilities & CAP_UNIX) { | 1776 | if (tcon->ses->capabilities & CAP_UNIX) { |
1520 | if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) { | 1777 | if(!CIFSSMBQFSUnixInfo(xid, tcon)) { |
1521 | if(!volume_info.no_psx_acl) { | 1778 | if(!volume_info.no_psx_acl) { |
1522 | if(CIFS_UNIX_POSIX_ACL_CAP & | 1779 | if(CIFS_UNIX_POSIX_ACL_CAP & |
1523 | le64_to_cpu(tcon->fsUnixInfo.Capability)) | 1780 | le64_to_cpu(tcon->fsUnixInfo.Capability)) |
@@ -1707,7 +1964,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1707 | /* We look for obvious messed up bcc or strings in response so we do not go off | 1964 | /* We look for obvious messed up bcc or strings in response so we do not go off |
1708 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 1965 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
1709 | terminating last Unicode string in response */ | 1966 | terminating last Unicode string in response */ |
1710 | ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); | 1967 | ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL); |
1968 | if(ses->serverOS == NULL) | ||
1969 | goto sesssetup_nomem; | ||
1711 | cifs_strfromUCS_le(ses->serverOS, | 1970 | cifs_strfromUCS_le(ses->serverOS, |
1712 | (wchar_t *)bcc_ptr, len,nls_codepage); | 1971 | (wchar_t *)bcc_ptr, len,nls_codepage); |
1713 | bcc_ptr += 2 * (len + 1); | 1972 | bcc_ptr += 2 * (len + 1); |
@@ -1717,7 +1976,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1717 | if (remaining_words > 0) { | 1976 | if (remaining_words > 0) { |
1718 | len = UniStrnlen((wchar_t *)bcc_ptr, | 1977 | len = UniStrnlen((wchar_t *)bcc_ptr, |
1719 | remaining_words-1); | 1978 | remaining_words-1); |
1720 | ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL); | 1979 | ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL); |
1980 | if(ses->serverNOS == NULL) | ||
1981 | goto sesssetup_nomem; | ||
1721 | cifs_strfromUCS_le(ses->serverNOS, | 1982 | cifs_strfromUCS_le(ses->serverNOS, |
1722 | (wchar_t *)bcc_ptr,len,nls_codepage); | 1983 | (wchar_t *)bcc_ptr,len,nls_codepage); |
1723 | bcc_ptr += 2 * (len + 1); | 1984 | bcc_ptr += 2 * (len + 1); |
@@ -1730,10 +1991,12 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1730 | } | 1991 | } |
1731 | remaining_words -= len + 1; | 1992 | remaining_words -= len + 1; |
1732 | if (remaining_words > 0) { | 1993 | if (remaining_words > 0) { |
1733 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | 1994 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); |
1734 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ | 1995 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ |
1735 | ses->serverDomain = | 1996 | ses->serverDomain = |
1736 | cifs_kcalloc(2*(len+1),GFP_KERNEL); | 1997 | kcalloc(1, 2*(len+1),GFP_KERNEL); |
1998 | if(ses->serverDomain == NULL) | ||
1999 | goto sesssetup_nomem; | ||
1737 | cifs_strfromUCS_le(ses->serverDomain, | 2000 | cifs_strfromUCS_le(ses->serverDomain, |
1738 | (wchar_t *)bcc_ptr,len,nls_codepage); | 2001 | (wchar_t *)bcc_ptr,len,nls_codepage); |
1739 | bcc_ptr += 2 * (len + 1); | 2002 | bcc_ptr += 2 * (len + 1); |
@@ -1741,21 +2004,25 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1741 | ses->serverDomain[1+(2*len)] = 0; | 2004 | ses->serverDomain[1+(2*len)] = 0; |
1742 | } /* else no more room so create dummy domain string */ | 2005 | } /* else no more room so create dummy domain string */ |
1743 | else | 2006 | else |
1744 | ses->serverDomain = | 2007 | ses->serverDomain = |
1745 | cifs_kcalloc(2, | 2008 | kcalloc(1, 2, GFP_KERNEL); |
1746 | GFP_KERNEL); | ||
1747 | } else { /* no room so create dummy domain and NOS string */ | 2009 | } else { /* no room so create dummy domain and NOS string */ |
2010 | /* if these kcallocs fail not much we | ||
2011 | can do, but better to not fail the | ||
2012 | sesssetup itself */ | ||
1748 | ses->serverDomain = | 2013 | ses->serverDomain = |
1749 | cifs_kcalloc(2, GFP_KERNEL); | 2014 | kcalloc(1, 2, GFP_KERNEL); |
1750 | ses->serverNOS = | 2015 | ses->serverNOS = |
1751 | cifs_kcalloc(2, GFP_KERNEL); | 2016 | kcalloc(1, 2, GFP_KERNEL); |
1752 | } | 2017 | } |
1753 | } else { /* ASCII */ | 2018 | } else { /* ASCII */ |
1754 | len = strnlen(bcc_ptr, 1024); | 2019 | len = strnlen(bcc_ptr, 1024); |
1755 | if (((long) bcc_ptr + len) - (long) | 2020 | if (((long) bcc_ptr + len) - (long) |
1756 | pByteArea(smb_buffer_response) | 2021 | pByteArea(smb_buffer_response) |
1757 | <= BCC(smb_buffer_response)) { | 2022 | <= BCC(smb_buffer_response)) { |
1758 | ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); | 2023 | ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL); |
2024 | if(ses->serverOS == NULL) | ||
2025 | goto sesssetup_nomem; | ||
1759 | strncpy(ses->serverOS,bcc_ptr, len); | 2026 | strncpy(ses->serverOS,bcc_ptr, len); |
1760 | 2027 | ||
1761 | bcc_ptr += len; | 2028 | bcc_ptr += len; |
@@ -1763,14 +2030,18 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1763 | bcc_ptr++; | 2030 | bcc_ptr++; |
1764 | 2031 | ||
1765 | len = strnlen(bcc_ptr, 1024); | 2032 | len = strnlen(bcc_ptr, 1024); |
1766 | ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); | 2033 | ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL); |
2034 | if(ses->serverNOS == NULL) | ||
2035 | goto sesssetup_nomem; | ||
1767 | strncpy(ses->serverNOS, bcc_ptr, len); | 2036 | strncpy(ses->serverNOS, bcc_ptr, len); |
1768 | bcc_ptr += len; | 2037 | bcc_ptr += len; |
1769 | bcc_ptr[0] = 0; | 2038 | bcc_ptr[0] = 0; |
1770 | bcc_ptr++; | 2039 | bcc_ptr++; |
1771 | 2040 | ||
1772 | len = strnlen(bcc_ptr, 1024); | 2041 | len = strnlen(bcc_ptr, 1024); |
1773 | ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL); | 2042 | ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL); |
2043 | if(ses->serverDomain == NULL) | ||
2044 | goto sesssetup_nomem; | ||
1774 | strncpy(ses->serverDomain, bcc_ptr, len); | 2045 | strncpy(ses->serverDomain, bcc_ptr, len); |
1775 | bcc_ptr += len; | 2046 | bcc_ptr += len; |
1776 | bcc_ptr[0] = 0; | 2047 | bcc_ptr[0] = 0; |
@@ -1790,7 +2061,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1790 | smb_buffer_response->WordCount)); | 2061 | smb_buffer_response->WordCount)); |
1791 | rc = -EIO; | 2062 | rc = -EIO; |
1792 | } | 2063 | } |
1793 | 2064 | sesssetup_nomem: /* do not return an error on nomem for the info strings, | |
2065 | since that could make reconnection harder, and | ||
2066 | reconnection might be needed to free memory */ | ||
1794 | if (smb_buffer) | 2067 | if (smb_buffer) |
1795 | cifs_buf_release(smb_buffer); | 2068 | cifs_buf_release(smb_buffer); |
1796 | 2069 | ||
@@ -1967,7 +2240,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1967 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 2240 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
1968 | terminating last Unicode string in response */ | 2241 | terminating last Unicode string in response */ |
1969 | ses->serverOS = | 2242 | ses->serverOS = |
1970 | cifs_kcalloc(2 * (len + 1), GFP_KERNEL); | 2243 | kcalloc(1, 2 * (len + 1), GFP_KERNEL); |
1971 | cifs_strfromUCS_le(ses->serverOS, | 2244 | cifs_strfromUCS_le(ses->serverOS, |
1972 | (wchar_t *) | 2245 | (wchar_t *) |
1973 | bcc_ptr, len, | 2246 | bcc_ptr, len, |
@@ -1981,7 +2254,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1981 | remaining_words | 2254 | remaining_words |
1982 | - 1); | 2255 | - 1); |
1983 | ses->serverNOS = | 2256 | ses->serverNOS = |
1984 | cifs_kcalloc(2 * (len + 1), | 2257 | kcalloc(1, 2 * (len + 1), |
1985 | GFP_KERNEL); | 2258 | GFP_KERNEL); |
1986 | cifs_strfromUCS_le(ses->serverNOS, | 2259 | cifs_strfromUCS_le(ses->serverNOS, |
1987 | (wchar_t *)bcc_ptr, | 2260 | (wchar_t *)bcc_ptr, |
@@ -1994,7 +2267,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
1994 | if (remaining_words > 0) { | 2267 | if (remaining_words > 0) { |
1995 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | 2268 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); |
1996 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ | 2269 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ |
1997 | ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); | 2270 | ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL); |
1998 | cifs_strfromUCS_le(ses->serverDomain, | 2271 | cifs_strfromUCS_le(ses->serverDomain, |
1999 | (wchar_t *)bcc_ptr, | 2272 | (wchar_t *)bcc_ptr, |
2000 | len, | 2273 | len, |
@@ -2005,10 +2278,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2005 | } /* else no more room so create dummy domain string */ | 2278 | } /* else no more room so create dummy domain string */ |
2006 | else | 2279 | else |
2007 | ses->serverDomain = | 2280 | ses->serverDomain = |
2008 | cifs_kcalloc(2,GFP_KERNEL); | 2281 | kcalloc(1, 2,GFP_KERNEL); |
2009 | } else { /* no room so create dummy domain and NOS string */ | 2282 | } else { /* no room so create dummy domain and NOS string */ |
2010 | ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); | 2283 | ses->serverDomain = kcalloc(1, 2, GFP_KERNEL); |
2011 | ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); | 2284 | ses->serverNOS = kcalloc(1, 2, GFP_KERNEL); |
2012 | } | 2285 | } |
2013 | } else { /* ASCII */ | 2286 | } else { /* ASCII */ |
2014 | 2287 | ||
@@ -2016,7 +2289,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2016 | if (((long) bcc_ptr + len) - (long) | 2289 | if (((long) bcc_ptr + len) - (long) |
2017 | pByteArea(smb_buffer_response) | 2290 | pByteArea(smb_buffer_response) |
2018 | <= BCC(smb_buffer_response)) { | 2291 | <= BCC(smb_buffer_response)) { |
2019 | ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL); | 2292 | ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL); |
2020 | strncpy(ses->serverOS, bcc_ptr, len); | 2293 | strncpy(ses->serverOS, bcc_ptr, len); |
2021 | 2294 | ||
2022 | bcc_ptr += len; | 2295 | bcc_ptr += len; |
@@ -2024,14 +2297,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2024 | bcc_ptr++; | 2297 | bcc_ptr++; |
2025 | 2298 | ||
2026 | len = strnlen(bcc_ptr, 1024); | 2299 | len = strnlen(bcc_ptr, 1024); |
2027 | ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); | 2300 | ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL); |
2028 | strncpy(ses->serverNOS, bcc_ptr, len); | 2301 | strncpy(ses->serverNOS, bcc_ptr, len); |
2029 | bcc_ptr += len; | 2302 | bcc_ptr += len; |
2030 | bcc_ptr[0] = 0; | 2303 | bcc_ptr[0] = 0; |
2031 | bcc_ptr++; | 2304 | bcc_ptr++; |
2032 | 2305 | ||
2033 | len = strnlen(bcc_ptr, 1024); | 2306 | len = strnlen(bcc_ptr, 1024); |
2034 | ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL); | 2307 | ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL); |
2035 | strncpy(ses->serverDomain, bcc_ptr, len); | 2308 | strncpy(ses->serverDomain, bcc_ptr, len); |
2036 | bcc_ptr += len; | 2309 | bcc_ptr += len; |
2037 | bcc_ptr[0] = 0; | 2310 | bcc_ptr[0] = 0; |
@@ -2281,7 +2554,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2281 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 2554 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
2282 | terminating last Unicode string in response */ | 2555 | terminating last Unicode string in response */ |
2283 | ses->serverOS = | 2556 | ses->serverOS = |
2284 | cifs_kcalloc(2 * (len + 1), GFP_KERNEL); | 2557 | kcalloc(1, 2 * (len + 1), GFP_KERNEL); |
2285 | cifs_strfromUCS_le(ses->serverOS, | 2558 | cifs_strfromUCS_le(ses->serverOS, |
2286 | (wchar_t *) | 2559 | (wchar_t *) |
2287 | bcc_ptr, len, | 2560 | bcc_ptr, len, |
@@ -2296,7 +2569,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2296 | remaining_words | 2569 | remaining_words |
2297 | - 1); | 2570 | - 1); |
2298 | ses->serverNOS = | 2571 | ses->serverNOS = |
2299 | cifs_kcalloc(2 * (len + 1), | 2572 | kcalloc(1, 2 * (len + 1), |
2300 | GFP_KERNEL); | 2573 | GFP_KERNEL); |
2301 | cifs_strfromUCS_le(ses-> | 2574 | cifs_strfromUCS_le(ses-> |
2302 | serverNOS, | 2575 | serverNOS, |
@@ -2313,7 +2586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2313 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | 2586 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); |
2314 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ | 2587 | /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ |
2315 | ses->serverDomain = | 2588 | ses->serverDomain = |
2316 | cifs_kcalloc(2 * | 2589 | kcalloc(1, 2 * |
2317 | (len + | 2590 | (len + |
2318 | 1), | 2591 | 1), |
2319 | GFP_KERNEL); | 2592 | GFP_KERNEL); |
@@ -2339,13 +2612,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2339 | } /* else no more room so create dummy domain string */ | 2612 | } /* else no more room so create dummy domain string */ |
2340 | else | 2613 | else |
2341 | ses->serverDomain = | 2614 | ses->serverDomain = |
2342 | cifs_kcalloc(2, | 2615 | kcalloc(1, 2, |
2343 | GFP_KERNEL); | 2616 | GFP_KERNEL); |
2344 | } else { /* no room so create dummy domain and NOS string */ | 2617 | } else { /* no room so create dummy domain and NOS string */ |
2345 | ses->serverDomain = | 2618 | ses->serverDomain = |
2346 | cifs_kcalloc(2, GFP_KERNEL); | 2619 | kcalloc(1, 2, GFP_KERNEL); |
2347 | ses->serverNOS = | 2620 | ses->serverNOS = |
2348 | cifs_kcalloc(2, GFP_KERNEL); | 2621 | kcalloc(1, 2, GFP_KERNEL); |
2349 | } | 2622 | } |
2350 | } else { /* ASCII */ | 2623 | } else { /* ASCII */ |
2351 | len = strnlen(bcc_ptr, 1024); | 2624 | len = strnlen(bcc_ptr, 1024); |
@@ -2353,7 +2626,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2353 | pByteArea(smb_buffer_response) | 2626 | pByteArea(smb_buffer_response) |
2354 | <= BCC(smb_buffer_response)) { | 2627 | <= BCC(smb_buffer_response)) { |
2355 | ses->serverOS = | 2628 | ses->serverOS = |
2356 | cifs_kcalloc(len + 1, | 2629 | kcalloc(1, len + 1, |
2357 | GFP_KERNEL); | 2630 | GFP_KERNEL); |
2358 | strncpy(ses->serverOS, | 2631 | strncpy(ses->serverOS, |
2359 | bcc_ptr, len); | 2632 | bcc_ptr, len); |
@@ -2364,7 +2637,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2364 | 2637 | ||
2365 | len = strnlen(bcc_ptr, 1024); | 2638 | len = strnlen(bcc_ptr, 1024); |
2366 | ses->serverNOS = | 2639 | ses->serverNOS = |
2367 | cifs_kcalloc(len + 1, | 2640 | kcalloc(1, len + 1, |
2368 | GFP_KERNEL); | 2641 | GFP_KERNEL); |
2369 | strncpy(ses->serverNOS, bcc_ptr, len); | 2642 | strncpy(ses->serverNOS, bcc_ptr, len); |
2370 | bcc_ptr += len; | 2643 | bcc_ptr += len; |
@@ -2373,7 +2646,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2373 | 2646 | ||
2374 | len = strnlen(bcc_ptr, 1024); | 2647 | len = strnlen(bcc_ptr, 1024); |
2375 | ses->serverDomain = | 2648 | ses->serverDomain = |
2376 | cifs_kcalloc(len + 1, | 2649 | kcalloc(1, len + 1, |
2377 | GFP_KERNEL); | 2650 | GFP_KERNEL); |
2378 | strncpy(ses->serverDomain, bcc_ptr, len); | 2651 | strncpy(ses->serverDomain, bcc_ptr, len); |
2379 | bcc_ptr += len; | 2652 | bcc_ptr += len; |
@@ -2675,7 +2948,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2675 | the end since (at least) WIN2K and Windows XP have a major bug in not null | 2948 | the end since (at least) WIN2K and Windows XP have a major bug in not null |
2676 | terminating last Unicode string in response */ | 2949 | terminating last Unicode string in response */ |
2677 | ses->serverOS = | 2950 | ses->serverOS = |
2678 | cifs_kcalloc(2 * (len + 1), GFP_KERNEL); | 2951 | kcalloc(1, 2 * (len + 1), GFP_KERNEL); |
2679 | cifs_strfromUCS_le(ses->serverOS, | 2952 | cifs_strfromUCS_le(ses->serverOS, |
2680 | (wchar_t *) | 2953 | (wchar_t *) |
2681 | bcc_ptr, len, | 2954 | bcc_ptr, len, |
@@ -2690,7 +2963,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2690 | remaining_words | 2963 | remaining_words |
2691 | - 1); | 2964 | - 1); |
2692 | ses->serverNOS = | 2965 | ses->serverNOS = |
2693 | cifs_kcalloc(2 * (len + 1), | 2966 | kcalloc(1, 2 * (len + 1), |
2694 | GFP_KERNEL); | 2967 | GFP_KERNEL); |
2695 | cifs_strfromUCS_le(ses-> | 2968 | cifs_strfromUCS_le(ses-> |
2696 | serverNOS, | 2969 | serverNOS, |
@@ -2706,7 +2979,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2706 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | 2979 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); |
2707 | /* last string not always null terminated (e.g. for Windows XP & 2000) */ | 2980 | /* last string not always null terminated (e.g. for Windows XP & 2000) */ |
2708 | ses->serverDomain = | 2981 | ses->serverDomain = |
2709 | cifs_kcalloc(2 * | 2982 | kcalloc(1, 2 * |
2710 | (len + | 2983 | (len + |
2711 | 1), | 2984 | 1), |
2712 | GFP_KERNEL); | 2985 | GFP_KERNEL); |
@@ -2731,17 +3004,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2731 | = 0; | 3004 | = 0; |
2732 | } /* else no more room so create dummy domain string */ | 3005 | } /* else no more room so create dummy domain string */ |
2733 | else | 3006 | else |
2734 | ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); | 3007 | ses->serverDomain = kcalloc(1, 2,GFP_KERNEL); |
2735 | } else { /* no room so create dummy domain and NOS string */ | 3008 | } else { /* no room so create dummy domain and NOS string */ |
2736 | ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); | 3009 | ses->serverDomain = kcalloc(1, 2, GFP_KERNEL); |
2737 | ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); | 3010 | ses->serverNOS = kcalloc(1, 2, GFP_KERNEL); |
2738 | } | 3011 | } |
2739 | } else { /* ASCII */ | 3012 | } else { /* ASCII */ |
2740 | len = strnlen(bcc_ptr, 1024); | 3013 | len = strnlen(bcc_ptr, 1024); |
2741 | if (((long) bcc_ptr + len) - | 3014 | if (((long) bcc_ptr + len) - |
2742 | (long) pByteArea(smb_buffer_response) | 3015 | (long) pByteArea(smb_buffer_response) |
2743 | <= BCC(smb_buffer_response)) { | 3016 | <= BCC(smb_buffer_response)) { |
2744 | ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); | 3017 | ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL); |
2745 | strncpy(ses->serverOS,bcc_ptr, len); | 3018 | strncpy(ses->serverOS,bcc_ptr, len); |
2746 | 3019 | ||
2747 | bcc_ptr += len; | 3020 | bcc_ptr += len; |
@@ -2749,14 +3022,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2749 | bcc_ptr++; | 3022 | bcc_ptr++; |
2750 | 3023 | ||
2751 | len = strnlen(bcc_ptr, 1024); | 3024 | len = strnlen(bcc_ptr, 1024); |
2752 | ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL); | 3025 | ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL); |
2753 | strncpy(ses->serverNOS, bcc_ptr, len); | 3026 | strncpy(ses->serverNOS, bcc_ptr, len); |
2754 | bcc_ptr += len; | 3027 | bcc_ptr += len; |
2755 | bcc_ptr[0] = 0; | 3028 | bcc_ptr[0] = 0; |
2756 | bcc_ptr++; | 3029 | bcc_ptr++; |
2757 | 3030 | ||
2758 | len = strnlen(bcc_ptr, 1024); | 3031 | len = strnlen(bcc_ptr, 1024); |
2759 | ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL); | 3032 | ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL); |
2760 | strncpy(ses->serverDomain, bcc_ptr, len); | 3033 | strncpy(ses->serverDomain, bcc_ptr, len); |
2761 | bcc_ptr += len; | 3034 | bcc_ptr += len; |
2762 | bcc_ptr[0] = 0; | 3035 | bcc_ptr[0] = 0; |
@@ -2868,7 +3141,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2868 | if(tcon->nativeFileSystem) | 3141 | if(tcon->nativeFileSystem) |
2869 | kfree(tcon->nativeFileSystem); | 3142 | kfree(tcon->nativeFileSystem); |
2870 | tcon->nativeFileSystem = | 3143 | tcon->nativeFileSystem = |
2871 | cifs_kcalloc(length + 2, GFP_KERNEL); | 3144 | kcalloc(1, length + 2, GFP_KERNEL); |
2872 | cifs_strfromUCS_le(tcon->nativeFileSystem, | 3145 | cifs_strfromUCS_le(tcon->nativeFileSystem, |
2873 | (wchar_t *) bcc_ptr, | 3146 | (wchar_t *) bcc_ptr, |
2874 | length, nls_codepage); | 3147 | length, nls_codepage); |
@@ -2886,7 +3159,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2886 | if(tcon->nativeFileSystem) | 3159 | if(tcon->nativeFileSystem) |
2887 | kfree(tcon->nativeFileSystem); | 3160 | kfree(tcon->nativeFileSystem); |
2888 | tcon->nativeFileSystem = | 3161 | tcon->nativeFileSystem = |
2889 | cifs_kcalloc(length + 1, GFP_KERNEL); | 3162 | kcalloc(1, length + 1, GFP_KERNEL); |
2890 | strncpy(tcon->nativeFileSystem, bcc_ptr, | 3163 | strncpy(tcon->nativeFileSystem, bcc_ptr, |
2891 | length); | 3164 | length); |
2892 | } | 3165 | } |
@@ -2959,6 +3232,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
2959 | int rc = 0; | 3232 | int rc = 0; |
2960 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; | 3233 | char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; |
2961 | int ntlmv2_flag = FALSE; | 3234 | int ntlmv2_flag = FALSE; |
3235 | int first_time = 0; | ||
2962 | 3236 | ||
2963 | /* what if server changes its buffer size after dropping the session? */ | 3237 | /* what if server changes its buffer size after dropping the session? */ |
2964 | if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { | 3238 | if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { |
@@ -2977,12 +3251,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
2977 | spin_unlock(&GlobalMid_Lock); | 3251 | spin_unlock(&GlobalMid_Lock); |
2978 | 3252 | ||
2979 | } | 3253 | } |
3254 | first_time = 1; | ||
2980 | } | 3255 | } |
2981 | if (!rc) { | 3256 | if (!rc) { |
2982 | pSesInfo->capabilities = pSesInfo->server->capabilities; | 3257 | pSesInfo->capabilities = pSesInfo->server->capabilities; |
2983 | if(linuxExtEnabled == 0) | 3258 | if(linuxExtEnabled == 0) |
2984 | pSesInfo->capabilities &= (~CAP_UNIX); | 3259 | pSesInfo->capabilities &= (~CAP_UNIX); |
2985 | pSesInfo->sequence_number = 0; | 3260 | /* pSesInfo->sequence_number = 0;*/ |
2986 | cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", | 3261 | cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", |
2987 | pSesInfo->server->secMode, | 3262 | pSesInfo->server->secMode, |
2988 | pSesInfo->server->capabilities, | 3263 | pSesInfo->server->capabilities, |
@@ -3015,7 +3290,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3015 | v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); | 3290 | v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); |
3016 | if(v2_response) { | 3291 | if(v2_response) { |
3017 | CalcNTLMv2_response(pSesInfo,v2_response); | 3292 | CalcNTLMv2_response(pSesInfo,v2_response); |
3018 | /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ | 3293 | /* if(first_time) |
3294 | cifs_calculate_ntlmv2_mac_key( | ||
3295 | pSesInfo->server->mac_signing_key, | ||
3296 | response, ntlm_session_key, */ | ||
3019 | kfree(v2_response); | 3297 | kfree(v2_response); |
3020 | /* BB Put dummy sig in SessSetup PDU? */ | 3298 | /* BB Put dummy sig in SessSetup PDU? */ |
3021 | } else { | 3299 | } else { |
@@ -3028,9 +3306,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3028 | pSesInfo->server->cryptKey, | 3306 | pSesInfo->server->cryptKey, |
3029 | ntlm_session_key); | 3307 | ntlm_session_key); |
3030 | 3308 | ||
3031 | cifs_calculate_mac_key(pSesInfo->mac_signing_key, | 3309 | if(first_time) |
3032 | ntlm_session_key, | 3310 | cifs_calculate_mac_key( |
3033 | pSesInfo->password); | 3311 | pSesInfo->server->mac_signing_key, |
3312 | ntlm_session_key, | ||
3313 | pSesInfo->password); | ||
3034 | } | 3314 | } |
3035 | /* for better security the weaker lanman hash not sent | 3315 | /* for better security the weaker lanman hash not sent |
3036 | in AuthSessSetup so we no longer calculate it */ | 3316 | in AuthSessSetup so we no longer calculate it */ |
@@ -3046,8 +3326,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3046 | pSesInfo->server->cryptKey, | 3326 | pSesInfo->server->cryptKey, |
3047 | ntlm_session_key); | 3327 | ntlm_session_key); |
3048 | 3328 | ||
3049 | cifs_calculate_mac_key(pSesInfo->mac_signing_key, | 3329 | if(first_time) |
3050 | ntlm_session_key, pSesInfo->password); | 3330 | cifs_calculate_mac_key( |
3331 | pSesInfo->server->mac_signing_key, | ||
3332 | ntlm_session_key, pSesInfo->password); | ||
3333 | |||
3051 | rc = CIFSSessSetup(xid, pSesInfo, | 3334 | rc = CIFSSessSetup(xid, pSesInfo, |
3052 | ntlm_session_key, nls_info); | 3335 | ntlm_session_key, nls_info); |
3053 | } | 3336 | } |