OpenCloudOS-Kernel/fs/cifs/dfs.c

77 lines
1.7 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2022 Paulo Alcantara <palcantara@suse.de>
*/
#include "cifsproto.h"
#include "cifs_debug.h"
#include "dns_resolve.h"
#include "fs_context.h"
#include "dfs.h"
/* Resolve UNC server name and set destination ip address in fs context */
static int resolve_unc(const char *path, struct smb3_fs_context *ctx)
{
int rc;
char *ip = NULL;
rc = dns_resolve_server_name_to_ip(path, &ip, NULL);
if (rc < 0) {
cifs_dbg(FYI, "%s: failed to resolve UNC server name: %d\n", __func__, rc);
return rc;
}
if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip, strlen(ip))) {
cifs_dbg(VFS, "%s: could not determinate destination address\n", __func__);
rc = -EHOSTUNREACH;
} else
rc = 0;
kfree(ip);
return rc;
}
/**
* dfs_parse_target_referral - set fs context for dfs target referral
*
* @full_path: full path in UNC format.
* @ref: dfs referral pointer.
* @ctx: smb3 fs context pointer.
*
* Return zero if dfs referral was parsed correctly, otherwise non-zero.
*/
int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_param *ref,
struct smb3_fs_context *ctx)
{
int rc;
const char *prepath = NULL;
char *path;
if (!full_path || !*full_path || !ref || !ctx)
return -EINVAL;
if (WARN_ON_ONCE(!ref->node_name || ref->path_consumed < 0))
return -EINVAL;
if (strlen(full_path) - ref->path_consumed) {
prepath = full_path + ref->path_consumed;
/* skip initial delimiter */
if (*prepath == '/' || *prepath == '\\')
prepath++;
}
path = cifs_build_devname(ref->node_name, prepath);
if (IS_ERR(path))
return PTR_ERR(path);
rc = smb3_parse_devname(path, ctx);
if (rc)
goto out;
rc = resolve_unc(path, ctx);
out:
kfree(path);
return rc;
}