[PATCH 1/2] MSDFS referral shuffling

Robin McCorkell rmccorkell at karoshi.org.uk
Fri Feb 27 04:58:47 MST 2015


Shuffle MSDFS referral list in smbd in accordance with [MS-DFSC] 3.2.1.1
When parsing an MSDFS symlink, the names are shuffled with a Fisher-Yates
algorithm.

Signed-off-by: Robin McCorkell <rmccorkell at karoshi.org.uk>
---
 docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml | 16 +++++++++++++
 lib/param/param_table.c                           |  9 +++++++
 source3/param/loadparm.c                          |  1 +
 source3/smbd/msdfs.c                              | 29 ++++++++++++++++++++---
 4 files changed, 52 insertions(+), 3 deletions(-)
 create mode 100644 docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml

diff --git a/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml b/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml
new file mode 100644
index 0000000..5796c70
--- /dev/null
+++ b/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml
@@ -0,0 +1,16 @@
+<samba:parameter name="msdfs shuffle referrals"
+                 context="S"
+                 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>If set to <constant>yes</constant>, Samba will shuffle
+	Dfs referrals for a given Dfs link if multiple are available,
+	allowing for load balancing across clients. For more information
+	on setting up a Dfs tree on	Samba, refer to the MSDFS chapter in
+	the Samba3-HOWTO book.</para>
+</description>
+
+<related>host msdfs</related>
+<related>msdfs root</related>
+<value type="default">no</value>
+</samba:parameter>
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 18b0628..00274ca 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -3942,6 +3942,15 @@ struct parm_struct parm_table[] = {
 		.flags		= FLAG_ADVANCED | FLAG_SHARE,
 	},
 	{
+		.label		= "msdfs shuffle referrals",
+		.type		= P_BOOL,
+		.p_class	= P_LOCAL,
+		.offset		= LOCAL_VAR(msdfs_shuffle_referrals),
+		.special	= NULL,
+		.enum_list	= NULL,
+		.flags		= FLAG_ADVANCED | FLAG_SHARE,
+	},
+	{
 		.label		= "host msdfs",
 		.type		= P_BOOL,
 		.p_class	= P_GLOBAL,
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index da50e3a..4a74843 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -222,6 +222,7 @@ static struct loadparm_service sDefault =
 	.inherit_acls = false,
 	.inherit_owner = false,
 	.msdfs_root = false,
+	.msdfs_shuffle_referrals = false,
 	.use_client_driver = false,
 	.default_devmode = true,
 	.force_printername = false,
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 3bd8a09..499fbf6 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -4,6 +4,7 @@
    MSDFS services for Samba
    Copyright (C) Shirish Kalele 2000
    Copyright (C) Jeremy Allison 2007
+   Copyright (C) Robin McCorkell 2015
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -428,6 +429,22 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
 	return NT_STATUS_OK;
 }
 
+static void shuffle_strlist(const char **list, int count)
+{
+	int i, r;
+	const char *tmp;
+
+	srandom(time(NULL));
+
+	for (i = count; i > 1; i--) {
+		r = random() % i;
+
+		tmp = list[i-1];
+		list[i-1] = list[r];
+		list[r] = tmp;
+	}
+}
+
 /**********************************************************************
  Parse the contents of a symlink to verify if it is an msdfs referral
  A valid referral is of the form:
@@ -448,6 +465,7 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
  **********************************************************************/
 
 static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
+				int snum,
 				const char *target,
 				struct referral **preflist,
 				int *refcount)
@@ -480,6 +498,11 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
 		count++;
 	}
 
+	/* shuffle alternate paths */
+	if (lp_msdfs_shuffle_referrals(snum)) {
+		shuffle_strlist(alt_path, count);
+	}
+
 	DEBUG(10,("parse_msdfs_symlink: count=%d\n", count));
 
 	if (count) {
@@ -1007,7 +1030,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
 			return NT_STATUS_NO_MEMORY;
 		}
 
-		if (!parse_msdfs_symlink(ctx, tmp, &ref, &refcount)) {
+		if (!parse_msdfs_symlink(ctx, snum, tmp, &ref, &refcount)) {
 			TALLOC_FREE(tmp);
 			TALLOC_FREE(pdp);
 			return NT_STATUS_INVALID_PARAMETER;
@@ -1056,7 +1079,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
 	}
 
 	/* We know this is a valid dfs link. Parse the targetpath. */
-	if (!parse_msdfs_symlink(ctx, targetpath,
+	if (!parse_msdfs_symlink(ctx, snum, targetpath,
 				&jucn->referral_list,
 				&jucn->referral_count)) {
 		DEBUG(3,("get_referred_path: failed to parse symlink "
@@ -1517,7 +1540,7 @@ static int form_junctions(TALLOC_CTX *ctx,
 					conn,
 					dname, &link_target,
 					NULL)) {
-			if (parse_msdfs_symlink(ctx,
+			if (parse_msdfs_symlink(ctx, snum,
 					link_target,
 					&jucn[cnt].referral_list,
 					&jucn[cnt].referral_count)) {
-- 
1.9.1



More information about the samba-technical mailing list