linux/fs/smb/client/cifssmb.c

// SPDX-License-Identifier: LGPL-2.1
/*
 *
 *   Copyright (C) International Business Machines  Corp., 2002,2010
 *   Author(s): Steve French ([email protected])
 *
 *   Contains the routines for constructing the SMB PDUs themselves
 *
 */

 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
 /* These are mostly routines that operate on a pathname, or on a tree id     */
 /* (mounted volume), but there are eight handle based routines which must be */
 /* treated slightly differently for reconnection purposes since we never     */
 /* want to reuse a stale file handle and only the caller knows the file info */

#include <linux/fs.h>
#include <linux/filelock.h>
#include <linux/kernel.h>
#include <linux/vfs.h>
#include <linux/slab.h>
#include <linux/posix_acl_xattr.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/task_io_accounting_ops.h>
#include <linux/uaccess.h>
#include <linux/netfs.h>
#include <trace/events/netfs.h>
#include "cifspdu.h"
#include "cifsfs.h"
#include "cifsglob.h"
#include "cifsacl.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "fscache.h"
#include "smbdirect.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif

#ifdef CONFIG_CIFS_POSIX
static struct {} protocols[] =;
#else
static struct {
	int index;
	char *name;
} protocols[] = {
	{CIFS_PROT, "\2NT LM 0.12"},
	{BAD_PROT, "\2"}
};
#endif

/* define the number of elements in the cifs dialect array */
#ifdef CONFIG_CIFS_POSIX
#define CIFS_NUM_PROT
#else /* not posix */
#define CIFS_NUM_PROT
#endif /* CIFS_POSIX */


/* reconnect the socket, tcon, and smb session if needed */
static int
cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
{}

/* Allocate and return pointer to an SMB request buffer, and set basic
   SMB information in the SMB header.  If the return code is zero, this
   function must have filled in request_buf pointer */
static int
small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
		void **request_buf)
{}

int
small_smb_init_no_tc(const int smb_command, const int wct,
		     struct cifs_ses *ses, void **request_buf)
{}

/* If the return code is zero, this function must fill in request_buf pointer */
static int
__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
			void **request_buf, void **response_buf)
{}

/* If the return code is zero, this function must fill in request_buf pointer */
static int
smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
	 void **request_buf, void **response_buf)
{}

static int
smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
			void **request_buf, void **response_buf)
{}

static int validate_t2(struct smb_t2_rsp *pSMB)
{}

static int
decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
{}

static bool
should_set_ext_sec_flag(enum securityEnum sectype)
{}

int
CIFSSMBNegotiate(const unsigned int xid,
		 struct cifs_ses *ses,
		 struct TCP_Server_Info *server)
{}

int
CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
{}

/*
 * This is a no-op for now. We're not really interested in the reply, but
 * rather in the fact that the server sent one and that server->lstrp
 * gets updated.
 *
 * FIXME: maybe we should consider checking that the reply matches request?
 */
static void
cifs_echo_callback(struct mid_q_entry *mid)
{}

int
CIFSSMBEcho(struct TCP_Server_Info *server)
{}

int
CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
{}

int
CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
		 const char *fileName, __u16 type,
		 const struct nls_table *nls_codepage, int remap)
{}

int
CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
	       struct cifs_sb_info *cifs_sb, struct dentry *dentry)
{}

int
CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
	     struct cifs_sb_info *cifs_sb)
{}

int
CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
	     struct cifs_tcon *tcon, const char *name,
	     struct cifs_sb_info *cifs_sb)
{}

int
CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
		__u32 posix_flags, __u64 mode, __u16 *netfid,
		FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
		const char *name, const struct nls_table *nls_codepage,
		int remap)
{}

static __u16 convert_disposition(int disposition)
{}

static int
access_flags_to_smbopen_mode(const int access_flags)
{}

int
SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
	    const char *fileName, const int openDisposition,
	    const int access_flags, const int create_options, __u16 *netfid,
	    int *pOplock, FILE_ALL_INFO *pfile_info,
	    const struct nls_table *nls_codepage, int remap)
{}

int
CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
	  FILE_ALL_INFO *buf)
{}

static void cifs_readv_worker(struct work_struct *work)
{}

static void
cifs_readv_callback(struct mid_q_entry *mid)
{}

/* cifs_async_readv - send an async write, and set up mid to handle result */
int
cifs_async_readv(struct cifs_io_subrequest *rdata)
{}

int
CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
	    unsigned int *nbytes, char **buf, int *pbuf_type)
{}


int
CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
	     unsigned int *nbytes, const char *buf)
{}

