#include <linux/fs.h>
#include <linux/net.h>
#include <linux/string.h>
#include <linux/sched/mm.h>
#include <linux/sched/signal.h>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/mempool.h>
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/kthread.h>
#include <linux/pagevec.h>
#include <linux/freezer.h>
#include <linux/namei.h>
#include <linux/uuid.h>
#include <linux/uaccess.h>
#include <asm/processor.h>
#include <linux/inet.h>
#include <linux/module.h>
#include <keys/user-type.h>
#include <net/ipv6.h>
#include <linux/parser.h>
#include <linux/bvec.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include "ntlmssp.h"
#include "nterr.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#include "smb2proto.h"
#include "smbdirect.h"
#include "dns_resolve.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs.h"
#include "dfs_cache.h"
#endif
#include "fs_context.h"
#include "cifs_swn.h"
#define TLINK_ERROR_EXPIRE …
#define TLINK_IDLE_EXPIRE …
#define MAX_STATUS_IO_TIMEOUT …
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
static void cifs_prune_tlinks(struct work_struct *work);
static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
{ … }
static void smb2_query_server_interfaces(struct work_struct *work)
{ … }
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
bool all_channels)
{ … }
void
cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
bool mark_smb_session)
{ … }
static void
cifs_abort_connection(struct TCP_Server_Info *server)
{ … }
static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets)
{ … }
static int __cifs_reconnect(struct TCP_Server_Info *server,
bool mark_smb_session)
{ … }
#ifdef CONFIG_CIFS_DFS_UPCALL
static int __reconnect_target_unlocked(struct TCP_Server_Info *server, const char *target)
{ … }
static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_cache_tgt_list *tl,
struct dfs_cache_tgt_iterator **target_hint)
{ … }
static int reconnect_dfs_server(struct TCP_Server_Info *server)
{ … }
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
{ … }
#else
int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session)
{
return __cifs_reconnect(server, mark_smb_session);
}
#endif
static void
cifs_echo_request(struct work_struct *work)
{ … }
static bool
allocate_buffers(struct TCP_Server_Info *server)
{ … }
static bool
server_unresponsive(struct TCP_Server_Info *server)
{ … }
static inline bool
zero_credits(struct TCP_Server_Info *server)
{ … }
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
{ … }
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read)
{ … }
ssize_t
cifs_discard_from_socket(struct TCP_Server_Info *server, size_t to_read)
{ … }
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
unsigned int page_offset, unsigned int to_read)
{ … }
int
cifs_read_iter_from_socket(struct TCP_Server_Info *server, struct iov_iter *iter,
unsigned int to_read)
{ … }
static bool
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
{ … }
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
{ … }
static unsigned int
smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{ … }
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
char *buf, int malformed)
{ … }
int
cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
{ … }
static noinline_for_stack void
clean_demultiplex_info(struct TCP_Server_Info *server)
{ … }
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{ … }
int
cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{ … }
static void
smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{ … }
static int
cifs_demultiplex_thread(void *p)
{ … }
int
cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs)
{ … }
bool
cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
{ … }
static bool
match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
{ … }
static bool match_server_address(struct TCP_Server_Info *server, struct sockaddr *addr)
{ … }
static bool
match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{ … }
static int match_server(struct TCP_Server_Info *server,
struct smb3_fs_context *ctx,
bool match_super)
{ … }
struct TCP_Server_Info *
cifs_find_tcp_session(struct smb3_fs_context *ctx)
{ … }
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
{ … }
struct TCP_Server_Info *
cifs_get_tcp_session(struct smb3_fs_context *ctx,
struct TCP_Server_Info *primary_server)
{ … }
static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{ … }
static int
cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{ … }
static struct cifs_ses *
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{ … }
void __cifs_put_smb_ses(struct cifs_ses *ses)
{ … }
#ifdef CONFIG_KEYS
#define CIFSCREDS_DESC_SIZE …
static int
cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
{ … }
#else
static inline int
cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
struct cifs_ses *ses __attribute__((unused)))
{
return -ENOSYS;
}
#endif
struct cifs_ses *
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{ … }
static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{ … }
static struct cifs_tcon *
cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{ … }
void
cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
{ … }
static struct cifs_tcon *
cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{ … }
void
cifs_put_tlink(struct tcon_link *tlink)
{ … }
static int
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{ … }
static int match_prepath(struct super_block *sb,
struct cifs_tcon *tcon,
struct cifs_mnt_data *mnt_data)
{ … }
int
cifs_match_super(struct super_block *sb, void *data)
{ … }
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key cifs_key[2];
static struct lock_class_key cifs_slock_key[2];
static inline void
cifs_reclassify_socket4(struct socket *sock)
{ … }
static inline void
cifs_reclassify_socket6(struct socket *sock)
{ … }
#else
static inline void
cifs_reclassify_socket4(struct socket *sock)
{
}
static inline void
cifs_reclassify_socket6(struct socket *sock)
{
}
#endif
static void rfc1002mangle(char *target, char *source, unsigned int length)
{ … }
static int
bind_socket(struct TCP_Server_Info *server)
{ … }
static int
ip_rfc1001_connect(struct TCP_Server_Info *server)
{ … }
static int
generic_ip_connect(struct TCP_Server_Info *server)
{ … }
static int
ip_connect(struct TCP_Server_Info *server)
{ … }
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
{ … }
#endif
int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
{ … }
void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
{ … }
int cifs_mount_get_session(struct cifs_mount_ctx *mnt_ctx)
{ … }
int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
{ … }
static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
struct cifs_tcon *tcon)
{ … }
static int
cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
char *full_path,
int added_treename)
{ … }
int cifs_is_path_remote(struct cifs_mount_ctx *mnt_ctx)
{ … }
#ifdef CONFIG_CIFS_DFS_UPCALL
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
{ … }
#else
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
{
int rc = 0;
struct cifs_mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, };
rc = cifs_mount_get_session(&mnt_ctx);
if (rc)
goto error;
rc = cifs_mount_get_tcon(&mnt_ctx);
if (!rc) {
if (WARN_ON(!mnt_ctx.server))
rc = -EHOSTDOWN;
else if (WARN_ON(!mnt_ctx.ses))
rc = -EACCES;
else if (WARN_ON(!mnt_ctx.tcon))
rc = -ENOENT;
}
if (rc)
goto error;
rc = cifs_is_path_remote(&mnt_ctx);
if (rc == -EREMOTE)
rc = -EOPNOTSUPP;
if (rc)
goto error;
rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon);
if (rc)
goto error;
free_xid(mnt_ctx.xid);
return rc;
error:
cifs_mount_put_conns(&mnt_ctx);
return rc;
}
#endif
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
int
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
const char *tree, struct cifs_tcon *tcon,
const struct nls_table *nls_codepage)
{ … }
#endif
static void delayed_free(struct rcu_head *p)
{ … }
void
cifs_umount(struct cifs_sb_info *cifs_sb)
{ … }
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
struct TCP_Server_Info *server)
{ … }
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
struct TCP_Server_Info *server,
struct nls_table *nls_info)
{ … }
static int
cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
{ … }
static struct cifs_tcon *
__cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
{ … }
static struct cifs_tcon *
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
{ … }
struct cifs_tcon *
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{ … }
static struct tcon_link *
tlink_rb_search(struct rb_root *root, kuid_t uid)
{ … }
static void
tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
{ … }
struct tcon_link *
cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
{ … }
static void
cifs_prune_tlinks(struct work_struct *work)
{ … }
#ifndef CONFIG_CIFS_DFS_UPCALL
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
int rc;
const struct smb_version_operations *ops = tcon->ses->server->ops;
spin_lock(&tcon->tc_lock);
if (tcon->need_reconnect)
tcon->status = TID_NEED_TCON;
if (tcon->status == TID_GOOD) {
spin_unlock(&tcon->tc_lock);
return 0;
}
if (tcon->status != TID_NEW &&
tcon->status != TID_NEED_TCON) {
spin_unlock(&tcon->tc_lock);
return -EHOSTDOWN;
}
tcon->status = TID_IN_TCON;
spin_unlock(&tcon->tc_lock);
rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, nlsc);
if (rc) {
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_IN_TCON)
tcon->status = TID_NEED_TCON;
spin_unlock(&tcon->tc_lock);
} else {
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_IN_TCON)
tcon->status = TID_GOOD;
tcon->need_reconnect = false;
spin_unlock(&tcon->tc_lock);
}
return rc;
}
#endif