[CIFS] whitespace/formatting fixes
[safe/jmp/linux-2.6] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2007
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
25  /* These are mostly routines that operate on a pathname, or on a tree id     */
26  /* (mounted volume), but there are eight handle based routines which must be */
27  /* treated slightly differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
40 #include "cifsacl.h"
41
42 #ifdef CONFIG_CIFS_POSIX
43 static struct {
44         int index;
45         char *name;
46 } protocols[] = {
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48         {LANMAN_PROT, "\2LM1.2X002"},
49         {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51         {CIFS_PROT, "\2NT LM 0.12"},
52         {POSIX_PROT, "\2POSIX 2"},
53         {BAD_PROT, "\2"}
54 };
55 #else
56 static struct {
57         int index;
58         char *name;
59 } protocols[] = {
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61         {LANMAN_PROT, "\2LM1.2X002"},
62         {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64         {CIFS_PROT, "\2NT LM 0.12"},
65         {BAD_PROT, "\2"}
66 };
67 #endif
68
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
73 #else
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
76 #else /* not posix */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
79 #else
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
83
84
85 /* Mark as invalid, all open files on tree connections since they
86    were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
88 {
89         struct cifsFileInfo *open_file = NULL;
90         struct list_head *tmp;
91         struct list_head *tmp1;
92
93 /* list all files open on tree connection and mark them invalid */
94         write_lock(&GlobalSMBSeslock);
95         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97                 if (open_file) {
98                         open_file->invalidHandle = TRUE;
99                 }
100         }
101         write_unlock(&GlobalSMBSeslock);
102         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
103            to this tcon */
104 }
105
106 /* If the return code is zero, this function must fill in request_buf pointer */
107 static int
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109          void **request_buf /* returned */)
110 {
111         int rc = 0;
112
113         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114            check for tcp and smb session status done differently
115            for those three - in the calling routine */
116         if (tcon) {
117                 if (tcon->tidStatus == CifsExiting) {
118                         /* only tree disconnect, open, and write,
119                         (and ulogoff which does not have tcon)
120                         are allowed as we start force umount */
121                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
122                            (smb_command != SMB_COM_OPEN_ANDX) &&
123                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
124                                 cFYI(1, ("can not send cmd %d while umounting",
125                                         smb_command));
126                                 return -ENODEV;
127                         }
128                 }
129                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130                                   (tcon->ses->server)) {
131                         struct nls_table *nls_codepage;
132                                 /* Give Demultiplex thread up to 10 seconds to
133                                    reconnect, should be greater than cifs socket
134                                    timeout which is 7 seconds */
135                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
136                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
138                                 if (tcon->ses->server->tcpStatus == CifsNeedReconnect) {
139                                         /* on "soft" mounts we wait once */
140                                         if ((tcon->retry == FALSE) ||
141                                            (tcon->ses->status == CifsExiting)) {
142                                                 cFYI(1, ("gave up waiting on "
143                                                       "reconnect in smb_init"));
144                                                 return -EHOSTDOWN;
145                                         } /* else "hard" mount - keep retrying
146                                              until process is killed or server
147                                              comes back on-line */
148                                 } else /* TCP session is reestablished now */
149                                         break;
150                         }
151
152                         nls_codepage = load_nls_default();
153                 /* need to prevent multiple threads trying to
154                 simultaneously reconnect the same SMB session */
155                         down(&tcon->ses->sesSem);
156                         if (tcon->ses->status == CifsNeedReconnect)
157                                 rc = cifs_setup_session(0, tcon->ses,
158                                                         nls_codepage);
159                         if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160                                 mark_open_files_invalid(tcon);
161                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
162                                               tcon, nls_codepage);
163                                 up(&tcon->ses->sesSem);
164                                 /* tell server which Unix caps we support */
165                                 if (tcon->ses->capabilities & CAP_UNIX)
166                                         reset_cifs_unix_caps(0 /* no xid */,
167                                                 tcon,
168                                                 NULL /* we do not know sb */,
169                                                 NULL /* no vol info */);
170                                 /* BB FIXME add code to check if wsize needs
171                                    update due to negotiated smb buffer size
172                                    shrinking */
173                                 if (rc == 0)
174                                         atomic_inc(&tconInfoReconnectCount);
175
176                                 cFYI(1, ("reconnect tcon rc = %d", rc));
177                                 /* Removed call to reopen open files here.
178                                    It is safer (and faster) to reopen files
179                                    one at a time as needed in read and write */
180
181                                 /* Check if handle based operation so we
182                                    know whether we can continue or not without
183                                    returning to caller to reset file handle */
184                                 switch (smb_command) {
185                                         case SMB_COM_READ_ANDX:
186                                         case SMB_COM_WRITE_ANDX:
187                                         case SMB_COM_CLOSE:
188                                         case SMB_COM_FIND_CLOSE2:
189                                         case SMB_COM_LOCKING_ANDX: {
190                                                 unload_nls(nls_codepage);
191                                                 return -EAGAIN;
192                                         }
193                                 }
194                         } else {
195                                 up(&tcon->ses->sesSem);
196                         }
197                         unload_nls(nls_codepage);
198
199                 } else {
200                         return -EIO;
201                 }
202         }
203         if (rc)
204                 return rc;
205
206         *request_buf = cifs_small_buf_get();
207         if (*request_buf == NULL) {
208                 /* BB should we add a retry in here if not a writepage? */
209                 return -ENOMEM;
210         }
211
212         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
213
214         if (tcon != NULL)
215                 cifs_stats_inc(&tcon->num_smbs_sent);
216
217         return rc;
218 }
219
220 int
221 small_smb_init_no_tc(const int smb_command, const int wct,
222                      struct cifsSesInfo *ses, void **request_buf)
223 {
224         int rc;
225         struct smb_hdr *buffer;
226
227         rc = small_smb_init(smb_command, wct, NULL, request_buf);
228         if (rc)
229                 return rc;
230
231         buffer = (struct smb_hdr *)*request_buf;
232         buffer->Mid = GetNextMid(ses->server);
233         if (ses->capabilities & CAP_UNICODE)
234                 buffer->Flags2 |= SMBFLG2_UNICODE;
235         if (ses->capabilities & CAP_STATUS32)
236                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
237
238         /* uid, tid can stay at zero as set in header assemble */
239
240         /* BB add support for turning on the signing when
241         this function is used after 1st of session setup requests */
242
243         return rc;
244 }
245
246 /* If the return code is zero, this function must fill in request_buf pointer */
247 static int
248 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
249          void **request_buf /* returned */ ,
250          void **response_buf /* returned */ )
251 {
252         int rc = 0;
253
254         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
255            check for tcp and smb session status done differently
256            for those three - in the calling routine */
257         if (tcon) {
258                 if (tcon->tidStatus == CifsExiting) {
259                         /* only tree disconnect, open, and write,
260                           (and ulogoff which does not have tcon)
261                           are allowed as we start force umount */
262                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
263                            (smb_command != SMB_COM_OPEN_ANDX) &&
264                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
265                                 cFYI(1, ("can not send cmd %d while umounting",
266                                         smb_command));
267                                 return -ENODEV;
268                         }
269                 }
270
271                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
272                                   (tcon->ses->server)) {
273                         struct nls_table *nls_codepage;
274                                 /* Give Demultiplex thread up to 10 seconds to
275                                    reconnect, should be greater than cifs socket
276                                    timeout which is 7 seconds */
277                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
278                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
279                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
280                                 if (tcon->ses->server->tcpStatus ==
281                                                 CifsNeedReconnect) {
282                                         /* on "soft" mounts we wait once */
283                                         if ((tcon->retry == FALSE) ||
284                                            (tcon->ses->status == CifsExiting)) {
285                                                 cFYI(1, ("gave up waiting on "
286                                                       "reconnect in smb_init"));
287                                                 return -EHOSTDOWN;
288                                         } /* else "hard" mount - keep retrying
289                                              until process is killed or server
290                                              comes on-line */
291                                 } else /* TCP session is reestablished now */
292                                         break;
293                         }
294                         nls_codepage = load_nls_default();
295                 /* need to prevent multiple threads trying to
296                 simultaneously reconnect the same SMB session */
297                         down(&tcon->ses->sesSem);
298                         if (tcon->ses->status == CifsNeedReconnect)
299                                 rc = cifs_setup_session(0, tcon->ses,
300                                                         nls_codepage);
301                         if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
302                                 mark_open_files_invalid(tcon);
303                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
304                                               tcon, nls_codepage);
305                                 up(&tcon->ses->sesSem);
306                                 /* tell server which Unix caps we support */
307                                 if (tcon->ses->capabilities & CAP_UNIX)
308                                         reset_cifs_unix_caps(0 /* no xid */,
309                                                 tcon,
310                                                 NULL /* do not know sb */,
311                                                 NULL /* no vol info */);
312                                 /* BB FIXME add code to check if wsize needs
313                                 update due to negotiated smb buffer size
314                                 shrinking */
315                                 if (rc == 0)
316                                         atomic_inc(&tconInfoReconnectCount);
317
318                                 cFYI(1, ("reconnect tcon rc = %d", rc));
319                                 /* Removed call to reopen open files here.
320                                    It is safer (and faster) to reopen files
321                                    one at a time as needed in read and write */
322
323                                 /* Check if handle based operation so we
324                                    know whether we can continue or not without
325                                    returning to caller to reset file handle */
326                                 switch (smb_command) {
327                                         case SMB_COM_READ_ANDX:
328                                         case SMB_COM_WRITE_ANDX:
329                                         case SMB_COM_CLOSE:
330                                         case SMB_COM_FIND_CLOSE2:
331                                         case SMB_COM_LOCKING_ANDX: {
332                                                 unload_nls(nls_codepage);
333                                                 return -EAGAIN;
334                                         }
335                                 }
336                         } else {
337                                 up(&tcon->ses->sesSem);
338                         }
339                         unload_nls(nls_codepage);
340
341                 } else {
342                         return -EIO;
343                 }
344         }
345         if (rc)
346                 return rc;
347
348         *request_buf = cifs_buf_get();
349         if (*request_buf == NULL) {
350                 /* BB should we add a retry in here if not a writepage? */
351                 return -ENOMEM;
352         }
353     /* Although the original thought was we needed the response buf for  */
354     /* potential retries of smb operations it turns out we can determine */
355     /* from the mid flags when the request buffer can be resent without  */
356     /* having to use a second distinct buffer for the response */
357         if (response_buf)
358                 *response_buf = *request_buf;
359
360         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
361                         wct /*wct */ );
362
363         if (tcon != NULL)
364                 cifs_stats_inc(&tcon->num_smbs_sent);
365
366         return rc;
367 }
368
369 static int validate_t2(struct smb_t2_rsp *pSMB)
370 {
371         int rc = -EINVAL;
372         int total_size;
373         char *pBCC;
374
375         /* check for plausible wct, bcc and t2 data and parm sizes */
376         /* check for parm and data offset going beyond end of smb */
377         if (pSMB->hdr.WordCount >= 10) {
378                 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
379                    (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
380                         /* check that bcc is at least as big as parms + data */
381                         /* check that bcc is less than negotiated smb buffer */
382                         total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
383                         if (total_size < 512) {
384                                 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
385                                 /* BCC le converted in SendReceive */
386                                 pBCC = (pSMB->hdr.WordCount * 2) +
387                                         sizeof(struct smb_hdr) +
388                                         (char *)pSMB;
389                                 if ((total_size <= (*(u16 *)pBCC)) &&
390                                    (total_size <
391                                         CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
392                                         return 0;
393                                 }
394                         }
395                 }
396         }
397         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
398                 sizeof(struct smb_t2_rsp) + 16);
399         return rc;
400 }
401 int
402 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
403 {
404         NEGOTIATE_REQ *pSMB;
405         NEGOTIATE_RSP *pSMBr;
406         int rc = 0;
407         int bytes_returned;
408         int i;
409         struct TCP_Server_Info *server;
410         u16 count;
411         unsigned int secFlags;
412         u16 dialect;
413
414         if (ses->server)
415                 server = ses->server;
416         else {
417                 rc = -EIO;
418                 return rc;
419         }
420         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
421                       (void **) &pSMB, (void **) &pSMBr);
422         if (rc)
423                 return rc;
424
425         /* if any of auth flags (ie not sign or seal) are overriden use them */
426         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
427                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
428         else /* if override flags set only sign/seal OR them with global auth */
429                 secFlags = extended_security | ses->overrideSecFlg;
430
431         cFYI(1, ("secFlags 0x%x", secFlags));
432
433         pSMB->hdr.Mid = GetNextMid(server);
434         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
435         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
436                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
437
438         count = 0;
439         for (i = 0; i < CIFS_NUM_PROT; i++) {
440                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
441                 count += strlen(protocols[i].name) + 1;
442                 /* null at end of source and target buffers anyway */
443         }
444         pSMB->hdr.smb_buf_length += count;
445         pSMB->ByteCount = cpu_to_le16(count);
446
447         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
448                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
449         if (rc != 0)
450                 goto neg_err_exit;
451
452         dialect = le16_to_cpu(pSMBr->DialectIndex);
453         cFYI(1, ("Dialect: %d", dialect));
454         /* Check wct = 1 error case */
455         if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
456                 /* core returns wct = 1, but we do not ask for core - otherwise
457                 small wct just comes when dialect index is -1 indicating we
458                 could not negotiate a common dialect */
459                 rc = -EOPNOTSUPP;
460                 goto neg_err_exit;
461 #ifdef CONFIG_CIFS_WEAK_PW_HASH
462         } else if ((pSMBr->hdr.WordCount == 13)
463                         && ((dialect == LANMAN_PROT)
464                                 || (dialect == LANMAN2_PROT))) {
465                 __s16 tmp;
466                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
467
468                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
469                         (secFlags & CIFSSEC_MAY_PLNTXT))
470                         server->secType = LANMAN;
471                 else {
472                         cERROR(1, ("mount failed weak security disabled"
473                                    " in /proc/fs/cifs/SecurityFlags"));
474                         rc = -EOPNOTSUPP;
475                         goto neg_err_exit;
476                 }
477                 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
478                 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
479                 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
480                                 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
481                 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
482                 /* even though we do not use raw we might as well set this
483                 accurately, in case we ever find a need for it */
484                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
485                         server->maxRw = 0xFF00;
486                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
487                 } else {
488                         server->maxRw = 0;/* we do not need to use raw anyway */
489                         server->capabilities = CAP_MPX_MODE;
490                 }
491                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
492                 if (tmp == -1) {
493                         /* OS/2 often does not set timezone therefore
494                          * we must use server time to calc time zone.
495                          * Could deviate slightly from the right zone.
496                          * Smallest defined timezone difference is 15 minutes
497                          * (i.e. Nepal).  Rounding up/down is done to match
498                          * this requirement.
499                          */
500                         int val, seconds, remain, result;
501                         struct timespec ts, utc;
502                         utc = CURRENT_TIME;
503                         ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
504                                                 le16_to_cpu(rsp->SrvTime.Time));
505                         cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
506                                 (int)ts.tv_sec, (int)utc.tv_sec,
507                                 (int)(utc.tv_sec - ts.tv_sec)));
508                         val = (int)(utc.tv_sec - ts.tv_sec);
509                         seconds = val < 0 ? -val : val;
510                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
511                         remain = seconds % MIN_TZ_ADJ;
512                         if (remain >= (MIN_TZ_ADJ / 2))
513                                 result += MIN_TZ_ADJ;
514                         if (val < 0)
515                                 result = - result;
516                         server->timeAdj = result;
517                 } else {
518                         server->timeAdj = (int)tmp;
519                         server->timeAdj *= 60; /* also in seconds */
520                 }
521                 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
522
523
524                 /* BB get server time for time conversions and add
525                 code to use it and timezone since this is not UTC */
526
527                 if (rsp->EncryptionKeyLength ==
528                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
529                         memcpy(server->cryptKey, rsp->EncryptionKey,
530                                 CIFS_CRYPTO_KEY_SIZE);
531                 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
532                         rc = -EIO; /* need cryptkey unless plain text */
533                         goto neg_err_exit;
534                 }
535
536                 cFYI(1, ("LANMAN negotiated"));
537                 /* we will not end up setting signing flags - as no signing
538                 was in LANMAN and server did not return the flags on */
539                 goto signing_check;
540 #else /* weak security disabled */
541         } else if (pSMBr->hdr.WordCount == 13) {
542                 cERROR(1, ("mount failed, cifs module not built "
543                           "with CIFS_WEAK_PW_HASH support"));
544                         rc = -EOPNOTSUPP;
545 #endif /* WEAK_PW_HASH */
546                 goto neg_err_exit;
547         } else if (pSMBr->hdr.WordCount != 17) {
548                 /* unknown wct */
549                 rc = -EOPNOTSUPP;
550                 goto neg_err_exit;
551         }
552         /* else wct == 17 NTLM */
553         server->secMode = pSMBr->SecurityMode;
554         if ((server->secMode & SECMODE_USER) == 0)
555                 cFYI(1, ("share mode security"));
556
557         if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
558 #ifdef CONFIG_CIFS_WEAK_PW_HASH
559                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
560 #endif /* CIFS_WEAK_PW_HASH */
561                         cERROR(1, ("Server requests plain text password"
562                                   " but client support disabled"));
563
564         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
565                 server->secType = NTLMv2;
566         else if (secFlags & CIFSSEC_MAY_NTLM)
567                 server->secType = NTLM;
568         else if (secFlags & CIFSSEC_MAY_NTLMV2)
569                 server->secType = NTLMv2;
570         /* else krb5 ... any others ... */
571
572         /* one byte, so no need to convert this or EncryptionKeyLen from
573            little endian */
574         server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
575         /* probably no need to store and check maxvcs */
576         server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
577                         (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
578         server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
579         cFYI(0, ("Max buf = %d", ses->server->maxBuf));
580         GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
581         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
582         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
583         server->timeAdj *= 60;
584         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
585                 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
586                        CIFS_CRYPTO_KEY_SIZE);
587         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
588                         && (pSMBr->EncryptionKeyLength == 0)) {
589                 /* decode security blob */
590         } else if (server->secMode & SECMODE_PW_ENCRYPT) {
591                 rc = -EIO; /* no crypt key only if plain text pwd */
592                 goto neg_err_exit;
593         }
594
595         /* BB might be helpful to save off the domain of server here */
596
597         if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
598                 (server->capabilities & CAP_EXTENDED_SECURITY)) {
599                 count = pSMBr->ByteCount;
600                 if (count < 16)
601                         rc = -EIO;
602                 else if (count == 16) {
603                         server->secType = RawNTLMSSP;
604                         if (server->socketUseCount.counter > 1) {
605                                 if (memcmp(server->server_GUID,
606                                            pSMBr->u.extended_response.
607                                            GUID, 16) != 0) {
608                                         cFYI(1, ("server UID changed"));
609                                         memcpy(server->server_GUID,
610                                                 pSMBr->u.extended_response.GUID,
611                                                 16);
612                                 }
613                         } else
614                                 memcpy(server->server_GUID,
615                                        pSMBr->u.extended_response.GUID, 16);
616                 } else {
617                         rc = decode_negTokenInit(pSMBr->u.extended_response.
618                                                  SecurityBlob,
619                                                  count - 16,
620                                                  &server->secType);
621                         if (rc == 1) {
622                         /* BB Need to fill struct for sessetup here */
623                                 rc = -EOPNOTSUPP;
624                         } else {
625                                 rc = -EINVAL;
626                         }
627                 }
628         } else
629                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
630
631 #ifdef CONFIG_CIFS_WEAK_PW_HASH
632 signing_check:
633 #endif
634         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
635                 /* MUST_SIGN already includes the MAY_SIGN FLAG
636                    so if this is zero it means that signing is disabled */
637                 cFYI(1, ("Signing disabled"));
638                 if (server->secMode & SECMODE_SIGN_REQUIRED)
639                         cERROR(1, ("Server requires "
640                                    "/proc/fs/cifs/PacketSigningEnabled "
641                                    "to be on"));
642                 server->secMode &=
643                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
644         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
645                 /* signing required */
646                 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
647                 if ((server->secMode &
648                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
649                         cERROR(1,
650                                 ("signing required but server lacks support"));
651                         rc = -EOPNOTSUPP;
652                 } else
653                         server->secMode |= SECMODE_SIGN_REQUIRED;
654         } else {
655                 /* signing optional ie CIFSSEC_MAY_SIGN */
656                 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
657                         server->secMode &=
658                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
659         }
660
661 neg_err_exit:
662         cifs_buf_release(pSMB);
663
664         cFYI(1, ("negprot rc %d", rc));
665         return rc;
666 }
667
668 int
669 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
670 {
671         struct smb_hdr *smb_buffer;
672         struct smb_hdr *smb_buffer_response; /* BB removeme BB */
673         int rc = 0;
674         int length;
675
676         cFYI(1, ("In tree disconnect"));
677         /*
678          *  If last user of the connection and
679          *  connection alive - disconnect it
680          *  If this is the last connection on the server session disconnect it
681          *  (and inside session disconnect we should check if tcp socket needs
682          *  to be freed and kernel thread woken up).
683          */
684         if (tcon)
685                 down(&tcon->tconSem);
686         else
687                 return -EIO;
688
689         atomic_dec(&tcon->useCount);
690         if (atomic_read(&tcon->useCount) > 0) {
691                 up(&tcon->tconSem);
692                 return -EBUSY;
693         }
694
695         /* No need to return error on this operation if tid invalidated and
696         closed on server already e.g. due to tcp session crashing */
697         if (tcon->tidStatus == CifsNeedReconnect) {
698                 up(&tcon->tconSem);
699                 return 0;
700         }
701
702         if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
703                 up(&tcon->tconSem);
704                 return -EIO;
705         }
706         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
707                             (void **)&smb_buffer);
708         if (rc) {
709                 up(&tcon->tconSem);
710                 return rc;
711         } else {
712                 smb_buffer_response = smb_buffer; /* BB removeme BB */
713         }
714         rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
715                          &length, 0);
716         if (rc)
717                 cFYI(1, ("Tree disconnect failed %d", rc));
718
719         if (smb_buffer)
720                 cifs_small_buf_release(smb_buffer);
721         up(&tcon->tconSem);
722
723         /* No need to return error on this operation if tid invalidated and
724         closed on server already e.g. due to tcp session crashing */
725         if (rc == -EAGAIN)
726                 rc = 0;
727
728         return rc;
729 }
730
731 int
732 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
733 {
734         struct smb_hdr *smb_buffer_response;
735         LOGOFF_ANDX_REQ *pSMB;
736         int rc = 0;
737         int length;
738
739         cFYI(1, ("In SMBLogoff for session disconnect"));
740         if (ses)
741                 down(&ses->sesSem);
742         else
743                 return -EIO;
744
745         atomic_dec(&ses->inUse);
746         if (atomic_read(&ses->inUse) > 0) {
747                 up(&ses->sesSem);
748                 return -EBUSY;
749         }
750         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
751         if (rc) {
752                 up(&ses->sesSem);
753                 return rc;
754         }
755
756         smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
757
758         if (ses->server) {
759                 pSMB->hdr.Mid = GetNextMid(ses->server);
760
761                 if (ses->server->secMode &
762                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
763                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
764         }
765
766         pSMB->hdr.Uid = ses->Suid;
767
768         pSMB->AndXCommand = 0xFF;
769         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
770                          smb_buffer_response, &length, 0);
771         if (ses->server) {
772                 atomic_dec(&ses->server->socketUseCount);
773                 if (atomic_read(&ses->server->socketUseCount) == 0) {
774                         spin_lock(&GlobalMid_Lock);
775                         ses->server->tcpStatus = CifsExiting;
776                         spin_unlock(&GlobalMid_Lock);
777                         rc = -ESHUTDOWN;
778                 }
779         }
780         up(&ses->sesSem);
781         cifs_small_buf_release(pSMB);
782
783         /* if session dead then we do not need to do ulogoff,
784                 since server closed smb session, no sense reporting
785                 error */
786         if (rc == -EAGAIN)
787                 rc = 0;
788         return rc;
789 }
790
791 int
792 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
793                const struct nls_table *nls_codepage, int remap)
794 {
795         DELETE_FILE_REQ *pSMB = NULL;
796         DELETE_FILE_RSP *pSMBr = NULL;
797         int rc = 0;
798         int bytes_returned;
799         int name_len;
800
801 DelFileRetry:
802         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
803                       (void **) &pSMBr);
804         if (rc)
805                 return rc;
806
807         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
808                 name_len =
809                     cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
810                                      PATH_MAX, nls_codepage, remap);
811                 name_len++;     /* trailing null */
812                 name_len *= 2;
813         } else {                /* BB improve check for buffer overruns BB */
814                 name_len = strnlen(fileName, PATH_MAX);
815                 name_len++;     /* trailing null */
816                 strncpy(pSMB->fileName, fileName, name_len);
817         }
818         pSMB->SearchAttributes =
819             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
820         pSMB->BufferFormat = 0x04;
821         pSMB->hdr.smb_buf_length += name_len + 1;
822         pSMB->ByteCount = cpu_to_le16(name_len + 1);
823         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
824                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
825         cifs_stats_inc(&tcon->num_deletes);
826         if (rc) {
827                 cFYI(1, ("Error in RMFile = %d", rc));
828         }
829
830         cifs_buf_release(pSMB);
831         if (rc == -EAGAIN)
832                 goto DelFileRetry;
833
834         return rc;
835 }
836
837 int
838 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
839              const struct nls_table *nls_codepage, int remap)
840 {
841         DELETE_DIRECTORY_REQ *pSMB = NULL;
842         DELETE_DIRECTORY_RSP *pSMBr = NULL;
843         int rc = 0;
844         int bytes_returned;
845         int name_len;
846
847         cFYI(1, ("In CIFSSMBRmDir"));
848 RmDirRetry:
849         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
850                       (void **) &pSMBr);
851         if (rc)
852                 return rc;
853
854         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
855                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
856                                          PATH_MAX, nls_codepage, remap);
857                 name_len++;     /* trailing null */
858                 name_len *= 2;
859         } else {                /* BB improve check for buffer overruns BB */
860                 name_len = strnlen(dirName, PATH_MAX);
861                 name_len++;     /* trailing null */
862                 strncpy(pSMB->DirName, dirName, name_len);
863         }
864
865         pSMB->BufferFormat = 0x04;
866         pSMB->hdr.smb_buf_length += name_len + 1;
867         pSMB->ByteCount = cpu_to_le16(name_len + 1);
868         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
869                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
870         cifs_stats_inc(&tcon->num_rmdirs);
871         if (rc) {
872                 cFYI(1, ("Error in RMDir = %d", rc));
873         }
874
875         cifs_buf_release(pSMB);
876         if (rc == -EAGAIN)
877                 goto RmDirRetry;
878         return rc;
879 }
880
881 int
882 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
883              const char *name, const struct nls_table *nls_codepage, int remap)
884 {
885         int rc = 0;
886         CREATE_DIRECTORY_REQ *pSMB = NULL;
887         CREATE_DIRECTORY_RSP *pSMBr = NULL;
888         int bytes_returned;
889         int name_len;
890
891         cFYI(1, ("In CIFSSMBMkDir"));
892 MkDirRetry:
893         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
894                       (void **) &pSMBr);
895         if (rc)
896                 return rc;
897
898         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
899                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
900                                             PATH_MAX, nls_codepage, remap);
901                 name_len++;     /* trailing null */
902                 name_len *= 2;
903         } else {                /* BB improve check for buffer overruns BB */
904                 name_len = strnlen(name, PATH_MAX);
905                 name_len++;     /* trailing null */
906                 strncpy(pSMB->DirName, name, name_len);
907         }
908
909         pSMB->BufferFormat = 0x04;
910         pSMB->hdr.smb_buf_length += name_len + 1;
911         pSMB->ByteCount = cpu_to_le16(name_len + 1);
912         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
913                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
914         cifs_stats_inc(&tcon->num_mkdirs);
915         if (rc) {
916                 cFYI(1, ("Error in Mkdir = %d", rc));
917         }
918
919         cifs_buf_release(pSMB);
920         if (rc == -EAGAIN)
921                 goto MkDirRetry;
922         return rc;
923 }
924
925 int
926 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
927                 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
928                 __u32 *pOplock, const char *name,
929                 const struct nls_table *nls_codepage, int remap)
930 {
931         TRANSACTION2_SPI_REQ *pSMB = NULL;
932         TRANSACTION2_SPI_RSP *pSMBr = NULL;
933         int name_len;
934         int rc = 0;
935         int bytes_returned = 0;
936         char *data_offset;
937         __u16 params, param_offset, offset, byte_count, count;
938         OPEN_PSX_REQ * pdata;
939         OPEN_PSX_RSP * psx_rsp;
940
941         cFYI(1, ("In POSIX Create"));
942 PsxCreat:
943         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
944                       (void **) &pSMBr);
945         if (rc)
946                 return rc;
947
948         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
949                 name_len =
950                     cifsConvertToUCS((__le16 *) pSMB->FileName, name,
951                                      PATH_MAX, nls_codepage, remap);
952                 name_len++;     /* trailing null */
953                 name_len *= 2;
954         } else {        /* BB improve the check for buffer overruns BB */
955                 name_len = strnlen(name, PATH_MAX);
956                 name_len++;     /* trailing null */
957                 strncpy(pSMB->FileName, name, name_len);
958         }
959
960         params = 6 + name_len;
961         count = sizeof(OPEN_PSX_REQ);
962         pSMB->MaxParameterCount = cpu_to_le16(2);
963         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
964         pSMB->MaxSetupCount = 0;
965         pSMB->Reserved = 0;
966         pSMB->Flags = 0;
967         pSMB->Timeout = 0;
968         pSMB->Reserved2 = 0;
969         param_offset = offsetof(struct smb_com_transaction2_spi_req,
970                                 InformationLevel) - 4;
971         offset = param_offset + params;
972         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
973         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
974         pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
975         pdata->Permissions = cpu_to_le64(mode);
976         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
977         pdata->OpenFlags =  cpu_to_le32(*pOplock);
978         pSMB->ParameterOffset = cpu_to_le16(param_offset);
979         pSMB->DataOffset = cpu_to_le16(offset);
980         pSMB->SetupCount = 1;
981         pSMB->Reserved3 = 0;
982         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
983         byte_count = 3 /* pad */  + params + count;
984
985         pSMB->DataCount = cpu_to_le16(count);
986         pSMB->ParameterCount = cpu_to_le16(params);
987         pSMB->TotalDataCount = pSMB->DataCount;
988         pSMB->TotalParameterCount = pSMB->ParameterCount;
989         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
990         pSMB->Reserved4 = 0;
991         pSMB->hdr.smb_buf_length += byte_count;
992         pSMB->ByteCount = cpu_to_le16(byte_count);
993         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
994                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
995         if (rc) {
996                 cFYI(1, ("Posix create returned %d", rc));
997                 goto psx_create_err;
998         }
999
1000         cFYI(1, ("copying inode info"));
1001         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1002
1003         if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1004                 rc = -EIO;      /* bad smb */
1005                 goto psx_create_err;
1006         }
1007
1008         /* copy return information to pRetData */
1009         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1010                         + le16_to_cpu(pSMBr->t2.DataOffset));
1011
1012         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1013         if (netfid)
1014                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1015         /* Let caller know file was created so we can set the mode. */
1016         /* Do we care about the CreateAction in any other cases? */
1017         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1018                 *pOplock |= CIFS_CREATE_ACTION;
1019         /* check to make sure response data is there */
1020         if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1021                 pRetData->Type = -1; /* unknown */
1022 #ifdef CONFIG_CIFS_DEBUG2
1023                 cFYI(1, ("unknown type"));
1024 #endif
1025         } else {
1026                 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1027                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1028                         cERROR(1, ("Open response data too small"));
1029                         pRetData->Type = -1;
1030                         goto psx_create_err;
1031                 }
1032                 memcpy((char *) pRetData,
1033                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1034                         sizeof (FILE_UNIX_BASIC_INFO));
1035         }
1036
1037 psx_create_err:
1038         cifs_buf_release(pSMB);
1039
1040         cifs_stats_inc(&tcon->num_mkdirs);
1041
1042         if (rc == -EAGAIN)
1043                 goto PsxCreat;
1044
1045         return rc;
1046 }
1047
1048 static __u16 convert_disposition(int disposition)
1049 {
1050         __u16 ofun = 0;
1051
1052         switch (disposition) {
1053                 case FILE_SUPERSEDE:
1054                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1055                         break;
1056                 case FILE_OPEN:
1057                         ofun = SMBOPEN_OAPPEND;
1058                         break;
1059                 case FILE_CREATE:
1060                         ofun = SMBOPEN_OCREATE;
1061                         break;
1062                 case FILE_OPEN_IF:
1063                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1064                         break;
1065                 case FILE_OVERWRITE:
1066                         ofun = SMBOPEN_OTRUNC;
1067                         break;
1068                 case FILE_OVERWRITE_IF:
1069                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1070                         break;
1071                 default:
1072                         cFYI(1, ("unknown disposition %d", disposition));
1073                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1074         }
1075         return ofun;
1076 }
1077
1078 int
1079 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1080             const char *fileName, const int openDisposition,
1081             const int access_flags, const int create_options, __u16 * netfid,
1082             int *pOplock, FILE_ALL_INFO * pfile_info,
1083             const struct nls_table *nls_codepage, int remap)
1084 {
1085         int rc = -EACCES;
1086         OPENX_REQ *pSMB = NULL;
1087         OPENX_RSP *pSMBr = NULL;
1088         int bytes_returned;
1089         int name_len;
1090         __u16 count;
1091
1092 OldOpenRetry:
1093         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1094                       (void **) &pSMBr);
1095         if (rc)
1096                 return rc;
1097
1098         pSMB->AndXCommand = 0xFF;       /* none */
1099
1100         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1101                 count = 1;      /* account for one byte pad to word boundary */
1102                 name_len =
1103                    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1104                                     fileName, PATH_MAX, nls_codepage, remap);
1105                 name_len++;     /* trailing null */
1106                 name_len *= 2;
1107         } else {                /* BB improve check for buffer overruns BB */
1108                 count = 0;      /* no pad */
1109                 name_len = strnlen(fileName, PATH_MAX);
1110                 name_len++;     /* trailing null */
1111                 strncpy(pSMB->fileName, fileName, name_len);
1112         }
1113         if (*pOplock & REQ_OPLOCK)
1114                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1115         else if (*pOplock & REQ_BATCHOPLOCK) {
1116                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1117         }
1118         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1119         /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1120         /* 0 = read
1121            1 = write
1122            2 = rw
1123            3 = execute
1124          */
1125         pSMB->Mode = cpu_to_le16(2);
1126         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1127         /* set file as system file if special file such
1128            as fifo and server expecting SFU style and
1129            no Unix extensions */
1130
1131         if (create_options & CREATE_OPTION_SPECIAL)
1132                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1133         else
1134                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1135
1136         /* if ((omode & S_IWUGO) == 0)
1137                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1138         /*  Above line causes problems due to vfs splitting create into two
1139             pieces - need to set mode after file created not while it is
1140             being created */
1141
1142         /* BB FIXME BB */
1143 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1144                                                  CREATE_OPTIONS_MASK); */
1145         /* BB FIXME END BB */
1146
1147         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1148         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1149         count += name_len;
1150         pSMB->hdr.smb_buf_length += count;
1151
1152         pSMB->ByteCount = cpu_to_le16(count);
1153         /* long_op set to 1 to allow for oplock break timeouts */
1154         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1155                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1156         cifs_stats_inc(&tcon->num_opens);
1157         if (rc) {
1158                 cFYI(1, ("Error in Open = %d", rc));
1159         } else {
1160         /* BB verify if wct == 15 */
1161
1162 /*              *pOplock = pSMBr->OplockLevel; */  /* BB take from action field BB */
1163
1164                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1165                 /* Let caller know file was created so we can set the mode. */
1166                 /* Do we care about the CreateAction in any other cases? */
1167         /* BB FIXME BB */
1168 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1169                         *pOplock |= CIFS_CREATE_ACTION; */
1170         /* BB FIXME END */
1171
1172                 if (pfile_info) {
1173                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1174                         pfile_info->LastAccessTime = 0; /* BB fixme */
1175                         pfile_info->LastWriteTime = 0; /* BB fixme */
1176                         pfile_info->ChangeTime = 0;  /* BB fixme */
1177                         pfile_info->Attributes =
1178                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1179                         /* the file_info buf is endian converted by caller */
1180                         pfile_info->AllocationSize =
1181                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1182                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1183                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1184                 }
1185         }
1186
1187         cifs_buf_release(pSMB);
1188         if (rc == -EAGAIN)
1189                 goto OldOpenRetry;
1190         return rc;
1191 }
1192
1193 int
1194 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1195             const char *fileName, const int openDisposition,
1196             const int access_flags, const int create_options, __u16 * netfid,
1197             int *pOplock, FILE_ALL_INFO * pfile_info,
1198             const struct nls_table *nls_codepage, int remap)
1199 {
1200         int rc = -EACCES;
1201         OPEN_REQ *pSMB = NULL;
1202         OPEN_RSP *pSMBr = NULL;
1203         int bytes_returned;
1204         int name_len;
1205         __u16 count;
1206
1207 openRetry:
1208         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1209                       (void **) &pSMBr);
1210         if (rc)
1211                 return rc;
1212
1213         pSMB->AndXCommand = 0xFF;       /* none */
1214
1215         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1216                 count = 1;      /* account for one byte pad to word boundary */
1217                 name_len =
1218                     cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1219                                      fileName, PATH_MAX, nls_codepage, remap);
1220                 name_len++;     /* trailing null */
1221                 name_len *= 2;
1222                 pSMB->NameLength = cpu_to_le16(name_len);
1223         } else {                /* BB improve check for buffer overruns BB */
1224                 count = 0;      /* no pad */
1225                 name_len = strnlen(fileName, PATH_MAX);
1226                 name_len++;     /* trailing null */
1227                 pSMB->NameLength = cpu_to_le16(name_len);
1228                 strncpy(pSMB->fileName, fileName, name_len);
1229         }
1230         if (*pOplock & REQ_OPLOCK)
1231                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1232         else if (*pOplock & REQ_BATCHOPLOCK) {
1233                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1234         }
1235         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1236         pSMB->AllocationSize = 0;
1237         /* set file as system file if special file such
1238            as fifo and server expecting SFU style and
1239            no Unix extensions */
1240         if (create_options & CREATE_OPTION_SPECIAL)
1241                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1242         else
1243                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1244         /* XP does not handle ATTR_POSIX_SEMANTICS */
1245         /* but it helps speed up case sensitive checks for other
1246         servers such as Samba */
1247         if (tcon->ses->capabilities & CAP_UNIX)
1248                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1249
1250         /* if ((omode & S_IWUGO) == 0)
1251                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1252         /*  Above line causes problems due to vfs splitting create into two
1253                 pieces - need to set mode after file created not while it is
1254                 being created */
1255         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1256         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1257         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1258         /* BB Expirement with various impersonation levels and verify */
1259         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1260         pSMB->SecurityFlags =
1261             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1262
1263         count += name_len;
1264         pSMB->hdr.smb_buf_length += count;
1265
1266         pSMB->ByteCount = cpu_to_le16(count);
1267         /* long_op set to 1 to allow for oplock break timeouts */
1268         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1269                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1270         cifs_stats_inc(&tcon->num_opens);
1271         if (rc) {
1272                 cFYI(1, ("Error in Open = %d", rc));
1273         } else {
1274                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1275                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1276                 /* Let caller know file was created so we can set the mode. */
1277                 /* Do we care about the CreateAction in any other cases? */
1278                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1279                         *pOplock |= CIFS_CREATE_ACTION;
1280                 if (pfile_info) {
1281                     memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1282                         36 /* CreationTime to Attributes */);
1283                     /* the file_info buf is endian converted by caller */
1284                     pfile_info->AllocationSize = pSMBr->AllocationSize;
1285                     pfile_info->EndOfFile = pSMBr->EndOfFile;
1286                     pfile_info->NumberOfLinks = cpu_to_le32(1);
1287                 }
1288         }
1289
1290         cifs_buf_release(pSMB);
1291         if (rc == -EAGAIN)
1292                 goto openRetry;
1293         return rc;
1294 }
1295
1296 int
1297 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1298             const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1299             char **buf, int *pbuf_type)
1300 {
1301         int rc = -EACCES;
1302         READ_REQ *pSMB = NULL;
1303         READ_RSP *pSMBr = NULL;
1304         char *pReadData = NULL;
1305         int wct;
1306         int resp_buf_type = 0;
1307         struct kvec iov[1];
1308
1309         cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1310         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1311                 wct = 12;
1312         else
1313                 wct = 10; /* old style read */
1314
1315         *nbytes = 0;
1316         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1317         if (rc)
1318                 return rc;
1319
1320         /* tcon and ses pointer are checked in smb_init */
1321         if (tcon->ses->server == NULL)
1322                 return -ECONNABORTED;
1323
1324         pSMB->AndXCommand = 0xFF;       /* none */
1325         pSMB->Fid = netfid;
1326         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1327         if (wct == 12)
1328                 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1329         else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1330                 return -EIO;
1331
1332         pSMB->Remaining = 0;
1333         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1334         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1335         if (wct == 12)
1336                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1337         else {
1338                 /* old style read */
1339                 struct smb_com_readx_req *pSMBW =
1340                         (struct smb_com_readx_req *)pSMB;
1341                 pSMBW->ByteCount = 0;
1342         }
1343
1344         iov[0].iov_base = (char *)pSMB;
1345         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1346         rc = SendReceive2(xid, tcon->ses, iov,
1347                           1 /* num iovecs */,
1348                           &resp_buf_type, 0);
1349         cifs_stats_inc(&tcon->num_reads);
1350         pSMBr = (READ_RSP *)iov[0].iov_base;
1351         if (rc) {
1352                 cERROR(1, ("Send error in read = %d", rc));
1353         } else {
1354                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1355                 data_length = data_length << 16;
1356                 data_length += le16_to_cpu(pSMBr->DataLength);
1357                 *nbytes = data_length;
1358
1359                 /*check that DataLength would not go beyond end of SMB */
1360                 if ((data_length > CIFSMaxBufSize)
1361                                 || (data_length > count)) {
1362                         cFYI(1, ("bad length %d for count %d",
1363                                  data_length, count));
1364                         rc = -EIO;
1365                         *nbytes = 0;
1366                 } else {
1367                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1368                             le16_to_cpu(pSMBr->DataOffset);
1369 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1370                                 cERROR(1,("Faulting on read rc = %d",rc));
1371                                 rc = -EFAULT;
1372                         }*/ /* can not use copy_to_user when using page cache*/
1373                         if (*buf)
1374                                 memcpy(*buf, pReadData, data_length);
1375                 }
1376         }
1377
1378 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1379         if (*buf) {
1380                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1381                         cifs_small_buf_release(iov[0].iov_base);
1382                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1383                         cifs_buf_release(iov[0].iov_base);
1384         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1385                 /* return buffer to caller to free */
1386                 *buf = iov[0].iov_base;
1387                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1388                         *pbuf_type = CIFS_SMALL_BUFFER;
1389                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1390                         *pbuf_type = CIFS_LARGE_BUFFER;
1391         } /* else no valid buffer on return - leave as null */
1392
1393         /* Note: On -EAGAIN error only caller can retry on handle based calls
1394                 since file handle passed in no longer valid */
1395         return rc;
1396 }
1397
1398
1399 int
1400 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1401              const int netfid, const unsigned int count,
1402              const __u64 offset, unsigned int *nbytes, const char *buf,
1403              const char __user *ubuf, const int long_op)
1404 {
1405         int rc = -EACCES;
1406         WRITE_REQ *pSMB = NULL;
1407         WRITE_RSP *pSMBr = NULL;
1408         int bytes_returned, wct;
1409         __u32 bytes_sent;
1410         __u16 byte_count;
1411
1412         /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1413         if (tcon->ses == NULL)
1414                 return -ECONNABORTED;
1415
1416         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1417                 wct = 14;
1418         else
1419                 wct = 12;
1420
1421         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1422                       (void **) &pSMBr);
1423         if (rc)
1424                 return rc;
1425         /* tcon and ses pointer are checked in smb_init */
1426         if (tcon->ses->server == NULL)
1427                 return -ECONNABORTED;
1428
1429         pSMB->AndXCommand = 0xFF;       /* none */
1430         pSMB->Fid = netfid;
1431         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1432         if (wct == 14)
1433                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1434         else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1435                 return -EIO;
1436
1437         pSMB->Reserved = 0xFFFFFFFF;
1438         pSMB->WriteMode = 0;
1439         pSMB->Remaining = 0;
1440
1441         /* Can increase buffer size if buffer is big enough in some cases ie we
1442         can send more if LARGE_WRITE_X capability returned by the server and if
1443         our buffer is big enough or if we convert to iovecs on socket writes
1444         and eliminate the copy to the CIFS buffer */
1445         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1446                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1447         } else {
1448                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1449                          & ~0xFF;
1450         }
1451
1452         if (bytes_sent > count)
1453                 bytes_sent = count;
1454         pSMB->DataOffset =
1455                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1456         if (buf)
1457             memcpy(pSMB->Data, buf, bytes_sent);
1458         else if (ubuf) {
1459                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1460                         cifs_buf_release(pSMB);
1461                         return -EFAULT;
1462                 }
1463         } else if (count != 0) {
1464                 /* No buffer */
1465                 cifs_buf_release(pSMB);
1466                 return -EINVAL;
1467         } /* else setting file size with write of zero bytes */
1468         if (wct == 14)
1469                 byte_count = bytes_sent + 1; /* pad */
1470         else /* wct == 12 */ {
1471                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1472         }
1473         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1474         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1475         pSMB->hdr.smb_buf_length += byte_count;
1476
1477         if (wct == 14)
1478                 pSMB->ByteCount = cpu_to_le16(byte_count);
1479         else { /* old style write has byte count 4 bytes earlier
1480                   so 4 bytes pad  */
1481                 struct smb_com_writex_req *pSMBW =
1482                         (struct smb_com_writex_req *)pSMB;
1483                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1484         }
1485
1486         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1487                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1488         cifs_stats_inc(&tcon->num_writes);
1489         if (rc) {
1490                 cFYI(1, ("Send error in write = %d", rc));
1491                 *nbytes = 0;
1492         } else {
1493                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1494                 *nbytes = (*nbytes) << 16;
1495                 *nbytes += le16_to_cpu(pSMBr->Count);
1496         }
1497
1498         cifs_buf_release(pSMB);
1499
1500         /* Note: On -EAGAIN error only caller can retry on handle based calls
1501                 since file handle passed in no longer valid */
1502
1503         return rc;
1504 }
1505
1506 int
1507 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1508              const int netfid, const unsigned int count,
1509              const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1510              int n_vec, const int long_op)
1511 {
1512         int rc = -EACCES;
1513         WRITE_REQ *pSMB = NULL;
1514         int wct;
1515         int smb_hdr_len;
1516         int resp_buf_type = 0;
1517
1518         cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1519
1520         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1521                 wct = 14;
1522         else
1523                 wct = 12;
1524         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1525         if (rc)
1526                 return rc;
1527         /* tcon and ses pointer are checked in smb_init */
1528         if (tcon->ses->server == NULL)
1529                 return -ECONNABORTED;
1530
1531         pSMB->AndXCommand = 0xFF;       /* none */
1532         pSMB->Fid = netfid;
1533         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1534         if (wct == 14)
1535                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1536         else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1537                 return -EIO;
1538         pSMB->Reserved = 0xFFFFFFFF;
1539         pSMB->WriteMode = 0;
1540         pSMB->Remaining = 0;
1541
1542         pSMB->DataOffset =
1543             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1544
1545         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1546         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1547         smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1548         if (wct == 14)
1549                 pSMB->hdr.smb_buf_length += count+1;
1550         else /* wct == 12 */
1551                 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1552         if (wct == 14)
1553                 pSMB->ByteCount = cpu_to_le16(count + 1);
1554         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1555                 struct smb_com_writex_req *pSMBW =
1556                                 (struct smb_com_writex_req *)pSMB;
1557                 pSMBW->ByteCount = cpu_to_le16(count + 5);
1558         }
1559         iov[0].iov_base = pSMB;
1560         if (wct == 14)
1561                 iov[0].iov_len = smb_hdr_len + 4;
1562         else /* wct == 12 pad bigger by four bytes */
1563                 iov[0].iov_len = smb_hdr_len + 8;
1564
1565
1566         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1567                           long_op);
1568         cifs_stats_inc(&tcon->num_writes);
1569         if (rc) {
1570                 cFYI(1, ("Send error Write2 = %d", rc));
1571                 *nbytes = 0;
1572         } else if (resp_buf_type == 0) {
1573                 /* presumably this can not happen, but best to be safe */
1574                 rc = -EIO;
1575                 *nbytes = 0;
1576         } else {
1577                 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1578                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1579                 *nbytes = (*nbytes) << 16;
1580                 *nbytes += le16_to_cpu(pSMBr->Count);
1581         }
1582
1583 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1584         if (resp_buf_type == CIFS_SMALL_BUFFER)
1585                 cifs_small_buf_release(iov[0].iov_base);
1586         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1587                 cifs_buf_release(iov[0].iov_base);
1588
1589         /* Note: On -EAGAIN error only caller can retry on handle based calls
1590                 since file handle passed in no longer valid */
1591
1592         return rc;
1593 }
1594
1595
1596 int
1597 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1598             const __u16 smb_file_id, const __u64 len,
1599             const __u64 offset, const __u32 numUnlock,
1600             const __u32 numLock, const __u8 lockType, const int waitFlag)
1601 {
1602         int rc = 0;
1603         LOCK_REQ *pSMB = NULL;
1604         LOCK_RSP *pSMBr = NULL;
1605         int bytes_returned;
1606         int timeout = 0;
1607         __u16 count;
1608
1609         cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1610         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1611
1612         if (rc)
1613                 return rc;
1614
1615         pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1616
1617         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1618                 timeout = -1; /* no response expected */
1619                 pSMB->Timeout = 0;
1620         } else if (waitFlag == TRUE) {
1621                 timeout = 3;  /* blocking operation, no timeout */
1622                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1623         } else {
1624                 pSMB->Timeout = 0;
1625         }
1626
1627         pSMB->NumberOfLocks = cpu_to_le16(numLock);
1628         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1629         pSMB->LockType = lockType;
1630         pSMB->AndXCommand = 0xFF;       /* none */
1631         pSMB->Fid = smb_file_id; /* netfid stays le */
1632
1633         if ((numLock != 0) || (numUnlock != 0)) {
1634                 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1635                 /* BB where to store pid high? */
1636                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1637                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1638                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1639                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1640                 count = sizeof(LOCKING_ANDX_RANGE);
1641         } else {
1642                 /* oplock break */
1643                 count = 0;
1644         }
1645         pSMB->hdr.smb_buf_length += count;
1646         pSMB->ByteCount = cpu_to_le16(count);
1647
1648         if (waitFlag) {
1649                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1650                         (struct smb_hdr *) pSMBr, &bytes_returned);
1651         } else {
1652                 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1653                          (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1654         }
1655         cifs_stats_inc(&tcon->num_locks);
1656         if (rc) {
1657                 cFYI(1, ("Send error in Lock = %d", rc));
1658         }
1659         cifs_small_buf_release(pSMB);
1660
1661         /* Note: On -EAGAIN error only caller can retry on handle based calls
1662         since file handle passed in no longer valid */
1663         return rc;
1664 }
1665
1666 int
1667 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1668                 const __u16 smb_file_id, const int get_flag, const __u64 len,
1669                 struct file_lock *pLockData, const __u16 lock_type,
1670                 const int waitFlag)
1671 {
1672         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1673         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1674         char *data_offset;
1675         struct cifs_posix_lock *parm_data;
1676         int rc = 0;
1677         int timeout = 0;
1678         int bytes_returned = 0;
1679         __u16 params, param_offset, offset, byte_count, count;
1680
1681         cFYI(1, ("Posix Lock"));
1682
1683         if (pLockData == NULL)
1684                 return EINVAL;
1685
1686         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1687
1688         if (rc)
1689                 return rc;
1690
1691         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1692
1693         params = 6;
1694         pSMB->MaxSetupCount = 0;
1695         pSMB->Reserved = 0;
1696         pSMB->Flags = 0;
1697         pSMB->Reserved2 = 0;
1698         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1699         offset = param_offset + params;
1700
1701         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1702
1703         count = sizeof(struct cifs_posix_lock);
1704         pSMB->MaxParameterCount = cpu_to_le16(2);
1705         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1706         pSMB->SetupCount = 1;
1707         pSMB->Reserved3 = 0;
1708         if (get_flag)
1709                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1710         else
1711                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1712         byte_count = 3 /* pad */  + params + count;
1713         pSMB->DataCount = cpu_to_le16(count);
1714         pSMB->ParameterCount = cpu_to_le16(params);
1715         pSMB->TotalDataCount = pSMB->DataCount;
1716         pSMB->TotalParameterCount = pSMB->ParameterCount;
1717         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1718         parm_data = (struct cifs_posix_lock *)
1719                         (((char *) &pSMB->hdr.Protocol) + offset);
1720
1721         parm_data->lock_type = cpu_to_le16(lock_type);
1722         if (waitFlag) {
1723                 timeout = 3;  /* blocking operation, no timeout */
1724                 parm_data->lock_flags = cpu_to_le16(1);
1725                 pSMB->Timeout = cpu_to_le32(-1);
1726         } else
1727                 pSMB->Timeout = 0;
1728
1729         parm_data->pid = cpu_to_le32(current->tgid);
1730         parm_data->start = cpu_to_le64(pLockData->fl_start);
1731         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
1732
1733         pSMB->DataOffset = cpu_to_le16(offset);
1734         pSMB->Fid = smb_file_id;
1735         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1736         pSMB->Reserved4 = 0;
1737         pSMB->hdr.smb_buf_length += byte_count;
1738         pSMB->ByteCount = cpu_to_le16(byte_count);
1739         if (waitFlag) {
1740                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1741                         (struct smb_hdr *) pSMBr, &bytes_returned);
1742         } else {
1743                 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1744                         (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1745         }
1746
1747         if (rc) {
1748                 cFYI(1, ("Send error in Posix Lock = %d", rc));
1749         } else if (get_flag) {
1750                 /* lock structure can be returned on get */
1751                 __u16 data_offset;
1752                 __u16 data_count;
1753                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1754
1755                 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1756                         rc = -EIO;      /* bad smb */
1757                         goto plk_err_exit;
1758                 }
1759                 if (pLockData == NULL) {
1760                         rc = -EINVAL;
1761                         goto plk_err_exit;
1762                 }
1763                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1764                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
1765                 if (data_count < sizeof(struct cifs_posix_lock)) {
1766                         rc = -EIO;
1767                         goto plk_err_exit;
1768                 }
1769                 parm_data = (struct cifs_posix_lock *)
1770                         ((char *)&pSMBr->hdr.Protocol + data_offset);
1771                 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1772                         pLockData->fl_type = F_UNLCK;
1773         }
1774
1775 plk_err_exit:
1776         if (pSMB)
1777                 cifs_small_buf_release(pSMB);
1778
1779         /* Note: On -EAGAIN error only caller can retry on handle based calls
1780            since file handle passed in no longer valid */
1781
1782         return rc;
1783 }
1784
1785
1786 int
1787 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1788 {
1789         int rc = 0;
1790         CLOSE_REQ *pSMB = NULL;
1791         CLOSE_RSP *pSMBr = NULL;
1792         int bytes_returned;
1793         cFYI(1, ("In CIFSSMBClose"));
1794
1795 /* do not retry on dead session on close */
1796         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1797         if (rc == -EAGAIN)
1798                 return 0;
1799         if (rc)
1800                 return rc;
1801
1802         pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1803
1804         pSMB->FileID = (__u16) smb_file_id;
1805         pSMB->LastWriteTime = 0xFFFFFFFF;
1806         pSMB->ByteCount = 0;
1807         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1808                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1809         cifs_stats_inc(&tcon->num_closes);
1810         if (rc) {
1811                 if (rc != -EINTR) {
1812                         /* EINTR is expected when user ctl-c to kill app */
1813                         cERROR(1, ("Send error in Close = %d", rc));
1814                 }
1815         }
1816
1817         cifs_small_buf_release(pSMB);
1818
1819         /* Since session is dead, file will be closed on server already */
1820         if (rc == -EAGAIN)
1821                 rc = 0;
1822
1823         return rc;
1824 }
1825
1826 int
1827 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1828               const char *fromName, const char *toName,
1829               const struct nls_table *nls_codepage, int remap)
1830 {
1831         int rc = 0;
1832         RENAME_REQ *pSMB = NULL;
1833         RENAME_RSP *pSMBr = NULL;
1834         int bytes_returned;
1835         int name_len, name_len2;
1836         __u16 count;
1837
1838         cFYI(1, ("In CIFSSMBRename"));
1839 renameRetry:
1840         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1841                       (void **) &pSMBr);
1842         if (rc)
1843                 return rc;
1844
1845         pSMB->BufferFormat = 0x04;
1846         pSMB->SearchAttributes =
1847             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1848                         ATTR_DIRECTORY);
1849
1850         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1851                 name_len =
1852                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1853                                      PATH_MAX, nls_codepage, remap);
1854                 name_len++;     /* trailing null */
1855                 name_len *= 2;
1856                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1857         /* protocol requires ASCII signature byte on Unicode string */
1858                 pSMB->OldFileName[name_len + 1] = 0x00;
1859                 name_len2 =
1860                     cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1861                                      toName, PATH_MAX, nls_codepage, remap);
1862                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1863                 name_len2 *= 2; /* convert to bytes */
1864         } else {        /* BB improve the check for buffer overruns BB */
1865                 name_len = strnlen(fromName, PATH_MAX);
1866                 name_len++;     /* trailing null */
1867                 strncpy(pSMB->OldFileName, fromName, name_len);
1868                 name_len2 = strnlen(toName, PATH_MAX);
1869                 name_len2++;    /* trailing null */
1870                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1871                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1872                 name_len2++;    /* trailing null */
1873                 name_len2++;    /* signature byte */
1874         }
1875
1876         count = 1 /* 1st signature byte */  + name_len + name_len2;
1877         pSMB->hdr.smb_buf_length += count;
1878         pSMB->ByteCount = cpu_to_le16(count);
1879
1880         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1881                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1882         cifs_stats_inc(&tcon->num_renames);
1883         if (rc) {
1884                 cFYI(1, ("Send error in rename = %d", rc));
1885         }
1886
1887         cifs_buf_release(pSMB);
1888
1889         if (rc == -EAGAIN)
1890                 goto renameRetry;
1891
1892         return rc;
1893 }
1894
1895 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1896                 int netfid, char *target_name,
1897                 const struct nls_table *nls_codepage, int remap)
1898 {
1899         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1900         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1901         struct set_file_rename *rename_info;
1902         char *data_offset;
1903         char dummy_string[30];
1904         int rc = 0;
1905         int bytes_returned = 0;
1906         int len_of_str;
1907         __u16 params, param_offset, offset, count, byte_count;
1908
1909         cFYI(1, ("Rename to File by handle"));
1910         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1911                         (void **) &pSMBr);
1912         if (rc)
1913                 return rc;
1914
1915         params = 6;
1916         pSMB->MaxSetupCount = 0;
1917         pSMB->Reserved = 0;
1918         pSMB->Flags = 0;
1919         pSMB->Timeout = 0;
1920         pSMB->Reserved2 = 0;
1921         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1922         offset = param_offset + params;
1923
1924         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1925         rename_info = (struct set_file_rename *) data_offset;
1926         pSMB->MaxParameterCount = cpu_to_le16(2);
1927         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1928         pSMB->SetupCount = 1;
1929         pSMB->Reserved3 = 0;
1930         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1931         byte_count = 3 /* pad */  + params;
1932         pSMB->ParameterCount = cpu_to_le16(params);
1933         pSMB->TotalParameterCount = pSMB->ParameterCount;
1934         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1935         pSMB->DataOffset = cpu_to_le16(offset);
1936         /* construct random name ".cifs_tmp<inodenum><mid>" */
1937         rename_info->overwrite = cpu_to_le32(1);
1938         rename_info->root_fid  = 0;
1939         /* unicode only call */
1940         if (target_name == NULL) {
1941                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
1942                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1943                                         dummy_string, 24, nls_codepage, remap);
1944         } else {
1945                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1946                                         target_name, PATH_MAX, nls_codepage,
1947                                         remap);
1948         }
1949         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1950         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1951         byte_count += count;
1952         pSMB->DataCount = cpu_to_le16(count);
1953         pSMB->TotalDataCount = pSMB->DataCount;
1954         pSMB->Fid = netfid;
1955         pSMB->InformationLevel =
1956                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1957         pSMB->Reserved4 = 0;
1958         pSMB->hdr.smb_buf_length += byte_count;
1959         pSMB->ByteCount = cpu_to_le16(byte_count);
1960         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1961                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1962         cifs_stats_inc(&pTcon->num_t2renames);
1963         if (rc) {
1964                 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
1965         }
1966
1967         cifs_buf_release(pSMB);
1968
1969         /* Note: On -EAGAIN error only caller can retry on handle based calls
1970                 since file handle passed in no longer valid */
1971
1972         return rc;
1973 }
1974
1975 int
1976 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
1977             const __u16 target_tid, const char *toName, const int flags,
1978             const struct nls_table *nls_codepage, int remap)
1979 {
1980         int rc = 0;
1981         COPY_REQ *pSMB = NULL;
1982         COPY_RSP *pSMBr = NULL;
1983         int bytes_returned;
1984         int name_len, name_len2;
1985         __u16 count;
1986
1987         cFYI(1, ("In CIFSSMBCopy"));
1988 copyRetry:
1989         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1990                         (void **) &pSMBr);
1991         if (rc)
1992                 return rc;
1993
1994         pSMB->BufferFormat = 0x04;
1995         pSMB->Tid2 = target_tid;
1996
1997         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1998
1999         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2000                 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2001                                             fromName, PATH_MAX, nls_codepage,
2002                                             remap);
2003                 name_len++;     /* trailing null */
2004                 name_len *= 2;
2005                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2006                 /* protocol requires ASCII signature byte on Unicode string */
2007                 pSMB->OldFileName[name_len + 1] = 0x00;
2008                 name_len2 =
2009                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2010                                 toName, PATH_MAX, nls_codepage, remap);
2011                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2012                 name_len2 *= 2; /* convert to bytes */
2013         } else {        /* BB improve the check for buffer overruns BB */
2014                 name_len = strnlen(fromName, PATH_MAX);
2015                 name_len++;     /* trailing null */
2016                 strncpy(pSMB->OldFileName, fromName, name_len);
2017                 name_len2 = strnlen(toName, PATH_MAX);
2018                 name_len2++;    /* trailing null */
2019                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2020                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2021                 name_len2++;    /* trailing null */
2022                 name_len2++;    /* signature byte */
2023         }
2024
2025         count = 1 /* 1st signature byte */  + name_len + name_len2;
2026         pSMB->hdr.smb_buf_length += count;
2027         pSMB->ByteCount = cpu_to_le16(count);
2028
2029         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2030                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2031         if (rc) {
2032                 cFYI(1, ("Send error in copy = %d with %d files copied",
2033                         rc, le16_to_cpu(pSMBr->CopyCount)));
2034         }
2035         if (pSMB)
2036                 cifs_buf_release(pSMB);
2037
2038         if (rc == -EAGAIN)
2039                 goto copyRetry;
2040
2041         return rc;
2042 }
2043
2044 int
2045 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2046                       const char *fromName, const char *toName,
2047                       const struct nls_table *nls_codepage)
2048 {
2049         TRANSACTION2_SPI_REQ *pSMB = NULL;
2050         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2051         char *data_offset;
2052         int name_len;
2053         int name_len_target;
2054         int rc = 0;
2055         int bytes_returned = 0;
2056         __u16 params, param_offset, offset, byte_count;
2057
2058         cFYI(1, ("In Symlink Unix style"));
2059 createSymLinkRetry:
2060         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2061                       (void **) &pSMBr);
2062         if (rc)
2063                 return rc;
2064
2065         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2066                 name_len =
2067                     cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2068                                   /* find define for this maxpathcomponent */
2069                                   , nls_codepage);
2070                 name_len++;     /* trailing null */
2071                 name_len *= 2;
2072
2073         } else {        /* BB improve the check for buffer overruns BB */
2074                 name_len = strnlen(fromName, PATH_MAX);
2075                 name_len++;     /* trailing null */
2076                 strncpy(pSMB->FileName, fromName, name_len);
2077         }
2078         params = 6 + name_len;
2079         pSMB->MaxSetupCount = 0;
2080         pSMB->Reserved = 0;
2081         pSMB->Flags = 0;
2082         pSMB->Timeout = 0;
2083         pSMB->Reserved2 = 0;
2084         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2085                                 InformationLevel) - 4;
2086         offset = param_offset + params;
2087
2088         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2089         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2090                 name_len_target =
2091                     cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2092                                   /* find define for this maxpathcomponent */
2093                                   , nls_codepage);
2094                 name_len_target++;      /* trailing null */
2095                 name_len_target *= 2;
2096         } else {        /* BB improve the check for buffer overruns BB */
2097                 name_len_target = strnlen(toName, PATH_MAX);
2098                 name_len_target++;      /* trailing null */
2099                 strncpy(data_offset, toName, name_len_target);
2100         }
2101
2102         pSMB->MaxParameterCount = cpu_to_le16(2);
2103         /* BB find exact max on data count below from sess */
2104         pSMB->MaxDataCount = cpu_to_le16(1000);
2105         pSMB->SetupCount = 1;
2106         pSMB->Reserved3 = 0;
2107         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2108         byte_count = 3 /* pad */  + params + name_len_target;
2109         pSMB->DataCount = cpu_to_le16(name_len_target);
2110         pSMB->ParameterCount = cpu_to_le16(params);
2111         pSMB->TotalDataCount = pSMB->DataCount;
2112         pSMB->TotalParameterCount = pSMB->ParameterCount;
2113         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2114         pSMB->DataOffset = cpu_to_le16(offset);
2115         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2116         pSMB->Reserved4 = 0;
2117         pSMB->hdr.smb_buf_length += byte_count;
2118         pSMB->ByteCount = cpu_to_le16(byte_count);
2119         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2120                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2121         cifs_stats_inc(&tcon->num_symlinks);
2122         if (rc) {
2123                 cFYI(1,
2124                      ("Send error in SetPathInfo (create symlink) = %d",
2125                       rc));
2126         }
2127
2128         if (pSMB)
2129                 cifs_buf_release(pSMB);
2130
2131         if (rc == -EAGAIN)
2132                 goto createSymLinkRetry;
2133
2134         return rc;
2135 }
2136
2137 int
2138 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2139                        const char *fromName, const char *toName,
2140                        const struct nls_table *nls_codepage, int remap)
2141 {
2142         TRANSACTION2_SPI_REQ *pSMB = NULL;
2143         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2144         char *data_offset;
2145         int name_len;
2146         int name_len_target;
2147         int rc = 0;
2148         int bytes_returned = 0;
2149         __u16 params, param_offset, offset, byte_count;
2150
2151         cFYI(1, ("In Create Hard link Unix style"));
2152 createHardLinkRetry:
2153         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2154                       (void **) &pSMBr);
2155         if (rc)
2156                 return rc;
2157
2158         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2159                 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2160                                             PATH_MAX, nls_codepage, remap);
2161                 name_len++;     /* trailing null */
2162                 name_len *= 2;
2163
2164         } else {        /* BB improve the check for buffer overruns BB */
2165                 name_len = strnlen(toName, PATH_MAX);
2166                 name_len++;     /* trailing null */
2167                 strncpy(pSMB->FileName, toName, name_len);
2168         }
2169         params = 6 + name_len;
2170         pSMB->MaxSetupCount = 0;
2171         pSMB->Reserved = 0;
2172         pSMB->Flags = 0;
2173         pSMB->Timeout = 0;
2174         pSMB->Reserved2 = 0;
2175         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2176                                 InformationLevel) - 4;
2177         offset = param_offset + params;
2178
2179         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2180         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2181                 name_len_target =
2182                     cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2183                                      nls_codepage, remap);
2184                 name_len_target++;      /* trailing null */
2185                 name_len_target *= 2;
2186         } else {        /* BB improve the check for buffer overruns BB */
2187                 name_len_target = strnlen(fromName, PATH_MAX);
2188                 name_len_target++;      /* trailing null */
2189                 strncpy(data_offset, fromName, name_len_target);
2190         }
2191
2192         pSMB->MaxParameterCount = cpu_to_le16(2);
2193         /* BB find exact max on data count below from sess*/
2194         pSMB->MaxDataCount = cpu_to_le16(1000);
2195         pSMB->SetupCount = 1;
2196         pSMB->Reserved3 = 0;
2197         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2198         byte_count = 3 /* pad */  + params + name_len_target;
2199         pSMB->ParameterCount = cpu_to_le16(params);
2200         pSMB->TotalParameterCount = pSMB->ParameterCount;
2201         pSMB->DataCount = cpu_to_le16(name_len_target);
2202         pSMB->TotalDataCount = pSMB->DataCount;
2203         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2204         pSMB->DataOffset = cpu_to_le16(offset);
2205         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2206         pSMB->Reserved4 = 0;
2207         pSMB->hdr.smb_buf_length += byte_count;
2208         pSMB->ByteCount = cpu_to_le16(byte_count);
2209         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2210                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2211         cifs_stats_inc(&tcon->num_hardlinks);
2212         if (rc) {
2213                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2214         }
2215
2216         cifs_buf_release(pSMB);
2217         if (rc == -EAGAIN)
2218                 goto createHardLinkRetry;
2219
2220         return rc;
2221 }
2222
2223 int
2224 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2225                    const char *fromName, const char *toName,
2226                    const struct nls_table *nls_codepage, int remap)
2227 {
2228         int rc = 0;
2229         NT_RENAME_REQ *pSMB = NULL;
2230         RENAME_RSP *pSMBr = NULL;
2231         int bytes_returned;
2232         int name_len, name_len2;
2233         __u16 count;
2234
2235         cFYI(1, ("In CIFSCreateHardLink"));
2236 winCreateHardLinkRetry:
2237
2238         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2239                       (void **) &pSMBr);
2240         if (rc)
2241                 return rc;
2242
2243         pSMB->SearchAttributes =
2244             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2245                         ATTR_DIRECTORY);
2246         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2247         pSMB->ClusterCount = 0;
2248
2249         pSMB->BufferFormat = 0x04;
2250
2251         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2252                 name_len =
2253                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2254                                      PATH_MAX, nls_codepage, remap);
2255                 name_len++;     /* trailing null */
2256                 name_len *= 2;
2257                 pSMB->OldFileName[name_len] = 0;        /* pad */
2258                 pSMB->OldFileName[name_len + 1] = 0x04;
2259                 name_len2 =
2260                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2261                                      toName, PATH_MAX, nls_codepage, remap);
2262                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2263                 name_len2 *= 2; /* convert to bytes */
2264         } else {        /* BB improve the check for buffer overruns BB */
2265                 name_len = strnlen(fromName, PATH_MAX);
2266                 name_len++;     /* trailing null */
2267                 strncpy(pSMB->OldFileName, fromName, name_len);
2268                 name_len2 = strnlen(toName, PATH_MAX);
2269                 name_len2++;    /* trailing null */
2270                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2271                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2272                 name_len2++;    /* trailing null */
2273                 name_len2++;    /* signature byte */
2274         }
2275
2276         count = 1 /* string type byte */  + name_len + name_len2;
2277         pSMB->hdr.smb_buf_length += count;
2278         pSMB->ByteCount = cpu_to_le16(count);
2279
2280         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2281                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2282         cifs_stats_inc(&tcon->num_hardlinks);
2283         if (rc) {
2284                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2285         }
2286         cifs_buf_release(pSMB);
2287         if (rc == -EAGAIN)
2288                 goto winCreateHardLinkRetry;
2289
2290         return rc;
2291 }
2292
2293 int
2294 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2295                         const unsigned char *searchName,
2296                         char *symlinkinfo, const int buflen,
2297                         const struct nls_table *nls_codepage)
2298 {
2299 /* SMB_QUERY_FILE_UNIX_LINK */
2300         TRANSACTION2_QPI_REQ *pSMB = NULL;
2301         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2302         int rc = 0;
2303         int bytes_returned;
2304         int name_len;
2305         __u16 params, byte_count;
2306
2307         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2308
2309 querySymLinkRetry:
2310         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2311                       (void **) &pSMBr);
2312         if (rc)
2313                 return rc;
2314
2315         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2316                 name_len =
2317                     cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2318                                   PATH_MAX, nls_codepage);
2319                 name_len++;     /* trailing null */
2320                 name_len *= 2;
2321         } else {        /* BB improve the check for buffer overruns BB */
2322                 name_len = strnlen(searchName, PATH_MAX);
2323                 name_len++;     /* trailing null */
2324                 strncpy(pSMB->FileName, searchName, name_len);
2325         }
2326
2327         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2328         pSMB->TotalDataCount = 0;
2329         pSMB->MaxParameterCount = cpu_to_le16(2);
2330         /* BB find exact max data count below from sess structure BB */
2331         pSMB->MaxDataCount = cpu_to_le16(4000);
2332         pSMB->MaxSetupCount = 0;
2333         pSMB->Reserved = 0;
2334         pSMB->Flags = 0;
2335         pSMB->Timeout = 0;
2336         pSMB->Reserved2 = 0;
2337         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2338         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2339         pSMB->DataCount = 0;
2340         pSMB->DataOffset = 0;
2341         pSMB->SetupCount = 1;
2342         pSMB->Reserved3 = 0;
2343         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2344         byte_count = params + 1 /* pad */ ;
2345         pSMB->TotalParameterCount = cpu_to_le16(params);
2346         pSMB->ParameterCount = pSMB->TotalParameterCount;
2347         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2348         pSMB->Reserved4 = 0;
2349         pSMB->hdr.smb_buf_length += byte_count;
2350         pSMB->ByteCount = cpu_to_le16(byte_count);
2351
2352         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2353                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2354         if (rc) {
2355                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2356         } else {
2357                 /* decode response */
2358
2359                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2360                 if (rc || (pSMBr->ByteCount < 2))
2361                 /* BB also check enough total bytes returned */
2362                         rc = -EIO;      /* bad smb */
2363                 else {
2364                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2365                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2366
2367                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2368                                 name_len = UniStrnlen((wchar_t *) ((char *)
2369                                         &pSMBr->hdr.Protocol + data_offset),
2370                                         min_t(const int, buflen, count) / 2);
2371                         /* BB FIXME investigate remapping reserved chars here */
2372                                 cifs_strfromUCS_le(symlinkinfo,
2373                                         (__le16 *) ((char *)&pSMBr->hdr.Protocol
2374                                                         + data_offset),
2375                                         name_len, nls_codepage);
2376                         } else {
2377                                 strncpy(symlinkinfo,
2378                                         (char *) &pSMBr->hdr.Protocol +
2379                                                 data_offset,
2380                                         min_t(const int, buflen, count));
2381                         }
2382                         symlinkinfo[buflen] = 0;
2383         /* just in case so calling code does not go off the end of buffer */
2384                 }
2385         }
2386         cifs_buf_release(pSMB);
2387         if (rc == -EAGAIN)
2388                 goto querySymLinkRetry;
2389         return rc;
2390 }
2391
2392 /* Initialize NT TRANSACT SMB into small smb request buffer.
2393    This assumes that all NT TRANSACTS that we init here have
2394    total parm and data under about 400 bytes (to fit in small cifs
2395    buffer size), which is the case so far, it easily fits. NB:
2396         Setup words themselves and ByteCount
2397         MaxSetupCount (size of returned setup area) and
2398         MaxParameterCount (returned parms size) must be set by caller */
2399 static int
2400 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2401                    const int parm_len, struct cifsTconInfo *tcon,
2402                    void **ret_buf)
2403 {
2404         int rc;
2405         __u32 temp_offset;
2406         struct smb_com_ntransact_req *pSMB;
2407
2408         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2409                                 (void **)&pSMB);
2410         if (rc)
2411                 return rc;
2412         *ret_buf = (void *)pSMB;
2413         pSMB->Reserved = 0;
2414         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2415         pSMB->TotalDataCount  = 0;
2416         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2417                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2418         pSMB->ParameterCount = pSMB->TotalParameterCount;
2419         pSMB->DataCount  = pSMB->TotalDataCount;
2420         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2421                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
2422         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2423         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2424         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2425         pSMB->SubCommand = cpu_to_le16(sub_command);
2426         return 0;
2427 }
2428
2429 static int
2430 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2431                    int *pdatalen, int *pparmlen)
2432 {
2433         char *end_of_smb;
2434         __u32 data_count, data_offset, parm_count, parm_offset;
2435         struct smb_com_ntransact_rsp *pSMBr;
2436
2437         if (buf == NULL)
2438                 return -EINVAL;
2439
2440         pSMBr = (struct smb_com_ntransact_rsp *)buf;
2441
2442         /* ByteCount was converted from little endian in SendReceive */
2443         end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2444                         (char *)&pSMBr->ByteCount;
2445
2446         data_offset = le32_to_cpu(pSMBr->DataOffset);
2447         data_count = le32_to_cpu(pSMBr->DataCount);
2448         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2449         parm_count = le32_to_cpu(pSMBr->ParameterCount);
2450
2451         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2452         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2453
2454         /* should we also check that parm and data areas do not overlap? */
2455         if (*ppparm > end_of_smb) {
2456                 cFYI(1, ("parms start after end of smb"));
2457                 return -EINVAL;
2458         } else if (parm_count + *ppparm > end_of_smb) {
2459                 cFYI(1, ("parm end after end of smb"));
2460                 return -EINVAL;
2461         } else if (*ppdata > end_of_smb) {
2462                 cFYI(1, ("data starts after end of smb"));
2463                 return -EINVAL;
2464         } else if (data_count + *ppdata > end_of_smb) {
2465                 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2466                         *ppdata, data_count, (data_count + *ppdata),
2467                         end_of_smb, pSMBr));
2468                 return -EINVAL;
2469         } else if (parm_count + data_count > pSMBr->ByteCount) {
2470                 cFYI(1, ("parm count and data count larger than SMB"));
2471                 return -EINVAL;
2472         }
2473         return 0;
2474 }
2475
2476 int
2477 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2478                         const unsigned char *searchName,
2479                         char *symlinkinfo, const int buflen, __u16 fid,
2480                         const struct nls_table *nls_codepage)
2481 {
2482         int rc = 0;
2483         int bytes_returned;
2484         int name_len;
2485         struct smb_com_transaction_ioctl_req *pSMB;
2486         struct smb_com_transaction_ioctl_rsp *pSMBr;
2487
2488         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2489         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2490                       (void **) &pSMBr);
2491         if (rc)
2492                 return rc;
2493
2494         pSMB->TotalParameterCount = 0 ;
2495         pSMB->TotalDataCount = 0;
2496         pSMB->MaxParameterCount = cpu_to_le32(2);
2497         /* BB find exact data count max from sess structure BB */
2498         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2499                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2500         pSMB->MaxSetupCount = 4;
2501         pSMB->Reserved = 0;
2502         pSMB->ParameterOffset = 0;
2503         pSMB->DataCount = 0;
2504         pSMB->DataOffset = 0;
2505         pSMB->SetupCount = 4;
2506         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2507         pSMB->ParameterCount = pSMB->TotalParameterCount;
2508         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2509         pSMB->IsFsctl = 1; /* FSCTL */
2510         pSMB->IsRootFlag = 0;
2511         pSMB->Fid = fid; /* file handle always le */
2512         pSMB->ByteCount = 0;
2513
2514         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2515                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2516         if (rc) {
2517                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2518         } else {                /* decode response */
2519                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2520                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2521                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2522                 /* BB also check enough total bytes returned */
2523                         rc = -EIO;      /* bad smb */
2524                 else {
2525                         if (data_count && (data_count < 2048)) {
2526                                 char *end_of_smb = 2 /* sizeof byte count */ +
2527                                                 pSMBr->ByteCount +
2528                                                 (char *)&pSMBr->ByteCount;
2529
2530                                 struct reparse_data *reparse_buf =
2531                                                 (struct reparse_data *)
2532                                                 ((char *)&pSMBr->hdr.Protocol
2533                                                                  + data_offset);
2534                                 if ((char *)reparse_buf >= end_of_smb) {
2535                                         rc = -EIO;
2536                                         goto qreparse_out;
2537                                 }
2538                                 if ((reparse_buf->LinkNamesBuf +
2539                                         reparse_buf->TargetNameOffset +
2540                                         reparse_buf->TargetNameLen) >
2541                                                 end_of_smb) {
2542                                         cFYI(1,("reparse buf extended beyond SMB"));
2543                                         rc = -EIO;
2544                                         goto qreparse_out;
2545                                 }
2546
2547                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2548                                         name_len = UniStrnlen((wchar_t *)
2549                                                 (reparse_buf->LinkNamesBuf +
2550                                                 reparse_buf->TargetNameOffset),
2551                                                 min(buflen/2,
2552                                                 reparse_buf->TargetNameLen / 2));
2553                                         cifs_strfromUCS_le(symlinkinfo,
2554                                                 (__le16 *) (reparse_buf->LinkNamesBuf +
2555                                                 reparse_buf->TargetNameOffset),
2556                                                 name_len, nls_codepage);
2557                                 } else { /* ASCII names */
2558                                         strncpy(symlinkinfo,
2559                                                 reparse_buf->LinkNamesBuf +
2560                                                 reparse_buf->TargetNameOffset,
2561                                                 min_t(const int, buflen,
2562                                                    reparse_buf->TargetNameLen));
2563                                 }
2564                         } else {
2565                                 rc = -EIO;
2566                                 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2567                         }
2568                         symlinkinfo[buflen] = 0; /* just in case so the caller
2569                                         does not go off the end of the buffer */
2570                         cFYI(1, ("readlink result - %s", symlinkinfo));
2571                 }
2572         }
2573 qreparse_out:
2574         cifs_buf_release(pSMB);
2575
2576         /* Note: On -EAGAIN error only caller can retry on handle based calls
2577                 since file handle passed in no longer valid */
2578
2579         return rc;
2580 }
2581
2582 #ifdef CONFIG_CIFS_POSIX
2583
2584 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2585 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2586                              struct cifs_posix_ace *cifs_ace)
2587 {
2588         /* u8 cifs fields do not need le conversion */
2589         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2590         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2591         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2592         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2593
2594         return;
2595 }
2596
2597 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2598 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2599                                const int acl_type, const int size_of_data_area)
2600 {
2601         int size =  0;
2602         int i;
2603         __u16 count;
2604         struct cifs_posix_ace *pACE;
2605         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2606         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2607
2608         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2609                 return -EOPNOTSUPP;
2610
2611         if (acl_type & ACL_TYPE_ACCESS) {
2612                 count = le16_to_cpu(cifs_acl->access_entry_count);
2613                 pACE = &cifs_acl->ace_array[0];
2614                 size = sizeof(struct cifs_posix_acl);
2615                 size += sizeof(struct cifs_posix_ace) * count;
2616                 /* check if we would go beyond end of SMB */
2617                 if (size_of_data_area < size) {
2618                         cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2619                                 size_of_data_area, size));
2620                         return -EINVAL;
2621                 }
2622         } else if (acl_type & ACL_TYPE_DEFAULT) {
2623                 count = le16_to_cpu(cifs_acl->access_entry_count);
2624                 size = sizeof(struct cifs_posix_acl);
2625                 size += sizeof(struct cifs_posix_ace) * count;
2626 /* skip past access ACEs to get to default ACEs */
2627                 pACE = &cifs_acl->ace_array[count];
2628                 count = le16_to_cpu(cifs_acl->default_entry_count);
2629                 size += sizeof(struct cifs_posix_ace) * count;
2630                 /* check if we would go beyond end of SMB */
2631                 if (size_of_data_area < size)
2632                         return -EINVAL;
2633         } else {
2634                 /* illegal type */
2635                 return -EINVAL;
2636         }
2637
2638         size = posix_acl_xattr_size(count);
2639         if ((buflen == 0) || (local_acl == NULL)) {
2640                 /* used to query ACL EA size */
2641         } else if (size > buflen) {
2642                 return -ERANGE;
2643         } else /* buffer big enough */ {
2644                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2645                 for (i = 0; i < count ; i++) {
2646                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
2647                         pACE++;
2648                 }
2649         }
2650         return size;
2651 }
2652
2653 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2654                                      const posix_acl_xattr_entry *local_ace)
2655 {
2656         __u16 rc = 0; /* 0 = ACL converted ok */
2657
2658         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2659         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2660         /* BB is there a better way to handle the large uid? */
2661         if (local_ace->e_id == cpu_to_le32(-1)) {
2662         /* Probably no need to le convert -1 on any arch but can not hurt */
2663                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2664         } else
2665                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2666         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2667         return rc;
2668 }
2669
2670 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2671 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2672                                const int buflen, const int acl_type)
2673 {
2674         __u16 rc = 0;
2675         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2676         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2677         int count;
2678         int i;
2679
2680         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2681                 return 0;
2682
2683         count = posix_acl_xattr_count((size_t)buflen);
2684         cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2685                 count, buflen, le32_to_cpu(local_acl->a_version)));
2686         if (le32_to_cpu(local_acl->a_version) != 2) {
2687                 cFYI(1, ("unknown POSIX ACL version %d",
2688                      le32_to_cpu(local_acl->a_version)));
2689                 return 0;
2690         }
2691         cifs_acl->version = cpu_to_le16(1);
2692         if (acl_type == ACL_TYPE_ACCESS)
2693                 cifs_acl->access_entry_count = cpu_to_le16(count);
2694         else if (acl_type == ACL_TYPE_DEFAULT)
2695                 cifs_acl->default_entry_count = cpu_to_le16(count);
2696         else {
2697                 cFYI(1, ("unknown ACL type %d", acl_type));
2698                 return 0;
2699         }
2700         for (i = 0; i < count; i++) {
2701                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2702                                         &local_acl->a_entries[i]);
2703                 if (rc != 0) {
2704                         /* ACE not converted */
2705                         break;
2706                 }
2707         }
2708         if (rc == 0) {
2709                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2710                 rc += sizeof(struct cifs_posix_acl);
2711                 /* BB add check to make sure ACL does not overflow SMB */
2712         }
2713         return rc;
2714 }
2715
2716 int
2717 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2718                    const unsigned char *searchName,
2719                    char *acl_inf, const int buflen, const int acl_type,
2720                    const struct nls_table *nls_codepage, int remap)
2721 {
2722 /* SMB_QUERY_POSIX_ACL */
2723         TRANSACTION2_QPI_REQ *pSMB = NULL;
2724         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2725         int rc = 0;
2726         int bytes_returned;
2727         int name_len;
2728         __u16 params, byte_count;
2729
2730         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2731
2732 queryAclRetry:
2733         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2734                 (void **) &pSMBr);
2735         if (rc)
2736                 return rc;
2737
2738         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2739                 name_len =
2740                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2741                                          PATH_MAX, nls_codepage, remap);
2742                 name_len++;     /* trailing null */
2743                 name_len *= 2;
2744                 pSMB->FileName[name_len] = 0;
2745                 pSMB->FileName[name_len+1] = 0;
2746         } else {        /* BB improve the check for buffer overruns BB */
2747                 name_len = strnlen(searchName, PATH_MAX);
2748                 name_len++;     /* trailing null */
2749                 strncpy(pSMB->FileName, searchName, name_len);
2750         }
2751
2752         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2753         pSMB->TotalDataCount = 0;
2754         pSMB->MaxParameterCount = cpu_to_le16(2);
2755         /* BB find exact max data count below from sess structure BB */
2756         pSMB->MaxDataCount = cpu_to_le16(4000);
2757         pSMB->MaxSetupCount = 0;
2758         pSMB->Reserved = 0;
2759         pSMB->Flags = 0;
2760         pSMB->Timeout = 0;
2761         pSMB->Reserved2 = 0;
2762         pSMB->ParameterOffset = cpu_to_le16(
2763                 offsetof(struct smb_com_transaction2_qpi_req,
2764                          InformationLevel) - 4);
2765         pSMB->DataCount = 0;
2766         pSMB->DataOffset = 0;
2767         pSMB->SetupCount = 1;
2768         pSMB->Reserved3 = 0;
2769         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2770         byte_count = params + 1 /* pad */ ;
2771         pSMB->TotalParameterCount = cpu_to_le16(params);
2772         pSMB->ParameterCount = pSMB->TotalParameterCount;
2773         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2774         pSMB->Reserved4 = 0;
2775         pSMB->hdr.smb_buf_length += byte_count;
2776         pSMB->ByteCount = cpu_to_le16(byte_count);
2777
2778         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2779                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2780         cifs_stats_inc(&tcon->num_acl_get);
2781         if (rc) {
2782                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2783         } else {
2784                 /* decode response */
2785
2786                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2787                 if (rc || (pSMBr->ByteCount < 2))
2788                 /* BB also check enough total bytes returned */
2789                         rc = -EIO;      /* bad smb */
2790                 else {
2791                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2792                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2793                         rc = cifs_copy_posix_acl(acl_inf,
2794                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2795                                 buflen, acl_type, count);
2796                 }
2797         }
2798         cifs_buf_release(pSMB);
2799         if (rc == -EAGAIN)
2800                 goto queryAclRetry;
2801         return rc;
2802 }
2803
2804 int
2805 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2806                    const unsigned char *fileName,
2807                    const char *local_acl, const int buflen,
2808                    const int acl_type,
2809                    const struct nls_table *nls_codepage, int remap)
2810 {
2811         struct smb_com_transaction2_spi_req *pSMB = NULL;
2812         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2813         char *parm_data;
2814         int name_len;
2815         int rc = 0;
2816         int bytes_returned = 0;
2817         __u16 params, byte_count, data_count, param_offset, offset;
2818
2819         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2820 setAclRetry:
2821         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2822                       (void **) &pSMBr);
2823         if (rc)
2824                 return rc;
2825         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2826                 name_len =
2827                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2828                                       PATH_MAX, nls_codepage, remap);
2829                 name_len++;     /* trailing null */
2830                 name_len *= 2;
2831         } else {        /* BB improve the check for buffer overruns BB */
2832                 name_len = strnlen(fileName, PATH_MAX);
2833                 name_len++;     /* trailing null */
2834                 strncpy(pSMB->FileName, fileName, name_len);
2835         }
2836         params = 6 + name_len;
2837         pSMB->MaxParameterCount = cpu_to_le16(2);
2838         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2839         pSMB->MaxSetupCount = 0;
2840         pSMB->Reserved = 0;
2841         pSMB->Flags = 0;
2842         pSMB->Timeout = 0;
2843         pSMB->Reserved2 = 0;
2844         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2845                                 InformationLevel) - 4;
2846         offset = param_offset + params;
2847         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2848         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2849
2850         /* convert to on the wire format for POSIX ACL */
2851         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2852
2853         if (data_count == 0) {
2854                 rc = -EOPNOTSUPP;
2855                 goto setACLerrorExit;
2856         }
2857         pSMB->DataOffset = cpu_to_le16(offset);
2858         pSMB->SetupCount = 1;
2859         pSMB->Reserved3 = 0;
2860         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2861         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2862         byte_count = 3 /* pad */  + params + data_count;
2863         pSMB->DataCount = cpu_to_le16(data_count);
2864         pSMB->TotalDataCount = pSMB->DataCount;
2865         pSMB->ParameterCount = cpu_to_le16(params);
2866         pSMB->TotalParameterCount = pSMB->ParameterCount;
2867         pSMB->Reserved4 = 0;
2868         pSMB->hdr.smb_buf_length += byte_count;
2869         pSMB->ByteCount = cpu_to_le16(byte_count);
2870         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2871                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2872         if (rc) {
2873                 cFYI(1, ("Set POSIX ACL returned %d", rc));
2874         }
2875
2876 setACLerrorExit:
2877         cifs_buf_release(pSMB);
2878         if (rc == -EAGAIN)
2879                 goto setAclRetry;
2880         return rc;
2881 }
2882
2883 /* BB fix tabs in this function FIXME BB */
2884 int
2885 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2886                const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2887 {
2888         int rc = 0;
2889         struct smb_t2_qfi_req *pSMB = NULL;
2890         struct smb_t2_qfi_rsp *pSMBr = NULL;
2891         int bytes_returned;
2892         __u16 params, byte_count;
2893
2894         cFYI(1, ("In GetExtAttr"));
2895         if (tcon == NULL)
2896                 return -ENODEV;
2897
2898 GetExtAttrRetry:
2899         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2900                         (void **) &pSMBr);
2901         if (rc)
2902                 return rc;
2903
2904         params = 2 /* level */ +2 /* fid */;
2905         pSMB->t2.TotalDataCount = 0;
2906         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2907         /* BB find exact max data count below from sess structure BB */
2908         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2909         pSMB->t2.MaxSetupCount = 0;
2910         pSMB->t2.Reserved = 0;
2911         pSMB->t2.Flags = 0;
2912         pSMB->t2.Timeout = 0;
2913         pSMB->t2.Reserved2 = 0;
2914         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2915                                                Fid) - 4);
2916         pSMB->t2.DataCount = 0;
2917         pSMB->t2.DataOffset = 0;
2918         pSMB->t2.SetupCount = 1;
2919         pSMB->t2.Reserved3 = 0;
2920         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2921         byte_count = params + 1 /* pad */ ;
2922         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2923         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2924         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2925         pSMB->Pad = 0;
2926         pSMB->Fid = netfid;
2927         pSMB->hdr.smb_buf_length += byte_count;
2928         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2929
2930         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2931                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2932         if (rc) {
2933                 cFYI(1, ("error %d in GetExtAttr", rc));
2934         } else {
2935                 /* decode response */
2936                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2937                 if (rc || (pSMBr->ByteCount < 2))
2938                 /* BB also check enough total bytes returned */
2939                         /* If rc should we check for EOPNOSUPP and
2940                            disable the srvino flag? or in caller? */
2941                         rc = -EIO;      /* bad smb */
2942                 else {
2943                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2944                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2945                         struct file_chattr_info *pfinfo;
2946                         /* BB Do we need a cast or hash here ? */
2947                         if (count != 16) {
2948                                 cFYI(1, ("Illegal size ret in GetExtAttr"));
2949                                 rc = -EIO;
2950                                 goto GetExtAttrOut;
2951                         }
2952                         pfinfo = (struct file_chattr_info *)
2953                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
2954                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2955                         *pMask = le64_to_cpu(pfinfo->mask);
2956                 }
2957         }
2958 GetExtAttrOut:
2959         cifs_buf_release(pSMB);
2960         if (rc == -EAGAIN)
2961                 goto GetExtAttrRetry;
2962         return rc;
2963 }
2964
2965 #endif /* CONFIG_POSIX */
2966
2967
2968 /* security id for everyone */
2969 static const struct cifs_sid sid_everyone =
2970                 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2971 /* group users */
2972 static const struct cifs_sid sid_user =
2973                 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2974
2975 /* Convert CIFS ACL to POSIX form */
2976 static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
2977 {
2978         return 0;
2979 }
2980
2981 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2982 int
2983 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2984                 /* BB fix up return info */ char *acl_inf, const int buflen,
2985                   const int acl_type /* ACCESS/DEFAULT not sure implication */)
2986 {
2987         int rc = 0;
2988         int buf_type = 0;
2989         QUERY_SEC_DESC_REQ * pSMB;
2990         struct kvec iov[1];
2991
2992         cFYI(1, ("GetCifsACL"));
2993
2994         rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2995                         8 /* parm len */, tcon, (void **) &pSMB);
2996         if (rc)
2997                 return rc;
2998
2999         pSMB->MaxParameterCount = cpu_to_le32(4);
3000         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3001         pSMB->MaxSetupCount = 0;
3002         pSMB->Fid = fid; /* file handle always le */
3003         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3004                                      CIFS_ACL_DACL);
3005         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3006         pSMB->hdr.smb_buf_length += 11;
3007         iov[0].iov_base = (char *)pSMB;
3008         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3009
3010         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3011         cifs_stats_inc(&tcon->num_acl_get);
3012         if (rc) {
3013                 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3014         } else {                /* decode response */
3015                 struct cifs_sid *psec_desc;
3016                 __le32 * parm;
3017                 int parm_len;
3018                 int data_len;
3019                 int acl_len;
3020                 struct smb_com_ntransact_rsp *pSMBr;
3021
3022 /* validate_nttransact */
3023                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3024                                         (char **)&psec_desc,
3025                                         &parm_len, &data_len);
3026                 if (rc)
3027                         goto qsec_out;
3028                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3029
3030                 cERROR(1, ("smb %p parm %p data %p",
3031                           pSMBr, parm, psec_desc));  /* BB removeme BB */
3032
3033                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3034                         rc = -EIO;      /* bad smb */
3035                         goto qsec_out;
3036                 }
3037
3038 /* BB check that data area is minimum length and as big as acl_len */
3039
3040                 acl_len = le32_to_cpu(*(__le32 *)parm);
3041                 /* BB check if (acl_len > bufsize) */
3042
3043                 parse_sec_desc(psec_desc, acl_len);
3044         }
3045 qsec_out:
3046         if (buf_type == CIFS_SMALL_BUFFER)
3047                 cifs_small_buf_release(iov[0].iov_base);
3048         else if (buf_type == CIFS_LARGE_BUFFER)
3049                 cifs_buf_release(iov[0].iov_base);
3050 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3051         return rc;
3052 }
3053
3054 /* Legacy Query Path Information call for lookup to old servers such
3055    as Win9x/WinME */
3056 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3057                         const unsigned char *searchName,
3058                         FILE_ALL_INFO *pFinfo,
3059                         const struct nls_table *nls_codepage, int remap)
3060 {
3061         QUERY_INFORMATION_REQ * pSMB;
3062         QUERY_INFORMATION_RSP * pSMBr;
3063         int rc = 0;
3064         int bytes_returned;
3065         int name_len;
3066
3067         cFYI(1, ("In SMBQPath path %s", searchName));
3068 QInfRetry:
3069         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3070                       (void **) &pSMBr);
3071         if (rc)
3072                 return rc;
3073
3074         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3075                 name_len =
3076                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3077                                         PATH_MAX, nls_codepage, remap);
3078                 name_len++;     /* trailing null */
3079                 name_len *= 2;
3080         } else {
3081                 name_len = strnlen(searchName, PATH_MAX);
3082                 name_len++;     /* trailing null */
3083                 strncpy(pSMB->FileName, searchName, name_len);
3084         }
3085         pSMB->BufferFormat = 0x04;
3086         name_len++; /* account for buffer type byte */
3087         pSMB->hdr.smb_buf_length += (__u16) name_len;
3088         pSMB->ByteCount = cpu_to_le16(name_len);
3089
3090         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3091                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3092         if (rc) {
3093                 cFYI(1, ("Send error in QueryInfo = %d", rc));
3094         } else if (pFinfo) {            /* decode response */
3095                 struct timespec ts;
3096                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3097                 /* BB FIXME - add time zone adjustment BB */
3098                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3099                 ts.tv_nsec = 0;
3100                 ts.tv_sec = time;
3101                 /* decode time fields */
3102                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3103                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3104                 pFinfo->LastAccessTime = 0;
3105                 pFinfo->AllocationSize =
3106                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3107                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3108                 pFinfo->Attributes =
3109                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3110         } else
3111                 rc = -EIO; /* bad buffer passed in */
3112
3113         cifs_buf_release(pSMB);
3114
3115         if (rc == -EAGAIN)
3116                 goto QInfRetry;
3117
3118         return rc;
3119 }
3120
3121
3122
3123
3124 int
3125 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3126                  const unsigned char *searchName,
3127                  FILE_ALL_INFO * pFindData,
3128                  int legacy /* old style infolevel */,
3129                  const struct nls_table *nls_codepage, int remap)
3130 {
3131 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3132         TRANSACTION2_QPI_REQ *pSMB = NULL;
3133         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3134         int rc = 0;
3135         int bytes_returned;
3136         int name_len;
3137         __u16 params, byte_count;
3138
3139 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3140 QPathInfoRetry:
3141         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3142                       (void **) &pSMBr);
3143         if (rc)
3144                 return rc;
3145
3146         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3147                 name_len =
3148                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3149                                      PATH_MAX, nls_codepage, remap);
3150                 name_len++;     /* trailing null */
3151                 name_len *= 2;
3152         } else {        /* BB improve the check for buffer overruns BB */
3153                 name_len = strnlen(searchName, PATH_MAX);
3154                 name_len++;     /* trailing null */
3155                 strncpy(pSMB->FileName, searchName, name_len);
3156         }
3157
3158         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3159         pSMB->TotalDataCount = 0;
3160         pSMB->MaxParameterCount = cpu_to_le16(2);
3161         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3162         pSMB->MaxSetupCount = 0;
3163         pSMB->Reserved = 0;
3164         pSMB->Flags = 0;
3165         pSMB->Timeout = 0;
3166         pSMB->Reserved2 = 0;
3167         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3168         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3169         pSMB->DataCount = 0;
3170         pSMB->DataOffset = 0;
3171         pSMB->SetupCount = 1;
3172         pSMB->Reserved3 = 0;
3173         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3174         byte_count = params + 1 /* pad */ ;
3175         pSMB->TotalParameterCount = cpu_to_le16(params);
3176         pSMB->ParameterCount = pSMB->TotalParameterCount;
3177         if (legacy)
3178                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3179         else
3180                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3181         pSMB->Reserved4 = 0;
3182         pSMB->hdr.smb_buf_length += byte_count;
3183         pSMB->ByteCount = cpu_to_le16(byte_count);
3184
3185         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3186                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3187         if (rc) {
3188                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3189         } else {                /* decode response */
3190                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3191
3192                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3193                         rc = -EIO;
3194                 else if (!legacy && (pSMBr->ByteCount < 40))
3195                         rc = -EIO;      /* bad smb */
3196                 else if (legacy && (pSMBr->ByteCount < 24))
3197                         rc = -EIO;  /* 24 or 26 expected but we do not read
3198                                         last field */
3199                 else if (pFindData) {
3200                         int size;
3201                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3202                         if (legacy) /* we do not read the last field, EAsize,
3203                                        fortunately since it varies by subdialect
3204                                        and on Set vs. Get, is two bytes or 4
3205                                        bytes depending but we don't care here */
3206                                 size = sizeof(FILE_INFO_STANDARD);
3207                         else
3208                                 size = sizeof(FILE_ALL_INFO);
3209                         memcpy((char *) pFindData,
3210                                (char *) &pSMBr->hdr.Protocol +
3211                                data_offset, size);
3212                 } else
3213                     rc = -ENOMEM;
3214         }
3215         cifs_buf_release(pSMB);
3216         if (rc == -EAGAIN)
3217                 goto QPathInfoRetry;
3218
3219         return rc;
3220 }
3221
3222 int
3223 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3224                      const unsigned char *searchName,
3225                      FILE_UNIX_BASIC_INFO * pFindData,
3226                      const struct nls_table *nls_codepage, int remap)
3227 {
3228 /* SMB_QUERY_FILE_UNIX_BASIC */
3229         TRANSACTION2_QPI_REQ *pSMB = NULL;
3230         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3231         int rc = 0;
3232         int bytes_returned = 0;
3233         int name_len;
3234         __u16 params, byte_count;
3235
3236         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3237 UnixQPathInfoRetry:
3238         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3239                       (void **) &pSMBr);
3240         if (rc)
3241                 return rc;
3242
3243         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3244                 name_len =
3245                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3246                                   PATH_MAX, nls_codepage, remap);
3247                 name_len++;     /* trailing null */
3248                 name_len *= 2;
3249         } else {        /* BB improve the check for buffer overruns BB */
3250                 name_len = strnlen(searchName, PATH_MAX);
3251                 name_len++;     /* trailing null */
3252                 strncpy(pSMB->FileName, searchName, name_len);
3253         }
3254
3255         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3256         pSMB->TotalDataCount = 0;
3257         pSMB->MaxParameterCount = cpu_to_le16(2);
3258         /* BB find exact max SMB PDU from sess structure BB */
3259         pSMB->MaxDataCount = cpu_to_le16(4000);
3260         pSMB->MaxSetupCount = 0;
3261         pSMB->Reserved = 0;
3262         pSMB->Flags = 0;
3263         pSMB->Timeout = 0;
3264         pSMB->Reserved2 = 0;
3265         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3266         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3267         pSMB->DataCount = 0;
3268         pSMB->DataOffset = 0;
3269         pSMB->SetupCount = 1;
3270         pSMB->Reserved3 = 0;
3271         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3272         byte_count = params + 1 /* pad */ ;
3273         pSMB->TotalParameterCount = cpu_to_le16(params);
3274         pSMB->ParameterCount = pSMB->TotalParameterCount;
3275         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3276         pSMB->Reserved4 = 0;
3277         pSMB->hdr.smb_buf_length += byte_count;
3278         pSMB->ByteCount = cpu_to_le16(byte_count);
3279
3280         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3281                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3282         if (rc) {
3283                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3284         } else {                /* decode response */
3285                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3286
3287                 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3288                         rc = -EIO;      /* bad smb */
3289                 } else {
3290                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3291                         memcpy((char *) pFindData,
3292                                (char *) &pSMBr->hdr.Protocol +
3293                                data_offset,
3294                                sizeof (FILE_UNIX_BASIC_INFO));
3295                 }
3296         }
3297         cifs_buf_release(pSMB);
3298         if (rc == -EAGAIN)
3299                 goto UnixQPathInfoRetry;
3300
3301         return rc;
3302 }
3303
3304 #if 0  /* function unused at present */
3305 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3306                const char *searchName, FILE_ALL_INFO * findData,
3307                const struct nls_table *nls_codepage)
3308 {
3309 /* level 257 SMB_ */
3310         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3311         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3312         int rc = 0;
3313         int bytes_returned;
3314         int name_len;
3315         __u16 params, byte_count;
3316
3317         cFYI(1, ("In FindUnique"));
3318 findUniqueRetry:
3319         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3320                       (void **) &pSMBr);
3321         if (rc)
3322                 return rc;
3323
3324         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3325                 name_len =
3326                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3327                                      PATH_MAX, nls_codepage);
3328                 name_len++;     /* trailing null */
3329                 name_len *= 2;
3330         } else {        /* BB improve the check for buffer overruns BB */
3331                 name_len = strnlen(searchName, PATH_MAX);
3332                 name_len++;     /* trailing null */
3333                 strncpy(pSMB->FileName, searchName, name_len);
3334         }
3335
3336         params = 12 + name_len /* includes null */ ;
3337         pSMB->TotalDataCount = 0;       /* no EAs */
3338         pSMB->MaxParameterCount = cpu_to_le16(2);
3339         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3340         pSMB->MaxSetupCount = 0;
3341         pSMB->Reserved = 0;
3342         pSMB->Flags = 0;
3343         pSMB->Timeout = 0;
3344         pSMB->Reserved2 = 0;
3345         pSMB->ParameterOffset = cpu_to_le16(
3346          offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3347         pSMB->DataCount = 0;
3348         pSMB->DataOffset = 0;
3349         pSMB->SetupCount = 1;   /* one byte, no need to le convert */
3350         pSMB->Reserved3 = 0;
3351         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3352         byte_count = params + 1 /* pad */ ;
3353         pSMB->TotalParameterCount = cpu_to_le16(params);
3354         pSMB->ParameterCount = pSMB->TotalParameterCount;
3355         pSMB->SearchAttributes =
3356             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3357                         ATTR_DIRECTORY);
3358         pSMB->SearchCount = cpu_to_le16(16);    /* BB increase */
3359         pSMB->SearchFlags = cpu_to_le16(1);
3360         pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3361         pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
3362         pSMB->hdr.smb_buf_length += byte_count;
3363         pSMB->ByteCount = cpu_to_le16(byte_count);
3364
3365         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3366                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3367
3368         if (rc) {
3369                 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3370         } else {                /* decode response */
3371                 cifs_stats_inc(&tcon->num_ffirst);
3372                 /* BB fill in */
3373         }
3374
3375         cifs_buf_release(pSMB);
3376         if (rc == -EAGAIN)
3377                 goto findUniqueRetry;
3378
3379         return rc;
3380 }
3381 #endif /* end unused (temporarily) function */
3382
3383 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3384 int
3385 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3386               const char *searchName,
3387               const struct nls_table *nls_codepage,
3388               __u16 *pnetfid,
3389               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3390 {
3391 /* level 257 SMB_ */
3392         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3393         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3394         T2_FFIRST_RSP_PARMS * parms;
3395         int rc = 0;
3396         int bytes_returned = 0;
3397         int name_len;
3398         __u16 params, byte_count;
3399
3400         cFYI(1, ("In FindFirst for %s", searchName));
3401
3402 findFirstRetry:
3403         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3404                       (void **) &pSMBr);
3405         if (rc)
3406                 return rc;
3407
3408         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3409                 name_len =
3410                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3411                                  PATH_MAX, nls_codepage, remap);
3412                 /* We can not add the asterik earlier in case
3413                 it got remapped to 0xF03A as if it were part of the
3414                 directory name instead of a wildcard */
3415                 name_len *= 2;
3416                 pSMB->FileName[name_len] = dirsep;
3417                 pSMB->FileName[name_len+1] = 0;
3418                 pSMB->FileName[name_len+2] = '*';
3419                 pSMB->FileName[name_len+3] = 0;
3420                 name_len += 4; /* now the trailing null */
3421                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3422                 pSMB->FileName[name_len+1] = 0;
3423                 name_len += 2;
3424         } else {        /* BB add check for overrun of SMB buf BB */
3425                 name_len = strnlen(searchName, PATH_MAX);
3426 /* BB fix here and in unicode clause above ie
3427                 if (name_len > buffersize-header)
3428                         free buffer exit; BB */
3429                 strncpy(pSMB->FileName, searchName, name_len);
3430                 pSMB->FileName[name_len] = dirsep;
3431                 pSMB->FileName[name_len+1] = '*';
3432                 pSMB->FileName[name_len+2] = 0;
3433                 name_len += 3;
3434         }
3435
3436         params = 12 + name_len /* includes null */ ;
3437         pSMB->TotalDataCount = 0;       /* no EAs */
3438         pSMB->MaxParameterCount = cpu_to_le16(10);
3439         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3440                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3441         pSMB->MaxSetupCount = 0;
3442         pSMB->Reserved = 0;
3443         pSMB->Flags = 0;
3444         pSMB->Timeout = 0;
3445         pSMB->Reserved2 = 0;
3446         byte_count = params + 1 /* pad */ ;
3447         pSMB->TotalParameterCount = cpu_to_le16(params);
3448         pSMB->ParameterCount = pSMB->TotalParameterCount;
3449         pSMB->ParameterOffset = cpu_to_le16(
3450               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3451                 - 4);
3452         pSMB->DataCount = 0;
3453         pSMB->DataOffset = 0;
3454         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
3455         pSMB->Reserved3 = 0;
3456         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3457         pSMB->SearchAttributes =
3458             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3459                         ATTR_DIRECTORY);
3460         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3461         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3462                 CIFS_SEARCH_RETURN_RESUME);
3463         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3464
3465         /* BB what should we set StorageType to? Does it matter? BB */
3466         pSMB->SearchStorageType = 0;
3467         pSMB->hdr.smb_buf_length += byte_count;
3468         pSMB->ByteCount = cpu_to_le16(byte_count);
3469
3470         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3471                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3472         cifs_stats_inc(&tcon->num_ffirst);
3473
3474         if (rc) {/* BB add logic to retry regular search if Unix search
3475                         rejected unexpectedly by server */
3476                 /* BB Add code to handle unsupported level rc */
3477                 cFYI(1, ("Error in FindFirst = %d", rc));
3478
3479                 cifs_buf_release(pSMB);
3480
3481                 /* BB eventually could optimize out free and realloc of buf */
3482                 /*    for this case */
3483                 if (rc == -EAGAIN)
3484                         goto findFirstRetry;
3485         } else { /* decode response */
3486                 /* BB remember to free buffer if error BB */
3487                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3488                 if (rc == 0) {
3489                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3490                                 psrch_inf->unicode = TRUE;
3491                         else
3492                                 psrch_inf->unicode = FALSE;
3493
3494                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3495                         psrch_inf->smallBuf = 0;
3496                         psrch_inf->srch_entries_start =
3497                                 (char *) &pSMBr->hdr.Protocol +
3498                                         le16_to_cpu(pSMBr->t2.DataOffset);
3499                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3500                                le16_to_cpu(pSMBr->t2.ParameterOffset));
3501
3502                         if (parms->EndofSearch)
3503                                 psrch_inf->endOfSearch = TRUE;
3504                         else
3505                                 psrch_inf->endOfSearch = FALSE;
3506
3507                         psrch_inf->entries_in_buffer =
3508                                         le16_to_cpu(parms->SearchCount);
3509                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3510                                 psrch_inf->entries_in_buffer;
3511                         *pnetfid = parms->SearchHandle;
3512                 } else {
3513                         cifs_buf_release(pSMB);
3514                 }
3515         }
3516
3517         return rc;
3518 }
3519
3520 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3521                  __u16 searchHandle, struct cifs_search_info *psrch_inf)
3522 {
3523         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3524         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3525         T2_FNEXT_RSP_PARMS * parms;
3526         char *response_data;
3527         int rc = 0;
3528         int bytes_returned, name_len;
3529         __u16 params, byte_count;
3530
3531         cFYI(1, ("In FindNext"));
3532
3533         if (psrch_inf->endOfSearch == TRUE)
3534                 return -ENOENT;
3535
3536         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3537                 (void **) &pSMBr);
3538         if (rc)
3539                 return rc;
3540
3541         params = 14; /* includes 2 bytes of null string, converted to LE below*/
3542         byte_count = 0;
3543         pSMB->TotalDataCount = 0;       /* no EAs */
3544         pSMB->MaxParameterCount = cpu_to_le16(8);
3545         pSMB->MaxDataCount =
3546                 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3547                                 0xFFFFFF00);
3548         pSMB->MaxSetupCount = 0;
3549         pSMB->Reserved = 0;
3550         pSMB->Flags = 0;
3551         pSMB->Timeout = 0;
3552         pSMB->Reserved2 = 0;
3553         pSMB->ParameterOffset =  cpu_to_le16(
3554               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3555         pSMB->DataCount = 0;
3556         pSMB->DataOffset = 0;
3557         pSMB->SetupCount = 1;
3558         pSMB->Reserved3 = 0;
3559         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3560         pSMB->SearchHandle = searchHandle;      /* always kept as le */
3561         pSMB->SearchCount =
3562                 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3563         /* test for Unix extensions */
3564 /*      if (tcon->ses->capabilities & CAP_UNIX) {
3565                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3566                 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3567         } else {
3568                 pSMB->InformationLevel =
3569                    cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3570                 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3571         } */
3572         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3573         pSMB->ResumeKey = psrch_inf->resume_key;
3574         pSMB->SearchFlags =
3575               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3576
3577         name_len = psrch_inf->resume_name_len;
3578         params += name_len;
3579         if (name_len < PATH_MAX) {
3580                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3581                 byte_count += name_len;
3582                 /* 14 byte parm len above enough for 2 byte null terminator */
3583                 pSMB->ResumeFileName[name_len] = 0;
3584                 pSMB->ResumeFileName[name_len+1] = 0;
3585         } else {
3586                 rc = -EINVAL;
3587                 goto FNext2_err_exit;
3588         }
3589         byte_count = params + 1 /* pad */ ;
3590         pSMB->TotalParameterCount = cpu_to_le16(params);
3591         pSMB->ParameterCount = pSMB->TotalParameterCount;
3592         pSMB->hdr.smb_buf_length += byte_count;
3593         pSMB->ByteCount = cpu_to_le16(byte_count);
3594
3595         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3596                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3597         cifs_stats_inc(&tcon->num_fnext);
3598         if (rc) {
3599                 if (rc == -EBADF) {
3600                         psrch_inf->endOfSearch = TRUE;
3601                         rc = 0; /* search probably was closed at end of search*/
3602                 } else
3603                         cFYI(1, ("FindNext returned = %d", rc));
3604         } else {                /* decode response */
3605                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3606
3607                 if (rc == 0) {
3608                         /* BB fixme add lock for file (srch_info) struct here */
3609                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3610                                 psrch_inf->unicode = TRUE;
3611                         else
3612                                 psrch_inf->unicode = FALSE;
3613                         response_data = (char *) &pSMBr->hdr.Protocol +
3614                                le16_to_cpu(pSMBr->t2.ParameterOffset);
3615                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
3616                         response_data = (char *)&pSMBr->hdr.Protocol +
3617                                 le16_to_cpu(pSMBr->t2.DataOffset);
3618                         if (psrch_inf->smallBuf)
3619                                 cifs_small_buf_release(
3620                                         psrch_inf->ntwrk_buf_start);
3621                         else
3622                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3623                         psrch_inf->srch_entries_start = response_data;
3624                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
3625                         psrch_inf->smallBuf = 0;
3626                         if (parms->EndofSearch)
3627                                 psrch_inf->endOfSearch = TRUE;
3628                         else
3629                                 psrch_inf->endOfSearch = FALSE;
3630                         psrch_inf->entries_in_buffer =
3631                                                 le16_to_cpu(parms->SearchCount);
3632                         psrch_inf->index_of_last_entry +=
3633                                 psrch_inf->entries_in_buffer;
3634 /*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3635             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3636
3637                         /* BB fixme add unlock here */
3638                 }
3639
3640         }
3641
3642         /* BB On error, should we leave previous search buf (and count and
3643         last entry fields) intact or free the previous one? */
3644
3645         /* Note: On -EAGAIN error only caller can retry on handle based calls
3646         since file handle passed in no longer valid */
3647 FNext2_err_exit:
3648         if (rc != 0)
3649                 cifs_buf_release(pSMB);
3650         return rc;
3651 }
3652
3653 int
3654 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3655               const __u16 searchHandle)
3656 {
3657         int rc = 0;
3658         FINDCLOSE_REQ *pSMB = NULL;
3659         CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3660         int bytes_returned;
3661
3662         cFYI(1, ("In CIFSSMBFindClose"));
3663         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3664
3665         /* no sense returning error if session restarted
3666                 as file handle has been closed */
3667         if (rc == -EAGAIN)
3668                 return 0;
3669         if (rc)
3670                 return rc;
3671
3672         pSMBr = (CLOSE_RSP *)pSMB;  /* BB removeme BB */
3673         pSMB->FileID = searchHandle;
3674         pSMB->ByteCount = 0;
3675         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3676                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3677         if (rc) {
3678                 cERROR(1, ("Send error in FindClose = %d", rc));
3679         }
3680         cifs_stats_inc(&tcon->num_fclose);
3681         cifs_small_buf_release(pSMB);
3682
3683         /* Since session is dead, search handle closed on server already */
3684         if (rc == -EAGAIN)
3685                 rc = 0;
3686
3687         return rc;
3688 }
3689
3690 int
3691 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3692                       const unsigned char *searchName,
3693                       __u64 * inode_number,
3694                       const struct nls_table *nls_codepage, int remap)
3695 {
3696         int rc = 0;
3697         TRANSACTION2_QPI_REQ *pSMB = NULL;
3698         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3699         int name_len, bytes_returned;
3700         __u16 params, byte_count;
3701
3702         cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3703         if (tcon == NULL)
3704                 return -ENODEV;
3705
3706 GetInodeNumberRetry:
3707         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3708                       (void **) &pSMBr);
3709         if (rc)
3710                 return rc;
3711
3712         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3713                 name_len =
3714                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3715                                          PATH_MAX, nls_codepage, remap);
3716                 name_len++;     /* trailing null */
3717                 name_len *= 2;
3718         } else {        /* BB improve the check for buffer overruns BB */
3719                 name_len = strnlen(searchName, PATH_MAX);
3720                 name_len++;     /* trailing null */
3721                 strncpy(pSMB->FileName, searchName, name_len);
3722         }
3723
3724         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3725         pSMB->TotalDataCount = 0;
3726         pSMB->MaxParameterCount = cpu_to_le16(2);
3727         /* BB find exact max data count below from sess structure BB */
3728         pSMB->MaxDataCount = cpu_to_le16(4000);
3729         pSMB->MaxSetupCount = 0;
3730         pSMB->Reserved = 0;
3731         pSMB->Flags = 0;
3732         pSMB->Timeout = 0;
3733         pSMB->Reserved2 = 0;
3734         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3735                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3736         pSMB->DataCount = 0;
3737         pSMB->DataOffset = 0;
3738         pSMB->SetupCount = 1;
3739         pSMB->Reserved3 = 0;
3740         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3741         byte_count = params + 1 /* pad */ ;
3742         pSMB->TotalParameterCount = cpu_to_le16(params);
3743         pSMB->ParameterCount = pSMB->TotalParameterCount;
3744         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3745         pSMB->Reserved4 = 0;
3746         pSMB->hdr.smb_buf_length += byte_count;
3747         pSMB->ByteCount = cpu_to_le16(byte_count);
3748
3749         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3750                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3751         if (rc) {
3752                 cFYI(1, ("error %d in QueryInternalInfo", rc));
3753         } else {
3754                 /* decode response */
3755                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3756                 if (rc || (pSMBr->ByteCount < 2))
3757                 /* BB also check enough total bytes returned */
3758                         /* If rc should we check for EOPNOSUPP and
3759                         disable the srvino flag? or in caller? */
3760                         rc = -EIO;      /* bad smb */
3761                 else {
3762                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3763                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3764                         struct file_internal_info *pfinfo;
3765                         /* BB Do we need a cast or hash here ? */
3766                         if (count < 8) {
3767                                 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3768                                 rc = -EIO;
3769                                 goto GetInodeNumOut;
3770                         }
3771                         pfinfo = (struct file_internal_info *)
3772                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3773                         *inode_number = pfinfo->UniqueId;
3774                 }
3775         }
3776 GetInodeNumOut:
3777         cifs_buf_release(pSMB);
3778         if (rc == -EAGAIN)
3779                 goto GetInodeNumberRetry;
3780         return rc;
3781 }
3782
3783 int
3784 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3785                 const unsigned char *searchName,
3786                 unsigned char **targetUNCs,
3787                 unsigned int *number_of_UNC_in_array,
3788                 const struct nls_table *nls_codepage, int remap)
3789 {
3790 /* TRANS2_GET_DFS_REFERRAL */
3791         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3792         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3793         struct dfs_referral_level_3 *referrals = NULL;
3794         int rc = 0;
3795         int bytes_returned;
3796         int name_len;
3797         unsigned int i;
3798         char *temp;
3799         __u16 params, byte_count;
3800         *number_of_UNC_in_array = 0;
3801         *targetUNCs = NULL;
3802
3803         cFYI(1, ("In GetDFSRefer the path %s", searchName));
3804         if (ses == NULL)
3805                 return -ENODEV;
3806 getDFSRetry:
3807         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3808                       (void **) &pSMBr);
3809         if (rc)
3810                 return rc;
3811
3812         /* server pointer checked in called function,
3813         but should never be null here anyway */
3814         pSMB->hdr.Mid = GetNextMid(ses->server);
3815         pSMB->hdr.Tid = ses->ipc_tid;
3816         pSMB->hdr.Uid = ses->Suid;
3817         if (ses->capabilities & CAP_STATUS32) {
3818                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3819         }
3820         if (ses->capabilities & CAP_DFS) {
3821                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3822         }
3823
3824         if (ses->capabilities & CAP_UNICODE) {
3825                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3826                 name_len =
3827                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3828                                      searchName, PATH_MAX, nls_codepage, remap);
3829                 name_len++;     /* trailing null */
3830                 name_len *= 2;
3831         } else {        /* BB improve the check for buffer overruns BB */
3832                 name_len = strnlen(searchName, PATH_MAX);
3833                 name_len++;     /* trailing null */
3834                 strncpy(pSMB->RequestFileName, searchName, name_len);
3835         }
3836
3837         if (ses->server) {
3838                 if (ses->server->secMode &
3839                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3840                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3841         }
3842
3843         pSMB->hdr.Uid = ses->Suid;
3844
3845         params = 2 /* level */  + name_len /*includes null */ ;
3846         pSMB->TotalDataCount = 0;
3847         pSMB->DataCount = 0;
3848         pSMB->DataOffset = 0;
3849         pSMB->MaxParameterCount = 0;
3850         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3851         pSMB->MaxSetupCount = 0;
3852         pSMB->Reserved = 0;
3853         pSMB->Flags = 0;
3854         pSMB->Timeout = 0;
3855         pSMB->Reserved2 = 0;
3856         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3857           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3858         pSMB->SetupCount = 1;
3859         pSMB->Reserved3 = 0;
3860         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3861         byte_count = params + 3 /* pad */ ;
3862         pSMB->ParameterCount = cpu_to_le16(params);
3863         pSMB->TotalParameterCount = pSMB->ParameterCount;
3864         pSMB->MaxReferralLevel = cpu_to_le16(3);
3865         pSMB->hdr.smb_buf_length += byte_count;
3866         pSMB->ByteCount = cpu_to_le16(byte_count);
3867
3868         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3869                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3870         if (rc) {
3871                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3872         } else {                /* decode response */
3873 /* BB Add logic to parse referrals here */
3874                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3875
3876                 /* BB Also check if enough total bytes returned? */
3877                 if (rc || (pSMBr->ByteCount < 17))
3878                         rc = -EIO;      /* bad smb */
3879                 else {
3880                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3881                         __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3882
3883                         cFYI(1,
3884                             ("Decoding GetDFSRefer response BCC: %d  Offset %d",
3885                               pSMBr->ByteCount, data_offset));
3886                         referrals =
3887                             (struct dfs_referral_level_3 *)
3888                                         (8 /* sizeof start of data block */ +
3889                                         data_offset +
3890                                         (char *) &pSMBr->hdr.Protocol);
3891                         cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
3892                                 le16_to_cpu(pSMBr->NumberOfReferrals),
3893                                 le16_to_cpu(pSMBr->DFSFlags),
3894                                 le16_to_cpu(referrals->ReferralSize),
3895                                 le16_to_cpu(referrals->ServerType),
3896                                 le16_to_cpu(referrals->ReferralFlags),
3897                                 le16_to_cpu(referrals->TimeToLive)));
3898                         /* BB This field is actually two bytes in from start of
3899                            data block so we could do safety check that DataBlock
3900                            begins at address of pSMBr->NumberOfReferrals */
3901                         *number_of_UNC_in_array =
3902                                         le16_to_cpu(pSMBr->NumberOfReferrals);
3903
3904                         /* BB Fix below so can return more than one referral */
3905                         if (*number_of_UNC_in_array > 1)
3906                                 *number_of_UNC_in_array = 1;
3907
3908                         /* get the length of the strings describing refs */
3909                         name_len = 0;
3910                         for (i = 0; i < *number_of_UNC_in_array; i++) {
3911                                 /* make sure that DfsPathOffset not past end */
3912                                 __u16 offset =
3913                                         le16_to_cpu(referrals->DfsPathOffset);
3914                                 if (offset > data_count) {
3915                                         /* if invalid referral, stop here and do
3916                                         not try to copy any more */
3917                                         *number_of_UNC_in_array = i;
3918                                         break;
3919                                 }
3920                                 temp = ((char *)referrals) + offset;
3921
3922                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3923                                         name_len += UniStrnlen((wchar_t *)temp,
3924                                                                 data_count);
3925                                 } else {
3926                                         name_len += strnlen(temp, data_count);
3927                                 }
3928                                 referrals++;
3929                                 /* BB add check that referral pointer does
3930                                    not fall off end PDU */
3931                         }
3932                         /* BB add check for name_len bigger than bcc */
3933                         *targetUNCs =
3934                                 kmalloc(name_len+1+(*number_of_UNC_in_array),
3935                                         GFP_KERNEL);
3936                         if (*targetUNCs == NULL) {
3937                                 rc = -ENOMEM;
3938                                 goto GetDFSRefExit;
3939                         }
3940                         /* copy the ref strings */
3941                         referrals = (struct dfs_referral_level_3 *)
3942                                         (8 /* sizeof data hdr */ + data_offset +
3943                                         (char *) &pSMBr->hdr.Protocol);
3944
3945                         for (i = 0; i < *number_of_UNC_in_array; i++) {
3946                                 temp = ((char *)referrals) +
3947                                           le16_to_cpu(referrals->DfsPathOffset);
3948                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3949                                         cifs_strfromUCS_le(*targetUNCs,
3950                                                           (__le16 *) temp,
3951                                                           name_len,
3952                                                           nls_codepage);
3953                                 } else {
3954                                         strncpy(*targetUNCs, temp, name_len);
3955                                 }
3956                                 /*  BB update target_uncs pointers */
3957                                 referrals++;
3958                         }
3959                         temp = *targetUNCs;
3960                         temp[name_len] = 0;
3961                 }
3962
3963         }
3964 GetDFSRefExit:
3965         if (pSMB)
3966                 cifs_buf_release(pSMB);
3967
3968         if (rc == -EAGAIN)
3969                 goto getDFSRetry;
3970
3971         return rc;
3972 }
3973
3974 /* Query File System Info such as free space to old servers such as Win 9x */
3975 int
3976 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3977 {
3978 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3979         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3980         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3981         FILE_SYSTEM_ALLOC_INFO *response_data;
3982         int rc = 0;
3983         int bytes_returned = 0;
3984         __u16 params, byte_count;
3985
3986         cFYI(1, ("OldQFSInfo"));
3987 oldQFSInfoRetry:
3988         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3989                 (void **) &pSMBr);
3990         if (rc)
3991                 return rc;
3992         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3993                       (void **) &pSMBr);
3994         if (rc)
3995                 return rc;
3996
3997         params = 2;     /* level */
3998         pSMB->TotalDataCount = 0;
3999         pSMB->MaxParameterCount = cpu_to_le16(2);
4000         pSMB->MaxDataCount = cpu_to_le16(1000);
4001         pSMB->MaxSetupCount = 0;
4002         pSMB->Reserved = 0;
4003         pSMB->Flags = 0;
4004         pSMB->Timeout = 0;
4005         pSMB->Reserved2 = 0;
4006         byte_count = params + 1 /* pad */ ;
4007         pSMB->TotalParameterCount = cpu_to_le16(params);
4008         pSMB->ParameterCount = pSMB->TotalParameterCount;
4009         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4010         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4011         pSMB->DataCount = 0;
4012         pSMB->DataOffset = 0;
4013         pSMB->SetupCount = 1;
4014         pSMB->Reserved3 = 0;
4015         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4016         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4017         pSMB->hdr.smb_buf_length += byte_count;
4018         pSMB->ByteCount = cpu_to_le16(byte_count);
4019
4020         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4021                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4022         if (rc) {
4023                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4024         } else {                /* decode response */
4025                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4026
4027                 if (rc || (pSMBr->ByteCount < 18))
4028                         rc = -EIO;      /* bad smb */
4029                 else {
4030                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4031                         cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
4032                                  pSMBr->ByteCount, data_offset));
4033
4034                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4035                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4036                         FSData->f_bsize =
4037                                 le16_to_cpu(response_data->BytesPerSector) *
4038                                 le32_to_cpu(response_data->
4039                                         SectorsPerAllocationUnit);
4040                         FSData->f_blocks =
4041                                le32_to_cpu(response_data->TotalAllocationUnits);
4042                         FSData->f_bfree = FSData->f_bavail =
4043                                 le32_to_cpu(response_data->FreeAllocationUnits);
4044                         cFYI(1,
4045                              ("Blocks: %lld  Free: %lld Block size %ld",
4046                               (unsigned long long)FSData->f_blocks,
4047                               (unsigned long long)FSData->f_bfree,
4048                               FSData->f_bsize));
4049                 }
4050         }
4051         cifs_buf_release(pSMB);
4052
4053         if (rc == -EAGAIN)
4054                 goto oldQFSInfoRetry;
4055
4056         return rc;
4057 }
4058
4059 int
4060 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4061 {
4062 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4063         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4064         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4065         FILE_SYSTEM_INFO *response_data;
4066         int rc = 0;
4067         int bytes_returned = 0;
4068         __u16 params, byte_count;
4069
4070         cFYI(1, ("In QFSInfo"));
4071 QFSInfoRetry:
4072         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4073                       (void **) &pSMBr);
4074         if (rc)
4075                 return rc;
4076
4077         params = 2;     /* level */
4078         pSMB->TotalDataCount = 0;
4079         pSMB->MaxParameterCount = cpu_to_le16(2);
4080         pSMB->MaxDataCount = cpu_to_le16(1000);
4081         pSMB->MaxSetupCount = 0;
4082         pSMB->Reserved = 0;
4083         pSMB->Flags = 0;
4084         pSMB->Timeout = 0;
4085         pSMB->Reserved2 = 0;
4086         byte_count = params + 1 /* pad */ ;
4087         pSMB->TotalParameterCount = cpu_to_le16(params);
4088         pSMB->ParameterCount = pSMB->TotalParameterCount;
4089         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4090                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4091         pSMB->DataCount = 0;
4092         pSMB->DataOffset = 0;
4093         pSMB->SetupCount = 1;
4094         pSMB->Reserved3 = 0;
4095         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4096         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4097         pSMB->hdr.smb_buf_length += byte_count;
4098         pSMB->ByteCount = cpu_to_le16(byte_count);
4099
4100         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4101                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102         if (rc) {
4103                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4104         } else {                /* decode response */
4105                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4106
4107                 if (rc || (pSMBr->ByteCount < 24))
4108                         rc = -EIO;      /* bad smb */
4109                 else {
4110                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4111
4112                         response_data =
4113                             (FILE_SYSTEM_INFO
4114                              *) (((char *) &pSMBr->hdr.Protocol) +
4115                                  data_offset);
4116                         FSData->f_bsize =
4117                             le32_to_cpu(response_data->BytesPerSector) *
4118                             le32_to_cpu(response_data->
4119                                         SectorsPerAllocationUnit);
4120                         FSData->f_blocks =
4121                             le64_to_cpu(response_data->TotalAllocationUnits);
4122                         FSData->f_bfree = FSData->f_bavail =
4123                             le64_to_cpu(response_data->FreeAllocationUnits);
4124                         cFYI(1,
4125                              ("Blocks: %lld  Free: %lld Block size %ld",
4126                               (unsigned long long)FSData->f_blocks,
4127                               (unsigned long long)FSData->f_bfree,
4128                               FSData->f_bsize));
4129                 }
4130         }
4131         cifs_buf_release(pSMB);
4132
4133         if (rc == -EAGAIN)
4134                 goto QFSInfoRetry;
4135
4136         return rc;
4137 }
4138
4139 int
4140 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4141 {
4142 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4143         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4144         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4145         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4146         int rc = 0;
4147         int bytes_returned = 0;
4148         __u16 params, byte_count;
4149
4150         cFYI(1, ("In QFSAttributeInfo"));
4151 QFSAttributeRetry:
4152         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4153                       (void **) &pSMBr);
4154         if (rc)
4155                 return rc;
4156
4157         params = 2;     /* level */
4158         pSMB->TotalDataCount = 0;
4159         pSMB->MaxParameterCount = cpu_to_le16(2);
4160         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4161         pSMB->MaxSetupCount = 0;
4162         pSMB->Reserved = 0;
4163         pSMB->Flags = 0;
4164         pSMB->Timeout = 0;
4165         pSMB->Reserved2 = 0;
4166         byte_count = params + 1 /* pad */ ;
4167         pSMB->TotalParameterCount = cpu_to_le16(params);
4168         pSMB->ParameterCount = pSMB->TotalParameterCount;
4169         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4170                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4171         pSMB->DataCount = 0;
4172         pSMB->DataOffset = 0;
4173         pSMB->SetupCount = 1;
4174         pSMB->Reserved3 = 0;
4175         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4176         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4177         pSMB->hdr.smb_buf_length += byte_count;
4178         pSMB->ByteCount = cpu_to_le16(byte_count);
4179
4180         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4181                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4182         if (rc) {
4183                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4184         } else {                /* decode response */
4185                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4186
4187                 if (rc || (pSMBr->ByteCount < 13)) {
4188                         /* BB also check if enough bytes returned */
4189                         rc = -EIO;      /* bad smb */
4190                 } else {
4191                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4192                         response_data =
4193                             (FILE_SYSTEM_ATTRIBUTE_INFO
4194                              *) (((char *) &pSMBr->hdr.Protocol) +
4195                                  data_offset);
4196                         memcpy(&tcon->fsAttrInfo, response_data,
4197                                sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4198                 }
4199         }
4200         cifs_buf_release(pSMB);
4201
4202         if (rc == -EAGAIN)
4203                 goto QFSAttributeRetry;
4204
4205         return rc;
4206 }
4207
4208 int
4209 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4210 {
4211 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4212         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4213         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4214         FILE_SYSTEM_DEVICE_INFO *response_data;
4215         int rc = 0;
4216         int bytes_returned = 0;
4217         __u16 params, byte_count;
4218
4219         cFYI(1, ("In QFSDeviceInfo"));
4220 QFSDeviceRetry:
4221         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4222                       (void **) &pSMBr);
4223         if (rc)
4224                 return rc;
4225
4226         params = 2;     /* level */
4227         pSMB->TotalDataCount = 0;
4228         pSMB->MaxParameterCount = cpu_to_le16(2);
4229         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4230         pSMB->MaxSetupCount = 0;
4231         pSMB->Reserved = 0;
4232         pSMB->Flags = 0;
4233         pSMB->Timeout = 0;
4234         pSMB->Reserved2 = 0;
4235         byte_count = params + 1 /* pad */ ;
4236         pSMB->TotalParameterCount = cpu_to_le16(params);
4237         pSMB->ParameterCount = pSMB->TotalParameterCount;
4238         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4239                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4240
4241         pSMB->DataCount = 0;
4242         pSMB->DataOffset = 0;
4243         pSMB->SetupCount = 1;
4244         pSMB->Reserved3 = 0;
4245         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4246         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4247         pSMB->hdr.smb_buf_length += byte_count;
4248         pSMB->ByteCount = cpu_to_le16(byte_count);
4249
4250         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4251                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4252         if (rc) {
4253                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4254         } else {                /* decode response */
4255                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4256
4257                 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4258                         rc = -EIO;      /* bad smb */
4259                 else {
4260                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4261                         response_data =
4262                             (FILE_SYSTEM_DEVICE_INFO *)
4263                                 (((char *) &pSMBr->hdr.Protocol) +
4264                                  data_offset);
4265                         memcpy(&tcon->fsDevInfo, response_data,
4266                                sizeof (FILE_SYSTEM_DEVICE_INFO));
4267                 }
4268         }
4269         cifs_buf_release(pSMB);
4270
4271         if (rc == -EAGAIN)
4272                 goto QFSDeviceRetry;
4273
4274         return rc;
4275 }
4276
4277 int
4278 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4279 {
4280 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4281         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4282         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4283         FILE_SYSTEM_UNIX_INFO *response_data;
4284         int rc = 0;
4285         int bytes_returned = 0;
4286         __u16 params, byte_count;
4287
4288         cFYI(1, ("In QFSUnixInfo"));
4289 QFSUnixRetry:
4290         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4291                       (void **) &pSMBr);
4292         if (rc)
4293                 return rc;
4294
4295         params = 2;     /* level */
4296         pSMB->TotalDataCount = 0;
4297         pSMB->DataCount = 0;
4298         pSMB->DataOffset = 0;
4299         pSMB->MaxParameterCount = cpu_to_le16(2);
4300         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
4301         pSMB->MaxSetupCount = 0;
4302         pSMB->Reserved = 0;
4303         pSMB->Flags = 0;
4304         pSMB->Timeout = 0;
4305         pSMB->Reserved2 = 0;
4306         byte_count = params + 1 /* pad */ ;
4307         pSMB->ParameterCount = cpu_to_le16(params);
4308         pSMB->TotalParameterCount = pSMB->ParameterCount;
4309         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4310                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4311         pSMB->SetupCount = 1;
4312         pSMB->Reserved3 = 0;
4313         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4314         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4315         pSMB->hdr.smb_buf_length += byte_count;
4316         pSMB->ByteCount = cpu_to_le16(byte_count);
4317
4318         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4319                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4320         if (rc) {
4321                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4322         } else {                /* decode response */
4323                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4324
4325                 if (rc || (pSMBr->ByteCount < 13)) {
4326                         rc = -EIO;      /* bad smb */
4327                 } else {
4328                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4329                         response_data =
4330                             (FILE_SYSTEM_UNIX_INFO
4331                              *) (((char *) &pSMBr->hdr.Protocol) +
4332                                  data_offset);
4333                         memcpy(&tcon->fsUnixInfo, response_data,
4334                                sizeof (FILE_SYSTEM_UNIX_INFO));
4335                 }
4336         }
4337         cifs_buf_release(pSMB);
4338
4339         if (rc == -EAGAIN)
4340                 goto QFSUnixRetry;
4341
4342
4343         return rc;
4344 }
4345
4346 int
4347 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4348 {
4349 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4350         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4351         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4352         int rc = 0;
4353         int bytes_returned = 0;
4354         __u16 params, param_offset, offset, byte_count;
4355
4356         cFYI(1, ("In SETFSUnixInfo"));
4357 SETFSUnixRetry:
4358         /* BB switch to small buf init to save memory */
4359         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4360                       (void **) &pSMBr);
4361         if (rc)
4362                 return rc;
4363
4364         params = 4;     /* 2 bytes zero followed by info level. */
4365         pSMB->MaxSetupCount = 0;
4366         pSMB->Reserved = 0;
4367         pSMB->Flags = 0;
4368         pSMB->Timeout = 0;
4369         pSMB->Reserved2 = 0;
4370         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4371                                 - 4;
4372         offset = param_offset + params;
4373
4374         pSMB->MaxParameterCount = cpu_to_le16(4);
4375         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
4376         pSMB->SetupCount = 1;
4377         pSMB->Reserved3 = 0;
4378         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4379         byte_count = 1 /* pad */ + params + 12;
4380
4381         pSMB->DataCount = cpu_to_le16(12);
4382         pSMB->ParameterCount = cpu_to_le16(params);
4383         pSMB->TotalDataCount = pSMB->DataCount;
4384         pSMB->TotalParameterCount = pSMB->ParameterCount;
4385         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4386         pSMB->DataOffset = cpu_to_le16(offset);
4387
4388         /* Params. */
4389         pSMB->FileNum = 0;
4390         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4391
4392         /* Data. */
4393         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4394         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4395         pSMB->ClientUnixCap = cpu_to_le64(cap);
4396
4397         pSMB->hdr.smb_buf_length += byte_count;
4398         pSMB->ByteCount = cpu_to_le16(byte_count);
4399
4400         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4401                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4402         if (rc) {
4403                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4404         } else {                /* decode response */
4405                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4406                 if (rc) {
4407                         rc = -EIO;      /* bad smb */
4408                 }
4409         }
4410         cifs_buf_release(pSMB);
4411
4412         if (rc == -EAGAIN)
4413                 goto SETFSUnixRetry;
4414
4415         return rc;
4416 }
4417
4418
4419
4420 int
4421 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4422                    struct kstatfs *FSData)
4423 {
4424 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4425         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4426         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4427         FILE_SYSTEM_POSIX_INFO *response_data;
4428         int rc = 0;
4429         int bytes_returned = 0;
4430         __u16 params, byte_count;
4431
4432         cFYI(1, ("In QFSPosixInfo"));
4433 QFSPosixRetry:
4434         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4435                       (void **) &pSMBr);
4436         if (rc)
4437                 return rc;
4438
4439         params = 2;     /* level */
4440         pSMB->TotalDataCount = 0;
4441         pSMB->DataCount = 0;
4442         pSMB->DataOffset = 0;
4443         pSMB->MaxParameterCount = cpu_to_le16(2);
4444         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
4445         pSMB->MaxSetupCount = 0;
4446         pSMB->Reserved = 0;
4447         pSMB->Flags = 0;
4448         pSMB->Timeout = 0;
4449         pSMB->Reserved2 = 0;
4450         byte_count = params + 1 /* pad */ ;
4451         pSMB->ParameterCount = cpu_to_le16(params);
4452         pSMB->TotalParameterCount = pSMB->ParameterCount;
4453         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4454                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4455         pSMB->SetupCount = 1;
4456         pSMB->Reserved3 = 0;
4457         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4458         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4459         pSMB->hdr.smb_buf_length += byte_count;
4460         pSMB->ByteCount = cpu_to_le16(byte_count);
4461
4462         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4463                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4464         if (rc) {
4465                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4466         } else {                /* decode response */
4467                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4468
4469                 if (rc || (pSMBr->ByteCount < 13)) {
4470                         rc = -EIO;      /* bad smb */
4471                 } else {
4472                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4473                         response_data =
4474                             (FILE_SYSTEM_POSIX_INFO
4475                              *) (((char *) &pSMBr->hdr.Protocol) +
4476                                  data_offset);
4477                         FSData->f_bsize =
4478                                         le32_to_cpu(response_data->BlockSize);
4479                         FSData->f_blocks =
4480                                         le64_to_cpu(response_data->TotalBlocks);
4481                         FSData->f_bfree =
4482                             le64_to_cpu(response_data->BlocksAvail);
4483                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4484                                 FSData->f_bavail = FSData->f_bfree;
4485                         } else {
4486                                 FSData->f_bavail =
4487                                     le64_to_cpu(response_data->UserBlocksAvail);
4488                         }
4489                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
4490                                 FSData->f_files =
4491                                      le64_to_cpu(response_data->TotalFileNodes);
4492                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
4493                                 FSData->f_ffree =
4494                                       le64_to_cpu(response_data->FreeFileNodes);
4495                 }
4496         }
4497         cifs_buf_release(pSMB);
4498
4499         if (rc == -EAGAIN)
4500                 goto QFSPosixRetry;
4501
4502         return rc;
4503 }
4504
4505
4506 /* We can not use write of zero bytes trick to
4507    set file size due to need for large file support.  Also note that
4508    this SetPathInfo is preferred to SetFileInfo based method in next
4509    routine which is only needed to work around a sharing violation bug
4510    in Samba which this routine can run into */
4511
4512 int
4513 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4514               __u64 size, int SetAllocation,
4515               const struct nls_table *nls_codepage, int remap)
4516 {
4517         struct smb_com_transaction2_spi_req *pSMB = NULL;
4518         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4519         struct file_end_of_file_info *parm_data;
4520         int name_len;
4521         int rc = 0;
4522         int bytes_returned = 0;
4523         __u16 params, byte_count, data_count, param_offset, offset;
4524
4525         cFYI(1, ("In SetEOF"));
4526 SetEOFRetry:
4527         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4528                       (void **) &pSMBr);
4529         if (rc)
4530                 return rc;
4531
4532         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4533                 name_len =
4534                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4535                                      PATH_MAX, nls_codepage, remap);
4536                 name_len++;     /* trailing null */
4537                 name_len *= 2;
4538         } else {        /* BB improve the check for buffer overruns BB */
4539                 name_len = strnlen(fileName, PATH_MAX);
4540                 name_len++;     /* trailing null */
4541                 strncpy(pSMB->FileName, fileName, name_len);
4542         }
4543         params = 6 + name_len;
4544         data_count = sizeof (struct file_end_of_file_info);
4545         pSMB->MaxParameterCount = cpu_to_le16(2);
4546         pSMB->MaxDataCount = cpu_to_le16(4100);
4547         pSMB->MaxSetupCount = 0;
4548         pSMB->Reserved = 0;
4549         pSMB->Flags = 0;
4550         pSMB->Timeout = 0;
4551         pSMB->Reserved2 = 0;
4552         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4553                                 InformationLevel) - 4;
4554         offset = param_offset + params;
4555         if (SetAllocation) {
4556                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4557                         pSMB->InformationLevel =
4558                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4559                 else
4560                         pSMB->InformationLevel =
4561                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4562         } else /* Set File Size */  {
4563             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4564                     pSMB->InformationLevel =
4565                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4566             else
4567                     pSMB->InformationLevel =
4568                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4569         }
4570
4571         parm_data =
4572             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4573                                        offset);
4574         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4575         pSMB->DataOffset = cpu_to_le16(offset);
4576         pSMB->SetupCount = 1;
4577         pSMB->Reserved3 = 0;
4578         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4579         byte_count = 3 /* pad */  + params + data_count;
4580         pSMB->DataCount = cpu_to_le16(data_count);
4581         pSMB->TotalDataCount = pSMB->DataCount;
4582         pSMB->ParameterCount = cpu_to_le16(params);
4583         pSMB->TotalParameterCount = pSMB->ParameterCount;
4584         pSMB->Reserved4 = 0;
4585         pSMB->hdr.smb_buf_length += byte_count;
4586         parm_data->FileSize = cpu_to_le64(size);
4587         pSMB->ByteCount = cpu_to_le16(byte_count);
4588         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4589                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4590         if (rc) {
4591                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4592         }
4593
4594         cifs_buf_release(pSMB);
4595
4596         if (rc == -EAGAIN)
4597                 goto SetEOFRetry;
4598
4599         return rc;
4600 }
4601
4602 int
4603 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4604                    __u16 fid, __u32 pid_of_opener, int SetAllocation)
4605 {
4606         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4607         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4608         char *data_offset;
4609         struct file_end_of_file_info *parm_data;
4610         int rc = 0;
4611         int bytes_returned = 0;
4612         __u16 params, param_offset, offset, byte_count, count;
4613
4614         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4615                         (long long)size));
4616         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4617
4618         if (rc)
4619                 return rc;
4620
4621         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4622
4623         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4624         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4625
4626         params = 6;
4627         pSMB->MaxSetupCount = 0;
4628         pSMB->Reserved = 0;
4629         pSMB->Flags = 0;
4630         pSMB->Timeout = 0;
4631         pSMB->Reserved2 = 0;
4632         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4633         offset = param_offset + params;
4634
4635         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4636
4637         count = sizeof(struct file_end_of_file_info);
4638         pSMB->MaxParameterCount = cpu_to_le16(2);
4639         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4640         pSMB->SetupCount = 1;
4641         pSMB->Reserved3 = 0;
4642         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4643         byte_count = 3 /* pad */  + params + count;
4644         pSMB->DataCount = cpu_to_le16(count);
4645         pSMB->ParameterCount = cpu_to_le16(params);
4646         pSMB->TotalDataCount = pSMB->DataCount;
4647         pSMB->TotalParameterCount = pSMB->ParameterCount;
4648         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4649         parm_data =
4650                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4651                                 + offset);
4652         pSMB->DataOffset = cpu_to_le16(offset);
4653         parm_data->FileSize = cpu_to_le64(size);
4654         pSMB->Fid = fid;
4655         if (SetAllocation) {
4656                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4657                         pSMB->InformationLevel =
4658                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4659                 else
4660                         pSMB->InformationLevel =
4661                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4662         } else /* Set File Size */  {
4663             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4664                     pSMB->InformationLevel =
4665                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4666             else
4667                     pSMB->InformationLevel =
4668                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4669         }
4670         pSMB->Reserved4 = 0;
4671         pSMB->hdr.smb_buf_length += byte_count;
4672         pSMB->ByteCount = cpu_to_le16(byte_count);
4673         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4674                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4675         if (rc) {
4676                 cFYI(1,
4677                      ("Send error in SetFileInfo (SetFileSize) = %d",
4678                       rc));
4679         }
4680
4681         if (pSMB)
4682                 cifs_small_buf_release(pSMB);
4683
4684         /* Note: On -EAGAIN error only caller can retry on handle based calls
4685                 since file handle passed in no longer valid */
4686
4687         return rc;
4688 }
4689
4690 /* Some legacy servers such as NT4 require that the file times be set on
4691    an open handle, rather than by pathname - this is awkward due to
4692    potential access conflicts on the open, but it is unavoidable for these
4693    old servers since the only other choice is to go from 100 nanosecond DCE
4694    time and resort to the original setpathinfo level which takes the ancient
4695    DOS time format with 2 second granularity */
4696 int
4697 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4698                     const FILE_BASIC_INFO *data, __u16 fid)
4699 {
4700         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4701         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4702         char *data_offset;
4703         int rc = 0;
4704         int bytes_returned = 0;
4705         __u16 params, param_offset, offset, byte_count, count;
4706
4707         cFYI(1, ("Set Times (via SetFileInfo)"));
4708         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4709
4710         if (rc)
4711                 return rc;
4712
4713         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4714
4715         /* At this point there is no need to override the current pid
4716         with the pid of the opener, but that could change if we someday
4717         use an existing handle (rather than opening one on the fly) */
4718         /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4719         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4720
4721         params = 6;
4722         pSMB->MaxSetupCount = 0;
4723         pSMB->Reserved = 0;
4724         pSMB->Flags = 0;
4725         pSMB->Timeout = 0;
4726         pSMB->Reserved2 = 0;
4727         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4728         offset = param_offset + params;
4729
4730         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4731
4732         count = sizeof (FILE_BASIC_INFO);
4733         pSMB->MaxParameterCount = cpu_to_le16(2);
4734         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4735         pSMB->SetupCount = 1;
4736         pSMB->Reserved3 = 0;
4737         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4738         byte_count = 3 /* pad */  + params + count;
4739         pSMB->DataCount = cpu_to_le16(count);
4740         pSMB->ParameterCount = cpu_to_le16(params);
4741         pSMB->TotalDataCount = pSMB->DataCount;
4742         pSMB->TotalParameterCount = pSMB->ParameterCount;
4743         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4744         pSMB->DataOffset = cpu_to_le16(offset);
4745         pSMB->Fid = fid;
4746         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4747                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4748         else
4749                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4750         pSMB->Reserved4 = 0;
4751         pSMB->hdr.smb_buf_length += byte_count;
4752         pSMB->ByteCount = cpu_to_le16(byte_count);
4753         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4754         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4755                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4756         if (rc) {
4757                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4758         }
4759
4760         cifs_small_buf_release(pSMB);
4761
4762         /* Note: On -EAGAIN error only caller can retry on handle based calls
4763                 since file handle passed in no longer valid */
4764
4765         return rc;
4766 }
4767
4768
4769 int
4770 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4771                 const FILE_BASIC_INFO *data,
4772                 const struct nls_table *nls_codepage, int remap)
4773 {
4774         TRANSACTION2_SPI_REQ *pSMB = NULL;
4775         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4776         int name_len;
4777         int rc = 0;
4778         int bytes_returned = 0;
4779         char *data_offset;
4780         __u16 params, param_offset, offset, byte_count, count;
4781
4782         cFYI(1, ("In SetTimes"));
4783
4784 SetTimesRetry:
4785         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4786                       (void **) &pSMBr);
4787         if (rc)
4788                 return rc;
4789
4790         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4791                 name_len =
4792                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4793                                      PATH_MAX, nls_codepage, remap);
4794                 name_len++;     /* trailing null */
4795                 name_len *= 2;
4796         } else {        /* BB improve the check for buffer overruns BB */
4797                 name_len = strnlen(fileName, PATH_MAX);
4798                 name_len++;     /* trailing null */
4799                 strncpy(pSMB->FileName, fileName, name_len);
4800         }
4801
4802         params = 6 + name_len;
4803         count = sizeof (FILE_BASIC_INFO);
4804         pSMB->MaxParameterCount = cpu_to_le16(2);
4805         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4806         pSMB->MaxSetupCount = 0;
4807         pSMB->Reserved = 0;
4808         pSMB->Flags = 0;
4809         pSMB->Timeout = 0;
4810         pSMB->Reserved2 = 0;
4811         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4812                                 InformationLevel) - 4;
4813         offset = param_offset + params;
4814         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4815         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4816         pSMB->DataOffset = cpu_to_le16(offset);
4817         pSMB->SetupCount = 1;
4818         pSMB->Reserved3 = 0;
4819         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4820         byte_count = 3 /* pad */  + params + count;
4821
4822         pSMB->DataCount = cpu_to_le16(count);
4823         pSMB->ParameterCount = cpu_to_le16(params);
4824         pSMB->TotalDataCount = pSMB->DataCount;
4825         pSMB->TotalParameterCount = pSMB->ParameterCount;
4826         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4827                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4828         else
4829                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4830         pSMB->Reserved4 = 0;
4831         pSMB->hdr.smb_buf_length += byte_count;
4832         memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4833         pSMB->ByteCount = cpu_to_le16(byte_count);
4834         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4835                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4836         if (rc) {
4837                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4838         }
4839
4840         cifs_buf_release(pSMB);
4841
4842         if (rc == -EAGAIN)
4843                 goto SetTimesRetry;
4844
4845         return rc;
4846 }
4847
4848 /* Can not be used to set time stamps yet (due to old DOS time format) */
4849 /* Can be used to set attributes */
4850 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
4851           handling it anyway and NT4 was what we thought it would be needed for
4852           Do not delete it until we prove whether needed for Win9x though */
4853 int
4854 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4855                 __u16 dos_attrs, const struct nls_table *nls_codepage)
4856 {
4857         SETATTR_REQ *pSMB = NULL;
4858         SETATTR_RSP *pSMBr = NULL;
4859         int rc = 0;
4860         int bytes_returned;
4861         int name_len;
4862
4863         cFYI(1, ("In SetAttrLegacy"));
4864
4865 SetAttrLgcyRetry:
4866         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4867                       (void **) &pSMBr);
4868         if (rc)
4869                 return rc;
4870
4871         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4872                 name_len =
4873                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4874                                 PATH_MAX, nls_codepage);
4875                 name_len++;     /* trailing null */
4876                 name_len *= 2;
4877         } else {        /* BB improve the check for buffer overruns BB */
4878                 name_len = strnlen(fileName, PATH_MAX);
4879                 name_len++;     /* trailing null */
4880                 strncpy(pSMB->fileName, fileName, name_len);
4881         }
4882         pSMB->attr = cpu_to_le16(dos_attrs);
4883         pSMB->BufferFormat = 0x04;
4884         pSMB->hdr.smb_buf_length += name_len + 1;
4885         pSMB->ByteCount = cpu_to_le16(name_len + 1);
4886         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4887                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4888         if (rc) {
4889                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4890         }
4891
4892         cifs_buf_release(pSMB);
4893
4894         if (rc == -EAGAIN)
4895                 goto SetAttrLgcyRetry;
4896
4897         return rc;
4898 }
4899 #endif /* temporarily unneeded SetAttr legacy function */
4900
4901 int
4902 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4903                     char *fileName, __u64 mode, __u64 uid, __u64 gid,
4904                     dev_t device, const struct nls_table *nls_codepage,
4905                     int remap)
4906 {
4907         TRANSACTION2_SPI_REQ *pSMB = NULL;
4908         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4909         int name_len;
4910         int rc = 0;
4911         int bytes_returned = 0;
4912         FILE_UNIX_BASIC_INFO *data_offset;
4913         __u16 params, param_offset, offset, count, byte_count;
4914
4915         cFYI(1, ("In SetUID/GID/Mode"));
4916 setPermsRetry:
4917         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4918                       (void **) &pSMBr);
4919         if (rc)
4920                 return rc;
4921
4922         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4923                 name_len =
4924                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4925                                      PATH_MAX, nls_codepage, remap);
4926                 name_len++;     /* trailing null */
4927                 name_len *= 2;
4928         } else {        /* BB improve the check for buffer overruns BB */
4929                 name_len = strnlen(fileName, PATH_MAX);
4930                 name_len++;     /* trailing null */
4931                 strncpy(pSMB->FileName, fileName, name_len);
4932         }
4933
4934         params = 6 + name_len;
4935         count = sizeof (FILE_UNIX_BASIC_INFO);
4936         pSMB->MaxParameterCount = cpu_to_le16(2);
4937         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4938         pSMB->MaxSetupCount = 0;
4939         pSMB->Reserved = 0;
4940         pSMB->Flags = 0;
4941         pSMB->Timeout = 0;
4942         pSMB->Reserved2 = 0;
4943         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4944                                 InformationLevel) - 4;
4945         offset = param_offset + params;
4946         data_offset =
4947             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4948                                       offset);
4949         memset(data_offset, 0, count);
4950         pSMB->DataOffset = cpu_to_le16(offset);
4951         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4952         pSMB->SetupCount = 1;
4953         pSMB->Reserved3 = 0;
4954         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4955         byte_count = 3 /* pad */  + params + count;
4956         pSMB->ParameterCount = cpu_to_le16(params);
4957         pSMB->DataCount = cpu_to_le16(count);
4958         pSMB->TotalParameterCount = pSMB->ParameterCount;
4959         pSMB->TotalDataCount = pSMB->DataCount;
4960         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4961         pSMB->Reserved4 = 0;
4962         pSMB->hdr.smb_buf_length += byte_count;
4963         /* Samba server ignores set of file size to zero due to bugs in some
4964         older clients, but we should be precise - we use SetFileSize to
4965         set file size and do not want to truncate file size to zero
4966         accidently as happened on one Samba server beta by putting
4967         zero instead of -1 here */
4968         data_offset->EndOfFile = NO_CHANGE_64;
4969         data_offset->NumOfBytes = NO_CHANGE_64;
4970         data_offset->LastStatusChange = NO_CHANGE_64;
4971         data_offset->LastAccessTime = NO_CHANGE_64;
4972         data_offset->LastModificationTime = NO_CHANGE_64;
4973         data_offset->Uid = cpu_to_le64(uid);
4974         data_offset->Gid = cpu_to_le64(gid);
4975         /* better to leave device as zero when it is  */
4976         data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4977         data_offset->DevMinor = cpu_to_le64(MINOR(device));
4978         data_offset->Permissions = cpu_to_le64(mode);
4979
4980         if (S_ISREG(mode))
4981                 data_offset->Type = cpu_to_le32(UNIX_FILE);
4982         else if (S_ISDIR(mode))
4983                 data_offset->Type = cpu_to_le32(UNIX_DIR);
4984         else if (S_ISLNK(mode))
4985                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4986         else if (S_ISCHR(mode))
4987                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4988         else if (S_ISBLK(mode))
4989                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4990         else if (S_ISFIFO(mode))
4991                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4992         else if (S_ISSOCK(mode))
4993                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4994
4995
4996         pSMB->ByteCount = cpu_to_le16(byte_count);
4997         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4998                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4999         if (rc) {
5000                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5001         }
5002
5003         if (pSMB)
5004                 cifs_buf_release(pSMB);
5005         if (rc == -EAGAIN)
5006                 goto setPermsRetry;
5007         return rc;
5008 }
5009
5010 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5011                   const int notify_subdirs, const __u16 netfid,
5012                   __u32 filter, struct file *pfile, int multishot,
5013                   const struct nls_table *nls_codepage)
5014 {
5015         int rc = 0;
5016         struct smb_com_transaction_change_notify_req *pSMB = NULL;
5017         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5018         struct dir_notify_req *dnotify_req;
5019         int bytes_returned;
5020
5021         cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5022         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5023                       (void **) &pSMBr);
5024         if (rc)
5025                 return rc;
5026
5027         pSMB->TotalParameterCount = 0 ;
5028         pSMB->TotalDataCount = 0;
5029         pSMB->MaxParameterCount = cpu_to_le32(2);
5030         /* BB find exact data count max from sess structure BB */
5031         pSMB->MaxDataCount = 0; /* same in little endian or be */
5032 /* BB VERIFY verify which is correct for above BB */
5033         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5034                                              MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5035
5036         pSMB->MaxSetupCount = 4;
5037         pSMB->Reserved = 0;
5038         pSMB->ParameterOffset = 0;
5039         pSMB->DataCount = 0;
5040         pSMB->DataOffset = 0;
5041         pSMB->SetupCount = 4; /* single byte does not need le conversion */
5042         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5043         pSMB->ParameterCount = pSMB->TotalParameterCount;
5044         if (notify_subdirs)
5045                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5046         pSMB->Reserved2 = 0;
5047         pSMB->CompletionFilter = cpu_to_le32(filter);
5048         pSMB->Fid = netfid; /* file handle always le */
5049         pSMB->ByteCount = 0;
5050
5051         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5052                         (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5053         if (rc) {
5054                 cFYI(1, ("Error in Notify = %d", rc));
5055         } else {
5056                 /* Add file to outstanding requests */
5057                 /* BB change to kmem cache alloc */
5058                 dnotify_req = kmalloc(
5059                                                 sizeof(struct dir_notify_req),
5060                                                  GFP_KERNEL);
5061                 if (dnotify_req) {
5062                         dnotify_req->Pid = pSMB->hdr.Pid;
5063                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5064                         dnotify_req->Mid = pSMB->hdr.Mid;
5065                         dnotify_req->Tid = pSMB->hdr.Tid;
5066                         dnotify_req->Uid = pSMB->hdr.Uid;
5067                         dnotify_req->netfid = netfid;
5068                         dnotify_req->pfile = pfile;
5069                         dnotify_req->filter = filter;
5070                         dnotify_req->multishot = multishot;
5071                         spin_lock(&GlobalMid_Lock);
5072                         list_add_tail(&dnotify_req->lhead,
5073                                         &GlobalDnotifyReqList);
5074                         spin_unlock(&GlobalMid_Lock);
5075                 } else
5076                         rc = -ENOMEM;
5077         }
5078         cifs_buf_release(pSMB);
5079         return rc;
5080 }
5081 #ifdef CONFIG_CIFS_XATTR
5082 ssize_t
5083 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5084                  const unsigned char *searchName,
5085                  char *EAData, size_t buf_size,
5086                  const struct nls_table *nls_codepage, int remap)
5087 {
5088                 /* BB assumes one setup word */
5089         TRANSACTION2_QPI_REQ *pSMB = NULL;
5090         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5091         int rc = 0;
5092         int bytes_returned;
5093         int name_len;
5094         struct fea *temp_fea;
5095         char *temp_ptr;
5096         __u16 params, byte_count;
5097
5098         cFYI(1, ("In Query All EAs path %s", searchName));
5099 QAllEAsRetry:
5100         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5101                       (void **) &pSMBr);
5102         if (rc)
5103                 return rc;
5104
5105         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5106                 name_len =
5107                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5108                                      PATH_MAX, nls_codepage, remap);
5109                 name_len++;     /* trailing null */
5110                 name_len *= 2;
5111         } else {        /* BB improve the check for buffer overruns BB */
5112                 name_len = strnlen(searchName, PATH_MAX);
5113                 name_len++;     /* trailing null */
5114                 strncpy(pSMB->FileName, searchName, name_len);
5115         }
5116
5117         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5118         pSMB->TotalDataCount = 0;
5119         pSMB->MaxParameterCount = cpu_to_le16(2);
5120         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5121         pSMB->MaxSetupCount = 0;
5122         pSMB->Reserved = 0;
5123         pSMB->Flags = 0;
5124         pSMB->Timeout = 0;
5125         pSMB->Reserved2 = 0;
5126         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5127         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5128         pSMB->DataCount = 0;
5129         pSMB->DataOffset = 0;
5130         pSMB->SetupCount = 1;
5131         pSMB->Reserved3 = 0;
5132         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5133         byte_count = params + 1 /* pad */ ;
5134         pSMB->TotalParameterCount = cpu_to_le16(params);
5135         pSMB->ParameterCount = pSMB->TotalParameterCount;
5136         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5137         pSMB->Reserved4 = 0;
5138         pSMB->hdr.smb_buf_length += byte_count;
5139         pSMB->ByteCount = cpu_to_le16(byte_count);
5140
5141         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5142                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5143         if (rc) {
5144                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5145         } else {                /* decode response */
5146                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5147
5148                 /* BB also check enough total bytes returned */
5149                 /* BB we need to improve the validity checking
5150                 of these trans2 responses */
5151                 if (rc || (pSMBr->ByteCount < 4))
5152                         rc = -EIO;      /* bad smb */
5153            /* else if (pFindData){
5154                         memcpy((char *) pFindData,
5155                                (char *) &pSMBr->hdr.Protocol +
5156                                data_offset, kl);
5157                 }*/ else {
5158                         /* check that length of list is not more than bcc */
5159                         /* check that each entry does not go beyond length
5160                            of list */
5161                         /* check that each element of each entry does not
5162                            go beyond end of list */
5163                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5164                         struct fealist *ea_response_data;
5165                         rc = 0;
5166                         /* validate_trans2_offsets() */
5167                         /* BB check if start of smb + data_offset > &bcc+ bcc */
5168                         ea_response_data = (struct fealist *)
5169                                 (((char *) &pSMBr->hdr.Protocol) +
5170                                 data_offset);
5171                         name_len = le32_to_cpu(ea_response_data->list_len);
5172                         cFYI(1, ("ea length %d", name_len));
5173                         if (name_len <= 8) {
5174                         /* returned EA size zeroed at top of function */
5175                                 cFYI(1, ("empty EA list returned from server"));
5176                         } else {
5177                                 /* account for ea list len */
5178                                 name_len -= 4;
5179                                 temp_fea = ea_response_data->list;
5180                                 temp_ptr = (char *)temp_fea;
5181                                 while (name_len > 0) {
5182                                         __u16 value_len;
5183                                         name_len -= 4;
5184                                         temp_ptr += 4;
5185                                         rc += temp_fea->name_len;
5186                                 /* account for prefix user. and trailing null */
5187                                         rc = rc + 5 + 1;
5188                                         if (rc < (int)buf_size) {
5189                                                 memcpy(EAData, "user.", 5);
5190                                                 EAData += 5;
5191                                                 memcpy(EAData, temp_ptr,
5192                                                        temp_fea->name_len);
5193                                                 EAData += temp_fea->name_len;
5194                                                 /* null terminate name */
5195                                                 *EAData = 0;
5196                                                 EAData = EAData + 1;
5197                                         } else if (buf_size == 0) {
5198                                                 /* skip copy - calc size only */
5199                                         } else {
5200                                                 /* stop before overrun buffer */
5201                                                 rc = -ERANGE;
5202                                                 break;
5203                                         }
5204                                         name_len -= temp_fea->name_len;
5205                                         temp_ptr += temp_fea->name_len;
5206                                         /* account for trailing null */
5207                                         name_len--;
5208                                         temp_ptr++;
5209                                         value_len =
5210                                               le16_to_cpu(temp_fea->value_len);
5211                                         name_len -= value_len;
5212                                         temp_ptr += value_len;
5213                                         /* BB check that temp_ptr is still
5214                                               within the SMB BB*/
5215
5216                                         /* no trailing null to account for
5217                                            in value len */
5218                                         /* go on to next EA */
5219                                         temp_fea = (struct fea *)temp_ptr;
5220                                 }
5221                         }
5222                 }
5223         }
5224         if (pSMB)
5225                 cifs_buf_release(pSMB);
5226         if (rc == -EAGAIN)
5227                 goto QAllEAsRetry;
5228
5229         return (ssize_t)rc;
5230 }
5231
5232 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5233                 const unsigned char *searchName, const unsigned char *ea_name,
5234                 unsigned char *ea_value, size_t buf_size,
5235                 const struct nls_table *nls_codepage, int remap)
5236 {
5237         TRANSACTION2_QPI_REQ *pSMB = NULL;
5238         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5239         int rc = 0;
5240         int bytes_returned;
5241         int name_len;
5242         struct fea *temp_fea;
5243         char *temp_ptr;
5244         __u16 params, byte_count;
5245
5246         cFYI(1, ("In Query EA path %s", searchName));
5247 QEARetry:
5248         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5249                       (void **) &pSMBr);
5250         if (rc)
5251                 return rc;
5252
5253         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5254                 name_len =
5255                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5256                                      PATH_MAX, nls_codepage, remap);
5257                 name_len++;     /* trailing null */
5258                 name_len *= 2;
5259         } else {        /* BB improve the check for buffer overruns BB */
5260                 name_len = strnlen(searchName, PATH_MAX);
5261                 name_len++;     /* trailing null */
5262                 strncpy(pSMB->FileName, searchName, name_len);
5263         }
5264
5265         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5266         pSMB->TotalDataCount = 0;
5267         pSMB->MaxParameterCount = cpu_to_le16(2);
5268         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5269         pSMB->MaxSetupCount = 0;
5270         pSMB->Reserved = 0;
5271         pSMB->Flags = 0;
5272         pSMB->Timeout = 0;
5273         pSMB->Reserved2 = 0;
5274         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5275                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5276         pSMB->DataCount = 0;
5277         pSMB->DataOffset = 0;
5278         pSMB->SetupCount = 1;
5279         pSMB->Reserved3 = 0;
5280         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5281         byte_count = params + 1 /* pad */ ;
5282         pSMB->TotalParameterCount = cpu_to_le16(params);
5283         pSMB->ParameterCount = pSMB->TotalParameterCount;
5284         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5285         pSMB->Reserved4 = 0;
5286         pSMB->hdr.smb_buf_length += byte_count;
5287         pSMB->ByteCount = cpu_to_le16(byte_count);
5288
5289         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5290                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5291         if (rc) {
5292                 cFYI(1, ("Send error in Query EA = %d", rc));
5293         } else {                /* decode response */
5294                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5295
5296                 /* BB also check enough total bytes returned */
5297                 /* BB we need to improve the validity checking
5298                 of these trans2 responses */
5299                 if (rc || (pSMBr->ByteCount < 4))
5300                         rc = -EIO;      /* bad smb */
5301            /* else if (pFindData){
5302                         memcpy((char *) pFindData,
5303                                (char *) &pSMBr->hdr.Protocol +
5304                                data_offset, kl);
5305                 }*/ else {
5306                         /* check that length of list is not more than bcc */
5307                         /* check that each entry does not go beyond length
5308                            of list */
5309                         /* check that each element of each entry does not
5310                            go beyond end of list */
5311                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5312                         struct fealist *ea_response_data;
5313                         rc = -ENODATA;
5314                         /* validate_trans2_offsets() */
5315                         /* BB check if start of smb + data_offset > &bcc+ bcc*/
5316                         ea_response_data = (struct fealist *)
5317                                 (((char *) &pSMBr->hdr.Protocol) +
5318                                 data_offset);
5319                         name_len = le32_to_cpu(ea_response_data->list_len);
5320                         cFYI(1, ("ea length %d", name_len));
5321                         if (name_len <= 8) {
5322                         /* returned EA size zeroed at top of function */
5323                                 cFYI(1, ("empty EA list returned from server"));
5324                         } else {
5325                                 /* account for ea list len */
5326                                 name_len -= 4;
5327                                 temp_fea = ea_response_data->list;
5328                                 temp_ptr = (char *)temp_fea;
5329                                 /* loop through checking if we have a matching
5330                                 name and then return the associated value */
5331                                 while (name_len > 0) {
5332                                         __u16 value_len;
5333                                         name_len -= 4;
5334                                         temp_ptr += 4;
5335                                         value_len =
5336                                               le16_to_cpu(temp_fea->value_len);
5337                                 /* BB validate that value_len falls within SMB,
5338                                 even though maximum for name_len is 255 */
5339                                         if (memcmp(temp_fea->name, ea_name,
5340                                                   temp_fea->name_len) == 0) {
5341                                                 /* found a match */
5342                                                 rc = value_len;
5343                                 /* account for prefix user. and trailing null */
5344                                                 if (rc <= (int)buf_size) {
5345                                                         memcpy(ea_value,
5346                                                                 temp_fea->name+temp_fea->name_len+1,
5347                                                                 rc);
5348                                                         /* ea values, unlike ea
5349                                                            names, are not null
5350                                                            terminated */
5351                                                 } else if (buf_size == 0) {
5352                                                 /* skip copy - calc size only */
5353                                                 } else {
5354                                                 /* stop before overrun buffer */
5355                                                         rc = -ERANGE;
5356                                                 }
5357                                                 break;
5358                                         }
5359                                         name_len -= temp_fea->name_len;
5360                                         temp_ptr += temp_fea->name_len;
5361                                         /* account for trailing null */
5362                                         name_len--;
5363                                         temp_ptr++;
5364                                         name_len -= value_len;
5365                                         temp_ptr += value_len;
5366                                         /* No trailing null to account for in
5367                                            value_len.  Go on to next EA */
5368                                         temp_fea = (struct fea *)temp_ptr;
5369                                 }
5370                         }
5371                 }
5372         }
5373         if (pSMB)
5374                 cifs_buf_release(pSMB);
5375         if (rc == -EAGAIN)
5376                 goto QEARetry;
5377
5378         return (ssize_t)rc;
5379 }
5380
5381 int
5382 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5383              const char *ea_name, const void *ea_value,
5384              const __u16 ea_value_len, const struct nls_table *nls_codepage,
5385              int remap)
5386 {
5387         struct smb_com_transaction2_spi_req *pSMB = NULL;
5388         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5389         struct fealist *parm_data;
5390         int name_len;
5391         int rc = 0;
5392         int bytes_returned = 0;
5393         __u16 params, param_offset, byte_count, offset, count;
5394
5395         cFYI(1, ("In SetEA"));
5396 SetEARetry:
5397         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5398                       (void **) &pSMBr);
5399         if (rc)
5400                 return rc;
5401
5402         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5403                 name_len =
5404                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5405                                      PATH_MAX, nls_codepage, remap);
5406                 name_len++;     /* trailing null */
5407                 name_len *= 2;
5408         } else {        /* BB improve the check for buffer overruns BB */
5409                 name_len = strnlen(fileName, PATH_MAX);
5410                 name_len++;     /* trailing null */
5411                 strncpy(pSMB->FileName, fileName, name_len);
5412         }
5413
5414         params = 6 + name_len;
5415
5416         /* done calculating parms using name_len of file name,
5417         now use name_len to calculate length of ea name
5418         we are going to create in the inode xattrs */
5419         if (ea_name == NULL)
5420                 name_len = 0;
5421         else
5422                 name_len = strnlen(ea_name, 255);
5423
5424         count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5425         pSMB->MaxParameterCount = cpu_to_le16(2);
5426         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5427         pSMB->MaxSetupCount = 0;
5428         pSMB->Reserved = 0;
5429         pSMB->Flags = 0;
5430         pSMB->Timeout = 0;
5431         pSMB->Reserved2 = 0;
5432         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5433                                 InformationLevel) - 4;
5434         offset = param_offset + params;
5435         pSMB->InformationLevel =
5436                 cpu_to_le16(SMB_SET_FILE_EA);
5437
5438         parm_data =
5439                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5440                                        offset);
5441         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5442         pSMB->DataOffset = cpu_to_le16(offset);
5443         pSMB->SetupCount = 1;
5444         pSMB->Reserved3 = 0;
5445         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5446         byte_count = 3 /* pad */  + params + count;
5447         pSMB->DataCount = cpu_to_le16(count);
5448         parm_data->list_len = cpu_to_le32(count);
5449         parm_data->list[0].EA_flags = 0;
5450         /* we checked above that name len is less than 255 */
5451         parm_data->list[0].name_len = (__u8)name_len;
5452         /* EA names are always ASCII */
5453         if (ea_name)
5454                 strncpy(parm_data->list[0].name, ea_name, name_len);
5455         parm_data->list[0].name[name_len] = 0;
5456         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5457         /* caller ensures that ea_value_len is less than 64K but
5458         we need to ensure that it fits within the smb */
5459
5460         /*BB add length check to see if it would fit in
5461              negotiated SMB buffer size BB */
5462         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5463         if (ea_value_len)
5464                 memcpy(parm_data->list[0].name+name_len+1,
5465                        ea_value, ea_value_len);
5466
5467         pSMB->TotalDataCount = pSMB->DataCount;
5468         pSMB->ParameterCount = cpu_to_le16(params);
5469         pSMB->TotalParameterCount = pSMB->ParameterCount;
5470         pSMB->Reserved4 = 0;
5471         pSMB->hdr.smb_buf_length += byte_count;
5472         pSMB->ByteCount = cpu_to_le16(byte_count);
5473         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5474                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5475         if (rc) {
5476                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5477         }
5478
5479         cifs_buf_release(pSMB);
5480
5481         if (rc == -EAGAIN)
5482                 goto SetEARetry;
5483
5484         return rc;
5485 }
5486
5487 #endif