/*
 * Check the mid_state and signature on received buffer (if any), and queue the
 * workqueue completion task.
 */
static void
cifs_writev_callback(struct mid_q_entry *mid)
{}

/* cifs_async_writev - send an async write, and set up mid to handle result */
void
cifs_async_writev(struct cifs_io_subrequest *wdata)
{}

int
CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
	      unsigned int *nbytes, struct kvec *iov, int n_vec)
{}

int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
{}

int
CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
	    const __u64 offset, const __u32 numUnlock,
	    const __u32 numLock, const __u8 lockType,
	    const bool waitFlag, const __u8 oplock_level)
{}

int
CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
		const __u16 smb_file_id, const __u32 netpid,
		const loff_t start_offset, const __u64 len,
		struct file_lock *pLockData, const __u16 lock_type,
		const bool waitFlag)
{}


int
CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
{}

int
CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
{}

int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
		  struct dentry *source_dentry,
		  const char *from_name, const char *to_name,
		  struct cifs_sb_info *cifs_sb)
{}

int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
		int netfid, const char *target_name,
		const struct nls_table *nls_codepage, int remap)
{}

int
CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
	    const char *fromName, const __u16 target_tid, const char *toName,
	    const int flags, const struct nls_table *nls_codepage, int remap)
{}

int
CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
		      const char *fromName, const char *toName,
		      const struct nls_table *nls_codepage, int remap)
{}

int
CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
		       const char *fromName, const char *toName,
		       const struct nls_table *nls_codepage, int remap)
{}

int CIFSCreateHardLink(const unsigned int xid,
		       struct cifs_tcon *tcon,
		       struct dentry *source_dentry,
		       const char *from_name, const char *to_name,
		       struct cifs_sb_info *cifs_sb)
{}

int
CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
			const unsigned char *searchName, char **symlinkinfo,
			const struct nls_table *nls_codepage, int remap)
{}

int cifs_query_reparse_point(const unsigned int xid,
			     struct cifs_tcon *tcon,
			     struct cifs_sb_info *cifs_sb,
			     const char *full_path,
			     u32 *tag, struct kvec *rsp,
			     int *rsp_buftype)
{}

int
CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
		    __u16 fid)
{}


#ifdef CONFIG_CIFS_POSIX

#ifdef CONFIG_FS_POSIX_ACL
/**
 * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
 * @ace: POSIX ACL entry to store converted ACL into
 * @cifs_ace: ACL in cifs format
 *
 * Convert an Access Control Entry from wire format to local POSIX xattr
 * format.
 *
 * Note that the @cifs_uid member is used to store both {g,u}id_t.
 */
static void cifs_init_posix_acl(struct posix_acl_entry *ace,
				struct cifs_posix_ace *cifs_ace)
{}

/**
 * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
 * @acl: ACLs returned in POSIX ACL format
 * @src: ACLs in cifs format
 * @acl_type: type of POSIX ACL requested
 * @size_of_data_area: size of SMB we got
 *
 * This function converts ACLs from cifs format to POSIX ACL format.
 * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
 * their uapi format is returned.
 */
static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
			     const int acl_type, const int size_of_data_area)
{}

/**
 * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
 * @cifs_ace: the cifs ACL entry to store into
 * @local_ace: the POSIX ACL entry to convert
 */
static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
			  const struct posix_acl_entry *local_ace)
{}

/**
 * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
 * @parm_data: ACLs in cifs format to convert to
 * @acl: ACLs in POSIX ACL format to convert from
 * @acl_type: the type of POSIX ACLs stored in @acl
 *
 * Return: the number cifs ACL entries after conversion
 */
static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
			       const int acl_type)
{}

int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
		    const unsigned char *searchName, struct posix_acl **acl,
		    const int acl_type, const struct nls_table *nls_codepage,
		    int remap)
{}

int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
		    const unsigned char *fileName, const struct posix_acl *acl,
		    const int acl_type, const struct nls_table *nls_codepage,
		    int remap)
{}
#else
int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
		    const unsigned char *searchName, struct posix_acl **acl,
		    const int acl_type, const struct nls_table *nls_codepage,
		    int remap)
{
	return -EOPNOTSUPP;
}

int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
		    const unsigned char *fileName, const struct posix_acl *acl,
		    const int acl_type, const struct nls_table *nls_codepage,
		    int remap)
{
	return -EOPNOTSUPP;
}
#endif /* CONFIG_FS_POSIX_ACL */

int
CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
{}

#endif /* CONFIG_POSIX */

/*
 * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
 * all NT TRANSACTS that we init here have total parm and data under about 400
 * bytes (to fit in small cifs buffer size), which is the case so far, it
 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
 * returned setup area) and MaxParameterCount (returned parms size) must be set
 * by caller
 */
static int
smb_init_nttransact(const __u16 sub_command, const int setup_count,
		   const int parm_len, struct cifs_tcon *tcon,
		   void **ret_buf)
{}

static int
validate_ntransact(char *buf, char **ppparm, char **ppdata,
		   __u32 *pparmlen, __u32 *pdatalen)
{}

/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
		  struct smb_ntsd **acl_inf, __u32 *pbuflen)
{}

int
CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
			struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
{}


/* Legacy Query Path Information call for lookup to old servers such
   as Win9x/WinME */
int
SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
		    const char *search_name, FILE_ALL_INFO *data,
		    const struct nls_table *nls_codepage, int remap)
{}

int
CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
		 u16 netfid, FILE_ALL_INFO *pFindData)
{}

int
CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
		 const char *search_name, FILE_ALL_INFO *data,
		 int legacy /* old style infolevel */,
		 const struct nls_table *nls_codepage, int remap)
{}

int
CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
{}

int
CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
		     const unsigned char *searchName,
		     FILE_UNIX_BASIC_INFO *pFindData,
		     const struct nls_table *nls_codepage, int remap)
{}

/* xid, tcon, searchName and codepage are input parms, rest are returned */
int
CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
	      const char *searchName, struct cifs_sb_info *cifs_sb,
	      __u16 *pnetfid, __u16 search_flags,
	      struct cifs_search_info *psrch_inf, bool msearch)
{}

int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
		 __u16 searchHandle, __u16 search_flags,
		 struct cifs_search_info *psrch_inf)
{}

int
CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
	      const __u16 searchHandle)
{}

int
CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
		      const char *search_name, __u64 *inode_number,
		      const struct nls_table *nls_codepage, int remap)
{}

int
CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
		const char *search_name, struct dfs_info3_param **target_nodes,
		unsigned int *num_of_nodes,
		const struct nls_table *nls_codepage, int remap)
{}

/* Query File System Info such as free space to old servers such as Win 9x */
int
SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
	      struct kstatfs *FSData)
{}

int
CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
	       struct kstatfs *FSData)
{}

int
CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
{}

int
CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
{}

int
CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
{}

int
CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
{}



int
CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
		   struct kstatfs *FSData)
{}


/*
 * We can not use write of zero bytes trick to set file size due to need for
 * large file support. Also note that this SetPathInfo is preferred to
 * SetFileInfo based method in next routine which is only needed to work around
 * a sharing violation bugin Samba which this routine can run into.
 */
int
CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
	      bool set_allocation, struct dentry *dentry)
{}

int
CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
{}

/* Some legacy servers such as NT4 require that the file times be set on
   an open handle, rather than by pathname - this is awkward due to
   potential access conflicts on the open, but it is unavoidable for these
   old servers since the only other choice is to go from 100 nanosecond DCE
   time and resort to the original setpathinfo level which takes the ancient
   DOS time format with 2 second granularity */
int
CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
{}

int
CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
			  bool delete_file, __u16 fid, __u32 pid_of_opener)
{}

static int
CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
		     const char *fileName, const FILE_BASIC_INFO *data,
		     const struct nls_table *nls_codepage,
		     struct cifs_sb_info *cifs_sb)
{}

int
CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
		   const char *fileName, const FILE_BASIC_INFO *data,
		   const struct nls_table *nls_codepage,
		     struct cifs_sb_info *cifs_sb)
{}

static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
			const struct cifs_unix_set_info_args *args)
{}

int
CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
		       const struct cifs_unix_set_info_args *args,
		       u16 fid, u32 pid_of_opener)
{}

int
CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
		       const char *file_name,
		       const struct cifs_unix_set_info_args *args,
		       const struct nls_table *nls_codepage, int remap)
{}

#ifdef CONFIG_CIFS_XATTR
/*
 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
 * function used by listxattr and getxattr type calls. When ea_name is set,
 * it looks for that attribute name and stuffs that value into the EAData
 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
 * buffer. In both cases, the return value is either the length of the
 * resulting data or a negative error code. If EAData is a NULL pointer then
 * the data isn't copied to it, but the length is returned.
 */
ssize_t
CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
		const unsigned char *searchName, const unsigned char *ea_name,
		char *EAData, size_t buf_size,
		struct cifs_sb_info *cifs_sb)
{}

int
CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
	     const char *fileName, const char *ea_name, const void *ea_value,
	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
	     struct cifs_sb_info *cifs_sb)
{}
#endif