[Pkg-samba-maint] [samba] 01/01: Imported Upstream version 4.3.6+dfsg

Jelmer Vernooij jelmer at moszumanska.debian.org
Wed Mar 9 03:28:21 UTC 2016


This is an automated email from the git hooks/post-receive script.

jelmer pushed a commit to annotated tag upstream/4.3.6+dfsg
in repository samba.

commit 2ce684deb1c267a84fe6fc762a11911c77f80ede
Author: Jelmer Vernooij <jelmer at jelmer.uk>
Date:   Sat Feb 27 23:27:47 2016 +0000

    Imported Upstream version 4.3.6+dfsg
---
 VERSION                                            |    2 +-
 WHATSNEW.txt                                       |  247 +++-
 auth/credentials/pycredentials.c                   |    8 +
 ctdb/common/system_aix.c                           |    4 +-
 ctdb/common/system_common.c                        |    2 +-
 ctdb/common/system_freebsd.c                       |    4 +-
 ctdb/common/system_gnu.c                           |    4 +-
 ctdb/common/system_kfreebsd.c                      |    4 +-
 ctdb/common/system_linux.c                         |   12 +-
 ctdb/config/events.d/11.natgw                      |    4 -
 ctdb/config/events.d/49.winbind                    |    7 -
 ctdb/tools/ctdb.c                                  |    4 +-
 ctdb/utils/smnotify/smnotify.c                     |    6 +-
 docs-xml/manpages/smbspool_krb5_wrapper.8.xml      |   64 +
 docs-xml/manpages/vfs_gpfs.8.xml                   |    6 +-
 docs-xml/smbdotconf/winbind/idmapconfig.xml        |   15 +-
 docs-xml/wscript_build                             |    1 +
 docs/manpages/dbwrap_tool.1                        |    4 +-
 docs/manpages/eventlogadm.8                        |    4 +-
 docs/manpages/findsmb.1                            |    4 +-
 docs/manpages/idmap_ad.8                           |    4 +-
 docs/manpages/idmap_autorid.8                      |    4 +-
 docs/manpages/idmap_hash.8                         |    4 +-
 docs/manpages/idmap_ldap.8                         |    4 +-
 docs/manpages/idmap_nss.8                          |    4 +-
 docs/manpages/idmap_rfc2307.8                      |    4 +-
 docs/manpages/idmap_rid.8                          |    4 +-
 docs/manpages/idmap_script.8                       |    4 +-
 docs/manpages/idmap_tdb.8                          |    4 +-
 docs/manpages/idmap_tdb2.8                         |    4 +-
 docs/manpages/libsmbclient.7                       |    4 +-
 docs/manpages/lmhosts.5                            |    4 +-
 docs/manpages/log2pcap.1                           |    4 +-
 docs/manpages/net.8                                |    4 +-
 docs/manpages/nmbd.8                               |    4 +-
 docs/manpages/nmblookup.1                          |    4 +-
 docs/manpages/ntlm_auth.1                          |    4 +-
 docs/manpages/pam_winbind.8                        |    4 +-
 docs/manpages/pam_winbind.conf.5                   |    4 +-
 docs/manpages/pdbedit.8                            |    4 +-
 docs/manpages/profiles.1                           |    4 +-
 docs/manpages/rpcclient.1                          |    4 +-
 docs/manpages/samba-regedit.8                      |    4 +-
 docs/manpages/samba-tool.8                         |    4 +-
 docs/manpages/samba.7                              |    4 +-
 docs/manpages/samba.8                              |    4 +-
 docs/manpages/sharesec.1                           |    4 +-
 docs/manpages/smb.conf.5                           |    8 +-
 docs/manpages/smbcacls.1                           |    4 +-
 docs/manpages/smbclient.1                          |    4 +-
 docs/manpages/smbcontrol.1                         |    4 +-
 docs/manpages/smbcquotas.1                         |    4 +-
 docs/manpages/smbd.8                               |    4 +-
 docs/manpages/smbget.1                             |    4 +-
 docs/manpages/smbgetrc.5                           |    4 +-
 docs/manpages/smbpasswd.5                          |    4 +-
 docs/manpages/smbpasswd.8                          |    4 +-
 docs/manpages/smbspool.8                           |    4 +-
 .../{vfs_xattr_tdb.8 => smbspool_krb5_wrapper.8}   |   31 +-
 docs/manpages/smbstatus.1                          |    4 +-
 docs/manpages/smbta-util.8                         |    4 +-
 docs/manpages/smbtar.1                             |    4 +-
 docs/manpages/smbtree.1                            |    4 +-
 docs/manpages/testparm.1                           |    4 +-
 docs/manpages/vfs_acl_tdb.8                        |    4 +-
 docs/manpages/vfs_acl_xattr.8                      |    4 +-
 docs/manpages/vfs_aio_fork.8                       |    4 +-
 docs/manpages/vfs_aio_linux.8                      |    4 +-
 docs/manpages/vfs_aio_pthread.8                    |    4 +-
 docs/manpages/vfs_audit.8                          |    4 +-
 docs/manpages/vfs_btrfs.8                          |    4 +-
 docs/manpages/vfs_cacheprime.8                     |    4 +-
 docs/manpages/vfs_cap.8                            |    4 +-
 docs/manpages/vfs_catia.8                          |    4 +-
 docs/manpages/vfs_ceph.8                           |    4 +-
 docs/manpages/vfs_commit.8                         |    4 +-
 docs/manpages/vfs_crossrename.8                    |    4 +-
 docs/manpages/vfs_default_quota.8                  |    4 +-
 docs/manpages/vfs_dirsort.8                        |    4 +-
 docs/manpages/vfs_extd_audit.8                     |    4 +-
 docs/manpages/vfs_fake_perms.8                     |    4 +-
 docs/manpages/vfs_fileid.8                         |    4 +-
 docs/manpages/vfs_fruit.8                          |    4 +-
 docs/manpages/vfs_full_audit.8                     |    4 +-
 docs/manpages/vfs_glusterfs.8                      |    4 +-
 docs/manpages/vfs_gpfs.8                           |   12 +-
 docs/manpages/vfs_linux_xfs_sgid.8                 |    4 +-
 docs/manpages/vfs_media_harmony.8                  |    4 +-
 docs/manpages/vfs_netatalk.8                       |    4 +-
 docs/manpages/vfs_prealloc.8                       |    4 +-
 docs/manpages/vfs_preopen.8                        |    4 +-
 docs/manpages/vfs_readahead.8                      |    4 +-
 docs/manpages/vfs_readonly.8                       |    4 +-
 docs/manpages/vfs_recycle.8                        |    4 +-
 docs/manpages/vfs_scannedonly.8                    |    4 +-
 docs/manpages/vfs_shadow_copy.8                    |    4 +-
 docs/manpages/vfs_shadow_copy2.8                   |    4 +-
 docs/manpages/vfs_shell_snap.8                     |    4 +-
 docs/manpages/vfs_smb_traffic_analyzer.8           |    4 +-
 docs/manpages/vfs_snapper.8                        |    4 +-
 docs/manpages/vfs_streams_depot.8                  |    4 +-
 docs/manpages/vfs_streams_xattr.8                  |    4 +-
 docs/manpages/vfs_syncops.8                        |    4 +-
 docs/manpages/vfs_time_audit.8                     |    4 +-
 docs/manpages/vfs_tsmsm.8                          |    4 +-
 docs/manpages/vfs_unityed_media.8                  |    4 +-
 docs/manpages/vfs_worm.8                           |    4 +-
 docs/manpages/vfs_xattr_tdb.8                      |    4 +-
 docs/manpages/vfs_zfsacl.8                         |    4 +-
 docs/manpages/vfstest.1                            |    4 +-
 docs/manpages/wbinfo.1                             |    4 +-
 docs/manpages/winbind_krb5_locator.7               |    4 +-
 docs/manpages/winbindd.8                           |    4 +-
 lib/async_req/wscript_build                        |    3 +-
 lib/dbwrap/dbwrap_rbt.c                            |  159 ++-
 lib/param/loadparm.c                               |   56 +-
 lib/tsocket/tsocket_bsd.c                          |   62 +-
 lib/util/util_strlist.c                            |   18 +-
 librpc/idl/dns.idl                                 |   18 +-
 librpc/idl/dnsp.idl                                |    4 +-
 librpc/idl/dnsserver.idl                           |    2 +-
 librpc/ndr/ndr_dns.c                               |   27 +
 librpc/ndr/ndr_dnsp.c                              |   24 +
 librpc/ndr/ndr_dnsp.h                              |    4 +
 librpc/wscript_build                               |   20 +-
 python/samba/__init__.py                           |   24 +
 python/samba/join.py                               |   19 +-
 python/samba/netcmd/domain.py                      |   23 +-
 python/samba/netcmd/fsmo.py                        |    3 +-
 python/samba/tests/core.py                         |   16 +
 python/samba/tests/dns.py                          |  640 ++++++---
 python/samba/tests/{getopt.py => get_opt.py}       |    0
 selftest/knownfail                                 |    2 +
 selftest/target/Samba3.pm                          |   71 +
 selftest/tests.py                                  |    2 +-
 source3/client/README.smbspool                     |   17 +
 source3/client/client.c                            |    4 +-
 source3/client/smbspool_krb5_wrapper.c             |  210 +++
 source3/include/proto.h                            |    1 -
 source3/include/vfs.h                              |   12 +-
 source3/lib/errmap_unix.c                          |    3 +
 source3/libsmb/cli_smb2_fnum.c                     |    5 +-
 source3/libsmb/cli_smb2_fnum.h                     |    1 +
 source3/libsmb/clifile.c                           |  135 +-
 source3/libsmb/libsmb_server.c                     |    4 +-
 source3/libsmb/proto.h                             |   20 +-
 source3/locking/locking.c                          |    3 +-
 source3/modules/vfs_acl_common.c                   |    4 +-
 source3/modules/vfs_fruit.c                        |  185 ++-
 source3/modules/vfs_shadow_copy2.c                 |  107 +-
 source3/modules/vfs_streams_xattr.c                |   39 +-
 source3/param/loadparm.c                           |  265 ++--
 source3/script/tests/test_dfree_command.sh         |   17 +-
 source3/script/tests/test_shadow_copy.sh           |  290 +++++
 source3/selftest/tests.py                          |    7 +-
 source3/smbd/close.c                               |    6 +-
 source3/smbd/dfree.c                               |    9 +-
 source3/smbd/dosmode.c                             |   32 +-
 source3/smbd/fileio.c                              |    8 +-
 source3/smbd/nttrans.c                             |   13 +
 source3/smbd/open.c                                |   24 +-
 source3/smbd/oplock.c                              |    3 +-
 source3/smbd/posix_acls.c                          |   39 +-
 source3/smbd/reply.c                               |    2 +-
 source3/smbd/smb2_close.c                          |    2 +-
 source3/smbd/smb2_create.c                         |    8 +
 source3/smbd/trans2.c                              |   68 +-
 source3/smbd/vfs.c                                 |   82 +-
 source3/torture/nbio.c                             |    2 +-
 source3/torture/torture.c                          |  415 ++++++
 source3/utils/smbcacls.c                           |    2 +-
 source3/utils/smbget.c                             |   15 +-
 source3/winbindd/winbindd_ads.c                    |   26 +-
 source3/winbindd/winbindd_cache.c                  |    4 +-
 source3/winbindd/winbindd_cm.c                     |  104 ++
 source3/winbindd/winbindd_dual_srv.c               |    8 -
 source3/winbindd/winbindd_ndr.c                    |    3 +
 source3/winbindd/winbindd_proto.h                  |    4 +
 source3/winbindd/winbindd_reconnect.c              |   38 +-
 ...nbindd_reconnect.c => winbindd_reconnect_ads.c} |  249 ++--
 source3/wscript_build                              |    9 +
 source4/auth/ntlm/auth_sam.c                       |    9 +-
 source4/auth/sam.c                                 |  158 ++-
 source4/dns_server/dns_query.c                     |   15 +-
 source4/dns_server/dns_update.c                    |   31 +-
 source4/dsdb/tests/python/password_lockout.py      |  359 +++++-
 source4/kdc/hdb-samba4.c                           |    7 +-
 source4/librpc/wscript_build                       |    4 +-
 source4/scripting/devel/createtrust                |   18 +-
 source4/selftest/tests.py                          |    3 +-
 source4/torture/smb2/create.c                      |   64 +
 source4/torture/vfs/fruit.c                        | 1359 +++++++++++++++++---
 testprogs/blackbox/dfree.sh                        |    8 +-
 193 files changed, 5125 insertions(+), 1428 deletions(-)

diff --git a/VERSION b/VERSION
index 083561f..2dec4b2 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=3
-SAMBA_VERSION_RELEASE=3
+SAMBA_VERSION_RELEASE=6
 
 ########################################################
 # If a official release has a serious bug              #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index ba2e101..a47ede4 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,247 @@
                    =============================
+                   Release Notes for Samba 4.3.6
+                           March 8, 2016
+                   =============================
+
+
+This is a security release in order to address the following CVEs:
+
+o  CVE-2015-7560 (Incorrect ACL get/set allowed on symlink path)
+o  CVE-2016-0771 (Out-of-bounds read in internal DNS server)
+
+=======
+Details
+=======
+
+o  CVE-2015-7560:
+   All versions of Samba from 3.2.0 to 4.4.0rc3 inclusive are vulnerable to
+   a malicious client overwriting the ownership of ACLs using symlinks.
+
+   An authenticated malicious client can use SMB1 UNIX extensions to
+   create a symlink to a file or directory, and then use non-UNIX SMB1
+   calls to overwrite the contents of the ACL on the file or directory
+   linked to.
+
+o  CVE-2016-0771:
+   All versions of Samba from 4.0.0 to 4.4.0rc3 inclusive, when deployed as
+   an AD DC and choose to run the internal DNS server, are vulnerable to an
+   out-of-bounds read issue during DNS TXT record handling caused by users
+   with permission to modify DNS records.
+
+   A malicious client can upload a specially constructed DNS TXT record,
+   resulting in a remote denial-of-service attack. As long as the affected
+   TXT record remains undisturbed in the Samba database, a targeted DNS
+   query may continue to trigger this exploit.
+
+   While unlikely, the out-of-bounds read may bypass safety checks and
+   allow leakage of memory from the server in the form of a DNS TXT reply.
+
+   By default only authenticated accounts can upload DNS records,
+   as "allow dns updates = secure only" is the default.
+   Any other value would allow anonymous clients to trigger this
+   bug, which is a much higher risk.
+
+
+Changes since 4.3.5:
+--------------------
+
+o  Jeremy Allison <jra at samba.org>
+   * BUG 11648: CVE-2015-7560: Getting and setting Windows ACLs on symlinks can
+     change permissions on link target.
+
+o  Garming Sam <garming at catalyst.net.nz>
+   * BUGs 11128, 11686: CVE-2016-0771: Read of uninitialized memory DNS TXT
+     handling.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * BUGs 11128, 11686: CVE-2016-0771: Read of uninitialized memory DNS TXT
+     handling.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Older release notes to follow:
+------------------------------
+
+                   =============================
+                   Release Notes for Samba 4.3.5
+                         February 23, 2016
+                   =============================
+
+
+This is the latest stable release of Samba 4.3.
+
+
+Changes since 4.3.4:
+--------------------
+
+o  Jeremy Allison <jra at samba.org>
+   * BUG 10489: s3: smbd: posix_acls: Fix check for setting u:g:o entry on a
+     filesystem with no ACL support.
+   * BUG 11703: s3: smbd: Fix timestamp rounding inside SMB2 create.
+
+o  Christian Ambach <ambi at samba.org>
+   * BUG 6482: s3:utils/smbget: Fix recursive download.
+   * BUG 11400: s3:smbd/oplock: Obey kernel oplock setting when releasing
+     oplocks.
+
+o  Alexander Bokovoy <ab at samba.org>
+   * BUG 11693: s3-parm: Clean up defaults when removing global parameters.
+
+o  Ralph Boehme <slow at samba.org>
+   * BUG 11684: s3:smbd: Ignore initial allocation size for directory creation.
+   * BUG 11714: lib/tsocket: Work around sockets not supporting FIONREAD.
+
+o  Amitay Isaacs <amitay at gmail.com>
+   * BUG 11705: ctdb: Remove error messages after kernel security update
+     (CVE-2015-8543).
+
+o  Volker Lendecke <vl at samba.org>
+   * BUG 11732: param: Fix str_list_v3 to accept ";" again.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * BUG 11699: Use M2Crypto.RC4.RC4 on platforms without Crypto.Cipher.ARC4.
+
+o  Jose A. Rivera <jarrpa at samba.org>
+   * BUG 11727: s3:smbd:open: Skip redundant call to file_set_dosmode when
+     creating a new file.
+
+o  Christof Schmitt <cs at samba.org>
+   * BUG 11670: winbindd: Handle expired sessions correctly.
+
+o  Andreas Schneider <asn at samba.org>
+   * BUG 11690: s3-client: Add a KRB5 wrapper for smbspool.
+
+o  Uri Simchoni <uri at samba.org>
+   * BUG 11580: vfs_shadow_copy2: Fix case where snapshots are outside the
+     share.
+   * BUG 11662: smbclient: Query disk usage relative to current directory.
+   * BUG 11681: smbd: Show correct disk size for different quota and dfree block
+     sizes.
+   * BUG 11682: smbcacls: Fix uninitialized variable.
+
+o  Martin Schwenke <martin at meltin.net>
+   * BUG 11719: ctdb-scripts: Drop use of "smbcontrol winbindd ip-dropped ...".
+
+o  Hemanth Thummala <hemanth.thummala at nutanix.com>
+   * BUG 11708: loadparm: Fix memory leak issue.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+----------------------------------------------------------------------
+
+
+                   =============================
+                   Release Notes for Samba 4.3.4
+                         January 12, 2016
+                   =============================
+
+
+This is the latest stable release of Samba 4.3.
+
+
+Changes since 4.3.3:
+--------------------
+
+o  Michael Adam <obnox at samba.org>
+   * BUG 11619: doc: Fix a typo in the smb.conf manpage, explanation of idmap
+     config.
+   * BUG 11647: s3:smbd: Fix a corner case of the symlink verification.
+
+o  Jeremy Allison <jra at samba.org>
+   * BUG 11624: s3: libsmb: Correctly initialize the list head when keeping a
+     list of primary followed by DFS connections.
+   * BUG 11625: Reduce the memory footprint of empty string options.
+
+o  Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+   * BUG 11659: Update lastLogon and lastLogonTimestamp.
+
+o  Ralph Boehme <slow at samba.org>
+   * BUG 11065: vfs_fruit: Enable POSIX directory rename semantics.
+   * BUG 11466: Copying files with vfs_fruit fails when using vfs_streams_xattr
+     without stream prefix and type suffix.
+   * BUG 11645: smbd: Make "hide dot files" option work with "store dos
+     attributes = yes".
+
+o  Günther Deschner <gd at samba.org>
+   * BUG 11639: lib/async_req: Do not install async_connect_send_test.
+
+o  Stefan Metzmacher <metze at samba.org>
+   * BUG 11394: Crash: Bad talloc magic value - access after free.
+
+o  Rowland Penny <repenny241155 at gmail.com>
+   * BUG 11613: samba-tool: Fix uncaught exception if no fSMORoleOwner
+     attribute is given.
+
+o  Karolin Seeger <kseeger at samba.org>
+   * BUG 11619: docs: Fix some typos in the idmap backend section.
+   * BUG 11641: docs: Fix typos in man vfs_gpfs.
+
+o  Uri Simchoni <uri at samba.org>
+   * BUG 11649: smbd: Do not disable "store dos attributes" on-the-fly.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the "Samba 4.1 and newer" product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+----------------------------------------------------------------------
+
+
+                   =============================
                    Release Notes for Samba 4.3.3
                          December 16, 2015
                    =============================
@@ -142,8 +385,8 @@ database (https://bugzilla.samba.org/).
 ======================================================================
 
 
-Older release notes to follow:
-------------------------------
+----------------------------------------------------------------------
+
 
                    =============================
                    Release Notes for Samba 4.3.2
diff --git a/auth/credentials/pycredentials.c b/auth/credentials/pycredentials.c
index e32d9a9..5fc2a70 100644
--- a/auth/credentials/pycredentials.c
+++ b/auth/credentials/pycredentials.c
@@ -209,6 +209,12 @@ static PyObject *py_creds_get_nt_hash(pytalloc_Object *self)
 	return PyString_FromStringAndSize(discard_const_p(char, ntpw->hash), 16);
 }
 
+static PyObject *py_creds_get_kerberos_state(pytalloc_Object *self)
+{
+	int state = cli_credentials_get_kerberos_state(PyCredentials_AsCliCredentials(self));
+	return PyInt_FromLong(state);
+}
+
 static PyObject *py_creds_set_kerberos_state(pytalloc_Object *self, PyObject *args)
 {
 	int state;
@@ -452,6 +458,8 @@ static PyMethodDef py_creds_methods[] = {
 		"Parse credentials string." },
 	{ "get_nt_hash", (PyCFunction)py_creds_get_nt_hash, METH_NOARGS,
 		NULL },
+	{ "get_kerberos_state", (PyCFunction)py_creds_get_kerberos_state, METH_NOARGS,
+		NULL },
 	{ "set_kerberos_state", (PyCFunction)py_creds_set_kerberos_state, METH_VARARGS,
 		NULL },
 	{ "set_krb_forwardable", (PyCFunction)py_creds_set_krb_forwardable, METH_VARARGS,
diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c
index 41f61ae..2637442 100644
--- a/ctdb/common/system_aix.c
+++ b/ctdb/common/system_aix.c
@@ -44,7 +44,7 @@ int ctdb_sys_open_sending_socket(void)
 	int s, ret;
 	uint32_t one = 1;
 
-	s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+	s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 	if (s == -1) {
 		DEBUG(DEBUG_CRIT,(" failed to open raw socket (%s)\n",
 			 strerror(errno)));
@@ -121,7 +121,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 
 
 
-	s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+	s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 	if (s == -1) {
 		DEBUG(DEBUG_CRIT,(" failed to open raw socket (%s)\n",
 			 strerror(errno)));
diff --git a/ctdb/common/system_common.c b/ctdb/common/system_common.c
index 899f3b5..3e30a6c 100644
--- a/ctdb/common/system_common.c
+++ b/ctdb/common/system_common.c
@@ -85,7 +85,7 @@ char *ctdb_sys_find_ifname(ctdb_sock_addr *addr)
 	struct ifconf ifc;
 	char *ptr;
 
-	s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+	s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 	if (s == -1) {
 		DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
 			 strerror(errno)));
diff --git a/ctdb/common/system_freebsd.c b/ctdb/common/system_freebsd.c
index 9597a7a..02f7cce 100644
--- a/ctdb/common/system_freebsd.c
+++ b/ctdb/common/system_freebsd.c
@@ -158,7 +158,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip4pkt.tcp.th_sum   = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
 
 		/* open a raw socket to send this segment from */
-		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
 				 strerror(errno)));
@@ -208,7 +208,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip6pkt.tcp.th_win   = htons(1234);
 		ip6pkt.tcp.th_sum   = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
 
-		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
 			return -1;
diff --git a/ctdb/common/system_gnu.c b/ctdb/common/system_gnu.c
index 2ab1399..1e0ae4c 100644
--- a/ctdb/common/system_gnu.c
+++ b/ctdb/common/system_gnu.c
@@ -156,7 +156,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
 
 		/* open a raw socket to send this segment from */
-		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
 				 strerror(errno)));
@@ -203,7 +203,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip6pkt.tcp.window   = htons(1234);
 		ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
 
-		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
 			return -1;
diff --git a/ctdb/common/system_kfreebsd.c b/ctdb/common/system_kfreebsd.c
index 41aa4d6..7cb6d92 100644
--- a/ctdb/common/system_kfreebsd.c
+++ b/ctdb/common/system_kfreebsd.c
@@ -156,7 +156,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
 
 		/* open a raw socket to send this segment from */
-		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
 				 strerror(errno)));
@@ -203,7 +203,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip6pkt.tcp.window   = htons(1234);
 		ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
 
-		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
 			return -1;
diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c
index fdb8d12..2e58853 100644
--- a/ctdb/common/system_linux.c
+++ b/ctdb/common/system_linux.c
@@ -93,7 +93,7 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
 
 	switch (addr->ip.sin_family) {
 	case AF_INET:
-		s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
+		s = socket(AF_PACKET, SOCK_RAW, ETHERTYPE_ARP);
 		if (s == -1){
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
 			return -1;
@@ -187,7 +187,7 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
 		close(s);
 		break;
 	case AF_INET6:
-		s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP));
+		s = socket(AF_PACKET, SOCK_RAW, ETHERTYPE_ARP);
 		if (s == -1){
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
 			return -1;
@@ -357,7 +357,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
 
 		/* open a raw socket to send this segment from */
-		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
 				 strerror(errno)));
@@ -406,7 +406,7 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
 		ip6pkt.tcp.window   = htons(1234);
 		ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
 
-		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		s = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
 		if (s == -1) {
 			DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
 			return -1;
@@ -447,7 +447,7 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data)
 	int s;
 
 	/* Open a socket to capture all traffic */
-	s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	s = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
 	if (s == -1) {
 		DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
 		return -1;
@@ -568,7 +568,7 @@ bool ctdb_sys_check_iface_exists(const char *iface)
 	int s;
 	struct ifreq ifr;
 
-	s = socket(PF_PACKET, SOCK_RAW, 0);
+	s = socket(AF_PACKET, SOCK_RAW, 0);
 	if (s == -1){
 		/* We dont know if the interface exists, so assume yes */
 		DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
diff --git a/ctdb/config/events.d/11.natgw b/ctdb/config/events.d/11.natgw
index 54e6cd9..29339f4 100755
--- a/ctdb/config/events.d/11.natgw
+++ b/ctdb/config/events.d/11.natgw
@@ -149,10 +149,6 @@ natgw_set_slave ()
 	_net="${_net_gw%@*}"
 	ip route add "$_net" via "$_natgwip" metric 10
     done
-
-    # Make sure winbindd does not stay bound to this address if we are
-    # no longer NATGW master
-    smbcontrol winbindd ip-dropped $CTDB_NATGW_PUBLIC_IP >/dev/null 2>&1
 }
 
 natgw_ensure_master ()
diff --git a/ctdb/config/events.d/49.winbind b/ctdb/config/events.d/49.winbind
index dee3c90..a1ea787 100755
--- a/ctdb/config/events.d/49.winbind
+++ b/ctdb/config/events.d/49.winbind
@@ -55,13 +55,6 @@ case "$1" in
 	ctdb_check_command wbinfo -p
 	;;
 
-     takeip|releaseip)
-	iface=$2
-	ip=$3
-	maskbits=$4
-
-	smbcontrol winbindd ip-dropped $ip >/dev/null 2>/dev/null
-	;;
     *)
 	ctdb_standard_event_handler "$@"
 	;;
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index c6da621..c5689c2 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -4496,7 +4496,7 @@ static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **
 
 	port = atoi(argv[0]);
 
-	s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 	if (s == -1) {
 		printf("Failed to open local socket\n");
 		return errno;
@@ -4508,7 +4508,7 @@ static int control_chktcpport(struct ctdb_context *ctdb, int argc, const char **
 	}
 
 	bzero(&sin, sizeof(sin));
-	sin.sin_family = PF_INET;
+	sin.sin_family = AF_INET;
 	sin.sin_port   = htons(port);
 	ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
 	close(s);
diff --git a/ctdb/utils/smnotify/smnotify.c b/ctdb/utils/smnotify/smnotify.c
index d7fd546..d5c5a4c 100644
--- a/ctdb/utils/smnotify/smnotify.c
+++ b/ctdb/utils/smnotify/smnotify.c
@@ -43,14 +43,14 @@ static int create_socket(const char *addr, int port)
 	int s;
         struct sockaddr_in sock_in;
 
-	s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 	if (s == -1) {
 		printf("Failed to open local socket\n");
 		exit(10);
 	}
 
 	bzero(&sock_in, sizeof(sock_in));
-	sock_in.sin_family = PF_INET;
+	sock_in.sin_family = AF_INET;
 	sock_in.sin_port   = htons(port);
 	inet_aton(addr, &sock_in.sin_addr);
 	if (bind(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) == -1) {
@@ -124,7 +124,7 @@ int main(int argc, const char *argv[])
 
 	/* Setup a sockaddr_in for the client we want to notify */
 	bzero(&sock_cl, sizeof(sock_cl));
-	sock_cl.sin_family = PF_INET;
+	sock_cl.sin_family = AF_INET;
 	sock_cl.sin_port   = htons(clientport);
 	inet_aton(client, &sock_cl.sin_addr);
 
diff --git a/docs-xml/manpages/smbspool_krb5_wrapper.8.xml b/docs-xml/manpages/smbspool_krb5_wrapper.8.xml
new file mode 100644
index 0000000..f9966e7
--- /dev/null
+++ b/docs-xml/manpages/smbspool_krb5_wrapper.8.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="smbspool.8">
+
+<refmeta>
+	<refentrytitle>smbspool_krb5_wrapper</refentrytitle>
+	<manvolnum>8</manvolnum>
+	<refmiscinfo class="source">Samba</refmiscinfo>
+	<refmiscinfo class="manual">System Administration tools</refmiscinfo>
+	<refmiscinfo class="version">4.4</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+	<refname>smbspool_krb5_wrapper</refname>
+	<refpurpose>This is a CUPS printing backend which calls smbspool</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+	<cmdsynopsis>
+		<command>smbspool_krb5_wrapper</command>
+		<arg choice="req">job</arg>
+		<arg choice="req">user</arg>
+		<arg choice="req">title</arg>
+		<arg choice="req">copies</arg>
+		<arg choice="req">options</arg>
+		<arg choice="opt">filename</arg>
+	</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+	<title>DESCRIPTION</title>
+
+	<para>This tool is part of the <citerefentry><refentrytitle>samba</refentrytitle>
+	<manvolnum>7</manvolnum></citerefentry> suite.</para>
+
+	<para>smbspool_krb5_wrapper is a tool that can be used to print using
+		Kerberos credentials. To get this working smbspool_krb5_wrapper
+		needs to be the smb backend of CUPS. It needs to be owned by
+		root and the permissions for the binary need to be 0700. Once
+		smbspool_krb5_wrapper switched to the user trying to print it
+		executes smbspool. It should not be called by a user.</para>
+
+</refsect1>
+
+<refsect1>
+	<title>SEE ALSO</title>
+	<para><citerefentry><refentrytitle>smbspool</refentrytitle>
+		<manvolnum>8</manvolnum></citerefentry>.</para>
+</refsect1>
+
+<refsect1>
+	<title>AUTHOR</title>
+
+	<para>The original Samba software and related utilities
+	were created by Andrew Tridgell. Samba is now developed
+	by the Samba Team as an Open Source project similar
+	to the way the Linux kernel is developed.</para>
+
+	<para>The smbspool_krb5_wrapper manpage was written by Andreas
+		Schneider.</para>
+</refsect1>
+
+</refentry>
diff --git a/docs-xml/manpages/vfs_gpfs.8.xml b/docs-xml/manpages/vfs_gpfs.8.xml
index 7bb4e90..e0c5951 100644
--- a/docs-xml/manpages/vfs_gpfs.8.xml
+++ b/docs-xml/manpages/vfs_gpfs.8.xml
@@ -42,14 +42,14 @@
 	</itemizedlist>
 	</para>
 
-	<para><command>NOTE:</command>This module follows the posix-acl behaviour
+	<para><command>NOTE:</command> This module follows the posix-acl behaviour
 	and hence allows permission stealing via chown. Samba might allow at a later
 	point in time, to restrict the chown via this module as such restrictions
 	are the responsibility of the underlying filesystem than of Samba.
 	</para>
 
 	<para>This module makes use of the smb.conf parameter
-	<smbconfoption name="acl map full control">acl map full control</smbconfoption>
+	<smbconfoption name="acl map full control"></smbconfoption>.
 	When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD
 	bit on a returned ACE entry for a file (not a directory) that already
 	contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD.
@@ -471,7 +471,7 @@
 	</para>
 	<para>
 	At build time, only the header file <command>gpfs_gpl.h</command>
-	is required , which is a symlink to <command>gpfs.h</command> in
+	is required, which is a symlink to <command>gpfs.h</command> in
 	gpfs versions newer than 3.2.1 PTF8.
 	</para>
 </refsect1>
diff --git a/docs-xml/smbdotconf/winbind/idmapconfig.xml b/docs-xml/smbdotconf/winbind/idmapconfig.xml
index 434d379..db24784 100644
--- a/docs-xml/smbdotconf/winbind/idmapconfig.xml
+++ b/docs-xml/smbdotconf/winbind/idmapconfig.xml
@@ -38,21 +38,16 @@
 		(<citerefentry><refentrytitle>idmap_tdb2</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
 		ldap
 		(<citerefentry><refentrytitle>idmap_ldap</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
-		,
 		rid
 		(<citerefentry><refentrytitle>idmap_rid</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
-		,
 		hash
 		(<citerefentry><refentrytitle>idmap_hash</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
-		,
 		autorid
 		(<citerefentry><refentrytitle>idmap_autorid</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
-		,
 		ad
-		(<citerefentry><refentrytitle>idmap_ad</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
-		,
-		and nss.
-		(<citerefentry><refentrytitle>idmap_nss</refentrytitle> <manvolnum>8</manvolnum></citerefentry>),
+		(<citerefentry><refentrytitle>idmap_ad</refentrytitle> <manvolnum>8</manvolnum></citerefentry>)
+		and nss
+		(<citerefentry><refentrytitle>idmap_nss</refentrytitle> <manvolnum>8</manvolnum></citerefentry>).
 		The corresponding manual pages contain the details, but
 		here is a summary.
 		</para>
@@ -65,9 +60,9 @@
 		mixture of the tdb and rid backend. It creates ranges for
 		each domain encountered and then uses the rid algorithm for each
 		of these automatically configured domains individually.
-		The ad backend usees unix IDs stored in Active Directory via
+		The ad backend uses unix ids stored in Active Directory via
 		the standard schema extensions. The nss backend reverses
-		the standard winbindd setup and gets the unixids via names
+		the standard winbindd setup and gets the unix ids via names
 		from nsswitch which can be useful in an ldap setup.
 		</para></listitem>
 		</varlistentry>
diff --git a/docs-xml/wscript_build b/docs-xml/wscript_build
index 5c42a31..8cdd2dd 100644
--- a/docs-xml/wscript_build
+++ b/docs-xml/wscript_build
@@ -38,6 +38,7 @@ manpages='''
          manpages/smbpasswd.5
          manpages/smbpasswd.8
          manpages/smbspool.8
+         manpages/smbspool_krb5_wrapper.8
          manpages/smbstatus.1
          manpages/smbta-util.8
          manpages/smbtar.1
diff --git a/docs/manpages/dbwrap_tool.1 b/docs/manpages/dbwrap_tool.1
index 7362765..38a088c 100644
--- a/docs/manpages/dbwrap_tool.1
+++ b/docs/manpages/dbwrap_tool.1
@@ -2,12 +2,12 @@
 .\"     Title: dbwrap_tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "DBWRAP_TOOL" "1" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "DBWRAP_TOOL" "1" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/eventlogadm.8 b/docs/manpages/eventlogadm.8
index 2375350..1fdf559 100644
--- a/docs/manpages/eventlogadm.8
+++ b/docs/manpages/eventlogadm.8
@@ -2,12 +2,12 @@
 .\"     Title: eventlogadm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "EVENTLOGADM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "EVENTLOGADM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/findsmb.1 b/docs/manpages/findsmb.1
index f1f9c6d..c0c1ea3 100644
--- a/docs/manpages/findsmb.1
+++ b/docs/manpages/findsmb.1
@@ -2,12 +2,12 @@
 .\"     Title: findsmb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "FINDSMB" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "FINDSMB" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ad.8 b/docs/manpages/idmap_ad.8
index 313771d..c33d927 100644
--- a/docs/manpages/idmap_ad.8
+++ b/docs/manpages/idmap_ad.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ad
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_AD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_autorid.8 b/docs/manpages/idmap_autorid.8
index ec7d0b2..e06e626 100644
--- a/docs/manpages/idmap_autorid.8
+++ b/docs/manpages/idmap_autorid.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_autorid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_AUTORID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_AUTORID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_hash.8 b/docs/manpages/idmap_hash.8
index 746d035..6b2c3b2 100644
--- a/docs/manpages/idmap_hash.8
+++ b/docs/manpages/idmap_hash.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_hash
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_HASH" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_HASH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_ldap.8 b/docs/manpages/idmap_ldap.8
index 4afcadc..8383973 100644
--- a/docs/manpages/idmap_ldap.8
+++ b/docs/manpages/idmap_ldap.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_ldap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_LDAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_LDAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_nss.8 b/docs/manpages/idmap_nss.8
index 2c40f24..5ebfafe 100644
--- a/docs/manpages/idmap_nss.8
+++ b/docs/manpages/idmap_nss.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_nss
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_NSS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_NSS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rfc2307.8 b/docs/manpages/idmap_rfc2307.8
index e4478ba..0f7532c 100644
--- a/docs/manpages/idmap_rfc2307.8
+++ b/docs/manpages/idmap_rfc2307.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rfc2307
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_RFC2307" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RFC2307" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_rid.8 b/docs/manpages/idmap_rid.8
index d237661..8a87aff 100644
--- a/docs/manpages/idmap_rid.8
+++ b/docs/manpages/idmap_rid.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_rid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_RID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_RID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_script.8 b/docs/manpages/idmap_script.8
index c12d3a5..85deee2 100644
--- a/docs/manpages/idmap_script.8
+++ b/docs/manpages/idmap_script.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_script
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_SCRIPT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_SCRIPT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb.8 b/docs/manpages/idmap_tdb.8
index fcc907c..dd060f7 100644
--- a/docs/manpages/idmap_tdb.8
+++ b/docs/manpages/idmap_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/idmap_tdb2.8 b/docs/manpages/idmap_tdb2.8
index 5a987e9..e38f223 100644
--- a/docs/manpages/idmap_tdb2.8
+++ b/docs/manpages/idmap_tdb2.8
@@ -2,12 +2,12 @@
 .\"     Title: idmap_tdb2
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "IDMAP_TDB2" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "IDMAP_TDB2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/libsmbclient.7 b/docs/manpages/libsmbclient.7
index de44485..e4b20e3 100644
--- a/docs/manpages/libsmbclient.7
+++ b/docs/manpages/libsmbclient.7
@@ -2,12 +2,12 @@
 .\"     Title: libsmbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: 7
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LIBSMBCLIENT" "7" "12/10/2015" "Samba 4\&.3" "7"
+.TH "LIBSMBCLIENT" "7" "02/24/2016" "Samba 4\&.3" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/lmhosts.5 b/docs/manpages/lmhosts.5
index 4152621..a8ff381 100644
--- a/docs/manpages/lmhosts.5
+++ b/docs/manpages/lmhosts.5
@@ -2,12 +2,12 @@
 .\"     Title: lmhosts
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LMHOSTS" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "LMHOSTS" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/log2pcap.1 b/docs/manpages/log2pcap.1
index 0033027..b489e7d 100644
--- a/docs/manpages/log2pcap.1
+++ b/docs/manpages/log2pcap.1
@@ -2,12 +2,12 @@
 .\"     Title: log2pcap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "LOG2PCAP" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "LOG2PCAP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/net.8 b/docs/manpages/net.8
index c483d78..b0978a9 100644
--- a/docs/manpages/net.8
+++ b/docs/manpages/net.8
@@ -2,12 +2,12 @@
 .\"     Title: net
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NET" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "NET" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8
index 155c6a5..bcf774a 100644
--- a/docs/manpages/nmbd.8
+++ b/docs/manpages/nmbd.8
@@ -2,12 +2,12 @@
 .\"     Title: nmbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NMBD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "NMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/nmblookup.1 b/docs/manpages/nmblookup.1
index d752790..6b2677d 100644
--- a/docs/manpages/nmblookup.1
+++ b/docs/manpages/nmblookup.1
@@ -2,12 +2,12 @@
 .\"     Title: nmblookup
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NMBLOOKUP" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "NMBLOOKUP" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/ntlm_auth.1 b/docs/manpages/ntlm_auth.1
index b2ddd10..1d0fed8 100644
--- a/docs/manpages/ntlm_auth.1
+++ b/docs/manpages/ntlm_auth.1
@@ -2,12 +2,12 @@
 .\"     Title: ntlm_auth
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "NTLM_AUTH" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "NTLM_AUTH" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.8 b/docs/manpages/pam_winbind.8
index 7ae4fd9..dbfca2b 100644
--- a/docs/manpages/pam_winbind.8
+++ b/docs/manpages/pam_winbind.8
@@ -2,12 +2,12 @@
 .\"     Title: pam_winbind
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: 8
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND" "8" "12/10/2015" "Samba 4\&.3" "8"
+.TH "PAM_WINBIND" "8" "02/24/2016" "Samba 4\&.3" "8"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pam_winbind.conf.5 b/docs/manpages/pam_winbind.conf.5
index f7a3554..9e3d7c8 100644
--- a/docs/manpages/pam_winbind.conf.5
+++ b/docs/manpages/pam_winbind.conf.5
@@ -2,12 +2,12 @@
 .\"     Title: pam_winbind.conf
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: 5
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PAM_WINBIND\&.CONF" "5" "12/10/2015" "Samba 4\&.3" "5"
+.TH "PAM_WINBIND\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "5"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/pdbedit.8 b/docs/manpages/pdbedit.8
index 6709a43..12245f1 100644
--- a/docs/manpages/pdbedit.8
+++ b/docs/manpages/pdbedit.8
@@ -2,12 +2,12 @@
 .\"     Title: pdbedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PDBEDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "PDBEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/profiles.1 b/docs/manpages/profiles.1
index 9570215..33296d1 100644
--- a/docs/manpages/profiles.1
+++ b/docs/manpages/profiles.1
@@ -2,12 +2,12 @@
 .\"     Title: profiles
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "PROFILES" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "PROFILES" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/rpcclient.1 b/docs/manpages/rpcclient.1
index a9e68f6..9e721db 100644
--- a/docs/manpages/rpcclient.1
+++ b/docs/manpages/rpcclient.1
@@ -2,12 +2,12 @@
 .\"     Title: rpcclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "RPCCLIENT" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "RPCCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-regedit.8 b/docs/manpages/samba-regedit.8
index 76db229..3b282b1 100644
--- a/docs/manpages/samba-regedit.8
+++ b/docs/manpages/samba-regedit.8
@@ -2,12 +2,12 @@
 .\"     Title: samba-regedit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA\-REGEDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-REGEDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba-tool.8 b/docs/manpages/samba-tool.8
index 2e3aafa..c55158d 100644
--- a/docs/manpages/samba-tool.8
+++ b/docs/manpages/samba-tool.8
@@ -2,12 +2,12 @@
 .\"     Title: samba-tool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA\-TOOL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA\-TOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7
index ad18244..3628bfd 100644
--- a/docs/manpages/samba.7
+++ b/docs/manpages/samba.7
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: Miscellanea
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA" "7" "12/10/2015" "Samba 4\&.3" "Miscellanea"
+.TH "SAMBA" "7" "02/24/2016" "Samba 4\&.3" "Miscellanea"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/samba.8 b/docs/manpages/samba.8
index 31120f4..0bd4e30 100644
--- a/docs/manpages/samba.8
+++ b/docs/manpages/samba.8
@@ -2,12 +2,12 @@
 .\"     Title: samba
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SAMBA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SAMBA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/sharesec.1 b/docs/manpages/sharesec.1
index 9761e1c..e654488 100644
--- a/docs/manpages/sharesec.1
+++ b/docs/manpages/sharesec.1
@@ -2,12 +2,12 @@
 .\"     Title: sharesec
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SHARESEC" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SHARESEC" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5
index 02ea1b6..796aa3a 100644
--- a/docs/manpages/smb.conf.5
+++ b/docs/manpages/smb.conf.5
@@ -2,12 +2,12 @@
 .\"     Title: smb.conf
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMB\&.CONF" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMB\&.CONF" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -4181,9 +4181,9 @@ There are three general options available:
 .PP
 backend = backend_name
 .RS 4
-This specifies the name of the idmap plugin to use as the SID/uid/gid backend for this domain\&. The standard backends are tdb (\fBidmap_tdb\fR(8)), tdb2 (\fBidmap_tdb2\fR(8)), ldap (\fBidmap_ldap\fR(8)), , rid (\fBidmap_rid\fR(8)), , hash (\fBidmap_hash\fR(8)), , autorid (\fBidmap_autorid\fR(8)), , ad (\fBidmap_ad\fR(8)), , and nss\&. (\fBidmap_nss\fR(8)), The corresponding manual pages contain the details, but here is a summary\&.
+This specifies the name of the idmap plugin to use as the SID/uid/gid backend for this domain\&. The standard backends are tdb (\fBidmap_tdb\fR(8)), tdb2 (\fBidmap_tdb2\fR(8)), ldap (\fBidmap_ldap\fR(8)), rid (\fBidmap_rid\fR(8)), hash (\fBidmap_hash\fR(8)), autorid (\fBidmap_autorid\fR(8)), ad (\fBidmap_ad\fR(8)) and nss (\fBidmap_nss\fR(8))\&. The corresponding manual pages contain the details, but here is a summary\&.
 .sp
-The first three of these create mappings of their own using internal unixid counters and store the mappings in a database\&. These are suitable for use in the default idmap configuration\&. The rid and hash backends use a pure algorithmic calculation to determine the unixid for a SID\&. The autorid module is a mixture of the tdb and rid backend\&. It creates ranges for each domain encountered and then uses the rid algorithm for each of these automatically configured domains individually\ [...]
+The first three of these create mappings of their own using internal unixid counters and store the mappings in a database\&. These are suitable for use in the default idmap configuration\&. The rid and hash backends use a pure algorithmic calculation to determine the unixid for a SID\&. The autorid module is a mixture of the tdb and rid backend\&. It creates ranges for each domain encountered and then uses the rid algorithm for each of these automatically configured domains individually\ [...]
 .RE
 .PP
 range = low \- high
diff --git a/docs/manpages/smbcacls.1 b/docs/manpages/smbcacls.1
index 5d93e71..291ac5e 100644
--- a/docs/manpages/smbcacls.1
+++ b/docs/manpages/smbcacls.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcacls
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCACLS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCACLS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbclient.1 b/docs/manpages/smbclient.1
index 907a2cc..395fbcf 100644
--- a/docs/manpages/smbclient.1
+++ b/docs/manpages/smbclient.1
@@ -2,12 +2,12 @@
 .\"     Title: smbclient
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCLIENT" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCLIENT" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcontrol.1 b/docs/manpages/smbcontrol.1
index 5b0b37e..c8cf7ff 100644
--- a/docs/manpages/smbcontrol.1
+++ b/docs/manpages/smbcontrol.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcontrol
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCONTROL" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCONTROL" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbcquotas.1 b/docs/manpages/smbcquotas.1
index 11e88df..22365d0 100644
--- a/docs/manpages/smbcquotas.1
+++ b/docs/manpages/smbcquotas.1
@@ -2,12 +2,12 @@
 .\"     Title: smbcquotas
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBCQUOTAS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBCQUOTAS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbd.8 b/docs/manpages/smbd.8
index e1e4ea5..0171d72 100644
--- a/docs/manpages/smbd.8
+++ b/docs/manpages/smbd.8
@@ -2,12 +2,12 @@
 .\"     Title: smbd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbget.1 b/docs/manpages/smbget.1
index 83846e4..566a67a 100644
--- a/docs/manpages/smbget.1
+++ b/docs/manpages/smbget.1
@@ -2,12 +2,12 @@
 .\"     Title: smbget
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBGET" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBGET" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbgetrc.5 b/docs/manpages/smbgetrc.5
index 573e6cc..c959419 100644
--- a/docs/manpages/smbgetrc.5
+++ b/docs/manpages/smbgetrc.5
@@ -2,12 +2,12 @@
 .\"     Title: smbgetrc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBGETRC" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBGETRC" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.5 b/docs/manpages/smbpasswd.5
index 3431a0a..31b52a9 100644
--- a/docs/manpages/smbpasswd.5
+++ b/docs/manpages/smbpasswd.5
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: File Formats and Conventions
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "5" "12/10/2015" "Samba 4\&.3" "File Formats and Conventions"
+.TH "SMBPASSWD" "5" "02/24/2016" "Samba 4\&.3" "File Formats and Conventions"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbpasswd.8 b/docs/manpages/smbpasswd.8
index ba7f39e..3d00776 100644
--- a/docs/manpages/smbpasswd.8
+++ b/docs/manpages/smbpasswd.8
@@ -2,12 +2,12 @@
 .\"     Title: smbpasswd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBPASSWD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBPASSWD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbspool.8 b/docs/manpages/smbspool.8
index 2c06f81..c4bc508 100644
--- a/docs/manpages/smbspool.8
+++ b/docs/manpages/smbspool.8
@@ -2,12 +2,12 @@
 .\"     Title: smbspool
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBSPOOL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBSPOOL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_xattr_tdb.8 b/docs/manpages/smbspool_krb5_wrapper.8
similarity index 62%
copy from docs/manpages/vfs_xattr_tdb.8
copy to docs/manpages/smbspool_krb5_wrapper.8
index 6fc4e13..bd6f2b5 100644
--- a/docs/manpages/vfs_xattr_tdb.8
+++ b/docs/manpages/smbspool_krb5_wrapper.8
@@ -1,13 +1,13 @@
 '\" t
-.\"     Title: vfs_xattr_tdb
+.\"     Title: smbspool_krb5_wrapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
-.\"    Source: Samba 4.3
+.\"    Source: Samba 4.4
 .\"  Language: English
 .\"
-.TH "VFS_XATTR_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBSPOOL_KRB5_WRAPPE" "8" "02/24/2016" "Samba 4\&.4" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -28,29 +28,22 @@
 .\" * MAIN CONTENT STARTS HERE *
 .\" -----------------------------------------------------------------
 .SH "NAME"
-vfs_xattr_tdb \- Save Extended Attributes (EAs) in a tdb file
+smbspool_krb5_wrapper \- This is a CUPS printing backend which calls smbspool
 .SH "SYNOPSIS"
 .HP \w'\ 'u
-vfs objects = xattr_tdb
+smbspool_krb5_wrapper {job} {user} {title} {copies} {options} [filename]
 .SH "DESCRIPTION"
 .PP
-This VFS module is part of the
+This tool is part of the
 \fBsamba\fR(7)
 suite\&.
 .PP
-The
-vfs_xattr_tdb
-VFS module stores Extended Attributes (EAs) in a tdb file\&. This enables the usage of Extended Attributes on OS and filesystems which do not support Extended Attributes by themselves\&.
+smbspool_krb5_wrapper is a tool that can be used to print using Kerberos credentials\&. To get this working smbspool_krb5_wrapper needs to be the smb backend of CUPS\&. It needs to be owned by root and the permissions for the binary need to be 0700\&. Once smbspool_krb5_wrapper switched to the user trying to print it executes smbspool\&. It should not be called by a user\&.
+.SH "SEE ALSO"
 .PP
-This module is stackable\&.
-.SH "OPTIONS"
-.PP
-xattr_tdb:file = PATH
-.RS 4
-Name of the tdb file the EAs are stored in\&. If this option is not set, the default filename
-xattr\&.tdb
-is used\&.
-.RE
+\fBsmbspool\fR(8)\&.
 .SH "AUTHOR"
 .PP
 The original Samba software and related utilities were created by Andrew Tridgell\&. Samba is now developed by the Samba Team as an Open Source project similar to the way the Linux kernel is developed\&.
+.PP
+The smbspool_krb5_wrapper manpage was written by Andreas Schneider\&.
diff --git a/docs/manpages/smbstatus.1 b/docs/manpages/smbstatus.1
index b99ac16..c2766d5 100644
--- a/docs/manpages/smbstatus.1
+++ b/docs/manpages/smbstatus.1
@@ -2,12 +2,12 @@
 .\"     Title: smbstatus
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBSTATUS" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBSTATUS" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbta-util.8 b/docs/manpages/smbta-util.8
index 3b2c570..f7349c7 100644
--- a/docs/manpages/smbta-util.8
+++ b/docs/manpages/smbta-util.8
@@ -2,12 +2,12 @@
 .\"     Title: smbta-util
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTA\-UTIL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMBTA\-UTIL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtar.1 b/docs/manpages/smbtar.1
index cfefbcb..130b1a3 100644
--- a/docs/manpages/smbtar.1
+++ b/docs/manpages/smbtar.1
@@ -2,12 +2,12 @@
 .\"     Title: smbtar
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTAR" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBTAR" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/smbtree.1 b/docs/manpages/smbtree.1
index f55444a..e757082 100644
--- a/docs/manpages/smbtree.1
+++ b/docs/manpages/smbtree.1
@@ -2,12 +2,12 @@
 .\"     Title: smbtree
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMBTREE" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "SMBTREE" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/testparm.1 b/docs/manpages/testparm.1
index 8b10943..5b42305 100644
--- a/docs/manpages/testparm.1
+++ b/docs/manpages/testparm.1
@@ -2,12 +2,12 @@
 .\"     Title: testparm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "TESTPARM" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "TESTPARM" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_tdb.8 b/docs/manpages/vfs_acl_tdb.8
index de7a868..9c69b5f 100644
--- a/docs/manpages/vfs_acl_tdb.8
+++ b/docs/manpages/vfs_acl_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_acl_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ACL_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_acl_xattr.8 b/docs/manpages/vfs_acl_xattr.8
index 2924319..9ed7731 100644
--- a/docs/manpages/vfs_acl_xattr.8
+++ b/docs/manpages/vfs_acl_xattr.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_acl_xattr
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ACL_XATTR" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ACL_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_fork.8 b/docs/manpages/vfs_aio_fork.8
index 325c4bc..a5a8838 100644
--- a/docs/manpages/vfs_aio_fork.8
+++ b/docs/manpages/vfs_aio_fork.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_fork
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_FORK" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_FORK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_linux.8 b/docs/manpages/vfs_aio_linux.8
index f1e618a..9029985 100644
--- a/docs/manpages/vfs_aio_linux.8
+++ b/docs/manpages/vfs_aio_linux.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_linux
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_LINUX" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_LINUX" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_aio_pthread.8 b/docs/manpages/vfs_aio_pthread.8
index f18774f..0606288 100644
--- a/docs/manpages/vfs_aio_pthread.8
+++ b/docs/manpages/vfs_aio_pthread.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_aio_pthread
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AIO_PTHREAD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AIO_PTHREAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_audit.8 b/docs/manpages/vfs_audit.8
index 3ee45ff..0154f99 100644
--- a/docs/manpages/vfs_audit.8
+++ b/docs/manpages/vfs_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_btrfs.8 b/docs/manpages/vfs_btrfs.8
index 35c6f42..aea6e5a 100644
--- a/docs/manpages/vfs_btrfs.8
+++ b/docs/manpages/vfs_btrfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_btrfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_BTRFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_BTRFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cacheprime.8 b/docs/manpages/vfs_cacheprime.8
index 6bb4ad6..ce1cad4 100644
--- a/docs/manpages/vfs_cacheprime.8
+++ b/docs/manpages/vfs_cacheprime.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cacheprime
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CACHEPRIME" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CACHEPRIME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_cap.8 b/docs/manpages/vfs_cap.8
index 7d7d042..326c412 100644
--- a/docs/manpages/vfs_cap.8
+++ b/docs/manpages/vfs_cap.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_cap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_catia.8 b/docs/manpages/vfs_catia.8
index c79a3c1..bc68933 100644
--- a/docs/manpages/vfs_catia.8
+++ b/docs/manpages/vfs_catia.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_catia
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CATIA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CATIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_ceph.8 b/docs/manpages/vfs_ceph.8
index ab16c76..73b3d61 100644
--- a/docs/manpages/vfs_ceph.8
+++ b/docs/manpages/vfs_ceph.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_ceph
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CEPH" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CEPH" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_commit.8 b/docs/manpages/vfs_commit.8
index 74cb5f3..afbb350 100644
--- a/docs/manpages/vfs_commit.8
+++ b/docs/manpages/vfs_commit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_commit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_COMMIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_COMMIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_crossrename.8 b/docs/manpages/vfs_crossrename.8
index 2bdca92..4b037a1 100644
--- a/docs/manpages/vfs_crossrename.8
+++ b/docs/manpages/vfs_crossrename.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_crossrename
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_CROSSRENAME" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_CROSSRENAME" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_default_quota.8 b/docs/manpages/vfs_default_quota.8
index c9aea70..9347894 100644
--- a/docs/manpages/vfs_default_quota.8
+++ b/docs/manpages/vfs_default_quota.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_default_quota
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_DEFAULT_QUOTA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DEFAULT_QUOTA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_dirsort.8 b/docs/manpages/vfs_dirsort.8
index 5196ce9..6455c07 100644
--- a/docs/manpages/vfs_dirsort.8
+++ b/docs/manpages/vfs_dirsort.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_dirsort
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_DIRSORT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_DIRSORT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_extd_audit.8 b/docs/manpages/vfs_extd_audit.8
index d965c3c..48f605b 100644
--- a/docs/manpages/vfs_extd_audit.8
+++ b/docs/manpages/vfs_extd_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_extd_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_EXTD_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_EXTD_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fake_perms.8 b/docs/manpages/vfs_fake_perms.8
index 53f9c94..68aac1f 100644
--- a/docs/manpages/vfs_fake_perms.8
+++ b/docs/manpages/vfs_fake_perms.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fake_perms
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FAKE_PERMS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FAKE_PERMS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fileid.8 b/docs/manpages/vfs_fileid.8
index 883e260..2121630 100644
--- a/docs/manpages/vfs_fileid.8
+++ b/docs/manpages/vfs_fileid.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fileid
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FILEID" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FILEID" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_fruit.8 b/docs/manpages/vfs_fruit.8
index 888afa5..7b8f212 100644
--- a/docs/manpages/vfs_fruit.8
+++ b/docs/manpages/vfs_fruit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_fruit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FRUIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FRUIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_full_audit.8 b/docs/manpages/vfs_full_audit.8
index 2ba226b..4ea3f03 100644
--- a/docs/manpages/vfs_full_audit.8
+++ b/docs/manpages/vfs_full_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_full_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_FULL_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_FULL_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_glusterfs.8 b/docs/manpages/vfs_glusterfs.8
index 8843d96..e70933f 100644
--- a/docs/manpages/vfs_glusterfs.8
+++ b/docs/manpages/vfs_glusterfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_glusterfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_GLUSTERFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GLUSTERFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_gpfs.8 b/docs/manpages/vfs_gpfs.8
index bb33eb9..a5b158e 100644
--- a/docs/manpages/vfs_gpfs.8
+++ b/docs/manpages/vfs_gpfs.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_gpfs
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_GPFS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_GPFS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -79,11 +79,11 @@ Lease support on GPFS
 .sp
 .RE
 .PP
-NOTE:This module follows the posix\-acl behaviour and hence allows permission stealing via chown\&. Samba might allow at a later point in time, to restrict the chown via this module as such restrictions are the responsibility of the underlying filesystem than of Samba\&.
+NOTE:
+This module follows the posix\-acl behaviour and hence allows permission stealing via chown\&. Samba might allow at a later point in time, to restrict the chown via this module as such restrictions are the responsibility of the underlying filesystem than of Samba\&.
 .PP
 This module makes use of the smb\&.conf parameter
-\m[blue]\fBacl map full control = acl map full control\fR\m[]
-When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD bit on a returned ACE entry for a file (not a directory) that already contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD\&. This can prevent Windows applications that request GENERIC_ALL access from getting ACCESS_DENIED errors when running against a filesystem with NFSv4 compatible ACLs\&.
+\m[blue]\fBacl map full control\fR\m[]\&. When set to yes (the default), this parameter will add in the FILE_DELETE_CHILD bit on a returned ACE entry for a file (not a directory) that already contains all file permissions except for FILE_DELETE and FILE_DELETE_CHILD\&. This can prevent Windows applications that request GENERIC_ALL access from getting ACCESS_DENIED errors when running against a filesystem with NFSv4 compatible ACLs\&.
 .PP
 This module is stackable\&.
 .PP
@@ -670,7 +670,7 @@ library was open source and could be used at run time\&.
 .PP
 At build time, only the header file
 gpfs_gpl\&.h
-is required , which is a symlink to
+is required, which is a symlink to
 gpfs\&.h
 in gpfs versions newer than 3\&.2\&.1 PTF8\&.
 .SH "VERSION"
diff --git a/docs/manpages/vfs_linux_xfs_sgid.8 b/docs/manpages/vfs_linux_xfs_sgid.8
index 16abafd..0acaee5 100644
--- a/docs/manpages/vfs_linux_xfs_sgid.8
+++ b/docs/manpages/vfs_linux_xfs_sgid.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_media_harmony.8 b/docs/manpages/vfs_media_harmony.8
index a589cdb..eefadb3 100644
--- a/docs/manpages/vfs_media_harmony.8
+++ b/docs/manpages/vfs_media_harmony.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_media_harmony
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_MEDIA_HARMONY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_MEDIA_HARMONY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_netatalk.8 b/docs/manpages/vfs_netatalk.8
index 32f13fd..6cbe456 100644
--- a/docs/manpages/vfs_netatalk.8
+++ b/docs/manpages/vfs_netatalk.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_netatalk
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_NETATALK" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_NETATALK" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_prealloc.8 b/docs/manpages/vfs_prealloc.8
index 5d809ed..242a7e4 100644
--- a/docs/manpages/vfs_prealloc.8
+++ b/docs/manpages/vfs_prealloc.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_prealloc
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_PREALLOC" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREALLOC" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_preopen.8 b/docs/manpages/vfs_preopen.8
index 3298111..db8e404 100644
--- a/docs/manpages/vfs_preopen.8
+++ b/docs/manpages/vfs_preopen.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_preopen
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_PREOPEN" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_PREOPEN" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readahead.8 b/docs/manpages/vfs_readahead.8
index 49da5b7..6c9fec5 100644
--- a/docs/manpages/vfs_readahead.8
+++ b/docs/manpages/vfs_readahead.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readahead
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_READAHEAD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READAHEAD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_readonly.8 b/docs/manpages/vfs_readonly.8
index b74fbac..c335680 100644
--- a/docs/manpages/vfs_readonly.8
+++ b/docs/manpages/vfs_readonly.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_readonly
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_READONLY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_READONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_recycle.8 b/docs/manpages/vfs_recycle.8
index 2300bfb..d8e1ae8 100644
--- a/docs/manpages/vfs_recycle.8
+++ b/docs/manpages/vfs_recycle.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_recycle
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_RECYCLE" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_RECYCLE" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_scannedonly.8 b/docs/manpages/vfs_scannedonly.8
index 175937d..a5d9d5d 100644
--- a/docs/manpages/vfs_scannedonly.8
+++ b/docs/manpages/vfs_scannedonly.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_scannedonly
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SCANNEDONLY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SCANNEDONLY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy.8 b/docs/manpages/vfs_shadow_copy.8
index bf13ea3..deff1c2 100644
--- a/docs/manpages/vfs_shadow_copy.8
+++ b/docs/manpages/vfs_shadow_copy.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shadow_copy
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shadow_copy2.8 b/docs/manpages/vfs_shadow_copy2.8
index 7c94588..f4da715 100644
--- a/docs/manpages/vfs_shadow_copy2.8
+++ b/docs/manpages/vfs_shadow_copy2.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shadow_copy2
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHADOW_COPY2" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHADOW_COPY2" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_shell_snap.8 b/docs/manpages/vfs_shell_snap.8
index 951772e..dba4e3f 100644
--- a/docs/manpages/vfs_shell_snap.8
+++ b/docs/manpages/vfs_shell_snap.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_shell_snap
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SHELL_SNAP" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SHELL_SNAP" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_smb_traffic_analyzer.8 b/docs/manpages/vfs_smb_traffic_analyzer.8
index f023b6d..b506a22 100644
--- a/docs/manpages/vfs_smb_traffic_analyzer.8
+++ b/docs/manpages/vfs_smb_traffic_analyzer.8
@@ -2,12 +2,12 @@
 .\"     Title: smb_traffic_analyzer
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "SMB_TRAFFIC_ANALYZER" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "SMB_TRAFFIC_ANALYZER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_snapper.8 b/docs/manpages/vfs_snapper.8
index 5f3c64a..401a35b 100644
--- a/docs/manpages/vfs_snapper.8
+++ b/docs/manpages/vfs_snapper.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_snapper
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SNAPPER" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SNAPPER" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_depot.8 b/docs/manpages/vfs_streams_depot.8
index 2b1456e..30238e2 100644
--- a/docs/manpages/vfs_streams_depot.8
+++ b/docs/manpages/vfs_streams_depot.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_streams_depot
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_DEPOT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_DEPOT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_streams_xattr.8 b/docs/manpages/vfs_streams_xattr.8
index 0eb4c5b..609d39e 100644
--- a/docs/manpages/vfs_streams_xattr.8
+++ b/docs/manpages/vfs_streams_xattr.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_streams_xattr
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_STREAMS_XATTR" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_STREAMS_XATTR" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_syncops.8 b/docs/manpages/vfs_syncops.8
index 97fb0d5..a36ff94 100644
--- a/docs/manpages/vfs_syncops.8
+++ b/docs/manpages/vfs_syncops.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_syncops
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_SYNCOPS" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_SYNCOPS" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_time_audit.8 b/docs/manpages/vfs_time_audit.8
index 948c08c..6e422fd 100644
--- a/docs/manpages/vfs_time_audit.8
+++ b/docs/manpages/vfs_time_audit.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_time_audit
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_TIME_AUDIT" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TIME_AUDIT" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_tsmsm.8 b/docs/manpages/vfs_tsmsm.8
index c15264a..973455e 100644
--- a/docs/manpages/vfs_tsmsm.8
+++ b/docs/manpages/vfs_tsmsm.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_tsmsm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_TSMSM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_TSMSM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_unityed_media.8 b/docs/manpages/vfs_unityed_media.8
index f8fce9c..a4263ee 100644
--- a/docs/manpages/vfs_unityed_media.8
+++ b/docs/manpages/vfs_unityed_media.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_unityed_media
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_UNITYED_MEDIA" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_UNITYED_MEDIA" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_worm.8 b/docs/manpages/vfs_worm.8
index f6635fe..9272ca4 100644
--- a/docs/manpages/vfs_worm.8
+++ b/docs/manpages/vfs_worm.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_worm
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_WORM" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_WORM" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_xattr_tdb.8 b/docs/manpages/vfs_xattr_tdb.8
index 6fc4e13..ab5624a 100644
--- a/docs/manpages/vfs_xattr_tdb.8
+++ b/docs/manpages/vfs_xattr_tdb.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_xattr_tdb
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_XATTR_TDB" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_XATTR_TDB" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfs_zfsacl.8 b/docs/manpages/vfs_zfsacl.8
index 6a7ceb6..49761b9 100644
--- a/docs/manpages/vfs_zfsacl.8
+++ b/docs/manpages/vfs_zfsacl.8
@@ -2,12 +2,12 @@
 .\"     Title: vfs_zfsacl
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFS_ZFSACL" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "VFS_ZFSACL" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/vfstest.1 b/docs/manpages/vfstest.1
index b0841c1..aa5f3d5 100644
--- a/docs/manpages/vfstest.1
+++ b/docs/manpages/vfstest.1
@@ -2,12 +2,12 @@
 .\"     Title: vfstest
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "VFSTEST" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "VFSTEST" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/wbinfo.1 b/docs/manpages/wbinfo.1
index 8231c0e..b50f729 100644
--- a/docs/manpages/wbinfo.1
+++ b/docs/manpages/wbinfo.1
@@ -2,12 +2,12 @@
 .\"     Title: wbinfo
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: User Commands
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WBINFO" "1" "12/10/2015" "Samba 4\&.3" "User Commands"
+.TH "WBINFO" "1" "02/24/2016" "Samba 4\&.3" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbind_krb5_locator.7 b/docs/manpages/winbind_krb5_locator.7
index c2cd229..b9a7ed6 100644
--- a/docs/manpages/winbind_krb5_locator.7
+++ b/docs/manpages/winbind_krb5_locator.7
@@ -2,12 +2,12 @@
 .\"     Title: winbind_krb5_locator
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: 7
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WINBIND_KRB5_LOCATOR" "7" "12/10/2015" "Samba 4\&.3" "7"
+.TH "WINBIND_KRB5_LOCATOR" "7" "02/24/2016" "Samba 4\&.3" "7"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/docs/manpages/winbindd.8 b/docs/manpages/winbindd.8
index 88a9457..8f30460 100644
--- a/docs/manpages/winbindd.8
+++ b/docs/manpages/winbindd.8
@@ -2,12 +2,12 @@
 .\"     Title: winbindd
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/10/2015
+.\"      Date: 02/24/2016
 .\"    Manual: System Administration tools
 .\"    Source: Samba 4.3
 .\"  Language: English
 .\"
-.TH "WINBINDD" "8" "12/10/2015" "Samba 4\&.3" "System Administration tools"
+.TH "WINBINDD" "8" "02/24/2016" "Samba 4\&.3" "System Administration tools"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/lib/async_req/wscript_build b/lib/async_req/wscript_build
index 9c25223..bf79fdd 100644
--- a/lib/async_req/wscript_build
+++ b/lib/async_req/wscript_build
@@ -9,5 +9,6 @@ bld.SAMBA_SUBSYSTEM('LIBASYNC_REQ',
 
 bld.SAMBA_BINARY('async_connect_send_test',
                  source='async_connect_send_test.c',
-                 deps='LIBASYNC_REQ'
+                 deps='LIBASYNC_REQ',
+                 install=False
 )
diff --git a/lib/dbwrap/dbwrap_rbt.c b/lib/dbwrap/dbwrap_rbt.c
index 03f2f57..a9cc641 100644
--- a/lib/dbwrap/dbwrap_rbt.c
+++ b/lib/dbwrap/dbwrap_rbt.c
@@ -22,11 +22,15 @@
 #include "dbwrap/dbwrap_private.h"
 #include "dbwrap/dbwrap_rbt.h"
 #include "../lib/util/rbtree.h"
+#include "../lib/util/dlinklist.h"
 
 #define DBWRAP_RBT_ALIGN(_size_) (((_size_)+15)&~15)
 
 struct db_rbt_ctx {
 	struct rb_root tree;
+	struct db_rbt_node *nodes;
+	size_t traverse_read;
+	struct db_rbt_node **traverse_nextp;
 };
 
 struct db_rbt_rec {
@@ -38,6 +42,7 @@ struct db_rbt_rec {
 struct db_rbt_node {
 	struct rb_node rb_node;
 	size_t keysize, valuesize;
+	struct db_rbt_node *prev, *next;
 };
 
 /*
@@ -121,11 +126,16 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
 	struct db_rbt_node *node;
 
 	struct rb_node ** p;
-	struct rb_node * parent;
+	struct rb_node *parent = NULL;
+	struct db_rbt_node *parent_node = NULL;
 
 	ssize_t reclen;
 	TDB_DATA this_key, this_val;
 
+	if (db_ctx->traverse_read > 0) {
+		return NT_STATUS_MEDIA_WRITE_PROTECTED;
+	}
+
 	if (rec_priv->node != NULL) {
 
 		/*
@@ -153,18 +163,25 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
 		return NT_STATUS_INSUFFICIENT_RESOURCES;
 	}
 
-	node = talloc_size(db_ctx, reclen);
+	node = talloc_zero_size(db_ctx, reclen);
 	if (node == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
 	if (rec_priv->node != NULL) {
+		if (db_ctx->traverse_nextp != NULL) {
+			if (*db_ctx->traverse_nextp == rec_priv->node) {
+				*db_ctx->traverse_nextp = node;
+			}
+		}
+
 		/*
 		 * We need to delete the key from the tree and start fresh,
 		 * there's not enough space in the existing record
 		 */
 
 		rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
+		DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
 
 		/*
 		 * Keep the existing node around for a while: If the record
@@ -172,8 +189,6 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
 		 */
 	}
 
-	ZERO_STRUCT(node->rb_node);
-
 	node->keysize = rec->key.dsize;
 	node->valuesize = data.dsize;
 
@@ -193,10 +208,11 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
 		TDB_DATA search_key, search_val;
 		int res;
 
-		parent = (*p);
-
 		r = db_rbt2node(*p);
 
+		parent = (*p);
+		parent_node = r;
+
 		db_rbt_parse_node(r, &search_key, &search_val);
 
 		res = db_rbt_compare(this_key, search_key);
@@ -213,6 +229,7 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
 	}
 
 	rb_link_node(&node->rb_node, parent, p);
+	DLIST_ADD_AFTER(db_ctx->nodes, node, parent_node);
 	rb_insert_color(&node->rb_node, &db_ctx->tree);
 
 	return NT_STATUS_OK;
@@ -224,26 +241,27 @@ static NTSTATUS db_rbt_delete(struct db_record *rec)
 		rec->db->private_data, struct db_rbt_ctx);
 	struct db_rbt_rec *rec_priv = (struct db_rbt_rec *)rec->private_data;
 
+	if (db_ctx->traverse_read > 0) {
+		return NT_STATUS_MEDIA_WRITE_PROTECTED;
+	}
+
 	if (rec_priv->node == NULL) {
 		return NT_STATUS_OK;
 	}
 
+	if (db_ctx->traverse_nextp != NULL) {
+		if (*db_ctx->traverse_nextp == rec_priv->node) {
+			*db_ctx->traverse_nextp = rec_priv->node->next;
+		}
+	}
+
 	rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
+	DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
 	TALLOC_FREE(rec_priv->node);
 
 	return NT_STATUS_OK;
 }
 
-static NTSTATUS db_rbt_store_deny(struct db_record *rec, TDB_DATA data, int flag)
-{
-	return NT_STATUS_MEDIA_WRITE_PROTECTED;
-}
-
-static NTSTATUS db_rbt_delete_deny(struct db_record *rec)
-{
-	return NT_STATUS_MEDIA_WRITE_PROTECTED;
-}
-
 struct db_rbt_search_result {
 	TDB_DATA key;
 	TDB_DATA val;
@@ -385,75 +403,65 @@ static NTSTATUS db_rbt_parse_record(struct db_context *db, TDB_DATA key,
 }
 
 static int db_rbt_traverse_internal(struct db_context *db,
-				    struct rb_node *n,
 				    int (*f)(struct db_record *db,
 					     void *private_data),
 				    void *private_data, uint32_t* count,
 				    bool rw)
 {
-	struct rb_node *rb_right;
-	struct rb_node *rb_left;
-	struct db_record rec;
-	struct db_rbt_rec rec_priv;
+	struct db_rbt_ctx *ctx = talloc_get_type_abort(
+		db->private_data, struct db_rbt_ctx);
+	struct db_rbt_node *cur = NULL;
+	struct db_rbt_node *next = NULL;
 	int ret;
 
-	if (n == NULL) {
-		return 0;
-	}
+	for (cur = ctx->nodes; cur != NULL; cur = next) {
+		struct db_record rec;
+		struct db_rbt_rec rec_priv;
 
-	rb_left = n->rb_left;
-	rb_right = n->rb_right;
+		rec_priv.node = cur;
+		next = rec_priv.node->next;
 
-	ret = db_rbt_traverse_internal(db, rb_left, f, private_data, count, rw);
-	if (ret != 0) {
-		return ret;
-	}
-
-	rec_priv.node = db_rbt2node(n);
-	/* n might be altered by the callback function */
-	n = NULL;
-
-	ZERO_STRUCT(rec);
-	rec.db = db;
-	rec.private_data = &rec_priv;
-	if (rw) {
+		ZERO_STRUCT(rec);
+		rec.db = db;
+		rec.private_data = &rec_priv;
 		rec.store = db_rbt_store;
 		rec.delete_rec = db_rbt_delete;
-	} else {
-		rec.store = db_rbt_store_deny;
-		rec.delete_rec = db_rbt_delete_deny;
-	}
-	db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
-
-	ret = f(&rec, private_data);
-	(*count) ++;
-	if (ret != 0) {
-		return ret;
-	}
+		db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
 
-	if (rec_priv.node != NULL) {
-		/*
-		 * If the current record is still there
-		 * we should take the current rb_right.
-		 */
-		rb_right = rec_priv.node->rb_node.rb_right;
+		if (rw) {
+			ctx->traverse_nextp = &next;
+		}
+		ret = f(&rec, private_data);
+		(*count) ++;
+		if (rw) {
+			ctx->traverse_nextp = NULL;
+		}
+		if (ret != 0) {
+			return ret;
+		}
+		if (rec_priv.node != NULL) {
+			next = rec_priv.node->next;
+		}
 	}
 
-	return db_rbt_traverse_internal(db, rb_right, f, private_data, count, rw);
+	return 0;
 }
 
-static int db_rbt_traverse(struct db_context *db,
-			   int (*f)(struct db_record *db,
-				    void *private_data),
-			   void *private_data)
+static int db_rbt_traverse_read(struct db_context *db,
+				int (*f)(struct db_record *db,
+					 void *private_data),
+				void *private_data)
 {
 	struct db_rbt_ctx *ctx = talloc_get_type_abort(
 		db->private_data, struct db_rbt_ctx);
 	uint32_t count = 0;
+	int ret;
 
-	int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
-					   f, private_data, &count,
-					   true /* rw */);
+	ctx->traverse_read++;
+	ret = db_rbt_traverse_internal(db,
+				       f, private_data, &count,
+				       false /* rw */);
+	ctx->traverse_read--;
 	if (ret != 0) {
 		return -1;
 	}
@@ -463,18 +471,27 @@ static int db_rbt_traverse(struct db_context *db,
 	return count;
 }
 
-static int db_rbt_traverse_read(struct db_context *db,
-				int (*f)(struct db_record *db,
-					 void *private_data),
-				void *private_data)
+static int db_rbt_traverse(struct db_context *db,
+			   int (*f)(struct db_record *db,
+				    void *private_data),
+			   void *private_data)
 {
 	struct db_rbt_ctx *ctx = talloc_get_type_abort(
 		db->private_data, struct db_rbt_ctx);
 	uint32_t count = 0;
+	int ret;
+
+	if (ctx->traverse_nextp != NULL) {
+		return -1;
+	};
+
+	if (ctx->traverse_read > 0) {
+		return db_rbt_traverse_read(db, f, private_data);
+	}
 
-	int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
-					   f, private_data, &count,
-					   false /* rw */);
+	ret = db_rbt_traverse_internal(db,
+				       f, private_data, &count,
+				       true /* rw */);
 	if (ret != 0) {
 		return -1;
 	}
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index c26442a..7b75f13 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -508,16 +508,36 @@ bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
 }
 
 
+/* this is used to prevent lots of mallocs of size 1 */
+static const char lpcfg_string_emtpy[] = "";
+
+/**
+ Free a string value.
+**/
+void lpcfg_string_free(char **s)
+{
+	if (s == NULL) {
+		return;
+	}
+	if (*s == lpcfg_string_emtpy) {
+		*s = NULL;
+		return;
+	}
+	TALLOC_FREE(*s);
+}
+
 /**
  * Set a string value, deallocating any existing space, and allocing the space
  * for the string
  */
 bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 {
-	talloc_free(*dest);
+	lpcfg_string_free(dest);
 
-	if (src == NULL)
-		src = "";
+	if ((src == NULL) || (*src == '\0')) {
+		*dest = discard_const_p(char, lpcfg_string_emtpy);
+		return true;
+	}
 
 	*dest = talloc_strdup(mem_ctx, src);
 	if ((*dest) == NULL) {
@@ -534,10 +554,12 @@ bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
  */
 bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 {
-	talloc_free(*dest);
+	lpcfg_string_free(dest);
 
-	if (src == NULL)
-		src = "";
+	if ((src == NULL) || (*src == '\0')) {
+		*dest = discard_const_p(char, lpcfg_string_emtpy);
+		return true;
+	}
 
 	*dest = strupper_talloc(mem_ctx, src);
 	if ((*dest) == NULL) {
@@ -811,9 +833,8 @@ void set_param_opt(TALLOC_CTX *mem_ctx,
 				   overridden */
 				return;
 			}
-			TALLOC_FREE(opt->value);
 			TALLOC_FREE(opt->list);
-			opt->value = talloc_strdup(opt, opt_value);
+			lpcfg_string_set(opt, &opt->value, opt_value);
 			opt->priority = priority;
 			not_added = false;
 			break;
@@ -825,16 +846,10 @@ void set_param_opt(TALLOC_CTX *mem_ctx,
 		if (new_opt == NULL) {
 			smb_panic("OOM");
 		}
-
-		new_opt->key = talloc_strdup(new_opt, opt_name);
-		if (new_opt->key == NULL) {
-			smb_panic("talloc_strdup failed");
-		}
-
-		new_opt->value = talloc_strdup(new_opt, opt_value);
-		if (new_opt->value == NULL) {
-			smb_panic("talloc_strdup failed");
-		}
+		new_opt->key = NULL;
+		lpcfg_string_set(new_opt, &new_opt->key, opt_name);
+		new_opt->value = NULL;
+		lpcfg_string_set(new_opt, &new_opt->value, opt_value);
 
 		new_opt->list = NULL;
 		new_opt->priority = priority;
@@ -2404,13 +2419,16 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 		if ((parm_table[i].type == P_STRING ||
 		     parm_table[i].type == P_USTRING) &&
 		    !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
+			TALLOC_CTX *parent_mem;
 			char **r;
 			if (parm_table[i].p_class == P_LOCAL) {
+				parent_mem = lp_ctx->sDefault;
 				r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
 			} else {
+				parent_mem = lp_ctx->globals;
 				r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
 			}
-			*r = talloc_strdup(lp_ctx, "");
+			lpcfg_string_set(parent_mem, r, "");
 		}
 	}
 
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index 8203755..0756fb3 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -132,6 +132,43 @@ static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
 	return -1;
 }
 
+#ifdef HAVE_LINUX_RTNETLINK_H
+/**
+ * Get the amount of pending bytes from a netlink socket
+ *
+ * For some reason netlink sockets don't support querying the amount of pending
+ * data via ioctl with FIONREAD, which is what we use in tsocket_bsd_pending()
+ * below.
+ *
+ * We know we are on Linux as we're using netlink, which means we have a working
+ * MSG_TRUNC flag to recvmsg() as well, so we use that together with MSG_PEEK.
+ **/
+static ssize_t tsocket_bsd_netlink_pending(int fd)
+{
+	struct iovec iov;
+	struct msghdr msg;
+	char buf[1];
+
+	iov = (struct iovec) {
+		.iov_base = buf,
+		.iov_len = sizeof(buf)
+	};
+
+	msg = (struct msghdr) {
+		.msg_iov = &iov,
+		.msg_iovlen = 1
+	};
+
+	return recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
+}
+#else
+static ssize_t tsocket_bsd_netlink_pending(int fd)
+{
+	errno = ENOSYS;
+	return -1;
+}
+#endif
+
 static ssize_t tsocket_bsd_pending(int fd)
 {
 	int ret, error;
@@ -640,6 +677,7 @@ struct tdgram_bsd {
 	void *event_ptr;
 	struct tevent_fd *fde;
 	bool optimize_recvfrom;
+	bool netlink;
 
 	void *readable_private;
 	void (*readable_handler)(void *private_data);
@@ -892,7 +930,12 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
 	int err;
 	bool retry;
 
-	ret = tsocket_bsd_pending(bsds->fd);
+	if (bsds->netlink) {
+		ret = tsocket_bsd_netlink_pending(bsds->fd);
+	} else {
+		ret = tsocket_bsd_pending(bsds->fd);
+	}
+
 	if (state->first_try && ret == 0) {
 		state->first_try = false;
 		/* retry later */
@@ -1395,6 +1438,11 @@ int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
 {
 	struct tdgram_context *dgram;
 	struct tdgram_bsd *bsds;
+#ifdef HAVE_LINUX_RTNETLINK_H
+	int result;
+	struct sockaddr sa;
+	socklen_t sa_len = sizeof(struct sockaddr);
+#endif
 
 	dgram = tdgram_context_create(mem_ctx,
 				      &tdgram_bsd_ops,
@@ -1409,6 +1457,18 @@ int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
 	talloc_set_destructor(bsds, tdgram_bsd_destructor);
 
 	*_dgram = dgram;
+
+#ifdef HAVE_LINUX_RTNETLINK_H
+	/*
+	 * Try to determine the protocol family and remember if it's
+	 * AF_NETLINK. We don't care if this fails.
+	 */
+	result = getsockname(fd, &sa, &sa_len);
+	if (result == 0 && sa.sa_family == AF_NETLINK) {
+		bsds->netlink = true;
+	}
+#endif
+
 	return 0;
 }
 
diff --git a/lib/util/util_strlist.c b/lib/util/util_strlist.c
index 987fdfb..2c1c2d5 100644
--- a/lib/util/util_strlist.c
+++ b/lib/util/util_strlist.c
@@ -552,7 +552,23 @@ char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
 		TALLOC_FREE(list);
 		return NULL;
 	}
-	if (!sep) sep = LIST_SEP;
+
+	/*
+	 * DON'T REPLACE THIS BY "LIST_SEP". The common version of
+	 * LIST_SEP does not contain the ;, which used to be accepted
+	 * by Samba 4.0 before param merges. It would be the far
+	 * better solution to split the _v3 version again to source3/
+	 * where it belongs, see the _v3 in its name.
+	 *
+	 * Unfortunately it is referenced in /lib/param/loadparm.c,
+	 * which depends on the version that the AD-DC mandates,
+	 * namely without the ; as part of the list separator. I am
+	 * missing the waf fu to properly work around the wrong
+	 * include paths here for this defect.
+	 */
+	if (sep == NULL) {
+		sep = " \t,;\n\r";
+	}
 
 	num = 0;
 	str = s;
diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl
index d247e0e..5435fcf 100644
--- a/librpc/idl/dns.idl
+++ b/librpc/idl/dns.idl
@@ -8,7 +8,7 @@
    encoding if it doesn't work out
 */
 
-import "misc.idl";
+import "misc.idl", "dnsp.idl";
 [
 	helper("librpc/ndr/ndr_dns.h"),
 	helpstring("DNS records"),
@@ -152,20 +152,12 @@ interface dns
 	} dns_soa_record;
 
 	typedef [public] struct {
-		[value(strlen(cpu))] uint8 cpu_length;
-		[charset(DOS)] uint8 cpu[cpu_length];
-		[value(strlen(os))] uint8 os_length;
-		[charset(DOS)] uint8 os[os_length];
-	} dns_hinfo_record;
-
-	typedef [public] struct {
 		uint16     preference;
 		dns_string exchange;
 	} dns_mx_record;
 
-	typedef [public] struct {
-		[value(strlen(txt))] uint8 length;
-		[charset(DOS)] uint8 txt[length];
+	typedef [public,nopull] struct {
+		dnsp_string_list txt;
 	} dns_txt_record;
 
 	typedef [public] struct {
@@ -232,7 +224,7 @@ interface dns
 		[case(DNS_QTYPE_CNAME)] dns_string       cname_record;
 		[case(DNS_QTYPE_SOA)]   dns_soa_record   soa_record;
 		[case(DNS_QTYPE_PTR)]   dns_string       ptr_record;
-		[case(DNS_QTYPE_HINFO)] dns_hinfo_record  hinfo_record;
+		[case(DNS_QTYPE_HINFO)] dnsp_hinfo       hinfo_record;
 		[case(DNS_QTYPE_MX)]    dns_mx_record    mx_record;
 		[case(DNS_QTYPE_TXT)]	dns_txt_record   txt_record;
 		[case(DNS_QTYPE_RP)]	dns_rp_record    rp_record;
@@ -270,7 +262,7 @@ interface dns
         /*
 	   this is a convenience hook for ndrdump
 	*/
-	void decode_dns_name_packet(
+	[nopython] void decode_dns_name_packet(
 				    [in] dns_name_packet packet
 				   );
 }
diff --git a/librpc/idl/dnsp.idl b/librpc/idl/dnsp.idl
index 4c49001..d705cfc 100644
--- a/librpc/idl/dnsp.idl
+++ b/librpc/idl/dnsp.idl
@@ -263,11 +263,11 @@ interface dnsp
 	/*
 	  these are convenience hooks for ndrdump
 	 */
-	void decode_DnssrvRpcRecord(
+	[nopython] void decode_DnssrvRpcRecord(
 		[in] dnsp_DnssrvRpcRecord blob
 		);
 
-	void decode_DnsProperty(
+	[nopython] void decode_DnsProperty(
 		[in] dnsp_DnsProperty blob
 		);
 }
diff --git a/librpc/idl/dnsserver.idl b/librpc/idl/dnsserver.idl
index ca9c371..c7742e7 100644
--- a/librpc/idl/dnsserver.idl
+++ b/librpc/idl/dnsserver.idl
@@ -73,7 +73,7 @@ import "misc.idl", "dnsp.idl";
 
 	typedef [public,gensize] struct {
 		[value(strlen(str))] uint8 len;
-		[charset(UTF8)] uint8 str[len];
+		[charset(UNIX)] uint8 str[len];
 	}
 	DNS_RPC_NAME;
 
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
index 0b9e3b0..065d992 100644
--- a/librpc/ndr/ndr_dns.c
+++ b/librpc/ndr/ndr_dns.c
@@ -30,6 +30,7 @@
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_dns.h"
 #include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
 #include "system/locale.h"
 #include "lib/util/util_net.h"
 
@@ -230,6 +231,29 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
 	return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
 }
 
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
+{
+	NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+	if (ndr_flags & NDR_SCALARS) {
+		enum ndr_err_code ndr_err;
+		uint32_t data_size = ndr->data_size;
+		uint32_t record_size = 0;
+		ndr_err = ndr_token_retrieve(&ndr->array_size_list, r,
+					     &record_size);
+		if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			NDR_PULL_NEED_BYTES(ndr, record_size);
+			ndr->data_size = ndr->offset + record_size;
+		}
+		NDR_CHECK(ndr_pull_align(ndr, 1));
+		NDR_CHECK(ndr_pull_dnsp_string_list(ndr, NDR_SCALARS, &r->txt));
+		NDR_CHECK(ndr_pull_trailer_align(ndr, 1));
+		ndr->data_size = data_size;
+	}
+	if (ndr_flags & NDR_BUFFERS) {
+	}
+	return NDR_ERR_SUCCESS;
+}
+
 _PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr,
 						int ndr_flags,
 						const struct dns_res_rec *r)
@@ -302,6 +326,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
 		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
 		_saved_offset1 = ndr->offset;
 		if (r->length > 0) {
+			NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list,
+						  &r->rdata,
+						  r->length));
 			NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->rdata,
 							    r->rr_type));
 			NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_SCALARS,
diff --git a/librpc/ndr/ndr_dnsp.c b/librpc/ndr/ndr_dnsp.c
index 46141c1..3cb96f9 100644
--- a/librpc/ndr/ndr_dnsp.c
+++ b/librpc/ndr/ndr_dnsp.c
@@ -222,3 +222,27 @@ enum ndr_err_code ndr_push_dnsp_string_list(struct ndr_push *ndr, int ndr_flags,
 	}
 	return NDR_ERR_SUCCESS;
 }
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+					    const struct dnsp_string_list *src,
+					    struct dnsp_string_list *dst)
+{
+	size_t i;
+
+	dst->count = 0;
+	dst->str = talloc_zero_array(mem_ctx, const char *, src->count);
+	if (dst->str == NULL) {
+		return NDR_ERR_ALLOC;
+	}
+
+	for (i = 0; i < src->count; i++) {
+		dst->str[i] = talloc_strdup(dst->str, src->str[i]);
+		if (dst->str[i] == NULL) {
+			TALLOC_FREE(dst->str);
+			return NDR_ERR_ALLOC;
+		}
+	}
+
+	dst->count = src->count;
+	return NDR_ERR_SUCCESS;
+}
diff --git a/librpc/ndr/ndr_dnsp.h b/librpc/ndr/ndr_dnsp.h
index 67f952c..0d56633 100644
--- a/librpc/ndr/ndr_dnsp.h
+++ b/librpc/ndr/ndr_dnsp.h
@@ -27,3 +27,7 @@ void ndr_print_dnsp_string(struct ndr_print *ndr, const char *name,
 				  const char *dns_string);
 enum ndr_err_code ndr_pull_dnsp_string(struct ndr_pull *ndr, int ndr_flags, const char **string);
 enum ndr_err_code ndr_push_dnsp_string(struct ndr_push *ndr, int ndr_flags, const char *string);
+
+enum ndr_err_code ndr_dnsp_string_list_copy(TALLOC_CTX *mem_ctx,
+					    const struct dnsp_string_list *src,
+					    struct dnsp_string_list *dst);
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 1594e72..d376bec 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -27,12 +27,12 @@ bld.SAMBA_SUBSYSTEM('NDR_NAMED_PIPE_AUTH',
 
 bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
     source='gen_ndr/ndr_dnsserver.c ndr/ndr_dnsserver.c',
-    public_deps='ndr'
+    public_deps='ndr NDR_DNSP'
     )
 
 bld.SAMBA_SUBSYSTEM('NDR_DNS',
     source='gen_ndr/ndr_dns.c ndr/ndr_dns.c',
-    public_deps='ndr'
+    public_deps='ndr NDR_DNSP'
     )
 
 bld.SAMBA_SUBSYSTEM('NDR_DSBACKUP',
@@ -371,7 +371,7 @@ bld.SAMBA_LIBRARY('ndr-standard',
     pc_files='ndr_standard.pc',
     deps='''NDR_SECURITY NDR_LSA NDR_SAMR NDR_NETLOGON NDR_EVENTLOG NDR_DFS
     NDR_NTSVCS NDR_SVCCTL NDR_INITSHUTDOWN NDR_WKSSVC NDR_SRVSVC NDR_WINREG
-    NDR_ECHO security NDR_DNS NDR_ATSVC NDR_SPOOLSS NDR_DSSETUP
+    NDR_ECHO security NDR_DNS NDR_DNSP NDR_ATSVC NDR_SPOOLSS NDR_DSSETUP
     NDR_SERVER_ID NDR_NOTIFY''',
     public_deps='ndr',
     public_headers='gen_ndr/samr.h gen_ndr/ndr_samr.h gen_ndr/lsa.h gen_ndr/netlogon.h gen_ndr/atsvc.h gen_ndr/ndr_atsvc.h gen_ndr/ndr_svcctl.h gen_ndr/svcctl.h',
@@ -453,11 +453,6 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_AUDIOSRV',
     public_deps='NDR_AUDIOSRV dcerpc-binding'
     )
 
-bld.SAMBA_SUBSYSTEM('RPC_NDR_DNS',
-    source='gen_ndr/ndr_dns_c.c',
-    public_deps='dcerpc-binding NDR_DNS'
-    )
-
 bld.SAMBA_SUBSYSTEM('RPC_NDR_ECHO',
     source='gen_ndr/ndr_echo_c.c',
     public_deps='dcerpc-binding NDR_ECHO'
@@ -640,11 +635,6 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_BACKUPKEY',
     public_deps='dcerpc-binding NDR_BACKUPKEY'
     )
 
-bld.SAMBA_SUBSYSTEM('RPC_NDR_DNSP',
-    source='gen_ndr/ndr_dnsp_c.c',
-    public_deps='dcerpc-binding NDR_DNSP'
-    )
-
 bld.SAMBA_SUBSYSTEM('RPC_NDR_DNSSERVER',
     source='gen_ndr/ndr_dnsserver_c.c',
     public_deps='dcerpc-binding ndr-standard'
@@ -679,7 +669,7 @@ bld.SAMBA_SUBSYSTEM('RPC_NDR_MDSSVC',
 bld.SAMBA_LIBRARY('ndr-samba',
     source=[],
     deps='''NDR_DRSBLOBS NDR_DRSUAPI NDR_IDMAP NDR_NTLMSSP NDR_SCHANNEL NDR_MGMT
-    NDR_DNSP NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM
+    NDR_DNSSERVER NDR_EPMAPPER NDR_XATTR NDR_UNIXINFO NDR_NAMED_PIPE_AUTH NDR_DCOM
     NDR_NTPRINTING NDR_FSRVP NDR_WITNESS NDR_MDSSVC NDR_OPEN_FILES NDR_SMBXSRV''',
     private_library=True,
     grouping_library=True
@@ -691,7 +681,7 @@ bld.SAMBA_LIBRARY('dcerpc-samba',
     deps='''RPC_NDR_LSA RPC_NDR_SAMR RPC_NDR_NETLOGON RPC_NDR_EVENTLOG
     RPC_NDR_DFS RPC_NDR_NTSVCS RPC_NDR_SVCCTL RPC_NDR_INITSHUTDOWN
     RPC_NDR_WKSSVC RPC_NDR_SRVSVC RPC_NDR_WINREG RPC_NDR_ECHO RPC_NDR_EPMAPPER
-    RPC_NDR_ATSVC RPC_NDR_SPOOLSS RPC_NDR_DNS''',
+    RPC_NDR_ATSVC RPC_NDR_SPOOLSS RPC_NDR_DNSSERVER''',
     public_deps='ndr-standard',
     private_library=True,
     grouping_library=True
diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 84b0b1f..aaf335c 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -362,6 +362,30 @@ def dn_from_dns_name(dnsdomain):
 def current_unix_time():
     return int(time.time())
 
+def string_to_byte_array(string):
+    blob = [0] * len(string)
+
+    for i in range(len(string)):
+        blob[i] = ord(string[i])
+
+    return blob
+
+def arcfour_encrypt(key, data):
+    try:
+        from Crypto.Cipher import ARC4
+        c = ARC4.new(key)
+        return c.encrypt(data)
+    except ImportError as e:
+        pass
+    try:
+        from M2Crypto.RC4 import RC4
+        c = RC4(key)
+        return c.update(data)
+    except ImportError as e:
+        pass
+    raise Exception("arcfour_encrypt() requires " +
+                    "python*-crypto or python*-m2crypto or m2crypto")
+
 import _glue
 version = _glue.version
 interface_ips = _glue.interface_ips
diff --git a/python/samba/join.py b/python/samba/join.py
index c356145..f71f3de 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -20,7 +20,7 @@
 
 from samba.auth import system_session
 from samba.samdb import SamDB
-from samba import gensec, Ldb, drs_utils
+from samba import gensec, Ldb, drs_utils, arcfour_encrypt, string_to_byte_array
 import ldb, samba, sys, uuid
 from samba.ndr import ndr_pack
 from samba.dcerpc import security, drsuapi, misc, nbt, lsa, drsblobs
@@ -944,19 +944,6 @@ class dc_join(object):
     def join_setup_trusts(ctx):
         """provision the local SAM."""
 
-        def arcfour_encrypt(key, data):
-            from Crypto.Cipher import ARC4
-            c = ARC4.new(key)
-            return c.encrypt(data)
-
-        def string_to_array(string):
-            blob = [0] * len(string)
-
-            for i in range(len(string)):
-                blob[i] = ord(string[i])
-
-            return blob
-
         print "Setup domain trusts with server %s" % ctx.server
         binding_options = ""  # why doesn't signing work here? w2k8r2 claims no session key
         lsaconn = lsa.lsarpc("ncacn_np:%s[%s]" % (ctx.server, binding_options),
@@ -986,7 +973,7 @@ class dc_join(object):
         except RuntimeError:
             pass
 
-        password_blob = string_to_array(ctx.trustdom_pass.encode('utf-16-le'))
+        password_blob = string_to_byte_array(ctx.trustdom_pass.encode('utf-16-le'))
 
         clear_value = drsblobs.AuthInfoClear()
         clear_value.size = len(password_blob)
@@ -1022,7 +1009,7 @@ class dc_join(object):
 
         auth_blob = lsa.DATA_BUF2()
         auth_blob.size = len(encrypted_trustpass)
-        auth_blob.data = string_to_array(encrypted_trustpass)
+        auth_blob.data = string_to_byte_array(encrypted_trustpass)
 
         auth_info = lsa.TrustDomainInfoAuthInfoInternal()
         auth_info.auth_blob = auth_blob
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index f0710f2..119e8b2 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -58,7 +58,7 @@ from samba.upgrade import upgrade_from_samba3
 from samba.drs_utils import (
                             sendDsReplicaSync, drsuapi_connect, drsException,
                             sendRemoveDsServer)
-
+from samba import arcfour_encrypt, string_to_byte_array
 
 from samba.dsdb import (
     DS_DOMAIN_FUNCTION_2000,
@@ -2125,24 +2125,16 @@ class cmd_domain_trust_create(DomainTrustCommand):
                     password = None
                     self.outf.write("Sorry, passwords do not match.\n")
 
-        def string_to_array(string):
-            blob = [0] * len(string)
-
-            for i in range(len(string)):
-                blob[i] = ord(string[i])
-
-            return blob
-
         incoming_secret = None
         outgoing_secret = None
         remote_policy_access = lsa.LSA_POLICY_VIEW_LOCAL_INFORMATION
         if create_location == "local":
             if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_INBOUND:
                 incoming_password = get_password("Incoming Trust")
-                incoming_secret = string_to_array(incoming_password.encode('utf-16-le'))
+                incoming_secret = string_to_byte_array(incoming_password.encode('utf-16-le'))
             if local_trust_info.trust_direction & lsa.LSA_TRUST_DIRECTION_OUTBOUND:
                 outgoing_password = get_password("Outgoing Trust")
-                outgoing_secret = string_to_array(outgoing_password.encode('utf-16-le'))
+                outgoing_secret = string_to_byte_array(outgoing_password.encode('utf-16-le'))
 
             remote_trust_info = None
         else:
@@ -2167,7 +2159,7 @@ class cmd_domain_trust_create(DomainTrustCommand):
                     #
                     # We can remove this once our client libraries
                     # support using the correct NTHASH.
-                    return string_to_array(pw1.encode('utf-16-le'))
+                    return string_to_byte_array(pw1.encode('utf-16-le'))
 
                 # We mix characters from generate_random_password
                 # with random numbers from random.randint()
@@ -2320,11 +2312,6 @@ class cmd_domain_trust_create(DomainTrustCommand):
             except RuntimeError as error:
                 raise self.RemoteRuntimeError(self, error, "failed to get netlogon dc info")
 
-        def arcfour_encrypt(key, data):
-            from Crypto.Cipher import ARC4
-            c = ARC4.new(key)
-            return c.encrypt(data)
-
         def generate_AuthInOutBlob(secret, update_time):
             if secret is None:
                 blob = drsblobs.trustAuthInOutBlob()
@@ -2368,7 +2355,7 @@ class cmd_domain_trust_create(DomainTrustCommand):
 
             auth_blob = lsa.DATA_BUF2()
             auth_blob.size = len(encrypted_trustpass)
-            auth_blob.data = string_to_array(encrypted_trustpass)
+            auth_blob.data = string_to_byte_array(encrypted_trustpass)
 
             auth_info = lsa.TrustDomainInfoAuthInfoInternal()
             auth_info.auth_blob = auth_blob
diff --git a/python/samba/netcmd/fsmo.py b/python/samba/netcmd/fsmo.py
index 0b4488f..3904bcb 100644
--- a/python/samba/netcmd/fsmo.py
+++ b/python/samba/netcmd/fsmo.py
@@ -38,7 +38,8 @@ def get_fsmo_roleowner(samdb, roledn):
     """
     res = samdb.search(roledn,
                        scope=ldb.SCOPE_BASE, attrs=["fSMORoleOwner"])
-    assert len(res) == 1
+    if len(res) == 0:
+        raise CommandError('"%s" does not have a FSMO roleowner' % roledn)
     master_owner = res[0]["fSMORoleOwner"][0]
     return master_owner
 
diff --git a/python/samba/tests/core.py b/python/samba/tests/core.py
index 8206e68..9dbaff1 100644
--- a/python/samba/tests/core.py
+++ b/python/samba/tests/core.py
@@ -20,6 +20,7 @@
 import ldb
 import os
 import samba
+from samba import arcfour_encrypt, string_to_byte_array
 from samba.tests import TestCase, TestCaseInTempDir
 
 class SubstituteVarTestCase(TestCase):
@@ -48,6 +49,21 @@ class SubstituteVarTestCase(TestCase):
         self.assertRaises(Exception, samba.check_all_substituted,
                 "Not subsituted: ${FOOBAR}")
 
+class ArcfourTestCase(TestCase):
+
+    def test_arcfour_direct(self):
+        key = '12345678'
+        plain = 'abcdefghi'
+        crypt_expected = '\xda\x91Z\xb0l\xd7\xb9\xcf\x99'
+        crypt_calculated = arcfour_encrypt(key, plain)
+        self.assertEquals(crypt_expected, crypt_calculated)
+
+class StringToByteArrayTestCase(TestCase):
+
+    def test_byte_array(self):
+        expected = [218, 145, 90, 176, 108, 215, 185, 207, 153]
+        calculated = string_to_byte_array('\xda\x91Z\xb0l\xd7\xb9\xcf\x99')
+        self.assertEquals(expected, calculated)
 
 class LdbExtensionTests(TestCaseInTempDir):
 
diff --git a/python/samba/tests/dns.py b/python/samba/tests/dns.py
index 04ac356..e0739d0 100644
--- a/python/samba/tests/dns.py
+++ b/python/samba/tests/dns.py
@@ -16,18 +16,67 @@
 #
 
 import os
+import sys
 import struct
 import random
 import socket
 import samba.ndr as ndr
-import samba.dcerpc.dns as dns
 from samba import credentials, param
 from samba.tests import TestCase
-from samba.dcerpc import dnsp, dnsserver
-
+from samba.dcerpc import dns, dnsp, dnsserver
+from samba.netcmd.dns import TXTRecord, dns_record_match, data_to_dns_record
+from samba.tests.subunitrun import SubunitOptions, TestProgram
+import samba.getopt as options
+import optparse
+
+parser = optparse.OptionParser("dns.py <server name> <server ip> [options]")
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+
+# This timeout only has relevance when testing against Windows
+# Format errors tend to return patchy responses, so a timeout is needed.
+parser.add_option("--timeout", type="int", dest="timeout",
+                  help="Specify timeout for DNS requests")
+
+# use command line creds if available
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+subunitopts = SubunitOptions(parser)
+parser.add_option_group(subunitopts)
+
+opts, args = parser.parse_args()
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+timeout = opts.timeout
+
+if len(args) < 2:
+    parser.print_usage()
+    sys.exit(1)
+
+server_name = args[0]
+server_ip = args[1]
+creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE)
+
+def make_txt_record(records):
+    rdata_txt = dns.txt_record()
+    s_list = dnsp.string_list()
+    s_list.count = len(records)
+    s_list.str = records
+    rdata_txt.txt = s_list
+    return rdata_txt
 
 class DNSTest(TestCase):
 
+    def setUp(self):
+        global server, server_ip, lp, creds
+        super(DNSTest, self).setUp()
+        self.server = server_name
+        self.server_ip = server_ip
+        self.lp = lp
+        self.creds = creds
+
     def errstr(self, errcode):
         "Return a readable error code"
         string_codes = [
@@ -83,9 +132,10 @@ class DNSTest(TestCase):
 
     def get_dns_domain(self):
         "Helper to get dns domain"
-        return os.getenv('REALM', 'example.com').lower()
+        return self.creds.get_realm().lower()
 
-    def dns_transaction_udp(self, packet, host=os.getenv('SERVER_IP'), dump=False):
+    def dns_transaction_udp(self, packet, host=server_ip,
+                            dump=False, timeout=timeout):
         "send a DNS query and read the reply"
         s = None
         try:
@@ -93,6 +143,7 @@ class DNSTest(TestCase):
             if dump:
                 print self.hexdump(send_packet)
             s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
+            s.settimeout(timeout)
             s.connect((host, 53))
             s.send(send_packet, 0)
             recv_packet = s.recv(2048, 0)
@@ -103,7 +154,8 @@ class DNSTest(TestCase):
             if s is not None:
                 s.close()
 
-    def dns_transaction_tcp(self, packet, host=os.getenv('SERVER_IP'), dump=False):
+    def dns_transaction_tcp(self, packet, host=server_ip,
+                            dump=False, timeout=timeout):
         "send a DNS query and read the reply"
         s = None
         try:
@@ -111,6 +163,7 @@ class DNSTest(TestCase):
             if dump:
                 print self.hexdump(send_packet)
             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+            s.settimeout(timeout)
             s.connect((host, 53))
             tcp_packet = struct.pack('!H', len(send_packet))
             tcp_packet += send_packet
@@ -123,6 +176,44 @@ class DNSTest(TestCase):
                 if s is not None:
                     s.close()
 
+    def make_txt_update(self, prefix, txt_array):
+        p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
+        updates = []
+
+        name = self.get_dns_domain()
+        u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
+        updates.append(u)
+        self.finish_name_packet(p, updates)
+
+        updates = []
+        r = dns.res_rec()
+        r.name = "%s.%s" % (prefix, self.get_dns_domain())
+        r.rr_type = dns.DNS_QTYPE_TXT
+        r.rr_class = dns.DNS_QCLASS_IN
+        r.ttl = 900
+        r.length = 0xffff
+        rdata = make_txt_record(txt_array)
+        r.rdata = rdata
+        updates.append(r)
+        p.nscount = len(updates)
+        p.nsrecs = updates
+
+        return p
+
+    def check_query_txt(self, prefix, txt_array):
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
+        questions = []
+
+        q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
+        questions.append(q)
+
+        self.finish_name_packet(p, questions)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.assertEquals(response.ancount, 1)
+        self.assertEquals(response.answers[0].rdata.txt.str, txt_array)
+
 class TestSimpleQueries(DNSTest):
 
     def test_one_a_query(self):
@@ -130,7 +221,7 @@ class TestSimpleQueries(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -141,14 +232,14 @@ class TestSimpleQueries(DNSTest):
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, 1)
         self.assertEquals(response.answers[0].rdata,
-                          os.getenv('SERVER_IP'))
+                          self.server_ip)
 
     def test_one_a_query_tcp(self):
         "create a query packet containing one query record via TCP"
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -159,14 +250,14 @@ class TestSimpleQueries(DNSTest):
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, 1)
         self.assertEquals(response.answers[0].rdata,
-                          os.getenv('SERVER_IP'))
+                          self.server_ip)
 
     def test_one_mx_query(self):
         "create a query packet causing an empty RCODE_OK answer"
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_MX, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -180,7 +271,7 @@ class TestSimpleQueries(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "invalid-%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "invalid-%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_MX, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -196,7 +287,7 @@ class TestSimpleQueries(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
         questions.append(q)
 
@@ -205,15 +296,22 @@ class TestSimpleQueries(DNSTest):
         questions.append(q)
 
         self.finish_name_packet(p, questions)
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+        try:
+            response = self.dns_transaction_udp(p)
+            self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+        except socket.timeout:
+            # Windows chooses not to respond to incorrectly formatted queries.
+            # Although this appears to be non-deterministic even for the same
+            # request twice, it also appears to be based on a how poorly the
+            # request is formatted.
+            pass
 
     def test_qtype_all_query(self):
         "create a QTYPE_ALL query"
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_ALL, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -230,7 +328,7 @@ class TestSimpleQueries(DNSTest):
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, num_answers)
         self.assertEquals(response.answers[0].rdata,
-                          os.getenv('SERVER_IP'))
+                          self.server_ip)
         if dc_ipv6 is not None:
             self.assertEquals(response.answers[1].rdata, dc_ipv6)
 
@@ -239,13 +337,20 @@ class TestSimpleQueries(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_ALL, dns.DNS_QCLASS_NONE)
         questions.append(q)
 
         self.finish_name_packet(p, questions)
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTIMP)
+        try:
+            response = self.dns_transaction_udp(p)
+            self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTIMP)
+        except socket.timeout:
+            # Windows chooses not to respond to incorrectly formatted queries.
+            # Although this appears to be non-deterministic even for the same
+            # request twice, it also appears to be based on a how poorly the
+            # request is formatted.
+            pass
 
 # Only returns an authority section entry in BIND and Win DNS
 # FIXME: Enable one Samba implements this feature
@@ -289,7 +394,7 @@ class TestDNSUpdates(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
         updates = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         u = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
         updates.append(u)
 
@@ -298,8 +403,15 @@ class TestDNSUpdates(DNSTest):
         updates.append(u)
 
         self.finish_name_packet(p, updates)
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+        try:
+            response = self.dns_transaction_udp(p)
+            self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+        except socket.timeout:
+            # Windows chooses not to respond to incorrectly formatted queries.
+            # Although this appears to be non-deterministic even for the same
+            # request twice, it also appears to be based on a how poorly the
+            # request is formatted.
+            pass
 
     def test_update_wrong_qclass(self):
         "create update with DNS_QCLASS_NONE"
@@ -327,7 +439,7 @@ class TestDNSUpdates(DNSTest):
 
         prereqs = []
         r = dns.res_rec()
-        r.name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        r.name = "%s.%s" % (self.server, self.get_dns_domain())
         r.rr_type = dns.DNS_QTYPE_TXT
         r.rr_class = dns.DNS_QCLASS_NONE
         r.ttl = 1
@@ -337,38 +449,18 @@ class TestDNSUpdates(DNSTest):
         p.ancount = len(prereqs)
         p.answers = prereqs
 
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
-
-# I'd love to test this one, but it segfaults. :)
-#    def test_update_prereq_with_non_null_length(self):
-#        "test update with a non-null length"
-#        p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
-#        updates = []
-#
-#        name = self.get_dns_domain()
-#
-#        u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
-#        updates.append(u)
-#        self.finish_name_packet(p, updates)
-#
-#        prereqs = []
-#        r = dns.res_rec()
-#        r.name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
-#        r.rr_type = dns.DNS_QTYPE_TXT
-#        r.rr_class = dns.DNS_QCLASS_ANY
-#        r.ttl = 0
-#        r.length = 1
-#        prereqs.append(r)
-#
-#        p.ancount = len(prereqs)
-#        p.answers = prereqs
-#
-#        response = self.dns_transaction_udp(p)
-#        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
-
-    def test_update_prereq_nonexisting_name(self):
-        "test update with a nonexisting name"
+        try:
+            response = self.dns_transaction_udp(p)
+            self.assert_dns_rcode_equals(response, dns.DNS_RCODE_FORMERR)
+        except socket.timeout:
+            # Windows chooses not to respond to incorrectly formatted queries.
+            # Although this appears to be non-deterministic even for the same
+            # request twice, it also appears to be based on a how poorly the
+            # request is formatted.
+            pass
+
+    def test_update_prereq_with_non_null_length(self):
+        "test update with a non-null length"
         p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
         updates = []
 
@@ -380,11 +472,11 @@ class TestDNSUpdates(DNSTest):
 
         prereqs = []
         r = dns.res_rec()
-        r.name = "idontexist.%s" % self.get_dns_domain()
+        r.name = "%s.%s" % (self.server, self.get_dns_domain())
         r.rr_type = dns.DNS_QTYPE_TXT
         r.rr_class = dns.DNS_QCLASS_ANY
         r.ttl = 0
-        r.length = 0
+        r.length = 1
         prereqs.append(r)
 
         p.ancount = len(prereqs)
@@ -393,8 +485,8 @@ class TestDNSUpdates(DNSTest):
         response = self.dns_transaction_udp(p)
         self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXRRSET)
 
-    def test_update_add_txt_record(self):
-        "test adding records works"
+    def test_update_prereq_nonexisting_name(self):
+        "test update with a nonexisting name"
         p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
         updates = []
 
@@ -404,76 +496,28 @@ class TestDNSUpdates(DNSTest):
         updates.append(u)
         self.finish_name_packet(p, updates)
 
-        updates = []
+        prereqs = []
         r = dns.res_rec()
-        r.name = "textrec.%s" % self.get_dns_domain()
+        r.name = "idontexist.%s" % self.get_dns_domain()
         r.rr_type = dns.DNS_QTYPE_TXT
-        r.rr_class = dns.DNS_QCLASS_IN
-        r.ttl = 900
-        r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
-        r.rdata = rdata
-        updates.append(r)
-        p.nscount = len(updates)
-        p.nsrecs = updates
-
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-
-        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
-        questions = []
-
-        name = "textrec.%s" % self.get_dns_domain()
-        q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
-        questions.append(q)
-
-        self.finish_name_packet(p, questions)
-        response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-        self.assertEquals(response.ancount, 1)
-        self.assertEquals(response.answers[0].rdata.txt, '"This is a test"')
-
-    def test_update_add_two_txt_records(self):
-        "test adding two txt records works"
-        p = self.make_name_packet(dns.DNS_OPCODE_UPDATE)
-        updates = []
-
-        name = self.get_dns_domain()
-
-        u = self.make_name_question(name, dns.DNS_QTYPE_SOA, dns.DNS_QCLASS_IN)
-        updates.append(u)
-        self.finish_name_packet(p, updates)
+        r.rr_class = dns.DNS_QCLASS_ANY
+        r.ttl = 0
+        r.length = 0
+        prereqs.append(r)
 
-        updates = []
-        r = dns.res_rec()
-        r.name = "textrec2.%s" % self.get_dns_domain()
-        r.rr_type = dns.DNS_QTYPE_TXT
-        r.rr_class = dns.DNS_QCLASS_IN
-        r.ttl = 900
-        r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test" "and this is a test, too"'
-        r.rdata = rdata
-        updates.append(r)
-        p.nscount = len(updates)
-        p.nsrecs = updates
+        p.ancount = len(prereqs)
+        p.answers = prereqs
 
         response = self.dns_transaction_udp(p)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-
-        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
-        questions = []
-
-        name = "textrec2.%s" % self.get_dns_domain()
-        q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
-        questions.append(q)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXRRSET)
 
-        self.finish_name_packet(p, questions)
+    def test_update_add_txt_record(self):
+        "test adding records works"
+        prefix, txt = 'textrec', ['"This is a test"']
+        p = self.make_txt_update(prefix, txt)
         response = self.dns_transaction_udp(p)
         self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
-        self.assertEquals(response.ancount, 1)
-        self.assertEquals(response.answers[0].rdata.txt, '"This is a test" "and this is a test, too"')
+        self.check_query_txt(prefix, txt)
 
     def test_delete_record(self):
         "Test if deleting records works"
@@ -497,8 +541,7 @@ class TestDNSUpdates(DNSTest):
         r.rr_class = dns.DNS_QCLASS_IN
         r.ttl = 900
         r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
+        rdata = make_txt_record(['"This is a test"'])
         r.rdata = rdata
         updates.append(r)
         p.nscount = len(updates)
@@ -534,8 +577,7 @@ class TestDNSUpdates(DNSTest):
         r.rr_class = dns.DNS_QCLASS_NONE
         r.ttl = 0
         r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
+        rdata = make_txt_record(['"This is a test"'])
         r.rdata = rdata
         updates.append(r)
         p.nscount = len(updates)
@@ -577,8 +619,7 @@ class TestDNSUpdates(DNSTest):
         r.rr_class = dns.DNS_QCLASS_IN
         r.ttl = 900
         r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
+        rdata = make_txt_record(['"This is a test"'])
         r.rdata = rdata
         updates.append(r)
         p.nscount = len(updates)
@@ -614,8 +655,7 @@ class TestDNSUpdates(DNSTest):
         r.rr_class = dns.DNS_QCLASS_NONE
         r.ttl = 0
         r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
+        rdata = make_txt_record(['"This is a test"'])
         r.rdata = rdata
         updates.append(r)
         p.nscount = len(updates)
@@ -652,8 +692,7 @@ class TestDNSUpdates(DNSTest):
         r.rr_class = dns.DNS_QCLASS_IN
         r.ttl = 900
         r.length = 0xffff
-        rdata = dns.txt_record()
-        rdata.txt = '"This is a test"'
+        rdata = make_txt_record(['"This is a test"'])
         r.rdata = rdata
         updates.append(r)
         p.nscount = len(updates)
@@ -738,7 +777,7 @@ class TestComplexQueries(DNSTest):
         r.rr_class = dns.DNS_QCLASS_IN
         r.ttl = 900
         r.length = 0xffff
-        r.rdata = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        r.rdata = "%s.%s" % (self.server, self.get_dns_domain())
         updates.append(r)
         p.nscount = len(updates)
         p.nsrecs = updates
@@ -764,7 +803,7 @@ class TestComplexQueries(DNSTest):
         r.rr_class = dns.DNS_QCLASS_NONE
         r.ttl = 0
         r.length = 0xffff
-        r.rdata = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        r.rdata = "%s.%s" % (self.server, self.get_dns_domain())
         updates.append(r)
         p.nscount = len(updates)
         p.nsrecs = updates
@@ -789,10 +828,10 @@ class TestComplexQueries(DNSTest):
         self.assertEquals(response.ancount, 2)
         self.assertEquals(response.answers[0].rr_type, dns.DNS_QTYPE_CNAME)
         self.assertEquals(response.answers[0].rdata, "%s.%s" %
-                          (os.getenv('SERVER'), self.get_dns_domain()))
+                          (self.server, self.get_dns_domain()))
         self.assertEquals(response.answers[1].rr_type, dns.DNS_QTYPE_A)
         self.assertEquals(response.answers[1].rdata,
-                          os.getenv('SERVER_IP'))
+                          self.server_ip)
 
 class TestInvalidQueries(DNSTest):
 
@@ -802,7 +841,7 @@ class TestInvalidQueries(DNSTest):
         s = None
         try:
             s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
-            s.connect((os.getenv('SERVER_IP'), 53))
+            s.connect((self.server_ip, 53))
             s.send("", 0)
         finally:
             if s is not None:
@@ -811,7 +850,7 @@ class TestInvalidQueries(DNSTest):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
 
-        name = "%s.%s" % (os.getenv('SERVER'), self.get_dns_domain())
+        name = "%s.%s" % (self.server, self.get_dns_domain())
         q = self.make_name_question(name, dns.DNS_QTYPE_A, dns.DNS_QCLASS_IN)
         print "asking for ", q.name
         questions.append(q)
@@ -822,10 +861,11 @@ class TestInvalidQueries(DNSTest):
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, 1)
         self.assertEquals(response.answers[0].rdata,
-                          os.getenv('SERVER_IP'))
+                          self.server_ip)
 
     def test_one_a_reply(self):
         "send a reply instead of a query"
+        global timeout
 
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
         questions = []
@@ -841,37 +881,29 @@ class TestInvalidQueries(DNSTest):
         try:
             send_packet = ndr.ndr_pack(p)
             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-            host=os.getenv('SERVER_IP')
+            s.settimeout(timeout)
+            host=self.server_ip
             s.connect((host, 53))
             tcp_packet = struct.pack('!H', len(send_packet))
             tcp_packet += send_packet
             s.send(tcp_packet, 0)
             recv_packet = s.recv(0xffff + 2, 0)
             self.assertEquals(0, len(recv_packet))
+        except socket.timeout:
+            # Windows chooses not to respond to incorrectly formatted queries.
+            # Although this appears to be non-deterministic even for the same
+            # request twice, it also appears to be based on a how poorly the
+            # request is formatted.
+            pass
         finally:
             if s is not None:
                 s.close()
 
 class TestZones(DNSTest):
-    def get_loadparm(self):
-        lp = param.LoadParm()
-        lp.load(os.getenv("SMB_CONF_PATH"))
-        return lp
-
-    def get_credentials(self, lp):
-        creds = credentials.Credentials()
-        creds.guess(lp)
-        creds.set_machine_account(lp)
-        creds.set_krb_forwardable(credentials.NO_KRB_FORWARDABLE)
-        return creds
-
     def setUp(self):
         super(TestZones, self).setUp()
-        self.lp = self.get_loadparm()
-        self.creds = self.get_credentials(self.lp)
-        self.server = os.getenv("SERVER_IP")
         self.zone = "test.lan"
-        self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s" % (self.server),
+        self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server_ip),
                                             self.lp, self.creds)
 
     def tearDown(self):
@@ -891,7 +923,7 @@ class TestZones(DNSTest):
         zone_create.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
         self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                        0,
-                                       self.server,
+                                       self.server_ip,
                                        None,
                                        0,
                                        'ZoneCreate',
@@ -901,7 +933,7 @@ class TestZones(DNSTest):
     def delete_zone(self, zone):
         self.rpc_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                        0,
-                                       self.server,
+                                       self.server_ip,
                                        zone,
                                        0,
                                        'DeleteZoneFromDs',
@@ -918,6 +950,7 @@ class TestZones(DNSTest):
         self.finish_name_packet(p, questions)
 
         response = self.dns_transaction_udp(p)
+        # Windows returns OK while BIND logically seems to return NXDOMAIN
         self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NXDOMAIN)
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, 0)
@@ -935,8 +968,293 @@ class TestZones(DNSTest):
         self.assert_dns_opcode_equals(response, dns.DNS_OPCODE_QUERY)
         self.assertEquals(response.ancount, 0)
 
+class TestRPCRoundtrip(DNSTest):
+    def setUp(self):
+        super(TestRPCRoundtrip, self).setUp()
+        self.rpc_conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server_ip),
+                                            self.lp, self.creds)
+
+    def tearDown(self):
+        super(TestRPCRoundtrip, self).tearDown()
+
+    def test_update_add_txt_rpc_to_dns(self):
+        prefix, txt = 'rpctextrec', ['"This is a test"']
+
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\""')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    def test_update_add_null_padded_txt_record(self):
+        "test adding records works"
+        prefix, txt = 'pad1textrec', ['"This is a test"', '', '']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" ""'))
+
+        prefix, txt = 'pad2textrec', ['"This is a test"', '', '', 'more text']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" "" "more text"'))
+
+        prefix, txt = 'pad3textrec', ['', '', '"This is a test"']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"" "" "\\"This is a test\\""'))
+
+    def test_update_add_padding_rpc_to_dns(self):
+        prefix, txt = 'pad1textrec', ['"This is a test"', '', '']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" ""')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+        prefix, txt = 'pad2textrec', ['"This is a test"', '', '', 'more text']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
 
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"\\"This is a test\\"" "" "" "more text"')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+        prefix, txt = 'pad3textrec', ['', '', '"This is a test"']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"" "" "\\"This is a test\\""')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    # Test is incomplete due to strlen against txt records
+    def test_update_add_null_char_txt_record(self):
+        "test adding records works"
+        prefix, txt = 'nulltextrec', ['NULL\x00BYTE']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, ['NULL'])
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"NULL"'))
+
+        prefix, txt = 'nulltextrec2', ['NULL\x00BYTE', 'NULL\x00BYTE']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, ['NULL', 'NULL'])
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"NULL" "NULL"'))
+
+    def test_update_add_null_char_rpc_to_dns(self):
+        prefix, txt = 'nulltextrec', ['NULL\x00BYTE']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"NULL"')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, ['NULL'])
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    def test_update_add_hex_char_txt_record(self):
+        "test adding records works"
+        prefix, txt = 'hextextrec', ['HIGH\xFFBYTE']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"HIGH\xFFBYTE"'))
+
+    def test_update_add_hex_rpc_to_dns(self):
+        prefix, txt = 'hextextrec', ['HIGH\xFFBYTE']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"HIGH\xFFBYTE"')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    def test_update_add_slash_txt_record(self):
+        "test adding records works"
+        prefix, txt = 'slashtextrec', ['Th\\=is=is a test']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"Th\\\\=is=is a test"'))
+
+    # This test fails against Windows as it eliminates slashes in RPC
+    # One typical use for a slash is in records like 'var=value' to
+    # escape '=' characters.
+    def test_update_add_slash_rpc_to_dns(self):
+        prefix, txt = 'slashtextrec', ['Th\\=is=is a test']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '"Th\\\\=is=is a test"')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    def test_update_add_two_txt_records(self):
+        "test adding two txt records works"
+        prefix, txt = 'textrec2', ['"This is a test"',
+                                   '"and this is a test, too"']
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, '"\\"This is a test\\""' +
+                             ' "\\"and this is a test, too\\""'))
+
+    def test_update_add_two_rpc_to_dns(self):
+        prefix, txt = 'textrec2', ['"This is a test"',
+                                   '"and this is a test, too"']
+        prefix = 'rpc' + prefix
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT,
+                                '"\\"This is a test\\""' +
+                                ' "\\"and this is a test, too\\""')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
+
+    def test_update_add_empty_txt_records(self):
+        "test adding two txt records works"
+        prefix, txt = 'emptytextrec', []
+        p = self.make_txt_update(prefix, txt)
+        response = self.dns_transaction_udp(p)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.check_query_txt(prefix, txt)
+        self.assertIsNotNone(dns_record_match(self.rpc_conn, self.server_ip,
+                             self.get_dns_domain(),
+                             "%s.%s" % (prefix, self.get_dns_domain()),
+                             dnsp.DNS_TYPE_TXT, ''))
+
+    def test_update_add_empty_rpc_to_dns(self):
+        prefix, txt = 'rpcemptytextrec', []
+
+        name = "%s.%s" % (prefix, self.get_dns_domain())
+
+        rec = data_to_dns_record(dnsp.DNS_TYPE_TXT, '')
+        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+        add_rec_buf.rec = rec
+        try:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                     0, self.server_ip, self.get_dns_domain(),
+                                     name, add_rec_buf, None)
+
+            self.check_query_txt(prefix, txt)
+        finally:
+            self.rpc_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                              0, self.server_ip, self.get_dns_domain(),
+                                              name, None, add_rec_buf)
 
-if __name__ == "__main__":
-    import unittest
-    unittest.main()
+TestProgram(module=__name__, opts=subunitopts)
diff --git a/python/samba/tests/getopt.py b/python/samba/tests/get_opt.py
similarity index 100%
rename from python/samba/tests/getopt.py
rename to python/samba/tests/get_opt.py
diff --git a/selftest/knownfail b/selftest/knownfail
index 0d74933..d9e2823 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -16,6 +16,8 @@
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).UID-REGRESSION-TEST # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).SHORTNAME-TEST # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-APPEND # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-ACL # Fails against the s4 ntvfs server
+^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).POSIX-SYMLINK-EA # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).NTTRANS-FSCTL # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).SMB2-NEGPROT # Fails against the s4 ntvfs server
 ^samba3.smbtorture_s3.plain\(ad_dc_ntvfs\).BAD-NBT-SESSION # Fails against the s4 ntvfs server
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 931667e..d16c440 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -590,6 +590,8 @@ sub setup_fileserver($$)
 
 	my $dfree_share_dir="$share_dir/dfree";
 	push(@dirs, $dfree_share_dir);
+	push(@dirs, "$dfree_share_dir/subdir1");
+	push(@dirs, "$dfree_share_dir/subdir2");
 
 	my $fileserver_options = "
 [lowercase]
@@ -1092,6 +1094,15 @@ sub provision($$$$$$$$)
 	my $manglenames_shrdir="$shrdir/manglenames";
 	push(@dirs,$manglenames_shrdir);
 
+	my $shadow_tstdir="$shrdir/shadow";
+	push(@dirs,$shadow_tstdir);
+	my $shadow_mntdir="$shadow_tstdir/mount";
+	push(@dirs,$shadow_mntdir);
+	my $shadow_basedir="$shadow_mntdir/base";
+	push(@dirs,$shadow_basedir);
+	my $shadow_shrdir="$shadow_basedir/share";
+	push(@dirs,$shadow_shrdir);
+
 	# this gets autocreated by winbindd
 	my $wbsockdir="$prefix_abs/winbindd";
 	my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1336,6 +1347,10 @@ sub provision($$$$$$$$)
 	# fruit:copyfile is a global option
 	fruit:copyfile = yes
 
+	#this does not mean that we use non-secure test env,
+	#it just means we ALLOW one to be configured.
+	allow insecure wide links = yes
+
 	# Begin extra options
 	$extra_options
 	# End extra options
@@ -1492,6 +1507,62 @@ sub provision($$$$$$$$)
 	shell_snap:delete command = $fake_snap_pl --delete
 	# a relative path here fails, the snapshot dir is no longer found
 	shadow:snapdir = $shrdir/.snapshots
+
+[shadow1]
+	path = $shadow_shrdir
+	comment = previous versions snapshots under mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+
+[shadow2]
+	path = $shadow_shrdir
+	comment = previous versions snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow3]
+	path = $shadow_shrdir
+	comment = previous versions with subvolume snapshots, snapshots under base dir
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:basedir = $shadow_basedir
+	shadow:snapdir = $shadow_basedir/.snapshots
+
+[shadow4]
+	path = $shadow_shrdir
+	comment = previous versions with subvolume snapshots, snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:basedir = $shadow_basedir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow5]
+	path = $shadow_shrdir
+	comment = previous versions at volume root snapshots under mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_shrdir
+
+[shadow6]
+	path = $shadow_shrdir
+	comment = previous versions at volume root snapshots outside mount point
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_shrdir
+	shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow7]
+	path = $shadow_shrdir
+	comment = previous versions snapshots everywhere
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	shadow:snapdirseverywhere = yes
+
+[shadow_wl]
+	path = $shadow_shrdir
+	comment = previous versions with wide links allowed
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $shadow_mntdir
+	wide links = yes
 	";
 	close(CONF);
 
diff --git a/selftest/tests.py b/selftest/tests.py
index 872fbaf..2a07f9e 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -48,7 +48,7 @@ planpythontestsuite("none", "api", name="ldb.python", extra_path=['lib/ldb/tests
 planpythontestsuite("none", "samba.tests.credentials")
 planpythontestsuite("none", "samba.tests.registry")
 planpythontestsuite("none", "samba.tests.auth")
-planpythontestsuite("none", "samba.tests.getopt")
+planpythontestsuite("none", "samba.tests.get_opt")
 planpythontestsuite("none", "samba.tests.security")
 planpythontestsuite("none", "samba.tests.dcerpc.misc")
 planpythontestsuite("none", "samba.tests.dcerpc.integer")
diff --git a/source3/client/README.smbspool b/source3/client/README.smbspool
new file mode 100644
index 0000000..f73167a
--- /dev/null
+++ b/source3/client/README.smbspool
@@ -0,0 +1,17 @@
+smbspool
+=========
+
+smbspool is a very small print spooling program that sends a print file to an
+SMB printer. The command-line arguments are position-dependent for
+compatibility with the CUPS.
+
+For printing support with Kerberos, CUPS 1.5+ needs a wrapper for the backend
+which sets the correct location of the Kerberos credential cache.
+
+smbspool_krb5_wrapper
+======================
+
+This tool can be used to print using Kerberos credentials. To get this working
+smbspool_krb5_wrapper needs to be the smb backend of CUPS. It needs to be owned
+by root and the permissions for the binary need to be 0700. Once
+smbspool_krb5_wrapper switched to the user trying to print it executes smbspool.
diff --git a/source3/client/client.c b/source3/client/client.c
index 034b48a..831b9bc 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -312,7 +312,7 @@ static int do_dskattr(void)
 		return 1;
 	}
 
-	status = cli_disk_size(targetcli, &bsize, &total, &avail);
+	status = cli_disk_size(targetcli, targetpath, &bsize, &total, &avail);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("Error in dskattr: %s\n", nt_errstr(status));
 		return 1;
@@ -3376,7 +3376,7 @@ static int cmd_getfacl(void)
 		return 1;
 	}
 
-	status = cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf);
+	status = cli_posix_getacl(targetcli, targetname, ctx, &rb_size, &retbuf);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("%s getfacl file %s\n",
 			 nt_errstr(status), src);
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
new file mode 100644
index 0000000..e19fd92
--- /dev/null
+++ b/source3/client/smbspool_krb5_wrapper.c
@@ -0,0 +1,210 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * CUPS printing backend helper to execute smbspool
+ *
+ * Copyright (C) 2010-2011 Andreas Schneider <asn at samba.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "system/passwd.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <cups/backend.h>
+
+#include "dynconfig/dynconfig.h"
+
+enum cups_smb_dbglvl_e {
+	CUPS_SMB_LOG_DEBUG = 0,
+	CUPS_SMB_LOG_ERROR,
+};
+static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...);
+
+#define CUPS_SMB_DEBUG(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
+#define CUPS_SMB_ERROR(...) cups_smb_debug(CUPS_SMB_LOG_DEBUG, __VA_ARGS__)
+
+static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...)
+{
+	const char *prefix = "DEBUG";
+	char buffer[1024];
+	va_list va;
+
+	va_start(va, format);
+	vsnprintf(buffer, sizeof(buffer), format, va);
+	va_end(va);
+
+	switch (lvl) {
+	case CUPS_SMB_LOG_DEBUG:
+		prefix = "DEBUG";
+		break;
+	case CUPS_SMB_LOG_ERROR:
+		prefix = "ERROR";
+		break;
+	}
+
+	fprintf(stderr,
+		"%s: SMBSPOOL_KRB5 - %s\n",
+		prefix,
+		buffer);
+}
+
+/*
+ * This is a helper binary to execute smbspool.
+ *
+ * It needs to be installed or symlinked as:
+ *      /usr/lib/cups/backend/smb
+ *
+ * The permissions of the binary need to be set to 0700 so that it is executed
+ * as root. The binary switches to the user which is passed via the environment
+ * variable AUTH_UID, so we can access the kerberos ticket.
+ */
+int main(int argc, char *argv[])
+{
+	char smbspool_cmd[PATH_MAX] = {0};
+	struct passwd *pwd;
+	char gen_cc[PATH_MAX] = {0};
+	struct stat sb;
+	char *env;
+	uid_t uid = (uid_t)-1;
+	gid_t gid = (gid_t)-1;
+	unsigned long tmp;
+	int cmp;
+	int rc;
+
+	uid = getuid();
+
+	CUPS_SMB_DEBUG("Started with uid=%d\n", uid);
+	if (uid != 0) {
+		goto smbspool;
+	}
+
+	/* Check if AuthInfoRequired is set to negotiate */
+	env = getenv("AUTH_INFO_REQUIRED");
+	if (env == NULL) {
+		CUPS_SMB_ERROR("AUTH_INFO_REQUIRED is not set");
+		fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+		return CUPS_BACKEND_AUTH_REQUIRED;
+	}
+
+	CUPS_SMB_DEBUG("AUTH_INFO_REQUIRED=%s", env);
+	cmp = strcmp(env, "negotiate");
+	if (cmp != 0) {
+		CUPS_SMB_ERROR("AUTH_INFO_REQUIRED is not set to negotiate");
+		fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+		return CUPS_BACKEND_AUTH_REQUIRED;
+	}
+
+	/*
+	 * AUTH_UID gets only set if we have an incoming connection over the
+	 * CUPS unix domain socket.
+	 */
+	env = getenv("AUTH_UID");
+	if (env == NULL) {
+		CUPS_SMB_ERROR("AUTH_UID is not set");
+		fprintf(stderr, "ATTR: auth-info-required=negotiate\n");
+		return CUPS_BACKEND_AUTH_REQUIRED;
+	}
+
+	if (strlen(env) > 10) {
+		CUPS_SMB_ERROR("Invalid AUTH_UID");
+		return CUPS_BACKEND_FAILED;
+	}
+
+	errno = 0;
+	tmp = strtoul(env, NULL, 10);
+	if (errno != 0 || tmp >= UINT32_MAX) {
+		CUPS_SMB_ERROR("Failed to convert AUTH_UID=%s", env);
+		return CUPS_BACKEND_FAILED;
+	}
+	uid = (uid_t)tmp;
+
+	pwd = getpwuid(uid);
+	if (pwd == NULL) {
+		CUPS_SMB_ERROR("Failed to find system user: %u - %s",
+			       uid, strerror(errno));
+		return CUPS_BACKEND_FAILED;
+	}
+	gid = pwd->pw_gid;
+
+	rc = setgroups(0, NULL);
+	if (rc != 0) {
+		CUPS_SMB_ERROR("Failed to clear groups - %s",
+			       strerror(errno));
+		return CUPS_BACKEND_FAILED;
+	}
+
+	CUPS_SMB_DEBUG("Switching to gid=%d", gid);
+	rc = setgid(gid);
+	if (rc != 0) {
+		CUPS_SMB_ERROR("Failed to switch to gid=%u",
+			       gid,
+			       strerror(errno));
+		return CUPS_BACKEND_FAILED;
+	}
+
+	CUPS_SMB_DEBUG("Switching to uid=%u", uid);
+	rc = setuid(uid);
+	if (rc != 0) {
+		CUPS_SMB_ERROR("Failed to switch to uid=%u",
+			       uid,
+			       strerror(errno));
+		return CUPS_BACKEND_FAILED;
+	}
+
+	snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid);
+
+	rc = lstat(gen_cc, &sb);
+	if (rc == 0) {
+		snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%d", uid);
+	} else {
+		snprintf(gen_cc, sizeof(gen_cc), "/run/user/%d/krb5cc", uid);
+
+		rc = lstat(gen_cc, &sb);
+		if (rc == 0 && S_ISDIR(sb.st_mode)) {
+			snprintf(gen_cc,
+				 sizeof(gen_cc),
+				 "DIR:/run/user/%d/krb5cc",
+				 uid);
+		} else {
+#if defined(__linux__)
+			snprintf(gen_cc,
+				 sizeof(gen_cc),
+				 "KEYRING:persistent:%d",
+				 uid);
+#endif
+		}
+	}
+
+	/*
+	 * Make sure we do not have LD_PRELOAD or other security relevant
+	 * environment variables set.
+	 */
+	clearenv();
+
+	CUPS_SMB_DEBUG("Setting KRB5CCNAME to '%s'", gen_cc);
+	setenv("KRB5CCNAME", gen_cc, 1);
+
+smbspool:
+	snprintf(smbspool_cmd,
+		 sizeof(smbspool_cmd),
+		 "%s/smbspool",
+		 get_dyn_BINDIR());
+
+	return execv(smbspool_cmd, argv);
+}
diff --git a/source3/include/proto.h b/source3/include/proto.h
index b8f4a67..4b86db0 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1094,7 +1094,6 @@ uint32_t lp_get_spoolss_state( void );
 struct smb_signing_state;
 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state);
 void set_use_sendfile(int snum, bool val);
-void set_store_dos_attributes(int snum, bool val);
 void lp_set_mangling_method(const char *new_method);
 bool lp_posix_pathnames(void);
 void lp_set_posix_pathnames(void);
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 9945375..d839be4 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -218,6 +218,9 @@ struct fsp_lease {
 	struct smb2_lease lease;
 };
 
+/* VFS ABI stability hack */
+#define posix_flags posix_open
+
 typedef struct files_struct {
 	struct files_struct *next, *prev;
 	uint64_t fnum;
@@ -255,7 +258,7 @@ typedef struct files_struct {
 	bool aio_write_behind;
 	bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */
 	bool delete_on_close;
-	bool posix_open;
+	uint8_t posix_flags;
 	bool is_sparse;
 	bool backup_intent; /* Handle was successfully opened with backup intent
 				and opener has privilege to do so. */
@@ -297,6 +300,13 @@ typedef struct files_struct {
 	struct tevent_req *deferred_close;
 } files_struct;
 
+#define FSP_POSIX_FLAGS_OPEN		0x01
+#define FSP_POSIX_FLAGS_RENAME		0x02
+
+#define FSP_POSIX_FLAGS_ALL			\
+	(FSP_POSIX_FLAGS_OPEN |			\
+	 FSP_POSIX_FLAGS_RENAME)
+
 struct vuid_cache_entry {
 	struct auth_session_info *session_info;
 	uint64_t vuid; /* SMB2 compat */
diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c
index 56d3f00..f572b99 100644
--- a/source3/lib/errmap_unix.c
+++ b/source3/lib/errmap_unix.c
@@ -115,6 +115,9 @@ static const struct {
 #ifdef ETXTBSY
 	{ ETXTBSY,      NT_STATUS_SHARING_VIOLATION },
 #endif
+#ifdef EOVERFLOW
+	{ EOVERFLOW,      NT_STATUS_ALLOTTED_SPACE_EXCEEDED },
+#endif
 };
 
 /*********************************************************************
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 816ad13..c9f4060 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -1592,7 +1592,8 @@ NTSTATUS cli_smb2_setattrE(struct cli_state *cli,
  Synchronous only.
 ***************************************************************/
 
-NTSTATUS cli_smb2_dskattr(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail)
+NTSTATUS cli_smb2_dskattr(struct cli_state *cli, const char *path,
+			  uint64_t *bsize, uint64_t *total, uint64_t *avail)
 {
 	NTSTATUS status;
 	uint16_t fnum = 0xffff;
@@ -1619,7 +1620,7 @@ NTSTATUS cli_smb2_dskattr(struct cli_state *cli, uint64_t *bsize, uint64_t *tota
 
 	/* First open the top level directory. */
 	status = cli_smb2_create_fnum(cli,
-			"",
+			path,
 			0,			/* create_flags */
 			FILE_READ_ATTRIBUTES,	/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index c97bc76..ceb5629 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -117,6 +117,7 @@ NTSTATUS cli_smb2_setattrE(struct cli_state *cli,
                         time_t access_time,
                         time_t write_time);
 NTSTATUS cli_smb2_dskattr(struct cli_state *cli,
+			const char *path,
 			uint64_t *bsize,
 			uint64_t *total,
 			uint64_t *avail);
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 9e1975b..0e790cd 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -587,25 +587,25 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli,
 }
 
 /****************************************************************************
- Do a POSIX getfacl (UNIX extensions).
+ Do a POSIX getacl - pathname based ACL get (UNIX extensions).
 ****************************************************************************/
 
-struct getfacl_state {
+struct getacl_state {
 	uint32_t num_data;
 	uint8_t *data;
 };
 
-static void cli_posix_getfacl_done(struct tevent_req *subreq);
+static void cli_posix_getacl_done(struct tevent_req *subreq);
 
-struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
+struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
 					struct cli_state *cli,
 					const char *fname)
 {
 	struct tevent_req *req = NULL, *subreq = NULL;
-	struct getfacl_state *state = NULL;
+	struct getacl_state *state = NULL;
 
-	req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
+	req = tevent_req_create(mem_ctx, &state, struct getacl_state);
 	if (req == NULL) {
 		return NULL;
 	}
@@ -614,16 +614,16 @@ struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
-	tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
+	tevent_req_set_callback(subreq, cli_posix_getacl_done, req);
 	return req;
 }
 
-static void cli_posix_getfacl_done(struct tevent_req *subreq)
+static void cli_posix_getacl_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
-	struct getfacl_state *state = tevent_req_data(
-		req, struct getfacl_state);
+	struct getacl_state *state = tevent_req_data(
+		req, struct getacl_state);
 	NTSTATUS status;
 
 	status = cli_qpathinfo_recv(subreq, state, &state->data,
@@ -635,12 +635,12 @@ static void cli_posix_getfacl_done(struct tevent_req *subreq)
 	tevent_req_done(req);
 }
 
-NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
+NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
 				TALLOC_CTX *mem_ctx,
 				size_t *prb_size,
 				char **retbuf)
 {
-	struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
+	struct getacl_state *state = tevent_req_data(req, struct getacl_state);
 	NTSTATUS status;
 
 	if (tevent_req_is_nterror(req, &status)) {
@@ -651,7 +651,7 @@ NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
 	return NT_STATUS_OK;
 }
 
-NTSTATUS cli_posix_getfacl(struct cli_state *cli,
+NTSTATUS cli_posix_getacl(struct cli_state *cli,
 			const char *fname,
 			TALLOC_CTX *mem_ctx,
 			size_t *prb_size,
@@ -676,7 +676,7 @@ NTSTATUS cli_posix_getfacl(struct cli_state *cli,
 		goto fail;
 	}
 
-	req = cli_posix_getfacl_send(frame,
+	req = cli_posix_getacl_send(frame,
 				ev,
 				cli,
 				fname);
@@ -689,7 +689,107 @@ NTSTATUS cli_posix_getfacl(struct cli_state *cli,
 		goto fail;
 	}
 
-	status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
+	status = cli_posix_getacl_recv(req, mem_ctx, prb_size, retbuf);
+
+ fail:
+	TALLOC_FREE(frame);
+	return status;
+}
+
+/****************************************************************************
+ Do a POSIX setacl - pathname based ACL set (UNIX extensions).
+****************************************************************************/
+
+struct setacl_state {
+	uint8_t *data;
+};
+
+static void cli_posix_setacl_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					struct cli_state *cli,
+					const char *fname,
+					const void *data,
+					size_t num_data)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct setacl_state *state = NULL;
+
+	req = tevent_req_create(mem_ctx, &state, struct setacl_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->data = talloc_memdup(state, data, num_data);
+	if (tevent_req_nomem(state->data, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = cli_setpathinfo_send(state,
+				ev,
+				cli,
+				SMB_SET_POSIX_ACL,
+				fname,
+				state->data,
+				num_data);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_posix_setacl_done, req);
+	return req;
+}
+
+static void cli_posix_setacl_done(struct tevent_req *subreq)
+{
+	NTSTATUS status = cli_setpathinfo_recv(subreq);
+	tevent_req_simple_finish_ntstatus(subreq, status);
+}
+
+NTSTATUS cli_posix_setacl_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_posix_setacl(struct cli_state *cli,
+			const char *fname,
+			const void *acl_buf,
+			size_t acl_buf_size)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct tevent_context *ev = NULL;
+	struct tevent_req *req = NULL;
+	NTSTATUS status = NT_STATUS_OK;
+
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		/*
+		 * Can't use sync call while an async call is in flight
+		 */
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto fail;
+	}
+
+	ev = samba_tevent_context_init(frame);
+	if (ev == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+
+	req = cli_posix_setacl_send(frame,
+				ev,
+				cli,
+				fname,
+				acl_buf,
+				acl_buf_size);
+	if (req == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+
+	status = cli_posix_setacl_recv(req);
 
  fail:
 	TALLOC_FREE(frame);
@@ -4199,7 +4299,8 @@ NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
 	return status;
 }
 
-NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail)
+NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
+		       uint64_t *total, uint64_t *avail)
 {
 	uint64_t sectors_per_block;
 	uint64_t bytes_per_sector;
@@ -4207,7 +4308,7 @@ NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total,
 	NTSTATUS status;
 
 	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
-		return cli_smb2_dskattr(cli, bsize, total, avail);
+		return cli_smb2_dskattr(cli, path, bsize, total, avail);
 	}
 
 	/*
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 2abd37e..06c0211 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -620,7 +620,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 	}
 
 	ZERO_STRUCTP(srv);
-	srv->cli = c;
+	DLIST_ADD(srv->cli, c);
 	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
         srv->no_pathinfo = False;
         srv->no_pathinfo2 = False;
@@ -816,7 +816,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
                 }
 
                 ZERO_STRUCTP(ipc_srv);
-                ipc_srv->cli = ipc_cli;
+                DLIST_ADD(ipc_srv->cli, ipc_cli);
 
                 nt_status = cli_rpc_pipe_open_noauth(
 			ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd);
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 5ebcf5f..dc9aa17 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -252,19 +252,30 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli,
 			const char *newname);
 uint32_t unix_perms_to_wire(mode_t perms);
 mode_t wire_perms_to_unix(uint32_t perms);
-struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
+struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
 					struct cli_state *cli,
 					const char *fname);
-NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
+NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
 				TALLOC_CTX *mem_ctx,
 				size_t *prb_size,
 				char **retbuf);
-NTSTATUS cli_posix_getfacl(struct cli_state *cli,
+NTSTATUS cli_posix_getacl(struct cli_state *cli,
 			const char *fname,
 			TALLOC_CTX *mem_ctx,
 			size_t *prb_size,
 			char **retbuf);
+struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					struct cli_state *cli,
+					const char *fname,
+					const void *acl_buf,
+					size_t acl_buf_size);
+NTSTATUS cli_posix_setacl_recv(struct tevent_req *req);
+NTSTATUS cli_posix_setacl(struct cli_state *cli,
+			const char *fname,
+			const void *acl_buf,
+			size_t acl_buf_size);
 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
 					struct tevent_context *ev,
 					struct cli_state *cli,
@@ -513,7 +524,8 @@ struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total,
 			  int *avail);
 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail);
-NTSTATUS cli_disk_size(struct cli_state *cli, uint64_t *bsize, uint64_t *total, uint64_t *avail);
+NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
+		       uint64_t *total, uint64_t *avail);
 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
 				struct tevent_context *ev,
 				struct cli_state *cli,
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7b8bc84..5a97460 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -847,7 +847,8 @@ bool set_share_mode(struct share_mode_lock *lck, struct files_struct *fsp,
 	e->id = fsp->file_id;
 	e->share_file_id = fsp->fh->gen_id;
 	e->uid = (uint32_t)uid;
-	e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
+	e->flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
+		SHARE_MODE_FLAG_POSIX_OPEN : 0;
 	e->name_hash = fsp->name_hash;
 
 	return true;
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index 625e7cb..f73e80c 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -1089,7 +1089,7 @@ static int chmod_acl_module_common(struct vfs_handle_struct *handle,
 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
 			struct files_struct *fsp, mode_t mode)
 {
-	if (fsp->posix_open) {
+	if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 		/* Only allow this on POSIX opens. */
 		return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
 	}
@@ -1109,7 +1109,7 @@ static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
 			struct files_struct *fsp, mode_t mode)
 {
-	if (fsp->posix_open) {
+	if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 		/* Only allow this on POSIX opens. */
 		return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
 	}
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index ecce85d..d87afa6 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -104,11 +104,12 @@ static int vfs_fruit_debug_level = DBGC_VFS;
  * REVIEW:
  * This is hokey, but what else can we do?
  */
+#define NETATALK_META_XATTR "org.netatalk.Metadata"
 #if defined(HAVE_ATTROPEN) || defined(FREEBSD)
-#define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
+#define AFPINFO_EA_NETATALK NETATALK_META_XATTR
 #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
 #else
-#define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
+#define AFPINFO_EA_NETATALK "user." NETATALK_META_XATTR
 #define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
 #endif
 
@@ -124,7 +125,8 @@ struct fruit_config_data {
 	enum fruit_meta meta;
 	enum fruit_locking locking;
 	enum fruit_encoding encoding;
-	bool use_aapl;
+	bool use_aapl;		/* config from smb.conf */
+	bool nego_aapl;		/* client negotiated AAPL */
 	bool use_copyfile;
 	bool readdir_attr_enabled;
 	bool unix_info_enabled;
@@ -1522,6 +1524,37 @@ static bool add_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
 	return true;
 }
 
+static bool del_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
+			     struct stream_struct **streams,
+			     const char *name)
+{
+	struct stream_struct *tmp = *streams;
+	int i;
+
+	if (*num_streams == 0) {
+		return true;
+	}
+
+	for (i = 0; i < *num_streams; i++) {
+		if (strequal_m(tmp[i].name, name)) {
+			break;
+		}
+	}
+
+	if (i == *num_streams) {
+		return true;
+	}
+
+	TALLOC_FREE(tmp[i].name);
+	if (*num_streams - 1 > i) {
+		memmove(&tmp[i], &tmp[i+1],
+			(*num_streams - i - 1) * sizeof(struct stream_struct));
+	}
+
+	*num_streams -= 1;
+	return true;
+}
+
 static bool empty_finderinfo(const struct adouble *ad)
 {
 
@@ -1894,6 +1927,9 @@ static NTSTATUS check_aapl(vfs_handle_struct *handle,
 				      out_context_blobs,
 				      SMB2_CREATE_TAG_AAPL,
 				      blob);
+	if (NT_STATUS_IS_OK(status)) {
+		config->nego_aapl = true;
+	}
 
 	return status;
 }
@@ -2419,7 +2455,7 @@ static int fruit_unlink(vfs_handle_struct *handle,
 		}
 
 		/* FIXME: direct unlink(), missing smb_fname */
-		DEBUG(1,("fruit_unlink: %s\n", adp));
+		DBG_DEBUG("fruit_unlink: %s\n", adp);
 		rc = unlink(adp);
 		if ((rc == -1) && (errno == ENOENT)) {
 			rc = 0;
@@ -2442,27 +2478,8 @@ static int fruit_unlink(vfs_handle_struct *handle,
 	}
 
 	if (is_afpresource_stream(smb_fname)) {
-		if (config->rsrc == FRUIT_RSRC_ADFILE) {
-			char *adp = NULL;
-
-			rc = adouble_path(talloc_tos(),
-					  smb_fname->base_name, &adp);
-			if (rc != 0) {
-				return -1;
-			}
-			/* FIXME: direct unlink(), missing smb_fname */
-			rc = unlink(adp);
-			if ((rc == -1) && (errno == ENOENT)) {
-				rc = 0;
-			}
-			TALLOC_FREE(adp);
-		} else {
-			rc = SMB_VFS_REMOVEXATTR(handle->conn,
-						 smb_fname->base_name,
-						 AFPRESOURCE_EA_NETATALK);
-		}
-
-		return rc;
+		/* OS X ignores deletes on the AFP_Resource stream */
+		return 0;
 	}
 
 	return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
@@ -2664,13 +2681,19 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
 		char afpinfo_buf[AFP_INFO_SIZE];
 		size_t to_return;
 
-		if ((offset < 0) || (offset >= AFP_INFO_SIZE)) {
+		/*
+		 * OS X has a off-by-1 error in the offset calculation, so we're
+		 * bug compatible here. It won't hurt, as any relevant real
+		 * world read requests from the AFP_AfpInfo stream will be
+		 * offset=0 n=60. offset is ignored anyway, see below.
+		 */
+		if ((offset < 0) || (offset >= AFP_INFO_SIZE + 1)) {
 			len = 0;
 			rc = 0;
 			goto exit;
 		}
 
-		to_return = AFP_INFO_SIZE - offset;
+		to_return = MIN(n, AFP_INFO_SIZE);
 
 		ai = afpinfo_new(talloc_tos());
 		if (ai == NULL) {
@@ -2693,7 +2716,10 @@ static ssize_t fruit_pread(vfs_handle_struct *handle,
 			goto exit;
 		}
 
-		memcpy(data, afpinfo_buf + offset, to_return);
+		/*
+		 * OS X ignores offset when reading from AFP_AfpInfo stream!
+		 */
+		memcpy(data, afpinfo_buf, to_return);
 		len = to_return;
 	} else {
 		len = SMB_VFS_NEXT_PREAD(
@@ -2784,6 +2810,23 @@ static ssize_t fruit_pwrite(vfs_handle_struct *handle,
 		}
 		memcpy(ad_entry(ad, ADEID_FINDERI),
 		       &ai->afpi_FinderInfo[0], ADEDLEN_FINDERI);
+		if (empty_finderinfo(ad)) {
+			/* Discard metadata */
+			if (config->meta == FRUIT_META_STREAM) {
+				rc = SMB_VFS_FTRUNCATE(fsp, 0);
+			} else {
+				rc = SMB_VFS_REMOVEXATTR(handle->conn,
+							 fsp->fsp_name->base_name,
+							 AFPINFO_EA_NETATALK);
+			}
+			if (rc != 0 && errno != ENOENT && errno != ENOATTR) {
+				DBG_WARNING("Can't delete metadata for %s: %s\n",
+					    fsp->fsp_name->base_name, strerror(errno));
+				goto exit;
+			}
+			rc = 0;
+			goto exit;
+		}
 		rc = ad_write(ad, name);
 	} else {
 		len = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n,
@@ -2842,6 +2885,17 @@ static int fruit_stat_meta(vfs_handle_struct *handle,
 			   struct smb_filename *smb_fname,
 			   bool follow_links)
 {
+	struct adouble *ad = NULL;
+
+	ad = ad_get(talloc_tos(), handle, smb_fname->base_name, ADOUBLE_META);
+	if (ad == NULL) {
+		DBG_INFO("fruit_stat_meta %s: %s\n",
+			 smb_fname_str_dbg(smb_fname), strerror(errno));
+		errno = ENOENT;
+		return -1;
+	}
+	TALLOC_FREE(ad);
+
 	/* Populate the stat struct with info from the base file. */
 	if (fruit_stat_base(handle, smb_fname, follow_links) == -1) {
 		return -1;
@@ -3095,6 +3149,7 @@ static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle,
 	struct fruit_config_data *config = NULL;
 	struct smb_filename *smb_fname = NULL;
 	struct adouble *ad = NULL;
+	NTSTATUS status;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config, struct fruit_config_data,
 				return NT_STATUS_UNSUCCESSFUL);
@@ -3143,8 +3198,23 @@ static NTSTATUS fruit_streaminfo(vfs_handle_struct *handle,
 
 	TALLOC_FREE(smb_fname);
 
-	return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
-				       pnum_streams, pstreams);
+	status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
+					 pnum_streams, pstreams);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	if (config->meta == FRUIT_META_NETATALK) {
+		/* Remove the Netatalk xattr from the list */
+		if (!del_fruit_stream(mem_ctx, pnum_streams, pstreams,
+				      ":" NETATALK_META_XATTR ":$DATA")) {
+				TALLOC_FREE(ad);
+				TALLOC_FREE(smb_fname);
+				return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	return NT_STATUS_OK;
 }
 
 static int fruit_ntimes(vfs_handle_struct *handle,
@@ -3208,19 +3278,23 @@ static int fruit_ftruncate_meta(struct vfs_handle_struct *handle,
 				off_t offset,
 				struct adouble *ad)
 {
-	/*
-	 * As this request hasn't been seen in the wild,
-	 * the only sensible use I can imagine is the client
-	 * truncating the stream to 0 bytes size.
-	 * We simply remove the metadata on such a request.
-	 */
-	if (offset != 0) {
+	struct fruit_config_data *config;
+
+	SMB_VFS_HANDLE_GET_DATA(handle, config,
+				struct fruit_config_data, return -1);
+
+	if (offset > 60) {
 		DBG_WARNING("ftruncate %s to %jd",
 			    fsp_str_dbg(fsp), (intmax_t)offset);
+		/* OS X returns NT_STATUS_ALLOTTED_SPACE_EXCEEDED  */
+		errno = EOVERFLOW;
 		return -1;
 	}
 
-	return SMB_VFS_FREMOVEXATTR(fsp, AFPRESOURCE_EA_NETATALK);
+	DBG_WARNING("ignoring ftruncate %s to %jd",
+		    fsp_str_dbg(fsp), (intmax_t)offset);
+	/* OS X returns success but does nothing  */
+	return 0;
 }
 
 static int fruit_ftruncate_rsrc(struct vfs_handle_struct *handle,
@@ -3267,8 +3341,8 @@ static int fruit_ftruncate(struct vfs_handle_struct *handle,
         struct adouble *ad =
 		(struct adouble *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
 
-	DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
-		   fsp_str_dbg(fsp), (double)offset));
+	DBG_DEBUG("fruit_ftruncate called for file %s offset %.0f\n",
+		   fsp_str_dbg(fsp), (double)offset);
 
 	if (ad == NULL) {
 		return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
@@ -3338,16 +3412,27 @@ static NTSTATUS fruit_create_file(vfs_handle_struct *handle,
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
+
 	fsp = *result;
 
-	if (config->copyfile_enabled) {
-		/*
-		 * Set a flag in the fsp. Gets used in copychunk to
-		 * check whether the special Apple copyfile semantics
-		 * for copychunk should be allowed in a copychunk
-		 * request with a count of 0.
-		 */
-		fsp->aapl_copyfile_supported = true;
+	if (config->nego_aapl) {
+		if (config->copyfile_enabled) {
+			/*
+			 * Set a flag in the fsp. Gets used in
+			 * copychunk to check whether the special
+			 * Apple copyfile semantics for copychunk
+			 * should be allowed in a copychunk request
+			 * with a count of 0.
+			 */
+			fsp->aapl_copyfile_supported = true;
+		}
+
+		if (fsp->is_directory) {
+			/*
+			 * Enable POSIX directory rename behaviour
+			 */
+			fsp->posix_flags |= FSP_POSIX_FLAGS_RENAME;
+		}
 	}
 
 	/*
@@ -3538,7 +3623,7 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
 	mode_t ms_nfs_mode;
 	int result;
 
-	DEBUG(1, ("fruit_fset_nt_acl: %s\n", fsp_str_dbg(fsp)));
+	DBG_DEBUG("fruit_fset_nt_acl: %s\n", fsp_str_dbg(fsp));
 
 	status = check_ms_nfs(handle, fsp, psd, &ms_nfs_mode, &do_chmod);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -3554,10 +3639,8 @@ static NTSTATUS fruit_fset_nt_acl(vfs_handle_struct *handle,
 
 	if (do_chmod) {
 		if (fsp->fh->fd != -1) {
-			DEBUG(1, ("fchmod: %s\n", fsp_str_dbg(fsp)));
 			result = SMB_VFS_FCHMOD(fsp, ms_nfs_mode);
 		} else {
-			DEBUG(1, ("chmod: %s\n", fsp_str_dbg(fsp)));
 			result = SMB_VFS_CHMOD(fsp->conn,
 					       fsp->fsp_name->base_name,
 					       ms_nfs_mode);
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index d1673a4..7ecdda5 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -434,10 +434,13 @@ static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
  * Convert from a name as handed in via the SMB layer
  * and a timestamp into the local path of the snapshot
  * of the provided file at the provided time.
+ * Also return the path in the snapshot corresponding
+ * to the file's share root.
  */
-static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
-				  struct vfs_handle_struct *handle,
-				  const char *name, time_t timestamp)
+static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
+				     struct vfs_handle_struct *handle,
+				     const char *name, time_t timestamp,
+				     size_t *snaproot_len)
 {
 	struct smb_filename converted_fname;
 	char *result = NULL;
@@ -447,10 +450,11 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 	size_t pathlen;
 	char *insert = NULL;
 	char *converted = NULL;
-	size_t insertlen;
+	size_t insertlen, connectlen = 0;
 	int i, saved_errno;
 	size_t min_offset;
 	struct shadow_copy2_config *config;
+	size_t in_share_offset = 0;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
 				return NULL);
@@ -492,6 +496,13 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			DEBUG(10, ("Found %s\n", converted));
 			result = converted;
 			converted = NULL;
+			if (snaproot_len != NULL) {
+				*snaproot_len = strlen(snapshot_path);
+				if (config->rel_connectpath != NULL) {
+					*snaproot_len +=
+					    strlen(config->rel_connectpath) + 1;
+				}
+			}
 			goto fail;
 		} else {
 			errno = ENOENT;
@@ -500,6 +511,7 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 		/* never reached ... */
 	}
 
+	connectlen = strlen(handle->conn->connectpath);
 	if (name[0] == 0) {
 		path = talloc_strdup(mem_ctx, handle->conn->connectpath);
 	} else {
@@ -575,6 +587,10 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			goto fail;
 		}
 
+		if (offset >= connectlen) {
+			in_share_offset = offset;
+		}
+
 		memcpy(converted+offset, insert, insertlen);
 
 		offset += insertlen;
@@ -588,6 +604,9 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
 			   ret, ret == 0 ? "ok" : strerror(errno)));
 		if (ret == 0) {
 			/* success */
+			if (snaproot_len != NULL) {
+				*snaproot_len = in_share_offset + insertlen;
+			}
 			break;
 		}
 		if (errno == ENOTDIR) {
@@ -624,6 +643,18 @@ fail:
 	return result;
 }
 
+/**
+ * Convert from a name as handed in via the SMB layer
+ * and a timestamp into the local path of the snapshot
+ * of the provided file at the provided time.
+ */
+static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
+				  struct vfs_handle_struct *handle,
+				  const char *name, time_t timestamp)
+{
+	return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
+}
+
 /*
   modify a sbuf return to ensure that inodes in the shadow directory
   are different from those in the main directory
@@ -1103,8 +1134,6 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	char *stripped = NULL;
 	char *tmp = NULL;
 	char *result = NULL;
-	char *inserted = NULL;
-	char *inserted_to, *inserted_end;
 	int saved_errno;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1121,29 +1150,9 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	}
 
 	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
-	if (result == NULL) {
-		goto done;
-	}
-
-	/*
-	 * Take away what we've inserted. This removes the @GMT-thingy
-	 * completely, but will give a path under the share root.
-	 */
-	inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
-	if (inserted == NULL) {
-		goto done;
-	}
-	inserted_to = strstr_m(result, inserted);
-	if (inserted_to == NULL) {
-		DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted));
-		goto done;
-	}
-	inserted_end = inserted_to + talloc_get_size(inserted) - 1;
-	memmove(inserted_to, inserted_end, strlen(inserted_end)+1);
 
 done:
 	saved_errno = errno;
-	TALLOC_FREE(inserted);
 	TALLOC_FREE(tmp);
 	TALLOC_FREE(stripped);
 	errno = saved_errno;
@@ -1777,6 +1786,51 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
 	return ret;
 }
 
+static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
+					    const char *fname)
+{
+	time_t timestamp;
+	char *stripped = NULL;
+	char *tmp = NULL;
+	char *result = NULL;
+	int saved_errno;
+	size_t rootpath_len = 0;
+
+	DBG_DEBUG("Calc connect path for [%s]\n", fname);
+
+	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+					 &timestamp, &stripped)) {
+		goto done;
+	}
+	if (timestamp == 0) {
+		return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+	}
+
+	tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
+				      &rootpath_len);
+	if (tmp == NULL) {
+		goto done;
+	}
+
+	DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
+		  (int)rootpath_len, tmp);
+
+	tmp[rootpath_len] = '\0';
+	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+	if (result == NULL) {
+		goto done;
+	}
+
+	DBG_DEBUG("connect path is [%s]\n", result);
+
+done:
+	saved_errno = errno;
+	TALLOC_FREE(tmp);
+	TALLOC_FREE(stripped);
+	errno = saved_errno;
+	return result;
+}
+
 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
 				       const char *path, uint64_t *bsize,
 				       uint64_t *dfree, uint64_t *dsize)
@@ -2078,6 +2132,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
 	.chmod_acl_fn = shadow_copy2_chmod_acl,
 	.chflags_fn = shadow_copy2_chflags,
 	.get_real_filename_fn = shadow_copy2_get_real_filename,
+	.connectpath_fn = shadow_copy2_connectpath,
 };
 
 NTSTATUS vfs_shadow_copy2_init(void);
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index 92bd1c9..b54809f 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -106,12 +106,18 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
 				       const char *stream_name,
 				       char **xattr_name)
 {
+	char *sname;
 	char *stype;
 	struct streams_xattr_config *config;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
 				return NT_STATUS_UNSUCCESSFUL);
 
+	sname = talloc_strdup(ctx, stream_name + 1);
+	if (sname == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	/*
 	 * With vfs_fruit option "fruit:encoding = native" we're
 	 * already converting stream names that contain illegal NTFS
@@ -126,41 +132,34 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
 	 * In check_path_syntax() we've already ensured the streamname
 	 * we got from the client is valid.
 	 */
-	stype = strrchr_m(stream_name + 1, ':');
+	stype = strrchr_m(sname, ':');
 
 	if (stype) {
+		/*
+		 * We only support one stream type: "$DATA"
+		 */
 		if (strcasecmp_m(stype, ":$DATA") != 0) {
+			talloc_free(sname);
 			return NT_STATUS_INVALID_PARAMETER;
 		}
+
+		/* Split name and type */
+		stype[0] = '\0';
 	}
 
-	*xattr_name = talloc_asprintf(ctx, "%s%s",
+	*xattr_name = talloc_asprintf(ctx, "%s%s%s",
 				      config->prefix,
-				      stream_name + 1);
+				      sname,
+				      config->store_stream_type ? ":$DATA" : "");
 	if (*xattr_name == NULL) {
+		talloc_free(sname);
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	if (stype != NULL) {
-		/* Normalize the stream type to upercase. */
-		if (!strupper_m(strrchr_m(*xattr_name, ':') + 1)) {
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	} else if (config->store_stream_type) {
-		/*
-		 * Append an explicit stream type if one wasn't
-		 * specified.
-		 */
-		*xattr_name = talloc_asprintf(ctx, "%s%s",
-					      *xattr_name, ":$DATA");
-		if (*xattr_name == NULL) {
-			return NT_STATUS_NO_MEMORY;
-		}
-	}
-
 	DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
 		   stream_name));
 
+	talloc_free(sname);
 	return NT_STATUS_OK;
 }
 
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 2f53a74..c576b22 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -266,44 +266,6 @@ static void set_allowed_client_auth(void);
 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
 static void free_param_opts(struct parmlist_entry **popts);
 
-/* this is used to prevent lots of mallocs of size 1 */
-static const char null_string[] = "";
-
-/**
- Free a string value.
-**/
-
-static void string_free(char **s)
-{
-	if (!s || !(*s))
-		return;
-	if (*s == null_string)
-		*s = NULL;
-	TALLOC_FREE(*s);
-}
-
-/**
- Set a string value, deallocating any existing space, and allocing the space
- for the string
-**/
-
-static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
-{
-	string_free(dest);
-
-	if (!src) {
-		src = "";
-	}
-
-	(*dest) = talloc_strdup(mem_ctx, src);
-	if ((*dest) == NULL) {
-		DEBUG(0,("Out of memory in string_init\n"));
-		return false;
-	}
-
-	return true;
-}
-
 /**
  *  Function to return the default value for the maximum number of open
  *  file descriptors permitted.  This function tries to consult the
@@ -367,7 +329,7 @@ static void free_one_parameter_common(void *parm_ptr,
 	if ((parm.type == P_STRING) ||
 	    (parm.type == P_USTRING))
 	{
-		string_free((char**)parm_ptr);
+		lpcfg_string_free((char**)parm_ptr);
 	} else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
 		TALLOC_FREE(*((char***)parm_ptr));
 	}
@@ -441,8 +403,25 @@ static void free_parameters_by_snum(int snum)
  */
 static void free_global_parameters(void)
 {
+	uint32_t i;
+	struct parm_struct *parm;
+
 	free_param_opts(&Globals.param_opt);
 	free_parameters_by_snum(GLOBAL_SECTION_SNUM);
+
+	/* Reset references in the defaults because the context is going to be freed */
+	for (i=0; parm_table[i].label; i++) {
+		parm = &parm_table[i];
+		if ((parm->type == P_STRING) ||
+		    (parm->type == P_USTRING)) {
+			if ((parm->def.svalue != NULL) &&
+			    (*(parm->def.svalue) != '\0')) {
+				if (talloc_parent(parm->def.svalue) == Globals.ctx) {
+					parm->def.svalue = NULL;
+				}
+			}
+		}
+	}
 	TALLOC_FREE(Globals.ctx);
 }
 
@@ -524,10 +503,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
 	if (!done_init) {
 		/* The logfile can be set before this is invoked. Free it if so. */
-		if (Globals.logfile != NULL) {
-			string_free(&Globals.logfile);
-			Globals.logfile = NULL;
-		}
+		lpcfg_string_free(&Globals.logfile);
 		done_init = true;
 	} else {
 		free_global_parameters();
@@ -550,13 +526,16 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 		if ((parm_table[i].type == P_STRING ||
 		     parm_table[i].type == P_USTRING))
 		{
-			string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
+			lpcfg_string_set(
+				Globals.ctx,
+				(char **)lp_parm_ptr(NULL, &parm_table[i]),
+				"");
 		}
 	}
 
 
-	string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
-	string_set(Globals.ctx, &sDefault.printjob_username, "%U");
+	lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
+	lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
 
 	init_printer_values(lp_ctx, Globals.ctx, &sDefault);
 
@@ -565,61 +544,75 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	DEBUG(3, ("Initialising global parameters\n"));
 
 	/* Must manually force to upper case here, as this does not go via the handler */
-	string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
+	lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
+			 myhostname_upper());
 
-	string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
-	string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
+	lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
+			 get_dyn_SMB_PASSWD_FILE());
+	lpcfg_string_set(Globals.ctx, &Globals.private_dir,
+			 get_dyn_PRIVATE_DIR());
 
 	/* use the new 'hash2' method by default, with a prefix of 1 */
-	string_set(Globals.ctx, &Globals.mangling_method, "hash2");
+	lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
 	Globals.mangle_prefix = 1;
 
-	string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
+	lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
 
 	/* using UTF8 by default allows us to support all chars */
-	string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
+	lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
+			 DEFAULT_UNIX_CHARSET);
 
 	/* Use codepage 850 as a default for the dos character set */
-	string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
+	lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
+			 DEFAULT_DOS_CHARSET);
 
 	/*
 	 * Allow the default PASSWD_CHAT to be overridden in local.h.
 	 */
-	string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
-
-	string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
-
-	string_set(Globals.ctx, &Globals.passwd_program, "");
-	string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
-	string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
-	string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
-	string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
-	string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
+	lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
+			 DEFAULT_PASSWD_CHAT);
+
+	lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
+
+	lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
+	lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
+			 get_dyn_LOCKDIR());
+	lpcfg_string_set(Globals.ctx, &Globals.state_directory,
+			 get_dyn_STATEDIR());
+	lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
+			 get_dyn_CACHEDIR());
+	lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
+			 get_dyn_PIDDIR());
+	lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
+			 "0.0.0.0");
 	/*
 	 * By default support explicit binding to broadcast
  	 * addresses.
- 	 */
+         */
 	Globals.nmbd_bind_explicit_broadcast = true;
 
 	s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
 	if (s == NULL) {
 		smb_panic("init_globals: ENOMEM");
 	}
-	string_set(Globals.ctx, &Globals.server_string, s);
+	lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
 	TALLOC_FREE(s);
 #ifdef DEVELOPER
-	string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
+	lpcfg_string_set(Globals.ctx, &Globals.panic_action,
+			 "/bin/sleep 999999999");
 #endif
 
-	string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
+	lpcfg_string_set(Globals.ctx, &Globals.socket_options,
+			 DEFAULT_SOCKET_OPTIONS);
 
-	string_set(Globals.ctx, &Globals.logon_drive, "");
+	lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
 	/* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
-	string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
-	string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
+	lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
+	lpcfg_string_set(Globals.ctx, &Globals.logon_path,
+			 "\\\\%N\\%U\\profile");
 
 	Globals.name_resolve_order = str_list_make_v3_const(NULL, "lmhosts wins host bcast", NULL);
-	string_set(Globals.ctx, &Globals.password_server, "*");
+	lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
 
 	Globals.algorithmic_rid_base = BASE_RID;
 
@@ -660,7 +653,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.syslog = 1;
 	Globals.syslog_only = false;
 	Globals.timestamp_logs = true;
-	string_set(Globals.ctx, &Globals.log_level, "0");
+	lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
 	Globals.debug_prefix_timestamp = false;
 	Globals.debug_hires_timestamp = true;
 	Globals.debug_pid = false;
@@ -676,9 +669,10 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
 	Globals.nis_homedir = false;
 #ifdef WITH_NISPLUS_HOME
-	string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
+	lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
+			 "auto_home.org_dir");
 #else
-	string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
+	lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
 #endif
 #endif
 	Globals.time_server = false;
@@ -723,14 +717,14 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.change_notify = true,
 	Globals.kernel_change_notify = true,
 
-	string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
-	string_set(Globals.ctx, &Globals.ldap_suffix, "");
-	string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
-	string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
-	string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
-	string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
+	lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
+	lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
+	lpcfg_string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
+	lpcfg_string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
+	lpcfg_string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
+	lpcfg_string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
 
-	string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
+	lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
 	Globals.ldap_ssl = LDAP_SSL_START_TLS;
 	Globals.ldap_ssl_ads = false;
 	Globals.ldap_deref = -1;
@@ -780,17 +774,17 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.wins_dns_proxy = true;
 
 	Globals.allow_trusted_domains = true;
-	string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
+	lpcfg_string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
 
-	string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
-	string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
-	string_set(Globals.ctx, &Globals.winbind_separator, "\\");
-	string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
+	lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
+	lpcfg_string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
+	lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
+	lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
 
-	string_set(Globals.ctx, &Globals.cups_server, "");
-	string_set(Globals.ctx, &Globals.iprint_server, "");
+	lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
+	lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
 
-	string_set(Globals.ctx, &Globals._ctdbd_socket, "");
+	lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
 
 	Globals.cluster_addresses = NULL;
 	Globals.clustering = false;
@@ -836,9 +830,9 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	if (s == NULL) {
 		smb_panic("init_globals: ENOMEM");
 	}
-	string_set(Globals.ctx, &Globals.usershare_path, s);
+	lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
 	TALLOC_FREE(s);
-	string_set(Globals.ctx, &Globals.usershare_template_share, "");
+	lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
 	Globals.usershare_max_shares = 0;
 	/* By default disallow sharing of directories not owned by the sharer. */
 	Globals.usershare_owner_only = true;
@@ -861,7 +855,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
 	Globals.smb2_leases = false;
 
-	string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
+	lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
+			 get_dyn_NCALRPCDIR());
 
 	Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
 
@@ -869,20 +864,23 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
 	Globals.tls_enabled = true;
 
-	string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
-	string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
-	string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
-	string_set(Globals.ctx, &Globals.tls_priority, "NORMAL:-VERS-SSL3.0");
+	lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
+	lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
+	lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
+	lpcfg_string_set(Globals.ctx, &Globals.tls_priority, "NORMAL:-VERS-SSL3.0");
 
-	string_set(Globals.ctx, &Globals.share_backend, "classic");
+	lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
 
 	Globals.iPreferredMaster = Auto;
 
 	Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
 
-	string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
+	lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
+		get_dyn_NTP_SIGND_SOCKET_DIR());
 
-	string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
+	lpcfg_string_set(Globals.ctx,
+		&Globals.winbindd_privileged_socket_directory,
+		get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
 
 	s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
 	if (s == NULL) {
@@ -1314,8 +1312,8 @@ static void free_param_opts(struct parmlist_entry **popts)
 	}
 	opt = *popts;
 	while (opt != NULL) {
-		string_free(&opt->key);
-		string_free(&opt->value);
+		lpcfg_string_free(&opt->key);
+		lpcfg_string_free(&opt->value);
 		TALLOC_FREE(opt->list);
 		next_opt = opt->next;
 		TALLOC_FREE(opt);
@@ -1339,7 +1337,7 @@ static void free_service(struct loadparm_service *pservice)
 
 	free_parameters(pservice);
 
-	string_free(&pservice->szService);
+	lpcfg_string_free(&pservice->szService);
 	TALLOC_FREE(pservice->copymap);
 
 	free_param_opts(&pservice->param_opt);
@@ -1402,7 +1400,7 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
 		return (-1);
 	}
 	ServicePtrs = tsp;
-	ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
+	ServicePtrs[iNumServices] = talloc_zero(ServicePtrs, struct loadparm_service);
 	if (!ServicePtrs[iNumServices]) {
 		DEBUG(0,("add_a_service: out of memory!\n"));
 		return (-1);
@@ -1413,7 +1411,8 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
 
 	copy_service(ServicePtrs[i], pservice, NULL);
 	if (name)
-		string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
+		lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
+				 name);
 
 	DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
 		i, ServicePtrs[i]->szService));
@@ -1502,7 +1501,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
 	if (!(*(ServicePtrs[iDefaultService]->path))
 	    || strequal(ServicePtrs[iDefaultService]->path,
 			lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
-		string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
+		lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
+				 pszHomedir);
 	}
 
 	if (!(*(ServicePtrs[i]->comment))) {
@@ -1510,7 +1510,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
 		if (comment == NULL) {
 			return false;
 		}
-		string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+		lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
+				 comment);
 		TALLOC_FREE(comment);
 	}
 
@@ -1558,10 +1559,10 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
 		return false;
 	}
 
-	string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
-	string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
-	string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
-	string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
 	ServicePtrs[i]->max_connections = 0;
 	ServicePtrs[i]->bAvailable = true;
 	ServicePtrs[i]->read_only = true;
@@ -1595,8 +1596,9 @@ bool lp_add_printer(const char *pszPrintername, int iDefaultService)
 	/* entry (if/when the 'available' keyword is implemented!).    */
 
 	/* the printer name is set to the service name. */
-	string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
-	string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
+			 pszPrintername);
+	lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
 
 	/* set the browseable flag from the gloabl default */
 	ServicePtrs[i]->browseable = sDefault.browseable;
@@ -2318,9 +2320,9 @@ bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *servic
 	add_to_file_list(NULL, &file_lists, pszParmValue, fname);
 
 	if (service == NULL) {
-		string_set(Globals.ctx, ptr, fname);
+		lpcfg_string_set(Globals.ctx, ptr, fname);
 	} else {
-		string_set(service, ptr, fname);
+		lpcfg_string_set(service, ptr, fname);
 	}
 
 	if (file_exist(fname)) {
@@ -2791,7 +2793,8 @@ void lp_add_one_printer(const char *name, const char *comment,
 	if (lp_servicenumber(name) < 0) {
 		lp_add_printer(name, printers);
 		if ((i = lp_servicenumber(name)) >= 0) {
-			string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+			lpcfg_string_set(ServicePtrs[i],
+					 &ServicePtrs[i]->comment, comment);
 			ServicePtrs[i]->autoloaded = true;
 		}
 	}
@@ -2875,9 +2878,13 @@ static void lp_save_defaults(void)
 				break;
 			case P_STRING:
 			case P_USTRING:
-				parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
+				lpcfg_string_set(
+					Globals.ctx,
+					&parm_table[i].def.svalue,
+					*(char **)lp_parm_ptr(
+						NULL, &parm_table[i]));
 				if (parm_table[i].def.svalue == NULL) {
-					smb_panic("talloc_strdup failed");
+					smb_panic("lpcfg_string_set() failed");
 				}
 				break;
 			case P_BOOL:
@@ -3353,8 +3360,10 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 
 	/* And note when it was loaded. */
 	ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
-	string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
-	string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
+	lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
+			 sharepath);
+	lpcfg_string_set(ServicePtrs[iService],
+			 &ServicePtrs[iService]->comment, comment);
 
 	ret = iService;
 
@@ -4206,7 +4215,7 @@ const char *lp_printername(TALLOC_CTX *ctx, int snum)
 
 void lp_set_logfile(const char *name)
 {
-	string_set(Globals.ctx, &Globals.logfile, name);
+	lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
 	debug_set_logfile(name);
 }
 
@@ -4293,20 +4302,9 @@ void set_use_sendfile(int snum, bool val)
 		sDefault._use_sendfile = val;
 }
 
-/*******************************************************************
- Turn off storing DOS attributes if this share doesn't support it.
-********************************************************************/
-
-void set_store_dos_attributes(int snum, bool val)
-{
-	if (!LP_SNUM_OK(snum))
-		return;
-	ServicePtrs[(snum)]->store_dos_attributes = val;
-}
-
 void lp_set_mangling_method(const char *new_method)
 {
-	string_set(Globals.ctx, &Globals.mangling_method, new_method);
+	lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
 }
 
 /*******************************************************************
@@ -4342,7 +4340,8 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
 	if (posix_default_lock_was_set) {
 		return posix_cifsx_locktype;
 	} else {
-		return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
+		return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
+			POSIX_LOCK : WINDOWS_LOCK;
 	}
 }
 
diff --git a/source3/script/tests/test_dfree_command.sh b/source3/script/tests/test_dfree_command.sh
index c9c3aa6..a60a52d 100755
--- a/source3/script/tests/test_dfree_command.sh
+++ b/source3/script/tests/test_dfree_command.sh
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
-# Blackbox test for 'dfree command'
+# Blackbox test for 'dfree command' and smbclient "l"
+# command disk free printout.
 #
 
 if [ $# -lt 6 ]; then
@@ -26,15 +27,16 @@ test_smbclient_dfree() {
 	name="$1"
 	share="$2"
 	cmd="$3"
+    expected="$4"
 	shift
 	shift
+    shift
 	subunit_start_test "$name"
 	output=$($VALGRIND $smbclient //$SERVER/$share -c "$cmd" $@ 2>&1)
 	status=$?
 	if [ x$status = x0 ]; then
-		echo "$output" | grep "2000 blocks of size 1024. 20 blocks available" >/dev/null
-		status=$?
-		if [ x$status = x0 ]; then
+		received=$(echo "$output" | awk '/blocks of size/ {print $1, $5, $6}')
+		if [ "$expected" = "$received" ]; then
 			subunit_pass_test "$name"
 		else
 			echo "$output" | subunit_fail_test "$name"
@@ -46,6 +48,11 @@ test_smbclient_dfree() {
 }
 
 
-test_smbclient_dfree "Test dfree command" dfree "l" -U$USERNAME%$PASSWORD || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command share root SMB3" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command share root NT1" dfree "l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command subdir1 SMB3" dfree "cd subdir1; l" "8000 1024. 80" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+test_smbclient_dfree "Test dfree command subdir2 SMB3" dfree "cd subdir2; l" "32000 1024. 320" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
+#SMB1 queries disk usage stat on the share's root, regardless of working directory
+test_smbclient_dfree "Test dfree command subdir1 NT1" dfree "cd subdir1; l" "2000 1024. 20" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
 
 exit $failed
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..eecd5b8
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,290 @@
+#!/bin/bash
+#
+# Blackbox test for shadow_copy2 VFS.
+#
+
+if [ $# -lt 7 ]; then
+cat <<EOF
+Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+DOMAIN=${3}
+USERNAME=${4}
+PASSWORD=${5}
+WORKDIR=${6}
+SMBCLIENT=${7}
+shift 7
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$*"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
+SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
+SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
+SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
+SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
+SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
+SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
+SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
+SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
+SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
+
+# build a hierarchy of files, symlinks, and directories
+build_files()
+{
+    local rootdir
+    local prefix
+    local version
+    local destdir
+    rootdir=$1
+    prefix=$2
+    version=$3
+    if [ -n "$prefix" ] ; then
+        destdir=$rootdir/$prefix
+    else
+        destdir=$rootdir
+    fi
+
+    mkdir -p $destdir
+    if [ "$version" = "latest" ] ; then
+        #non-snapshot files
+        # for non-snapshot version, create legit files
+        # so that wide-link checks focus on snapshot files
+        touch $destdir/foo
+        mkdir -p $destdir/bar
+        touch $destdir/bar/baz
+        touch $destdir/bar/lfoo
+        touch $destdir/bar/letcpasswd
+        touch $destdir/bar/loutside
+    elif [ "$version" = "fullsnap" ] ; then
+        #snapshot files
+        touch $destdir/foo
+        mkdir -p $destdir/bar
+        touch $destdir/bar/baz
+        ln -fs ../foo $destdir/bar/lfoo
+        ln -fs /etc/passwd $destdir/bar/letcpasswd
+        ln -fs ../../outside $destdir/bar/loutside
+        touch `dirname $destdir`/outside
+    else #subshare snapshot - at bar
+        touch $destdir/baz
+        ln -fs ../foo $destdir/lfoo
+        ln -fs /etc/passwd $destdir/letcpasswd
+        ln -fs ../../outside $destdir/loutside
+        touch `dirname $destdir`/../outside
+    fi
+
+}
+
+# build a snapshots directory
+build_snapshots()
+{
+    local where     #where to build snapshots
+    local prefix    #prefix from snapshot dir to share root
+    local start     #timestamp index of first snapshot
+    local end       #timestamp index of last snapshot
+    local sub       #creat a snapshot of subtree of share
+    local snapdir
+    local snapname
+    local i
+    local version
+
+    where=$1
+    prefix=$2
+    start=$3
+    end=$4
+    sub=$5
+
+    snapdir=$where/.snapshots
+    mkdir -p $snapdir
+
+    version="fullsnap"
+    if [ "$sub" = "1" ] ; then
+        version="subsnap"
+        prefix=""
+
+        # a valid link target for an inner symlink -
+        # the link is not broken yet should be blocked
+        # by wide link checks
+        touch $snapdir/foo
+    fi
+
+    for i in `seq $start $end` ; do
+        snapname=${SNAPSHOTS[$i]}
+        mkdir $snapdir/$snapname
+        build_files $snapdir/$snapname "$prefix" $version
+    done
+}
+
+# Test listing previous versions of a file
+test_count_versions()
+{
+    local share
+    local path
+    local expected_count
+    local versions
+
+    share=$1
+    path=$2
+    expected_count=$3
+    versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
+    if [ "$versions" = "$expected_count" ] ; then
+        true
+    else
+        echo "expected $expected_count versions of $path, got $versions"
+        false
+    fi
+}
+
+# Test fetching a previous version of a file
+test_fetch_snap_file()
+{
+    local share
+    local path
+    local snapidx
+
+    share=$1
+    path=$2
+    snapidx=$3
+    $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
+        -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
+}
+
+test_shadow_copy_fixed()
+{
+    local share     #share to contact
+    local where     #where to place snapshots
+    local prefix    #prefix to files inside snapshot
+    local msg
+    local allow_wl
+    local ncopies_allowd
+    local ncopies_blocked
+
+    share=$1
+    where=$2
+    prefix=$3
+    msg=$4
+    allow_wl=$5
+
+    ncopies_allowed=4
+    ncopies_blocked=1
+    if [ -n "$allow_wl" ] ; then
+        ncopies_blocked=4
+    fi
+
+    #delete snapshots from previous tests
+    find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+    build_snapshots $WORKDIR/$where "$prefix" 0 2
+
+    testit "$msg - regular file" \
+        test_count_versions $share foo $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - regular file in subdir" \
+        test_count_versions $share bar/baz $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - local symlink" \
+        test_count_versions $share bar/lfoo $ncopies_allowed || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - abs symlink outside" \
+        test_count_versions $share bar/letcpasswd $ncopies_blocked || \
+        failed=`expr $failed + 1`
+
+    testit "$msg - rel symlink outside" \
+        test_count_versions $share bar/loutside $ncopies_blocked || \
+        failed=`expr $failed + 1`
+}
+
+test_shadow_copy_everywhere()
+{
+    local share     #share to contact
+
+    share=$1
+
+    #delete snapshots from previous tests
+    find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+    build_snapshots "$WORKDIR/mount" "base/share" 0 0
+    build_snapshots "$WORKDIR/mount/base" "share" 1 2
+    build_snapshots "$WORKDIR/mount/base/share" "" 3 5
+    build_snapshots "$WORKDIR/mount/base/share/bar" "" 6 9 1
+
+    testit "snapshots in each dir - regular file" \
+        test_count_versions $share foo 4 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - regular file in subdir" \
+        test_count_versions $share bar/baz 5 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - local symlink (but outside snapshot)" \
+        test_count_versions $share bar/lfoo 1 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - abs symlink outside" \
+        test_count_versions $share bar/letcpasswd 1 || \
+        failed=`expr $failed + 1`
+
+    testit "snapshots in each dir - rel symlink outside" \
+        test_count_versions $share bar/loutside 1 || \
+        failed=`expr $failed + 1`
+
+    #the previous versions of the file bar/lfoo points to are outside its
+    #snapshot, and are not reachable. However, but previous versions
+    #taken at different, non-overlapping times higher up the
+    #hierarchy are still reachable.
+    testit "fetch a previous version of a regular file" \
+        test_fetch_snap_file $share "bar/baz" 6 || \
+        failed=`expr $failed + 1`
+
+    testit_expect_failure "fetch a (non-existent) previous version of a symlink" \
+        test_fetch_snap_file $share "bar/lfoo" 6 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (1)" \
+        test_fetch_snap_file $share "bar/lfoo" 0 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (2)" \
+        test_fetch_snap_file $share "bar/lfoo" 1 || \
+        failed=`expr $failed + 1`
+
+    testit "fetch a previous version of a symlink via browsing (3)" \
+        test_fetch_snap_file $share "bar/lfoo" 3 || \
+        failed=`expr $failed + 1`
+
+}
+
+#build "latest" files
+build_files $WORKDIR/mount base/share "latest"
+
+failed=0
+
+# a test with wide links allowed - also to verify that what's later
+# being blocked is a result of server security measures and not
+# a testing artifact.
+test_shadow_copy_fixed shadow_wl mount base/share "shadow copies with wide links allowed" 1
+
+# tests for a fixed snapshot location
+test_shadow_copy_fixed shadow1 mount base/share "full volume snapshots mounted under volume"
+test_shadow_copy_fixed shadow2 . base/share "full volume snapshots mounted outside volume"
+test_shadow_copy_fixed shadow3 mount/base share "sub volume snapshots mounted under snapshot point"
+test_shadow_copy_fixed shadow4 . share "sub volume snapshots mounted outside"
+test_shadow_copy_fixed shadow5 mount/base/share "" "full volume snapshots and share mounted under volume"
+test_shadow_copy_fixed shadow6 . "" "full volume snapshots and share mounted outside"
+
+# tests for snapshot everywhere - one snapshot location
+test_shadow_copy_fixed shadow7 mount base/share "'everywhere' full volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base share "'everywhere' sub volume snapshots"
+test_shadow_copy_fixed shadow7 mount/base/share "" "'everywhere' share snapshots"
+
+# a test for snapshots everywhere - multiple snapshot locations
+test_shadow_copy_everywhere shadow7
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 630927b..79db4b5 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -78,7 +78,7 @@ tests = ["RW1", "RW2", "RW3"]
 for t in tests:
     plantestsuite("samba3.smbtorture_s3.vfs_aio_fork(simpleserver).%s" % t, "simpleserver", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/vfs_aio_fork', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
 
-posix_tests = ["POSIX", "POSIX-APPEND"]
+posix_tests = ["POSIX", "POSIX-APPEND", "POSIX-SYMLINK-ACL", "POSIX-SYMLINK-EA"]
 
 for t in posix_tests:
     plantestsuite("samba3.smbtorture_s3.plain(nt4_dc).%s" % t, "nt4_dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER_IP/posix_share', '$USERNAME', '$PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"])
@@ -177,6 +177,7 @@ for env in ["nt4_dc"]:
 for env in ["fileserver"]:
     plantestsuite("samba3.blackbox.preserve_case (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_preserve_case.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
     plantestsuite("samba3.blackbox.dfree_command (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_command.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
+    plantestsuite("samba3.blackbox.shadow_copy2 (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3])
 
     #
     # tar command tests
@@ -380,8 +381,8 @@ for t in tests:
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmpsort -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     elif t == "vfs.fruit":
-        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=torture:share1=vfs_fruit --option=torture:share2=tmp --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share')
-        plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD --option=torture:share1=vfs_fruit --option=torture:share2=tmp --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share')
+        plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/nt4_dc/share')
+        plansmbtorture4testsuite(t, "ad_dc", '//$SERVER_IP/vfs_fruit -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/ad_dc/share')
     elif t == "rpc.schannel_anon_setpw":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$%', description="anonymous password set")
         plansmbtorture4testsuite(t, "nt4_dc_schannel", '//$SERVER_IP/tmp -U$%', description="anonymous password set (schannel enforced server-side)")
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 0e75bf0..1cb5460 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -327,7 +327,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
 			if (e->name_hash != fsp->name_hash) {
 				continue;
 			}
-			if (fsp->posix_open
+			if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)
 			    && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
 				continue;
 			}
@@ -1103,7 +1103,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
 			struct share_mode_entry *e = &lck->data->share_modes[i];
 			if (is_valid_share_mode_entry(e) &&
 					e->name_hash == fsp->name_hash) {
-				if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
+				if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
+				    (e->flags & SHARE_MODE_FLAG_POSIX_OPEN))
+				{
 					continue;
 				}
 				if (serverid_equal(&self, &e->pid) &&
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 32a3a69..0c38837 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -123,7 +123,14 @@ uint64_t sys_disk_free(connection_struct *conn, const char *path,
 	}
 
 	if (disk_quotas(path, &bsize_q, &dfree_q, &dsize_q)) {
-		(*bsize) = bsize_q;
+		uint64_t min_bsize = MIN(*bsize, bsize_q);
+
+		(*dfree) = (*dfree) * (*bsize) / min_bsize;
+		(*dsize) = (*dsize) * (*bsize) / min_bsize;
+		dfree_q = dfree_q * bsize_q / min_bsize;
+		dsize_q = dsize_q * bsize_q / min_bsize;
+
+		(*bsize) = min_bsize;
 		(*dfree) = MIN(*dfree,dfree_q);
 		(*dsize) = MIN(*dsize,dsize_q);
 	}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 72acd4e..907f3f9 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -279,18 +279,9 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 				   SAMBA_XATTR_DOS_ATTRIB, attrstr,
 				   sizeof(attrstr));
 	if (sizeret == -1) {
-		if (errno == ENOSYS
-#if defined(ENOTSUP)
-			|| errno == ENOTSUP) {
-#else
-				) {
-#endif
-			DEBUG(1,("get_ea_dos_attribute: Cannot get attribute "
-				 "from EA on file %s: Error = %s\n",
-				 smb_fname_str_dbg(smb_fname),
-				 strerror(errno)));
-			set_store_dos_attributes(SNUM(conn), False);
-		}
+		DBG_INFO("get_ea_dos_attribute: Cannot get attribute "
+			 "from EA on file %s: Error = %s\n",
+			 smb_fname_str_dbg(smb_fname), strerror(errno));
 		return False;
 	}
 
@@ -365,7 +356,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
 		dosattr |= FILE_ATTRIBUTE_DIRECTORY;
 	}
 	/* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */
-	*pattr = (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
+	*pattr |= (uint32_t)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE));
 
 	DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
 
@@ -430,18 +421,9 @@ static bool set_ea_dos_attribute(connection_struct *conn,
 		files_struct *fsp = NULL;
 
 		if((errno != EPERM) && (errno != EACCES)) {
-			if (errno == ENOSYS
-#if defined(ENOTSUP)
-				|| errno == ENOTSUP) {
-#else
-				) {
-#endif
-				DEBUG(1,("set_ea_dos_attributes: Cannot set "
-					 "attribute EA on file %s: Error = %s\n",
-					 smb_fname_str_dbg(smb_fname),
-					 strerror(errno) ));
-				set_store_dos_attributes(SNUM(conn), False);
-			}
+			DBG_INFO("set_ea_dos_attributes: Cannot set "
+				 "attribute EA on file %s: Error = %s\n",
+				 smb_fname_str_dbg(smb_fname), strerror(errno));
 			return false;
 		}
 
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 2fe0432..156c139 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -193,7 +193,7 @@ void trigger_write_time_update(struct files_struct *fsp)
 {
 	int delay;
 
-	if (fsp->posix_open) {
+	if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 		/* Don't use delayed writes on POSIX files. */
 		return;
 	}
@@ -238,7 +238,7 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
 {
 	struct smb_file_time ft;
 
-	if (fsp->posix_open) {
+	if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 		/* Don't use delayed writes on POSIX files. */
 		return;
 	}
@@ -284,7 +284,7 @@ void mark_file_modified(files_struct *fsp)
 	}
 	trigger_write_time_update(fsp);
 
-	if (fsp->posix_open) {
+	if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 		return;
 	}
 	if (!(lp_store_dos_attributes(SNUM(fsp->conn)) ||
@@ -1047,7 +1047,7 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug
 int fsp_stat(files_struct *fsp)
 {
 	if (fsp->fh->fd == -1) {
-		if (fsp->posix_open) {
+		if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 			return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
 		} else {
 			return SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 04dddee..9233738 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -875,6 +875,12 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
 		return NT_STATUS_OK;
 	}
 
+	if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+		DEBUG(10, ("ACL set on symlink %s denied.\n",
+			fsp_str_dbg(fsp)));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (psd->owner_sid == NULL) {
 		security_info_sent &= ~SECINFO_OWNER;
 	}
@@ -1905,6 +1911,13 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
+	if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+		DEBUG(10, ("ACL get on symlink %s denied.\n",
+			fsp_str_dbg(fsp)));
+		TALLOC_FREE(frame);
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
 			SECINFO_GROUP|SECINFO_SACL)) {
 		/* Don't return SECINFO_LABEL if anything else was
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 162e834..eb6058f 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -362,7 +362,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
 	 * client should be doing this.
 	 */
 
-	if (fsp->posix_open || !lp_follow_symlinks(SNUM(conn))) {
+	if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || !lp_follow_symlinks(SNUM(conn))) {
 		flags |= O_NOFOLLOW;
 	}
 #endif
@@ -945,7 +945,7 @@ static NTSTATUS open_file(files_struct *fsp,
 				access_mask);
 
 		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
-				fsp->posix_open &&
+				(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) &&
 				S_ISLNK(smb_fname->st.st_ex_mode)) {
 			/* This is a POSIX stat open for delete
 			 * or rename on a symlink that points
@@ -2705,7 +2705,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	fsp->access_mask = open_access_mask; /* We change this to the
 					      * requested access_mask after
 					      * the open is done. */
-	fsp->posix_open = posix_open;
+	fsp->posix_flags |= posix_open ? FSP_POSIX_FLAGS_OPEN : 0;
 
 	if (timeval_is_zero(&request_time)) {
 		request_time = fsp->open_time;
@@ -3167,8 +3167,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 	}
 
 	if (info != FILE_WAS_OPENED) {
-		/* Files should be initially set as archive */
-		if (lp_map_archive(SNUM(conn)) ||
+		/* Overwritten files should be initially set as archive */
+		if ((info == FILE_WAS_OVERWRITTEN && lp_map_archive(SNUM(conn))) ||
 		    lp_store_dos_attributes(SNUM(conn))) {
 			if (!posix_open) {
 				if (file_set_dosmode(conn, smb_fname,
@@ -3571,7 +3571,9 @@ static NTSTATUS open_directory(connection_struct *conn,
 	fsp->oplock_type = NO_OPLOCK;
 	fsp->sent_oplock_break = NO_BREAK_SENT;
 	fsp->is_directory = True;
-	fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
+	if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+		fsp->posix_flags |= FSP_POSIX_FLAGS_ALL;
+	}
 	status = fsp_set_smb_fname(fsp, smb_dname);
 	if (!NT_STATUS_IS_OK(status)) {
 		file_free(req, fsp);
@@ -4704,15 +4706,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
 
 	/* Save the requested allocation size. */
 	if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
-		if (allocation_size
-		    && (allocation_size > fsp->fsp_name->st.st_ex_size)) {
+		if ((allocation_size > fsp->fsp_name->st.st_ex_size)
+		    && !(fsp->is_directory))
+		{
 			fsp->initial_allocation_size = smb_roundup(
 				fsp->conn, allocation_size);
-			if (fsp->is_directory) {
-				/* Can't set allocation size on a directory. */
-				status = NT_STATUS_ACCESS_DENIED;
-				goto fail;
-			}
 			if (vfs_allocate_file_space(
 				    fsp, fsp->initial_allocation_size) == -1) {
 				status = NT_STATUS_DISK_FULL;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 4d84347..4f108d9 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -96,9 +96,10 @@ static void release_file_oplock(files_struct *fsp)
 {
 	struct smbd_server_connection *sconn = fsp->conn->sconn;
 	struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
+	bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks;
 
 	if ((fsp->oplock_type != NO_OPLOCK) &&
-	    koplocks) {
+	    use_kernel) {
 		koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
 	}
 
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index b69e5b4..80d4fea 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3085,7 +3085,7 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
 	canon_ace *group_ace = NULL;
 	canon_ace *other_ace = NULL;
 
-	if (ace_count != 3) {
+	if (ace_count > 5) {
 		DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
 			 "entries for file %s to convert to posix perms.\n",
 			 fsp_str_dbg(fsp)));
@@ -3107,6 +3107,43 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
 		return False;
 	}
 
+	/*
+	 * Ensure all ACE entries are owner, group or other.
+	 * We can't set if there are any other SIDs.
+	 */
+	for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
+		if (ace_p == owner_ace || ace_p == group_ace ||
+				ace_p == other_ace) {
+			continue;
+		}
+		if (ace_p->owner_type == UID_ACE) {
+			if (ace_p->unix_ug.id != owner_ace->unix_ug.id) {
+				DEBUG(3,("Invalid uid %u in ACE for file %s.\n",
+					(unsigned int)ace_p->unix_ug.id,
+					fsp_str_dbg(fsp)));
+				return false;
+			}
+		} else if (ace_p->owner_type == GID_ACE) {
+			if (ace_p->unix_ug.id != group_ace->unix_ug.id) {
+				DEBUG(3,("Invalid gid %u in ACE for file %s.\n",
+					(unsigned int)ace_p->unix_ug.id,
+					fsp_str_dbg(fsp)));
+				return false;
+			}
+		} else {
+			/*
+			 * There should be no duplicate WORLD_ACE entries.
+			 */
+
+			DEBUG(3,("Invalid type %u, uid %u in "
+				"ACE for file %s.\n",
+				(unsigned int)ace_p->owner_type,
+				(unsigned int)ace_p->unix_ug.id,
+				fsp_str_dbg(fsp)));
+			return false;
+		}
+	}
+
 	*posix_perms = (mode_t)0;
 
 	*posix_perms |= owner_ace->perms;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b6f9992..c9d0d81 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2669,7 +2669,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
 	}
 
 	if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
-		if (fsp->posix_open) {
+		if (fsp->posix_flags & (FSP_POSIX_FLAGS_OPEN|FSP_POSIX_FLAGS_RENAME)) {
 			return NT_STATUS_OK;
 		}
 
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
index ed53e1b..367c9fa 100644
--- a/source3/smbd/smb2_close.c
+++ b/source3/smbd/smb2_close.c
@@ -231,7 +231,7 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	posix_open = fsp->posix_open;
+	posix_open = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN);
 	smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
 	if (smb_fname == NULL) {
 		return NT_STATUS_NO_MEMORY;
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index ad21533..76d6d69 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1281,6 +1281,14 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 	state->out_last_write_ts = result->fsp_name->st.st_ex_mtime;
 	state->out_change_ts = get_change_timespec(smb1req->conn,
 					result, result->fsp_name);
+
+	if (lp_dos_filetime_resolution(SNUM(smb2req->tcon->compat))) {
+		dos_filetime_timespec(&state->out_creation_ts);
+		dos_filetime_timespec(&state->out_last_access_ts);
+		dos_filetime_timespec(&state->out_last_write_ts);
+		dos_filetime_timespec(&state->out_change_ts);
+	}
+
 	state->out_allocation_size =
 			SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
 					       &(result->fsp_name->st));
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index d5a38d4..ff1ef15 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -54,6 +54,34 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
 				files_struct *fsp,
 				const SMB_STRUCT_STAT *psbuf);
 
+/****************************************************************************
+ Check if an open file handle or pathname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+			const files_struct *fsp,
+			const char *name)
+{
+	SMB_STRUCT_STAT sbuf;
+	const SMB_STRUCT_STAT *pst = NULL;
+
+	if (fsp) {
+		pst = &fsp->fsp_name->st;
+	} else {
+		int ret = vfs_stat_smb_basename(conn,
+				name,
+				&sbuf);
+		if (ret == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+		pst = &sbuf;
+	}
+	if (S_ISLNK(pst->st_ex_mode)) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+	return NT_STATUS_OK;
+}
+
 /********************************************************************
  The canonical "check access" based on object handle or path function.
 ********************************************************************/
@@ -209,12 +237,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
 	char **names, **tmp;
 	size_t num_names;
 	ssize_t sizeret = -1;
+	NTSTATUS status;
+
+	if (pnames) {
+		*pnames = NULL;
+	}
+	*pnum_names = 0;
 
 	if (!lp_ea_support(SNUM(conn))) {
-		if (pnames) {
-			*pnames = NULL;
-		}
-		*pnum_names = 0;
+		return NT_STATUS_OK;
+	}
+
+	status = refuse_symlink(conn, fsp, fname);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * Just return no EA's on a symlink.
+		 */
 		return NT_STATUS_OK;
 	}
 
@@ -264,10 +302,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
 
 	if (sizeret == 0) {
 		TALLOC_FREE(names);
-		if (pnames) {
-			*pnames = NULL;
-		}
-		*pnum_names = 0;
 		return NT_STATUS_OK;
 	}
 
@@ -625,6 +659,11 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
 		return NT_STATUS_EAS_NOT_SUPPORTED;
 	}
 
+	status = refuse_symlink(conn, fsp, smb_fname->base_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
@@ -5251,6 +5290,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 				uint16_t num_file_acls = 0;
 				uint16_t num_def_acls = 0;
 
+				status = refuse_symlink(conn,
+						fsp,
+						smb_fname->base_name);
+				if (!NT_STATUS_IS_OK(status)) {
+					return status;
+				}
+
 				if (fsp && fsp->fh->fd != -1) {
 					file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
 						talloc_tos());
@@ -6748,6 +6794,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
 	uint16_t num_def_acls;
 	bool valid_file_acls = True;
 	bool valid_def_acls = True;
+	NTSTATUS status;
 
 	if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -6775,6 +6822,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	status = refuse_symlink(conn, fsp, smb_fname->base_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
 		smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
 		(unsigned int)num_file_acls,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index f14ecbe..1a2ee3d 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -982,7 +982,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
 	struct smb_filename *smb_fname_cwd = NULL;
 	struct privilege_paths *priv_paths = NULL;
 	int ret;
-	bool matched;
 
 	DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
 			fname,
@@ -1077,18 +1076,32 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
 	}
 
 	rootdir_len = strlen(conn_rootdir);
-	matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
-
-	if (!matched || (resolved_name[rootdir_len] != '/' &&
-			 resolved_name[rootdir_len] != '\0')) {
-		DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
-			"attempt: %s is a symlink outside the "
-			"share path\n",
-			dir_name));
-		DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
-		DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
-		status = NT_STATUS_ACCESS_DENIED;
-		goto err;
+
+	/*
+	 * In the case of rootdir_len == 1, we know that conn_rootdir is
+	 * "/", and we also know that resolved_name starts with a slash.
+	 * So, in this corner case, resolved_name is automatically a
+	 * sub-directory of the conn_rootdir. Thus we can skip the string
+	 * comparison and the next character checks (which are even
+	 * wrong in this case).
+	 */
+	if (rootdir_len != 1) {
+		bool matched;
+
+		matched = (strncmp(conn_rootdir, resolved_name,
+				rootdir_len) == 0);
+
+		if (!matched || (resolved_name[rootdir_len] != '/' &&
+				 resolved_name[rootdir_len] != '\0')) {
+			DEBUG(2, ("check_reduced_name_with_privilege: Bad "
+				"access attempt: %s is a symlink outside the "
+				"share path\n",
+				dir_name));
+			DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
+			DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
+			status = NT_STATUS_ACCESS_DENIED;
+			goto err;
+		}
 	}
 
 	/* Now ensure that the last component either doesn't
@@ -1220,7 +1233,6 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 	if (!allow_widelinks || !allow_symlinks) {
 		const char *conn_rootdir;
 		size_t rootdir_len;
-		bool matched;
 
 		conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
 		if (conn_rootdir == NULL) {
@@ -1231,17 +1243,33 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 		}
 
 		rootdir_len = strlen(conn_rootdir);
-		matched = (strncmp(conn_rootdir, resolved_name,
-				rootdir_len) == 0);
-		if (!matched || (resolved_name[rootdir_len] != '/' &&
-				 resolved_name[rootdir_len] != '\0')) {
-			DEBUG(2, ("check_reduced_name: Bad access "
-				"attempt: %s is a symlink outside the "
-				"share path\n", fname));
-			DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
-			DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
-			SAFE_FREE(resolved_name);
-			return NT_STATUS_ACCESS_DENIED;
+
+		/*
+		 * In the case of rootdir_len == 1, we know that
+		 * conn_rootdir is "/", and we also know that
+		 * resolved_name starts with a slash.  So, in this
+		 * corner case, resolved_name is automatically a
+		 * sub-directory of the conn_rootdir. Thus we can skip
+		 * the string comparison and the next character checks
+		 * (which are even wrong in this case).
+		 */
+		if (rootdir_len != 1) {
+			bool matched;
+
+			matched = (strncmp(conn_rootdir, resolved_name,
+					rootdir_len) == 0);
+			if (!matched || (resolved_name[rootdir_len] != '/' &&
+					 resolved_name[rootdir_len] != '\0')) {
+				DEBUG(2, ("check_reduced_name: Bad access "
+					"attempt: %s is a symlink outside the "
+					"share path\n", fname));
+				DEBUGADD(2, ("conn_rootdir =%s\n",
+					     conn_rootdir));
+				DEBUGADD(2, ("resolved_name=%s\n",
+					     resolved_name));
+				SAFE_FREE(resolved_name);
+				return NT_STATUS_ACCESS_DENIED;
+			}
 		}
 
 		/* Extra checks if all symlinks are disallowed. */
@@ -1316,7 +1344,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp)
 	int ret;
 
 	if(fsp->fh->fd == -1) {
-		if (fsp->posix_open) {
+		if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
 			ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
 		} else {
 			ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
@@ -1946,7 +1974,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                 path = fsp->fsp_name->base_name;
         }
 
-	if (fsp->posix_open || as_root) {
+	if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || as_root) {
 		ret = SMB_VFS_LCHOWN(fsp->conn,
 			path,
 			uid, gid);
diff --git a/source3/torture/nbio.c b/source3/torture/nbio.c
index 6373a10..6c87f9a 100644
--- a/source3/torture/nbio.c
+++ b/source3/torture/nbio.c
@@ -287,7 +287,7 @@ void nb_qfsinfo(int level)
 {
 	uint64_t bsize, total, avail;
 	/* this is not the right call - we need cli_qfsinfo() */
-	cli_disk_size(c, &bsize, &total, &avail);
+	cli_disk_size(c, "", &bsize, &total, &avail);
 }
 
 static NTSTATUS find_fn(const char *mnt, struct file_info *finfo, const char *name,
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 7bb776f..e75f2aa 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -5816,6 +5816,380 @@ static bool run_simple_posix_open_test(int dummy)
 	return correct;
 }
 
+/*
+  Test POSIX and Windows ACLs are rejected on symlinks.
+ */
+static bool run_acl_symlink_test(int dummy)
+{
+	static struct cli_state *cli;
+	const char *fname = "posix_file";
+	const char *sname = "posix_symlink";
+	uint16_t fnum = (uint16_t)-1;
+	bool correct = false;
+	NTSTATUS status;
+	char *posix_acl = NULL;
+	size_t posix_acl_len = 0;
+	char *posix_acl_sym = NULL;
+	size_t posix_acl_len_sym = 0;
+	struct security_descriptor *sd = NULL;
+	struct security_descriptor *sd_sym = NULL;
+	TALLOC_CTX *frame = NULL;
+
+	frame = talloc_stackframe();
+
+	printf("Starting acl symlink test\n");
+
+	if (!torture_open_connection(&cli, 0)) {
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+	status = torture_setup_unix_extensions(cli);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	cli_setatr(cli, fname, 0, 0);
+	cli_posix_unlink(cli, fname);
+	cli_setatr(cli, sname, 0, 0);
+	cli_posix_unlink(cli, sname);
+
+	status = cli_ntcreate(cli,
+			fname,
+			0,
+			READ_CONTROL_ACCESS,
+			0,
+			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+			FILE_CREATE,
+			0x0,
+			0x0,
+			&fnum,
+			NULL);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_ntcreate of %s failed (%s)\n",
+			fname,
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Get the Windows ACL on the file. */
+	status = cli_query_secdesc(cli,
+				fnum,
+				frame,
+				&sd);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_query_secdesc failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Get the POSIX ACL on the file. */
+	status = cli_posix_getacl(cli,
+				fname,
+				frame,
+				&posix_acl_len,
+				&posix_acl);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_posix_getacl failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	status = cli_close(cli, fnum);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close failed (%s)\n", nt_errstr(status));
+		goto out;
+	}
+	fnum = (uint16_t)-1;
+
+	/* Now create a symlink. */
+	status = cli_posix_symlink(cli, fname, sname);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+			sname,
+			fname,
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Open a handle on the symlink. */
+	status = cli_ntcreate(cli,
+			sname,
+			0,
+			READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
+			0,
+			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+			FILE_OPEN,
+			0x0,
+			0x0,
+			&fnum,
+			NULL);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_posix_open of %s failed (%s)\n",
+			sname,
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Get the Windows ACL on the symlink handle. Should fail */
+	status = cli_query_secdesc(cli,
+				fnum,
+				frame,
+				&sd_sym);
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		printf("cli_query_secdesc on a symlink gave %s. "
+			"Should be NT_STATUS_ACCESS_DENIED.\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Get the POSIX ACL on the symlink pathname. Should fail. */
+	status = cli_posix_getacl(cli,
+				sname,
+				frame,
+				&posix_acl_len_sym,
+				&posix_acl_sym);
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		printf("cli_posix_getacl on a symlink gave %s. "
+			"Should be NT_STATUS_ACCESS_DENIED.\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Set the Windows ACL on the symlink handle. Should fail */
+	status = cli_set_security_descriptor(cli,
+				fnum,
+				SECINFO_DACL,
+				sd);
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		printf("cli_query_secdesc on a symlink gave %s. "
+			"Should be NT_STATUS_ACCESS_DENIED.\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Set the POSIX ACL on the symlink pathname. Should fail. */
+	status = cli_posix_setacl(cli,
+				sname,
+				posix_acl,
+				posix_acl_len);
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		printf("cli_posix_getacl on a symlink gave %s. "
+			"Should be NT_STATUS_ACCESS_DENIED.\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	printf("ACL symlink test passed\n");
+	correct = true;
+
+  out:
+
+	if (fnum != (uint16_t)-1) {
+		cli_close(cli, fnum);
+		fnum = (uint16_t)-1;
+	}
+
+	cli_setatr(cli, sname, 0, 0);
+	cli_posix_unlink(cli, sname);
+	cli_setatr(cli, fname, 0, 0);
+	cli_posix_unlink(cli, fname);
+
+	if (!torture_close_connection(cli)) {
+		correct = false;
+	}
+
+	TALLOC_FREE(frame);
+	return correct;
+}
+
+/*
+  Test setting EA's are rejected on symlinks.
+ */
+static bool run_ea_symlink_test(int dummy)
+{
+	static struct cli_state *cli;
+	const char *fname = "posix_file_ea";
+	const char *sname = "posix_symlink_ea";
+	const char *ea_name = "testea_name";
+	const char *ea_value = "testea_value";
+	uint16_t fnum = (uint16_t)-1;
+	bool correct = false;
+	NTSTATUS status;
+	size_t i, num_eas;
+	struct ea_struct *eas = NULL;
+	TALLOC_CTX *frame = NULL;
+
+	frame = talloc_stackframe();
+
+	printf("Starting EA symlink test\n");
+
+	if (!torture_open_connection(&cli, 0)) {
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+	status = torture_setup_unix_extensions(cli);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(frame);
+		return false;
+	}
+
+	cli_setatr(cli, fname, 0, 0);
+	cli_posix_unlink(cli, fname);
+	cli_setatr(cli, sname, 0, 0);
+	cli_posix_unlink(cli, sname);
+
+	status = cli_ntcreate(cli,
+			fname,
+			0,
+			READ_CONTROL_ACCESS,
+			0,
+			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+			FILE_CREATE,
+			0x0,
+			0x0,
+			&fnum,
+			NULL);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_ntcreate of %s failed (%s)\n",
+			fname,
+			nt_errstr(status));
+		goto out;
+	}
+
+	status = cli_close(cli, fnum);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("close failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+	fnum = (uint16_t)-1;
+
+	/* Set an EA on the path. */
+	status = cli_set_ea_path(cli,
+				fname,
+				ea_name,
+				ea_value,
+				strlen(ea_value)+1);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_set_ea_path failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Now create a symlink. */
+	status = cli_posix_symlink(cli, fname, sname);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+			sname,
+			fname,
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Get the EA list on the path. Should return value set. */
+	status = cli_get_ea_list_path(cli,
+				fname,
+				frame,
+				&num_eas,
+				&eas);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_get_ea_list_path failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Ensure the EA we set is there. */
+	for (i=0; i<num_eas; i++) {
+		if (strcmp(eas[i].name, ea_name) == 0 &&
+				eas[i].value.length == strlen(ea_value)+1 &&
+				memcmp(eas[i].value.data,
+					ea_value,
+					eas[i].value.length) == 0) {
+			break;
+		}
+	}
+
+	if (i == num_eas) {
+		printf("Didn't find EA on pathname %s\n",
+			fname);
+		goto out;
+	}
+
+	num_eas = 0;
+	TALLOC_FREE(eas);
+
+	/* Get the EA list on the symlink. Should return empty list. */
+	status = cli_get_ea_list_path(cli,
+				sname,
+				frame,
+				&num_eas,
+				&eas);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_get_ea_list_path failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	if (num_eas != 0) {
+		printf("cli_get_ea_list_path failed (%s)\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	/* Set an EA on the symlink. Should fail. */
+	status = cli_set_ea_path(cli,
+				sname,
+				ea_name,
+				ea_value,
+				strlen(ea_value)+1);
+
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+		printf("cli_set_ea_path on a symlink gave %s. "
+			"Should be NT_STATUS_ACCESS_DENIED.\n",
+			nt_errstr(status));
+		goto out;
+	}
+
+	printf("EA symlink test passed\n");
+	correct = true;
+
+  out:
+
+	if (fnum != (uint16_t)-1) {
+		cli_close(cli, fnum);
+		fnum = (uint16_t)-1;
+	}
+
+	cli_setatr(cli, sname, 0, 0);
+	cli_posix_unlink(cli, sname);
+	cli_setatr(cli, fname, 0, 0);
+	cli_posix_unlink(cli, fname);
+
+	if (!torture_close_connection(cli)) {
+		correct = false;
+	}
+
+	TALLOC_FREE(frame);
+	return correct;
+}
 
 static uint32_t open_attrs_table[] = {
 		FILE_ATTRIBUTE_NORMAL,
@@ -8348,11 +8722,29 @@ static bool rbt_testval(struct db_context *db, const char *key,
 	return ret;
 }
 
+static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
+{
+	int *count2 = (int *)private_data;
+	(*count2)++;
+	return 0;
+}
+
+static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
+{
+	int *count2 = (int *)private_data;
+	(*count2)++;
+	dbwrap_record_delete(rec);
+	return 0;
+}
+
 static bool run_local_rbtree(int dummy)
 {
 	struct db_context *db;
 	bool ret = false;
 	int i;
+	NTSTATUS status;
+	int count = 0;
+	int count2 = 0;
 
 	db = db_open_rbt(NULL);
 
@@ -8395,6 +8787,27 @@ static bool run_local_rbtree(int dummy)
 	}
 
 	ret = true;
+	count = 0; count2 = 0;
+	status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+				      &count2, &count);
+	printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+	if ((count != count2) || (count != 1000)) {
+		ret = false;
+	}
+	count = 0; count2 = 0;
+	status = dbwrap_traverse(db, local_rbtree_traverse_delete,
+				 &count2, &count);
+	printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+	if ((count != count2) || (count != 1000)) {
+		ret = false;
+	}
+	count = 0; count2 = 0;
+	status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+				      &count2, &count);
+	printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+	if ((count != count2) || (count != 0)) {
+		ret = false;
+	}
 
  done:
 	TALLOC_FREE(db);
@@ -9604,6 +10017,8 @@ static struct {
 	{"OPEN", run_opentest, 0},
 	{"POSIX", run_simple_posix_open_test, 0},
 	{"POSIX-APPEND", run_posix_append, 0},
+	{"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
+	{"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
 	{"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
 	{"ASYNC-ECHO", run_async_echo, 0},
 	{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 2596069..d50219c 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -791,7 +791,7 @@ int main(int argc, char *argv[])
 	poptContext pc;
 	/* numeric is set when the user wants numeric SIDs and ACEs rather
 	   than going via LSA calls to resolve them */
-	int numeric;
+	int numeric = 0;
 
 	struct poptOption long_options[] = {
 		POPT_AUTOHELP
diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c
index c3eb471..127d6b1 100644
--- a/source3/utils/smbget.c
+++ b/source3/utils/smbget.c
@@ -91,10 +91,18 @@ static void human_readable(off_t s, char *buffer, int l)
 static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
 {
 	static char hasasked = 0;
+	static char *savedwg;
+	static char *savedun;
+	static char *savedpw;
 	char *wgtmp, *usertmp;
 	char tmp[128];
 
-	if(hasasked) return;
+	if (hasasked) {
+		strncpy(wg, savedwg, wglen - 1);
+		strncpy(un, savedun, unlen - 1);
+		strncpy(pw, savedpw, pwlen - 1);
+		return;
+	}
 	hasasked = 1;
 
 	if(!nonprompt && !username) {
@@ -119,6 +127,11 @@ static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen,
 
 	if(workgroup)strncpy(wg, workgroup, wglen-1);
 
+	/* save the values found for later */
+	savedwg = SMB_STRDUP(wg);
+	savedun = SMB_STRDUP(un);
+	savedpw = SMB_STRDUP(pw);
+
 	wgtmp = SMB_STRNDUP(wg, wglen); 
 	usertmp = SMB_STRNDUP(un, unlen);
 	if(!quiet)printf("Using workgroup %s, %s%s\n", wgtmp, *usertmp?"user ":"guest user", usertmp);
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 78350fd..791b05f 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -38,6 +38,7 @@
 #define DBGC_CLASS DBGC_WINBIND
 
 extern struct winbindd_methods reconnect_methods;
+extern struct winbindd_methods msrpc_methods;
 
 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
 
@@ -563,9 +564,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 			    struct dom_sid *sid,
 			    enum lsa_SidType *type)
 {
-	return reconnect_methods.name_to_sid(domain, mem_ctx,
-					     domain_name, name, flags,
-					     sid, type);
+	return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
+					 flags, sid, type);
 }
 
 /* convert a domain SID to a user or group name - use rpc methods */
@@ -576,8 +576,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 			    char **name,
 			    enum lsa_SidType *type)
 {
-	return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
-					     domain_name, name, type);
+	return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
+					 domain_name, name, type);
 }
 
 /* convert a list of rids to names - use rpc methods */
@@ -590,9 +590,9 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
 			      char ***names,
 			      enum lsa_SidType **types)
 {
-	return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
-					       rids, num_rids,
-					       domain_name, names, types);
+	return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
+					   rids, num_rids,
+					   domain_name, names, types);
 }
 
 /* If you are looking for "dn_lookup": Yes, it used to be here!
@@ -1142,10 +1142,8 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
 				   uint32_t num_sids, const struct dom_sid *sids,
 				   uint32_t *num_aliases, uint32_t **alias_rids)
 {
-	return reconnect_methods.lookup_useraliases(domain, mem_ctx,
-						    num_sids, sids,
-						    num_aliases,
-						    alias_rids);
+	return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
+						num_aliases, alias_rids);
 }
 
 static NTSTATUS add_primary_group_members(
@@ -1527,7 +1525,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
 			       struct samr_DomInfo12 *policy)
 {
-	return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
+	return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
 }
 
 /* find the password policy of a domain - use rpc methods */
@@ -1535,7 +1533,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
 				TALLOC_CTX *mem_ctx,
 				struct samr_DomInfo1 *policy)
 {
-	return reconnect_methods.password_policy(domain, mem_ctx, policy);
+	return msrpc_methods.password_policy(domain, mem_ctx, policy);
 }
 
 /* get a list of trusted domains */
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 4e270ca..3562217 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -46,7 +46,7 @@
 
 extern struct winbindd_methods reconnect_methods;
 #ifdef HAVE_ADS
-extern struct winbindd_methods ads_methods;
+extern struct winbindd_methods reconnect_ads_methods;
 #endif
 extern struct winbindd_methods builtin_passdb_methods;
 extern struct winbindd_methods sam_passdb_methods;
@@ -168,7 +168,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
 		    && domain->active_directory
 		    && !lp_winbind_rpc_only()) {
 			DEBUG(5,("get_cache: Setting ADS methods for domain %s\n", domain->name));
-			domain->backend = &ads_methods;
+			domain->backend = &reconnect_ads_methods;
 		} else {
 #endif	/* HAVE_ADS */
 			DEBUG(5,("get_cache: Setting MS-RPC methods for domain %s\n", domain->name));
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 842307f..1964fcff 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2683,6 +2683,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	NTSTATUS status, result;
 	struct netlogon_creds_cli_context *p_creds;
 	struct cli_credentials *creds = NULL;
+	bool retry = false; /* allow one retry attempt for expired session */
 
 	if (sid_check_is_our_sam(&domain->sid)) {
 		if (domain->rodc == false || need_rw_dc == false) {
@@ -2690,6 +2691,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 		}
 	}
 
+retry:
 	status = init_dc_connection_rpc(domain, need_rw_dc);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
@@ -2733,6 +2735,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 					      smbXcli_conn_remote_name(conn->cli->conn),
 					      creds,
 					      &conn->samr_pipe);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10,("cm_connect_sam: failed to connect to SAMR "
 			  "pipe for domain %s using NTLMSSP "
@@ -2753,6 +2763,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 				      SEC_FLAG_MAXIMUM_ALLOWED,
 				      &conn->sam_connect_handle,
 				      &result);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->samr_pipe);
+		retry = true;
+		goto retry;
+	}
+
 	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
 		goto open_domain;
 	}
@@ -2790,6 +2808,13 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 		(conn->cli, &ndr_table_samr, NCACN_NP,
 		 creds, p_creds, &conn->samr_pipe);
 
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for "
 			  "domain %s using schannel. Error was %s\n",
@@ -2804,6 +2829,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 				      SEC_FLAG_MAXIMUM_ALLOWED,
 				      &conn->sam_connect_handle,
 				      &result);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->samr_pipe);
+		retry = true;
+		goto retry;
+	}
+
 	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
 		goto open_domain;
 	}
@@ -2830,6 +2863,13 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
 					  &conn->samr_pipe);
 
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		goto done;
 	}
@@ -2839,6 +2879,14 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 				      SEC_FLAG_MAXIMUM_ALLOWED,
 				      &conn->sam_connect_handle,
 				      &result);
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->samr_pipe);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10,("cm_connect_sam: rpccli_samr_Connect2 failed "
 			  "for domain %s Error was %s\n",
@@ -2960,7 +3008,9 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 	struct netlogon_creds_cli_context *p_creds;
 	struct cli_credentials *creds = NULL;
+	bool retry = false; /* allow one retry attempt for expired session */
 
+retry:
 	result = init_dc_connection_rpc(domain, false);
 	if (!NT_STATUS_IS_OK(result))
 		return result;
@@ -2995,6 +3045,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 		 smbXcli_conn_remote_name(conn->cli->conn),
 		 creds,
 		 &conn->lsa_pipe);
+
+	if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
 			  "domain %s using NTLMSSP authenticated pipe: user "
@@ -3012,6 +3070,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
 					SEC_FLAG_MAXIMUM_ALLOWED,
 					&conn->lsa_policy);
+	if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->lsa_pipe);
+		retry = true;
+		goto retry;
+	}
+
 	if (NT_STATUS_IS_OK(result)) {
 		goto done;
 	}
@@ -3047,6 +3112,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 		(conn->cli, &ndr_table_lsarpc, NCACN_NP,
 		 creds, p_creds, &conn->lsa_pipe);
 
+	if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(result)) {
 		DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for "
 			  "domain %s using schannel. Error was %s\n",
@@ -3059,6 +3131,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
 					SEC_FLAG_MAXIMUM_ALLOWED,
 					&conn->lsa_policy);
+
+	if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->lsa_pipe);
+		retry = true;
+		goto retry;
+	}
+
 	if (NT_STATUS_IS_OK(result)) {
 		goto done;
 	}
@@ -3083,6 +3163,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	result = cli_rpc_pipe_open_noauth(conn->cli,
 					  &ndr_table_lsarpc,
 					  &conn->lsa_pipe);
+
+	if (NT_STATUS_EQUAL(result, NT_STATUS_NETWORK_SESSION_EXPIRED)
+	    && !retry) {
+		invalidate_cm_connection(domain);
+		retry = true;
+		goto retry;
+	}
+
 	if (!NT_STATUS_IS_OK(result)) {
 		goto done;
 	}
@@ -3090,6 +3178,14 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	result = rpccli_lsa_open_policy(conn->lsa_pipe, mem_ctx, True,
 					SEC_FLAG_MAXIMUM_ALLOWED,
 					&conn->lsa_policy);
+
+	if (NT_STATUS_EQUAL(result, NT_STATUS_IO_DEVICE_ERROR) && !retry) {
+		invalidate_cm_connection(domain);
+		TALLOC_FREE(conn->lsa_pipe);
+		retry = true;
+		goto retry;
+	}
+
  done:
 	if (!NT_STATUS_IS_OK(result)) {
 		invalidate_cm_connection(domain);
@@ -3312,6 +3408,14 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
 	}
 
 	status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+		/*
+		 * SMB2 session expired, needs reauthentication. Drop
+		 * connection and retry.
+		 */
+		invalidate_cm_connection(domain);
+		status = cm_connect_netlogon_transport(domain, NCACN_NP, cli);
+	}
 
 	return status;
 }
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 44e4842..cdd9bbd 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -741,14 +741,6 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
 
 reconnect:
 	status = cm_connect_netlogon(domain, &netlogon_pipe);
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
-		/*
-		 * Retry to open new connection with new kerberos ticket.
-		 */
-		invalidate_cm_connection(domain);
-		status = cm_connect_netlogon(domain, &netlogon_pipe);
-	}
-
 	reset_cm_connection_on_error(domain, status);
         if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(3, ("could not open handle to NETLOGON pipe: %s\n",
diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c
index 37b7e02..029e883 100644
--- a/source3/winbindd/winbindd_ndr.c
+++ b/source3/winbindd/winbindd_ndr.c
@@ -75,6 +75,7 @@ void ndr_print_winbindd_cm_conn(struct ndr_print *ndr,
 
 #ifdef HAVE_ADS
 extern struct winbindd_methods ads_methods;
+extern struct winbindd_methods reconnect_ads_methods;
 #endif
 extern struct winbindd_methods msrpc_methods;
 extern struct winbindd_methods builtin_passdb_methods;
@@ -100,6 +101,8 @@ void ndr_print_winbindd_methods(struct ndr_print *ndr,
 #ifdef HAVE_ADS
 	} else if (r == &ads_methods) {
 		ndr_print_string(ndr, name, "ads_methods");
+	} else if (r == &reconnect_ads_methods) {
+		ndr_print_string(ndr, name, "reconnect_ads_methods");
 #endif
 	} else if (r == &builtin_passdb_methods) {
 		ndr_print_string(ndr, name, "builtin_passdb_methods");
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 9920a3f..6e50718 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -933,4 +933,8 @@ ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name);
 
 /* The following definitions come from winbindd/winbindd_irpc.c  */
 NTSTATUS wb_irpc_register(void);
+
+/* The following definitions come from winbindd/winbindd_reconnect.c  */
+bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain);
+
 #endif /*  _WINBINDD_PROTO_H_  */
diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect.c
index e45f9b1..f7dd805 100644
--- a/source3/winbindd/winbindd_reconnect.c
+++ b/source3/winbindd/winbindd_reconnect.c
@@ -27,7 +27,7 @@
 
 extern struct winbindd_methods msrpc_methods;
 
-static bool reconnect_need_retry(NTSTATUS status)
+bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain)
 {
 	if (NT_STATUS_IS_OK(status)) {
 		return false;
@@ -69,6 +69,14 @@ static bool reconnect_need_retry(NTSTATUS status)
 		return false;
 	}
 
+	if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) {
+		/*
+		 * RPC call sent on expired session, needs
+		 * reauthentication.
+		 */
+		invalidate_cm_connection(domain);
+	}
+
 	return true;
 }
 
@@ -83,7 +91,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
 	result = msrpc_methods.query_user_list(domain, mem_ctx,
 					       num_entries, info);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.query_user_list(domain, mem_ctx,
 						       num_entries, info);
 	return result;
@@ -100,7 +108,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
 	result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
 					       num_entries, info);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
 						       num_entries, info);
 	return result;
@@ -118,7 +126,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 	result = msrpc_methods.enum_local_groups(domain, mem_ctx,
 						 num_entries, info);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.enum_local_groups(domain, mem_ctx,
 							 num_entries, info);
 
@@ -139,7 +147,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 	result = msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
 					   flags, sid, type);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.name_to_sid(domain, mem_ctx,
 						   domain_name, name, flags,
 						   sid, type);
@@ -162,7 +170,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 	result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
 					   domain_name, name, type);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
 						   domain_name, name, type);
 
@@ -183,7 +191,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
 	result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
 					     rids, num_rids,
 					     domain_name, names, types);
-	if (reconnect_need_retry(result)) {
+	if (reconnect_need_retry(result, domain)) {
 		result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
 						     rids, num_rids,
 						     domain_name, names,
@@ -204,7 +212,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 	result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
 					  user_info);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
 						  user_info);
 
@@ -223,7 +231,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
 						 user_sid, num_groups,
 						 user_gids);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
 							 user_sid, num_groups,
 							 user_gids);
@@ -243,7 +251,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
 						  num_aliases,
 						  alias_rids);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
 							  num_sids, sids,
 							  num_aliases,
@@ -268,7 +276,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 					       sid_mem, names,
 					       name_types);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
 						       group_sid, type,
 						       num_names,
@@ -285,7 +293,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
 
 	result = msrpc_methods.sequence_number(domain, seq);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.sequence_number(domain, seq);
 
 	return result;
@@ -300,7 +308,7 @@ static NTSTATUS lockout_policy(struct winbindd_domain *domain,
 
 	result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
 
 	return result;
@@ -315,7 +323,7 @@ static NTSTATUS password_policy(struct winbindd_domain *domain,
  
 	result = msrpc_methods.password_policy(domain, mem_ctx, policy);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.password_policy(domain, mem_ctx, policy);
 	
 	return result;
@@ -330,7 +338,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 
 	result = msrpc_methods.trusted_domains(domain, mem_ctx, trusts);
 
-	if (reconnect_need_retry(result))
+	if (reconnect_need_retry(result, domain))
 		result = msrpc_methods.trusted_domains(domain, mem_ctx,
 						       trusts);
 
diff --git a/source3/winbindd/winbindd_reconnect.c b/source3/winbindd/winbindd_reconnect_ads.c
similarity index 50%
copy from source3/winbindd/winbindd_reconnect.c
copy to source3/winbindd/winbindd_reconnect_ads.c
index e45f9b1..7ea8298 100644
--- a/source3/winbindd/winbindd_reconnect.c
+++ b/source3/winbindd/winbindd_reconnect_ads.c
@@ -1,20 +1,22 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
-   Wrapper around winbindd_rpc.c to centralize retry logic.
+   Wrapper around winbindd_ads.c to centralize retry logic.
+   Copyright (C) Christof Schmitt 2016
 
+   Based on winbindd_reconnect.c
    Copyright (C) Volker Lendecke 2005
-   
+
    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
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -22,55 +24,12 @@
 #include "includes.h"
 #include "winbindd.h"
 
+#ifdef HAVE_ADS
+
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-extern struct winbindd_methods msrpc_methods;
-
-static bool reconnect_need_retry(NTSTATUS status)
-{
-	if (NT_STATUS_IS_OK(status)) {
-		return false;
-	}
-
-	if (!NT_STATUS_IS_ERR(status)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_MEMBER)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_PRIVILEGE)) {
-		return false;
-	}
-
-	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
-		return false;
-	}
-
-	return true;
-}
+extern struct winbindd_methods ads_methods;
 
 /* List all users */
 static NTSTATUS query_user_list(struct winbindd_domain *domain,
@@ -80,12 +39,14 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.query_user_list(domain, mem_ctx,
-					       num_entries, info);
+	result = ads_methods.query_user_list(domain, mem_ctx,
+					     num_entries, info);
+
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.query_user_list(domain, mem_ctx,
+						     num_entries, info);
+	}
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.query_user_list(domain, mem_ctx,
-						       num_entries, info);
 	return result;
 }
 
@@ -97,17 +58,18 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
-					       num_entries, info);
+	result = ads_methods.enum_dom_groups(domain, mem_ctx,
+					     num_entries, info);
+
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.enum_dom_groups(domain, mem_ctx,
+						     num_entries, info);
+	}
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
-						       num_entries, info);
 	return result;
 }
 
 /* List all domain groups */
-
 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 				  TALLOC_CTX *mem_ctx,
 				  uint32_t *num_entries,
@@ -115,12 +77,13 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.enum_local_groups(domain, mem_ctx,
-						 num_entries, info);
+	result = ads_methods.enum_local_groups(domain, mem_ctx,
+					       num_entries, info);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.enum_local_groups(domain, mem_ctx,
-							 num_entries, info);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.enum_local_groups(domain, mem_ctx,
+						       num_entries, info);
+	}
 
 	return result;
 }
@@ -136,13 +99,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
-					   flags, sid, type);
+	result = ads_methods.name_to_sid(domain, mem_ctx, domain_name, name,
+					 flags, sid, type);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.name_to_sid(domain, mem_ctx,
-						   domain_name, name, flags,
-						   sid, type);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.name_to_sid(domain, mem_ctx,
+						 domain_name, name, flags,
+						 sid, type);
+	}
 
 	return result;
 }
@@ -159,12 +123,12 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
-					   domain_name, name, type);
+	result = ads_methods.sid_to_name(domain, mem_ctx, sid,
+					 domain_name, name, type);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
-						   domain_name, name, type);
+	if (reconnect_need_retry(result, domain))
+		result = ads_methods.sid_to_name(domain, mem_ctx, sid,
+						 domain_name, name, type);
 
 	return result;
 }
@@ -180,33 +144,32 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
-					     rids, num_rids,
-					     domain_name, names, types);
-	if (reconnect_need_retry(result)) {
-		result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
-						     rids, num_rids,
-						     domain_name, names,
-						     types);
+	result = ads_methods.rids_to_names(domain, mem_ctx, sid,
+					   rids, num_rids,
+					   domain_name, names, types);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.rids_to_names(domain, mem_ctx, sid,
+						   rids, num_rids, domain_name,
+						   names, types);
 	}
 
 	return result;
 }
 
 /* Lookup user information from a rid or username. */
-static NTSTATUS query_user(struct winbindd_domain *domain, 
-			   TALLOC_CTX *mem_ctx, 
+static NTSTATUS query_user(struct winbindd_domain *domain,
+			   TALLOC_CTX *mem_ctx,
 			   const struct dom_sid *user_sid,
 			   struct wbint_userinfo *user_info)
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
-					  user_info);
+	result = ads_methods.query_user(domain, mem_ctx, user_sid, user_info);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.query_user(domain, mem_ctx, user_sid,
-						  user_info);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.query_user(domain, mem_ctx, user_sid,
+						user_info);
+	}
 
 	return result;
 }
@@ -215,39 +178,40 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
 				  TALLOC_CTX *mem_ctx,
 				  const struct dom_sid *user_sid,
-				  uint32_t *num_groups, struct dom_sid **user_gids)
+				  uint32_t *num_groups,
+				  struct dom_sid **user_gids)
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
-						 user_sid, num_groups,
-						 user_gids);
+	result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid,
+					       num_groups, user_gids);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
-							 user_sid, num_groups,
-							 user_gids);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.lookup_usergroups(domain, mem_ctx,
+						       user_sid, num_groups,
+						       user_gids);
+	}
 
 	return result;
 }
 
 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
 				   TALLOC_CTX *mem_ctx,
-				   uint32_t num_sids, const struct dom_sid *sids,
+				   uint32_t num_sids,
+				   const struct dom_sid *sids,
 				   uint32_t *num_aliases, uint32_t **alias_rids)
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
-						  num_sids, sids,
-						  num_aliases,
-						  alias_rids);
+	result = ads_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
+						num_aliases, alias_rids);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
-							  num_sids, sids,
-							  num_aliases,
-							  alias_rids);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.lookup_useraliases(domain, mem_ctx,
+							num_sids, sids,
+							num_aliases,
+							alias_rids);
+	}
 
 	return result;
 }
@@ -263,17 +227,15 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
-					       group_sid, type, num_names,
-					       sid_mem, names,
-					       name_types);
+	result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid, type,
+					     num_names, sid_mem, names,
+					     name_types);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
-						       group_sid, type,
-						       num_names,
-						       sid_mem, names,
-						       name_types);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid,
+						     type, num_names, sid_mem,
+						     names, name_types);
+	}
 
 	return result;
 }
@@ -283,41 +245,44 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.sequence_number(domain, seq);
+	result = ads_methods.sequence_number(domain, seq);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.sequence_number(domain, seq);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.sequence_number(domain, seq);
+	}
 
 	return result;
 }
 
 /* find the lockout policy of a domain */
-static NTSTATUS lockout_policy(struct winbindd_domain *domain, 
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
 			       TALLOC_CTX *mem_ctx,
 			       struct samr_DomInfo12 *policy)
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+	result = ads_methods.lockout_policy(domain, mem_ctx, policy);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.lockout_policy(domain, mem_ctx, policy);
+	}
 
 	return result;
 }
 
 /* find the password policy of a domain */
-static NTSTATUS password_policy(struct winbindd_domain *domain, 
+static NTSTATUS password_policy(struct winbindd_domain *domain,
 				TALLOC_CTX *mem_ctx,
 				struct samr_DomInfo1 *policy)
 {
- 	NTSTATUS result;
- 
-	result = msrpc_methods.password_policy(domain, mem_ctx, policy);
+	NTSTATUS result;
+
+	result = ads_methods.password_policy(domain, mem_ctx, policy);
+
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.password_policy(domain, mem_ctx, policy);
+	}
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.password_policy(domain, mem_ctx, policy);
-	
 	return result;
 }
 
@@ -328,18 +293,18 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 {
 	NTSTATUS result;
 
-	result = msrpc_methods.trusted_domains(domain, mem_ctx, trusts);
+	result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
 
-	if (reconnect_need_retry(result))
-		result = msrpc_methods.trusted_domains(domain, mem_ctx,
-						       trusts);
+	if (reconnect_need_retry(result, domain)) {
+		result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
+	}
 
 	return result;
 }
 
 /* the rpc backend methods are exposed via this structure */
-struct winbindd_methods reconnect_methods = {
-	False,
+struct winbindd_methods reconnect_ads_methods = {
+	true,
 	query_user_list,
 	enum_dom_groups,
 	enum_local_groups,
@@ -355,3 +320,5 @@ struct winbindd_methods reconnect_methods = {
 	password_policy,
 	trusted_domains,
 };
+
+#endif
diff --git a/source3/wscript_build b/source3/wscript_build
index ace4b99..ba670d3 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -908,6 +908,7 @@ bld.SAMBA3_BINARY('winbindd/winbindd',
                  winbindd/winbindd_msrpc.c
                  winbindd/winbindd_rpc.c
                  winbindd/winbindd_reconnect.c
+                 winbindd/winbindd_reconnect_ads.c
                  winbindd/winbindd_ads.c
                  winbindd/winbindd_samr.c
                  winbindd/winbindd_dual.c
@@ -1185,6 +1186,14 @@ bld.SAMBA3_BINARY('smbspool',
                  libsmb
                  samba3core''')
 
+bld.SAMBA3_BINARY('smbspool_krb5_wrapper',
+                 source='client/smbspool_krb5_wrapper.c',
+                 deps='''
+                 DYNCONFIG
+                 cups
+                 ''',
+                 enabled=bld.CONFIG_SET('HAVE_CUPS'))
+
 bld.SAMBA3_BINARY('testparm',
                  source='utils/testparm.c',
                  deps='''
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index 17f3cfc..43c7a3d 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -294,6 +294,7 @@ static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_con
 		struct samr_Password *nt_history_pwd = NULL;
 		struct samr_Password *lm_history_pwd = NULL;
 		NTTIME pwdLastSet;
+		struct timeval tv_now;
 		NTTIME now;
 		int allowed_period_mins;
 		NTTIME allowed_period;
@@ -414,7 +415,8 @@ static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_con
 		 */
 		allowed_period = allowed_period_mins * 60 * 1000*1000*10;
 		pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0);
-		unix_to_nt_time(&now, time(NULL));
+		tv_now = timeval_current();
+		now = timeval_to_nttime(&tv_now);
 
 		if (now < pwdLastSet) {
 			/*
@@ -491,6 +493,7 @@ static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
 				     DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key)
 {
 	NTSTATUS nt_status;
+	bool interactive = (user_info->password_state == AUTH_PASSWORD_HASH);
 	uint16_t acct_flags = samdb_result_acct_flags(msg, NULL);
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 	if (!tmp_ctx) {
@@ -526,7 +529,9 @@ static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
 		return nt_status;
 	}
 
-	nt_status = authsam_zero_bad_pwd_count(auth_context->sam_ctx, msg);
+	nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
+						     msg, domain_dn,
+						     interactive);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		TALLOC_FREE(tmp_ctx);
 		return nt_status;
diff --git a/source4/auth/sam.c b/source4/auth/sam.c
index f7bc693..cdfe8dd 100644
--- a/source4/auth/sam.c
+++ b/source4/auth/sam.c
@@ -83,6 +83,7 @@ const char *user_attrs[] = {
 	"homeDirectory",
 	"homeDrive",
 	"lastLogon",
+	"lastLogonTimestamp",
 	"lastLogoff",
 	"accountExpires",
 	"badPwdCount",
@@ -691,20 +692,132 @@ NTSTATUS authsam_update_bad_pwd_count(struct ldb_context *sam_ctx,
 	return NT_STATUS_OK;
 }
 
-NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
-				    const struct ldb_message *msg)
+
+static NTSTATUS authsam_update_lastlogon_timestamp(struct ldb_context *sam_ctx,
+					    struct ldb_message *msg_mod,
+					    struct ldb_dn *domain_dn,
+					    NTTIME old_timestamp,
+					    NTTIME now)
+{
+	/*
+	 * We only set lastLogonTimestamp if the current value is older than
+	 * now - msDS-LogonTimeSyncInterval days.
+	 *
+	 * msDS-LogonTimeSyncInterval is an int32_t number of days, while
+	 * lastLogonTimestamp is in the 64 bit 100ns NTTIME format.
+	 *
+	 * The docs say: "the initial update, after the domain functional
+	 * level is raised to DS_BEHAVIOR_WIN2003 or higher, is calculated as
+	 * 14 days minus a random percentage of 5 days", but we aren't doing
+	 * that. The blogosphere seems to think that this randomised update
+	 * happens everytime, but [MS-ADA1] doesn't agree.
+	 *
+	 * Dochelp referred us to the following blog post:
+	 * http://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx
+	 *
+	 * en msDS-LogonTimeSyncInterval is zero, the lastLogonTimestamp is
+	 * not changed.
+	 */
+	static const char *attrs[] = { "msDS-LogonTimeSyncInterval",
+					NULL };
+	int ret;
+	struct ldb_result *domain_res = NULL;
+	TALLOC_CTX *mem_ctx = NULL;
+	int32_t sync_interval;
+	NTTIME sync_interval_nt;
+
+	mem_ctx = talloc_new(msg_mod);
+	if (mem_ctx == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ret = dsdb_search_dn(sam_ctx, mem_ctx, &domain_res, domain_dn, attrs,
+			     0);
+	if (ret != LDB_SUCCESS || domain_res->count != 1) {
+		TALLOC_FREE(mem_ctx);
+		return NT_STATUS_INTERNAL_DB_CORRUPTION;
+	}
+
+	sync_interval = ldb_msg_find_attr_as_int(domain_res->msgs[0],
+						 "msDS-LogonTimeSyncInterval",
+						 14);
+	DEBUG(5, ("sync interval is %d\n", sync_interval));
+	if (sync_interval == 0){
+		/*
+		 * Setting msDS-LogonTimeSyncInterval to zero is how you ask
+		 * that nothing happens here.
+		 */
+		TALLOC_FREE(mem_ctx);
+		return NT_STATUS_OK;
+	}
+	else if (sync_interval >= 5){
+		/*
+		 * Subtract "a random percentage of 5" days. Presumably this
+		 * percentage is between 0 and 100, and modulus is accurate
+		 * enough.
+		 */
+		uint32_t r = generate_random() % 6;
+		sync_interval -= r;
+		DEBUG(5, ("randomised sync interval is %d (-%d)\n", sync_interval, r));
+	}
+	/* In the case where sync_interval < 5 there is no randomisation */
+
+	sync_interval_nt = sync_interval * 24LL * 3600LL * 10000000LL;
+
+	DEBUG(5, ("old timestamp is %lld, threshold %lld, diff %lld\n",
+		  (long long int)old_timestamp,
+		  (long long int)(now - sync_interval_nt),
+		  (long long int)(old_timestamp - now + sync_interval_nt)));
+
+	if (old_timestamp > now){
+		DEBUG(0, ("lastLogonTimestamp is in the future! (%lld > %lld)\n",
+			  (long long int)old_timestamp, (long long int)now));
+		/* then what? */
+
+	} else if (old_timestamp < now - sync_interval_nt){
+		DEBUG(5, ("updating lastLogonTimestamp to %lld\n",
+			  (long long int)now));
+
+		/* The time has come to update lastLogonTimestamp */
+		ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod,
+					  "lastLogonTimestamp", now);
+
+		if (ret != LDB_SUCCESS) {
+			TALLOC_FREE(mem_ctx);
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+	TALLOC_FREE(mem_ctx);
+	return NT_STATUS_OK;
+}
+
+
+
+/* Reset the badPwdCount to zero and update the lastLogon time. */
+NTSTATUS authsam_logon_success_accounting(struct ldb_context *sam_ctx,
+					  const struct ldb_message *msg,
+					  struct ldb_dn *domain_dn,
+					  bool interactive_or_kerberos)
 {
 	int ret;
+	NTSTATUS status;
 	int badPwdCount;
 	int64_t lockoutTime;
 	struct ldb_message *msg_mod;
 	TALLOC_CTX *mem_ctx;
+	struct timeval tv_now;
+	NTTIME now;
+	NTTIME lastLogonTimestamp;
+	NTTIME lastLogon;
 
 	lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0);
 	badPwdCount = ldb_msg_find_attr_as_int(msg, "badPwdCount", 0);
-	if (lockoutTime == 0 && badPwdCount == 0) {
-		return NT_STATUS_OK;
-	}
+	lastLogonTimestamp = \
+		ldb_msg_find_attr_as_int64(msg, "lastLogonTimestamp", 0);
+	lastLogon = ldb_msg_find_attr_as_int64(msg, "lastLogon", 0);
+
+	DEBUG(5, ("lastLogonTimestamp is %lld\n",
+		  (long long int)lastLogonTimestamp));
 
 	mem_ctx = talloc_new(msg);
 	if (mem_ctx == NULL) {
@@ -726,7 +839,7 @@ NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
 			TALLOC_FREE(mem_ctx);
 			return NT_STATUS_NO_MEMORY;
 		}
-	} else {
+	} else if (badPwdCount != 0) {
 		ret = samdb_msg_add_int(sam_ctx, msg_mod, msg_mod, "badPwdCount", 0);
 		if (ret != LDB_SUCCESS) {
 			TALLOC_FREE(mem_ctx);
@@ -734,14 +847,37 @@ NTSTATUS authsam_zero_bad_pwd_count(struct ldb_context *sam_ctx,
 		}
 	}
 
-	ret = dsdb_replace(sam_ctx, msg_mod, 0);
-	if (ret != LDB_SUCCESS) {
-		DEBUG(0, ("Failed to set badPwdCount and lockoutTime to 0 on %s: %s\n",
-			  ldb_dn_get_linearized(msg_mod->dn), ldb_errstring(sam_ctx)));
+	tv_now = timeval_current();
+	now = timeval_to_nttime(&tv_now);
+
+	if (interactive_or_kerberos || lastLogon == 0 ||
+	    (badPwdCount != 0 && lockoutTime == 0)) {
+		ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod,
+					  "lastLogon", now);
+		if (ret != LDB_SUCCESS) {
+			TALLOC_FREE(mem_ctx);
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+	status = authsam_update_lastlogon_timestamp(sam_ctx, msg_mod, domain_dn,
+						    lastLogonTimestamp, now);
+	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(mem_ctx);
-		return NT_STATUS_INTERNAL_ERROR;
+		return NT_STATUS_NO_MEMORY;
 	}
 
+	if (msg_mod->num_elements > 0) {
+		ret = dsdb_replace(sam_ctx, msg_mod, 0);
+		if (ret != LDB_SUCCESS) {
+			DEBUG(0, ("Failed to set badPwdCount and lockoutTime "
+				  "to 0 and/or  lastlogon to now (%lld) "
+				  "%s: %s\n", (long long int)now,
+				  ldb_dn_get_linearized(msg_mod->dn),
+				  ldb_errstring(sam_ctx)));
+			TALLOC_FREE(mem_ctx);
+			return NT_STATUS_INTERNAL_ERROR;
+		}
+	}
 	TALLOC_FREE(mem_ctx);
 	return NT_STATUS_OK;
 }
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 4e3c6cc..9e30b71 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -46,8 +46,7 @@ static WERROR create_response_rr(const struct dns_name_question *question,
 {
 	struct dns_res_rec *ans = *answers;
 	uint16_t ai = *ancount;
-	char *tmp;
-	uint32_t i;
+	enum ndr_err_code ndr_err;
 
 	ZERO_STRUCT(ans[ai]);
 
@@ -101,14 +100,12 @@ static WERROR create_response_rr(const struct dns_name_question *question,
 		}
 		break;
 	case DNS_QTYPE_TXT:
-		tmp = talloc_asprintf(ans, "\"%s\"", rec->data.txt.str[0]);
-		W_ERROR_HAVE_NO_MEMORY(tmp);
-		for (i=1; i<rec->data.txt.count; i++) {
-			tmp = talloc_asprintf_append_buffer(
-				tmp, " \"%s\"", rec->data.txt.str[i]);
-			W_ERROR_HAVE_NO_MEMORY(tmp);
+		ndr_err = ndr_dnsp_string_list_copy(ans,
+						    &rec->data.txt,
+						    &ans[ai].rdata.txt_record.txt);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			return WERR_NOMEM;
 		}
-		ans[ai].rdata.txt_record.txt = tmp;
 		break;
 	default:
 		DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
index c002b4d..60a4b36 100644
--- a/source4/dns_server/dns_update.c
+++ b/source4/dns_server/dns_update.c
@@ -299,9 +299,7 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
 			     const struct dns_res_rec *rrec,
 			     struct dnsp_DnssrvRpcRecord *r)
 {
-	char *tmp;
-	char *txt_record_txt;
-	char *saveptr = NULL;
+	enum ndr_err_code ndr_err;
 
 	if (rrec->rr_type == DNS_QTYPE_ALL) {
 		return DNS_ERR(FORMAT_ERROR);
@@ -354,28 +352,11 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
 		W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
 		break;
 	case DNS_QTYPE_TXT:
-		r->data.txt.count = 0;
-		r->data.txt.str = talloc_array(mem_ctx, const char *,
-					       r->data.txt.count);
-		W_ERROR_HAVE_NO_MEMORY(r->data.txt.str);
-
-		txt_record_txt = talloc_strdup(r->data.txt.str,
-					       rrec->rdata.txt_record.txt);
-		W_ERROR_HAVE_NO_MEMORY(txt_record_txt);
-
-		tmp = strtok_r(txt_record_txt, "\"", &saveptr);
-		while (tmp) {
-			if (strcmp(tmp, " ") == 0) {
-				tmp = strtok_r(NULL, "\"", &saveptr);
-				continue;
-			}
-			r->data.txt.str = talloc_realloc(mem_ctx, r->data.txt.str, const char *,
-							r->data.txt.count+1);
-			r->data.txt.str[r->data.txt.count] = talloc_strdup(r->data.txt.str, tmp);
-			W_ERROR_HAVE_NO_MEMORY(r->data.txt.str[r->data.txt.count]);
-
-			r->data.txt.count++;
-			tmp = strtok_r(NULL, "\"", &saveptr);
+		ndr_err = ndr_dnsp_string_list_copy(mem_ctx,
+						    &rrec->rdata.txt_record.txt,
+						    &r->data.txt);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			return WERR_NOMEM;
 		}
 
 		break;
diff --git a/source4/dsdb/tests/python/password_lockout.py b/source4/dsdb/tests/python/password_lockout.py
index 133b40b..e6badbc 100755
--- a/source4/dsdb/tests/python/password_lockout.py
+++ b/source4/dsdb/tests/python/password_lockout.py
@@ -51,10 +51,24 @@ if len(args) < 1:
 host = args[0]
 
 lp = sambaopts.get_loadparm()
-creds = credopts.get_credentials(lp)
+global_creds = credopts.get_credentials(lp)
 
 # Force an encrypted connection
-creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
+global_creds.set_gensec_features(global_creds.get_gensec_features() |
+                                 gensec.FEATURE_SEAL)
+
+def insta_creds(template=global_creds):
+    # get a copy of the global creds or a the passed in creds
+    c = Credentials()
+    c.set_username("testuser")
+    c.set_password("thatsAcomplPASS1")
+    c.set_domain(template.get_domain())
+    c.set_realm(template.get_realm())
+    c.set_workstation(template.get_workstation())
+    c.set_gensec_features(c.get_gensec_features()
+                          | gensec.FEATURE_SEAL)
+    c.set_kerberos_state(template.get_kerberos_state())
+    return c
 
 #
 # Tests start here
@@ -129,6 +143,12 @@ userAccountControl: %d
         if mode == "ignore":
             return
 
+        if mode == "absent":
+            self.assertFalse(name in res[0],
+                            msg="attr[%s] not missing on dn[%s]" %
+                            (name, res[0].dn))
+            return
+
         self.assertTrue(name in res[0],
                         msg="attr[%s] missing on dn[%s]" %
                         (name, res[0].dn))
@@ -136,39 +156,56 @@ userAccountControl: %d
                         msg="attr[%s]=%r on dn[%s]" %
                         (name, res[0][name], res[0].dn))
 
+
+        print  "%s = '%s'" % (name, res[0][name][0])
+
         if mode == "present":
             return
+
         if mode == "equal":
-            self.assertTrue(str(res[0][name][0]) == str(value),
-                            msg="attr[%s]=[%s] != [%s] on dn[%s]" %
-                            (name, str(res[0][name][0]), str(value), res[0].dn))
+            v = int(res[0][name][0])
+            value = int(value)
+            msg = ("attr[%s]=[%s] != [%s] on dn[%s]\n"
+                   "(diff %d; actual value is %s than expected)"  %
+                   (name, v, value, res[0].dn, v - value,
+                    ('less' if v < value else 'greater')))
+
+            self.assertTrue(v == value, msg)
             return
+
         if mode == "greater":
             v = int(res[0][name][0])
             self.assertTrue(v > int(value),
-                            msg="attr[%s]=[%s] <= [%s] on dn[%s]" %
-                            (name, v, int(value), res[0].dn))
+                            msg="attr[%s]=[%s] <= [%s] on dn[%s] (diff %d)" %
+                            (name, v, int(value), res[0].dn, v - int(value)))
             return
         if mode == "less":
             v = int(res[0][name][0])
             self.assertTrue(v < int(value),
-                            msg="attr[%s]=[%s] >= [%s] on dn[%s]" %
-                            (name, v, int(value), res[0].dn))
+                            msg="attr[%s]=[%s] >= [%s] on dn[%s] (diff %d)" %
+                            (name, v, int(value), res[0].dn, v - int(value)))
             return
         self.assertEqual(mode, not mode, "Invalid Mode[%s]" % mode)
 
     def _check_account(self, dn,
                        badPwdCount=None,
                        badPasswordTime=None,
+                       lastLogon=None,
+                       lastLogonTimestamp=None,
                        lockoutTime=None,
                        userAccountControl=None,
                        msDSUserAccountControlComputed=None,
-                       effective_bad_password_count=None):
-
+                       effective_bad_password_count=None,
+                       msg=None):
+        print '-=' * 36
+        if msg is not None:
+            print  "\033[01;32m %s \033[00m\n" % msg
         attrs = [
            "objectSid",
            "badPwdCount",
            "badPasswordTime",
+           "lastLogon",
+           "lastLogonTimestamp",
            "lockoutTime",
            "userAccountControl",
            "msDS-User-Account-Control-Computed"
@@ -182,6 +219,8 @@ userAccountControl: %d
         self.assertTrue(len(res) == 1)
         self._check_attribute(res, "badPwdCount", badPwdCount)
         self._check_attribute(res, "badPasswordTime", badPasswordTime)
+        self._check_attribute(res, "lastLogon", lastLogon)
+        self._check_attribute(res, "lastLogonTimestamp", lastLogonTimestamp)
         self._check_attribute(res, "lockoutTime", lockoutTime)
         self._check_attribute(res, "userAccountControl", userAccountControl)
         self._check_attribute(res, "msDS-User-Account-Control-Computed",
@@ -233,10 +272,21 @@ userAccountControl: %d
         time.sleep(0.01)
         return res
 
+    def assertLoginFailure(self, url, creds, lp, errno=ERR_INVALID_CREDENTIALS):
+        try:
+            ldb = SamDB(url=url, credentials=creds, lp=lp)
+            self.fail("Login unexpectedly succeeded")
+        except LdbError, (num, msg):
+            if errno is not None:
+                self.assertEquals(num, errno, ("Login failed in the wrong way"
+                                               "(got err %d, expected %d)" %
+                                               (num, errno)))
+
     def setUp(self):
         super(PasswordTests, self).setUp()
 
-        self.ldb = SamDB(url=host_url, session_info=system_session(lp), credentials=creds, lp=lp)
+        self.ldb = SamDB(url=host_url, session_info=system_session(lp),
+                         credentials=global_creds, lp=lp)
 
         # Gets back the basedn
         base_dn = self.ldb.domain_dn()
@@ -315,7 +365,7 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
         self.base_dn = self.ldb.domain_dn()
 
         self.domain_sid = security.dom_sid(self.ldb.get_domain_sid())
-        self.samr = samr.samr("ncacn_ip_tcp:%s[sign]" % host, lp, creds)
+        self.samr = samr.samr("ncacn_ip_tcp:%s[sign]" % host, lp, global_creds)
         self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
         self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
 
@@ -329,6 +379,8 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=0,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -343,6 +395,8 @@ lockoutThreshold: """ + str(lockoutThreshold) + """
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=0,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -371,6 +425,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", 0),
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -394,6 +450,8 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -406,6 +464,8 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -413,24 +473,22 @@ userPassword: thatsAcomplPASS1
         # Open a second LDB connection with the user credentials. Use the
         # command line credentials for informations like the domain, the realm
         # and the workstation.
-        creds2 = Credentials()
-        creds2.set_username("testuser")
-        creds2.set_password("thatsAcomplPASS1")
-        creds2.set_domain(creds.get_domain())
-        creds2.set_realm(creds.get_realm())
-        creds2.set_workstation(creds.get_workstation())
-        creds2.set_gensec_features(creds2.get_gensec_features()
-                                                          | gensec.FEATURE_SEAL)
+        creds2 = insta_creds()
 
         self.ldb2 = SamDB(url=host_url, credentials=creds2, lp=lp)
 
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=('greater', 0),
+                                  lastLogonTimestamp=('greater', 0),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
 
+        lastLogon = int(res[0]["lastLogon"][0])
+        self.assertGreater(lastLogon, badPasswordTime)
+
      # (Re)adds the test user "testuser3" with no password atm
         delete_force(self.ldb, "cn=testuser3,cn=users," + self.base_dn)
         self.ldb.add({
@@ -441,6 +499,8 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=0,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -469,6 +529,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", 0),
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -492,6 +554,8 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime3,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT |
                                     dsdb.UF_ACCOUNTDISABLE |
@@ -504,6 +568,8 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime3,
+                                  lastLogon=0,
+                                  lastLogonTimestamp=('absent', None),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -511,19 +577,16 @@ userPassword: thatsAcomplPASS1
         # Open a second LDB connection with the user credentials. Use the
         # command line credentials for informations like the domain, the realm
         # and the workstation.
-        creds3 = Credentials()
+        creds3 = insta_creds()
         creds3.set_username("testuser3")
         creds3.set_password("thatsAcomplPASS1")
-        creds3.set_domain(creds.get_domain())
-        creds3.set_realm(creds.get_realm())
-        creds3.set_workstation(creds.get_workstation())
-        creds3.set_gensec_features(creds3.get_gensec_features()
-                                                          | gensec.FEATURE_SEAL)
         self.ldb3 = SamDB(url=host_url, credentials=creds3, lp=lp)
 
         res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime3,
+                                  lastLogon=('greater', badPasswordTime3),
+                                  lastLogonTimestamp=('greater', badPasswordTime3),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -536,10 +599,14 @@ userPassword: thatsAcomplPASS1
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=("greater", 0),
+                                  lastLogon=('greater', 0),
+                                  lastLogonTimestamp=('greater', 0),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
         badPasswordTime = int(res[0]["badPasswordTime"][0])
+        lastLogon = int(res[0]["lastLogon"][0])
+        lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
 
         # Change password on a connection as another user
 
@@ -561,6 +628,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -579,6 +648,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -601,6 +672,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -626,6 +699,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=("greater", badPasswordTime),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -651,6 +726,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -675,6 +752,8 @@ userPassword: thatsAcomplPASS2
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=lockoutTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
@@ -697,6 +776,8 @@ userPassword: thatsAcomplPASS2x
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -713,6 +794,8 @@ userPassword: thatsAcomplPASS2
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -736,6 +819,8 @@ userPassword: thatsAcomplPASS2x
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -753,6 +838,8 @@ userPassword: thatsAcomplPASS2x
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -778,16 +865,21 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=lockoutTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
 
         self._reset_by_method(res, method)
 
+        # Here bad password counts are reset without logon success.
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -807,6 +899,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -830,6 +924,8 @@ userPassword: thatsAcomplPASS2XYZ
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -854,6 +950,8 @@ userPassword: thatsAcomplPASS2XYZ
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -864,6 +962,8 @@ userPassword: thatsAcomplPASS2XYZ
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -885,10 +985,13 @@ userPassword: thatsAcomplPASS2XYZ
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=("greater", 0),
+                                  lastLogon=("greater", 0),
+                                  lastLogonTimestamp=("greater", 0),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
         badPasswordTime = int(res[0]["badPasswordTime"][0])
+        lastLogon = int(res[0]["lastLogon"][0])
 
         # Change password on a connection as another user
 
@@ -910,6 +1013,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -928,6 +1033,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -950,6 +1057,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -963,6 +1072,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -988,6 +1099,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=("greater", badPasswordTime),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1013,6 +1126,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1036,6 +1151,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1059,6 +1176,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1070,6 +1189,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1088,6 +1209,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1111,6 +1234,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1135,6 +1260,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1148,6 +1275,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1171,6 +1300,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=("greater", badPasswordTime),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1183,6 +1314,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3, effective_bad_password_count=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1197,51 +1330,60 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=3, effective_bad_password_count=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=lockoutTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogon,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
 
     def _test_login_lockout(self, use_kerberos):
         # This unlocks by waiting for account_lockout_duration
-        print "Performs a lockout attempt against LDAP using NTLM or Kerberos"
+        if use_kerberos == MUST_USE_KERBEROS:
+            lastlogon_relation = 'greater'
+            print "Performs a lockout attempt against LDAP using Kerberos"
+        else:
+            lastlogon_relation = 'equal'
+            print "Performs a lockout attempt against LDAP using NTLM"
 
         # Change password on a connection as another user
-
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=("greater", 0),
+                                  lastLogon=("greater", 0),
+                                  lastLogonTimestamp=("greater", 0),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
         badPasswordTime = int(res[0]["badPasswordTime"][0])
+        lastLogon = int(res[0]["lastLogon"][0])
+        firstLogon = lastLogon
+        lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+        print firstLogon
+        print lastLogonTimestamp
+
+
+        self.assertGreater(lastLogon, badPasswordTime)
 
         # Open a second LDB connection with the user credentials. Use the
         # command line credentials for informations like the domain, the realm
         # and the workstation.
-        creds_lockout = Credentials()
-        creds_lockout.set_username("testuser")
-        creds_lockout.set_domain(creds.get_domain())
-        creds_lockout.set_realm(creds.get_realm())
-        creds_lockout.set_workstation(creds.get_workstation())
-        creds_lockout.set_gensec_features(creds_lockout.get_gensec_features()
-                                          | gensec.FEATURE_SEAL)
+        creds_lockout = insta_creds()
         creds_lockout.set_kerberos_state(use_kerberos)
 
         # The wrong password
         creds_lockout.set_password("thatsAcomplPASS1x")
 
-        try:
-            ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
-
-        except LdbError, (num, msg):
-            self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+        self.assertLoginFailure(host_url, creds_lockout, lp)
 
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
-                                  msDSUserAccountControlComputed=0)
+                                  msDSUserAccountControlComputed=0,
+                                  msg='lastlogontimestamp with wrong password')
         badPasswordTime = int(res[0]["badPasswordTime"][0])
 
         # Correct old password
@@ -1249,25 +1391,31 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
 
         ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
 
+        # lastLogonTimestamp should not change
+        # lastLogon increases if badPwdCount is non-zero (!)
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=('greater', lastLogon),
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
-                                  msDSUserAccountControlComputed=0)
+                                  msDSUserAccountControlComputed=0,
+                                  msg='LLTimestamp is updated to lastlogon')
+
+        lastLogon = int(res[0]["lastLogon"][0])
+        self.assertGreater(lastLogon, badPasswordTime)
 
         # The wrong password
         creds_lockout.set_password("thatsAcomplPASS1x")
 
-        try:
-            ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
-
-        except LdbError, (num, msg):
-            self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+        self.assertLoginFailure(host_url, creds_lockout, lp)
 
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1286,6 +1434,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1306,6 +1456,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=("greater", badPasswordTime),
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=("greater", badPasswordTime),
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1324,6 +1476,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
@@ -1340,12 +1494,14 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
 
-        # The correct password
+        # The correct password, but we are locked out
         creds_lockout.set_password("thatsAcomplPASS1")
         try:
             ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
@@ -1356,32 +1512,50 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=lockoutTime,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
 
+        # wait for the lockout to end
         time.sleep(self.account_lockout_duration + 1)
+        print self.account_lockout_duration + 1
 
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=3, effective_bad_password_count=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=lockoutTime,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
 
+        lastLogon = int(res[0]["lastLogon"][0])
+
         # The correct password after letting the timeout expire
+
         creds_lockout.set_password("thatsAcomplPASS1")
-        ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+
+        creds_lockout2 = insta_creds(creds_lockout)
+
+        ldb_lockout = SamDB(url=host_url, credentials=creds_lockout2, lp=lp)
+        time.sleep(3)
 
         res = self._check_account("cn=testuser,cn=users," + self.base_dn,
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
+                                  lastLogon=(lastlogon_relation, lastLogon),
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   lockoutTime=0,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
-                                  msDSUserAccountControlComputed=0)
+                                  msDSUserAccountControlComputed=0,
+                                  msg="lastLogon is way off")
+
+        lastLogon = int(res[0]["lastLogon"][0])
 
         # The wrong password
         creds_lockout.set_password("thatsAcomplPASS1x")
@@ -1395,6 +1569,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1412,6 +1588,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=2,
                                   badPasswordTime=("greater", badPasswordTime),
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1423,6 +1601,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=2, effective_bad_password_count=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1439,6 +1619,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=1,
                                   badPasswordTime=("greater", badPasswordTime),
                                   lockoutTime=0,
+                                  lastLogon=lastLogon,
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1452,6 +1634,8 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
                                   badPwdCount=0,
                                   badPasswordTime=badPasswordTime,
                                   lockoutTime=0,
+                                  lastLogon=("greater", lastLogon),
+                                  lastLogonTimestamp=lastLogonTimestamp,
                                   userAccountControl=
                                     dsdb.UF_NORMAL_ACCOUNT,
                                   msDSUserAccountControlComputed=0)
@@ -1462,6 +1646,79 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le'))
     def test_login_lockout_kerberos(self):
         self._test_login_lockout(MUST_USE_KERBEROS)
 
+    def _test_multiple_logon(self, use_kerberos):
+        # Test the happy case in which a user logs on correctly, then
+        # logs on correctly again, so that the bad password and
+        # lockout times are both zero the second time. The lastlogon
+        # time should increase.
+
+        # Open a second LDB connection with the user credentials. Use the
+        # command line credentials for informations like the domain, the realm
+        # and the workstation.
+        creds2 = insta_creds()
+        creds2.set_kerberos_state(use_kerberos)
+        self.assertEqual(creds2.get_kerberos_state(), use_kerberos)
+
+        if use_kerberos == MUST_USE_KERBEROS:
+            print "Testing multiple logon with Kerberos"
+            lastlogon_relation = 'greater'
+        else:
+            print "Testing multiple logon with NTLM"
+            lastlogon_relation = 'equal'
+
+        SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+        res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+                                  badPwdCount=0,
+                                  badPasswordTime=("greater", 0),
+                                  lastLogon=("greater", 0),
+                                  lastLogonTimestamp=("greater", 0),
+                                  userAccountControl=
+                                    dsdb.UF_NORMAL_ACCOUNT,
+                                  msDSUserAccountControlComputed=0)
+        badPasswordTime = int(res[0]["badPasswordTime"][0])
+        lastLogon = int(res[0]["lastLogon"][0])
+        lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+        firstLogon = lastLogon
+        print "last logon is %d" % lastLogon
+        self.assertGreater(lastLogon, badPasswordTime)
+
+        time.sleep(1)
+        SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+        res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+                                  badPwdCount=0,
+                                  badPasswordTime=badPasswordTime,
+                                  lastLogon=(lastlogon_relation, lastLogon),
+                                  lastLogonTimestamp=lastLogonTimestamp,
+                                  userAccountControl=
+                                  dsdb.UF_NORMAL_ACCOUNT,
+                                  msDSUserAccountControlComputed=0,
+                                  msg=("second logon, firstlogon was %s" %
+                                       firstLogon))
+
+
+        lastLogon = int(res[0]["lastLogon"][0])
+
+        time.sleep(1)
+
+        SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+
+        res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+                                  badPwdCount=0,
+                                  badPasswordTime=badPasswordTime,
+                                  lastLogon=(lastlogon_relation, lastLogon),
+                                  lastLogonTimestamp=lastLogonTimestamp,
+                                  userAccountControl=
+                                    dsdb.UF_NORMAL_ACCOUNT,
+                                  msDSUserAccountControlComputed=0)
+
+    def test_multiple_logon_ntlm(self):
+        self._test_multiple_logon(DONT_USE_KERBEROS)
+
+    def test_multiple_logon_kerberos(self):
+        self._test_multiple_logon(MUST_USE_KERBEROS)
+
     def tearDown(self):
         super(PasswordTests, self).tearDown()
         delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn)
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c
index 77f6a90..c4a4bb4 100644
--- a/source4/kdc/hdb-samba4.c
+++ b/source4/kdc/hdb-samba4.c
@@ -184,10 +184,13 @@ static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
 									struct samba_kdc_db_context);
 	struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry);
 
+	struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
+
 	if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
-		authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, ldb_get_default_basedn(kdc_db_ctx->samdb));
+		authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
 	} else if (hdb_auth_status == HDB_AUTH_SUCCESS) {
-		authsam_zero_bad_pwd_count(kdc_db_ctx->samdb, p->msg);
+		authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
+						 domain_dn, true);
 	}
 	return 0;
 }
diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build
index 781611e..4da3eaa 100755
--- a/source4/librpc/wscript_build
+++ b/source4/librpc/wscript_build
@@ -167,7 +167,7 @@ bld.SAMBA_PYTHON('python_echo',
 
 bld.SAMBA_PYTHON('python_dns',
 	source='../../librpc/gen_ndr/py_dns.c',
-	deps='RPC_NDR_DNS pytalloc-util pyrpc_util',
+	deps='NDR_DNS pytalloc-util pyrpc_util',
 	realname='samba/dcerpc/dns.so'
 	)
 
@@ -324,7 +324,7 @@ bld.SAMBA_PYTHON('python_dcerpc_drsblobs',
 
 bld.SAMBA_PYTHON('python_dcerpc_dnsp',
 	source='../../librpc/gen_ndr/py_dnsp.c',
-	deps='pytalloc-util pyrpc_util NDR_SECURITY RPC_NDR_DNSP',
+	deps='pytalloc-util pyrpc_util NDR_SECURITY NDR_DNSP',
 	realname='samba/dcerpc/dnsp.so'
 	)
 
diff --git a/source4/scripting/devel/createtrust b/source4/scripting/devel/createtrust
index 7f1ba33..6c0de1c 100755
--- a/source4/scripting/devel/createtrust
+++ b/source4/scripting/devel/createtrust
@@ -11,21 +11,9 @@ import samba
 import samba.getopt as options
 from samba.dcerpc import lsa, security, drsblobs
 from samba.ndr import ndr_pack
+from samba import arcfour_encrypt, string_to_byte_array
 import random
 
-def arcfour_encrypt(key, data):
-    from Crypto.Cipher import ARC4
-    c = ARC4.new(key)
-    return c.encrypt(data)
-
-def string_to_array(string):
-    blob = [0] * len(string)
-
-    for i in range(len(string)):
-        blob[i] = ord(string[i])
-
-    return blob
-
 ########### main code ###########
 if __name__ == "__main__":
     parser = OptionParser("createtrust [options] server")
@@ -73,7 +61,7 @@ if __name__ == "__main__":
     info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
     info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
 
-    password_blob = string_to_array("password".encode('utf-16-le'))
+    password_blob = string_to_byte_array("password".encode('utf-16-le'))
 
     clear_value = drsblobs.AuthInfoClear()
     clear_value.size = len(password_blob)
@@ -123,7 +111,7 @@ if __name__ == "__main__":
 
     auth_blob = lsa.DATA_BUF2()
     auth_blob.size = len(encrypted_trustpass)
-    auth_blob.data = string_to_array(encrypted_trustpass)
+    auth_blob.data = string_to_byte_array(encrypted_trustpass)
 
     auth_info = lsa.TrustDomainInfoAuthInfoInternal()
     auth_info.auth_blob = auth_blob
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index e284c2c..69330f2 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -290,7 +290,8 @@ for f in sorted(os.listdir(os.path.join(samba4srcdir, "../pidl/tests"))):
         planperltestsuite("pidl.%s" % f[:-3], os.path.normpath(os.path.join(samba4srcdir, "../pidl/tests", f)))
 
 # DNS tests
-planpythontestsuite("fl2003dc:local", "samba.tests.dns")
+plantestsuite_loadlist("samba.tests.dns", "fl2003dc:local", [python, os.path.join(srcdir(), "python/samba/tests/dns.py"), '$SERVER', '$SERVER_IP', '--machine-pass', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
+
 for t in smbtorture4_testsuites("dns_internal."):
     plansmbtorture4testsuite(t, "ad_dc_ntvfs:local", '//$SERVER/whavever')
 
diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c
index 68dbbc1..1275aa8 100644
--- a/source4/torture/smb2/create.c
+++ b/source4/torture/smb2/create.c
@@ -1666,6 +1666,69 @@ done:
 	return ret;
 }
 
+/*
+  test directory creation with an initial allocation size > 0
+*/
+static bool test_dir_alloc_size(struct torture_context *tctx,
+				struct smb2_tree *tree)
+{
+	bool ret = true;
+	const char *dname = DNAME "\\torture_alloc_size.dir";
+	NTSTATUS status;
+	struct smb2_create c;
+	struct smb2_handle h1 = {{0}}, h2;
+
+	torture_comment(tctx, "Checking initial allocation size on directories\n");
+
+	smb2_deltree(tree, dname);
+
+	status = torture_smb2_testdir(tree, DNAME, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+
+	ZERO_STRUCT(c);
+	c.in.create_disposition = NTCREATEX_DISP_CREATE;
+	c.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
+	c.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+	c.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
+	c.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	c.in.fname = dname;
+	/*
+	 * An insanely large value so we can check the value is
+	 * ignored: Samba either returns 0 (current behaviour), or,
+	 * once vfswrap_get_alloc_size() is fixed to allow retrieving
+	 * the allocated size for directories, returns
+	 * smb_roundup(..., stat.st_size) which would be 1 MB by
+	 * default.
+	 *
+	 * Windows returns 0 for emtpy directories, once directories
+	 * have a few entries it starts replying with values > 0.
+	 */
+	c.in.alloc_size = 1024*1024*1024;
+
+	status = smb2_create(tree, tctx, &c);
+	h2 = c.out.file.handle;
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"dir create with initial alloc size failed");
+
+	smb2_util_close(tree, h2);
+
+	torture_comment(tctx, "Got directory alloc size: %ju\n", (uintmax_t)c.out.alloc_size);
+
+	/*
+	 * See above for the rational for this test
+	 */
+	if (c.out.alloc_size > 1024*1024) {
+		torture_fail_goto(tctx, done, talloc_asprintf(tctx, "bad alloc size: %ju",
+							      (uintmax_t)c.out.alloc_size));
+	}
+
+done:
+	if (!smb2_util_handle_empty(h1)) {
+		smb2_util_close(tree, h1);
+	}
+	smb2_deltree(tree, DNAME);
+	return ret;
+}
 
 /*
    basic testing of SMB2 read
@@ -1686,6 +1749,7 @@ struct torture_suite *torture_smb2_create_init(void)
 	torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
 	torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
 	torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup);
+	torture_suite_add_1smb2_test(suite, "dir-alloc-size", test_dir_alloc_size);
 
 	suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
 
diff --git a/source4/torture/vfs/fruit.c b/source4/torture/vfs/fruit.c
index 1c1d4ad..d74eb65 100644
--- a/source4/torture/vfs/fruit.c
+++ b/source4/torture/vfs/fruit.c
@@ -64,7 +64,7 @@ static bool check_stream_list(struct smb2_tree *tree,
 			      const char *fname,
 			      int num_exp,
 			      const char **exp,
-			      struct smb2_handle h);
+			      bool is_dir);
 
 static int qsort_string(char * const *s1, char * const *s2)
 {
@@ -849,7 +849,7 @@ static bool torture_write_afpinfo(struct smb2_tree *tree,
 	char *infobuf;
 	bool ret = true;
 
-	full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM);
+	full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
 	if (full_name == NULL) {
 	    torture_comment(tctx, "talloc_asprintf error\n");
 	    return false;
@@ -900,7 +900,8 @@ static bool check_stream(struct smb2_tree *tree,
 	struct smb2_create create;
 	struct smb2_read r;
 	NTSTATUS status;
-	const char *full_name;
+	char *full_name;
+	bool ret = true;
 
 	full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
 	if (full_name == NULL) {
@@ -917,22 +918,21 @@ static bool check_stream(struct smb2_tree *tree,
 
 	status = smb2_create(tree, mem_ctx, &create);
 	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(full_name);
 		if (value == NULL) {
 			return true;
-		} else {
-			torture_comment(tctx, "Unable to open stream %s\n",
-			    full_name);
-			sleep(10000000);
-			return false;
 		}
+		torture_comment(tctx, "Unable to open stream %s\n", full_name);
+		return false;
 	}
 
 	handle = create.out.file.handle;
 	if (value == NULL) {
+		TALLOC_FREE(full_name);
+		smb2_util_close(tree, handle);
 		return true;
 	}
 
-
 	ZERO_STRUCT(r);
 	r.in.file.handle = handle;
 	r.in.length      = read_count;
@@ -940,19 +940,24 @@ static bool check_stream(struct smb2_tree *tree,
 
 	status = smb2_read(tree, tree, &r);
 
-	if (!NT_STATUS_IS_OK(status)) {
-		torture_comment(tctx, "(%s) Failed to read %lu bytes from "
-		    "stream '%s'\n", location, (long)strlen(value), full_name);
-		return false;
-	}
+	torture_assert_ntstatus_ok_goto(
+		tctx, status, ret, done,
+		talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
+				location, (long)strlen(value), full_name));
 
-	if (memcmp(r.out.data.data + comp_offset, value, comp_count) != 0) {
-		torture_comment(tctx, "(%s) Bad data in stream\n", location);
-		return false;
-	}
+	torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
+			    talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
+					    (intmax_t)r.out.data.length, (intmax_t)read_count));
 
+	torture_assert_goto(
+		tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
+		ret, done,
+		talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
+
+done:
+	TALLOC_FREE(full_name);
 	smb2_util_close(tree, handle);
-	return true;
+	return ret;
 }
 
 /**
@@ -1188,9 +1193,79 @@ static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
 	return true;
 }
 
-static bool test_read_atalk_metadata(struct torture_context *tctx,
-				     struct smb2_tree *tree1,
-				     struct smb2_tree *tree2)
+static bool enable_aapl(struct torture_context *tctx,
+			struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	NTSTATUS status;
+	bool ret = true;
+	struct smb2_create io;
+	DATA_BLOB data;
+	struct smb2_create_blob *aapl = NULL;
+	uint32_t aapl_server_caps;
+	uint32_t expexted_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
+				   SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+				   SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
+				   SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
+	bool is_osx_server = torture_setting_bool(tctx, "osx", false);
+
+	ZERO_STRUCT(io);
+	io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
+	io.in.file_attributes    = FILE_ATTRIBUTE_DIRECTORY;
+	io.in.create_disposition = NTCREATEX_DISP_OPEN;
+	io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
+			      NTCREATEX_SHARE_ACCESS_READ |
+			      NTCREATEX_SHARE_ACCESS_WRITE);
+	io.in.fname = "";
+
+	/*
+	 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
+	 * controls behaviour of Apple's SMB2 extensions for the whole
+	 * session!
+	 */
+
+	data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
+	SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
+	SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
+			     SMB2_CRTCTX_AAPL_VOLUME_CAPS |
+			     SMB2_CRTCTX_AAPL_MODEL_INFO));
+	SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
+			      SMB2_CRTCTX_AAPL_UNIX_BASED |
+			      SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
+
+	status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
+
+	status = smb2_create(tree, tctx, &io);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+
+	status = smb2_util_close(tree, io.out.file.handle);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
+
+	/*
+	 * Now check returned AAPL context
+	 */
+	torture_comment(tctx, "Comparing returned AAPL capabilities\n");
+
+	aapl = smb2_create_blob_find(&io.out.blobs,
+				     SMB2_CREATE_TAG_AAPL);
+	torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
+
+	if (!is_osx_server) {
+		torture_assert_goto(tctx, aapl->data.length == 50, ret, done, "bad AAPL size");
+	}
+
+	aapl_server_caps = BVAL(aapl->data.data, 16);
+	torture_assert_goto(tctx, aapl_server_caps == expexted_scaps,
+			    ret, done, "bad AAPL caps");
+
+done:
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static bool test_read_netatalk_metadata(struct torture_context *tctx,
+					struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\torture_read_metadata";
@@ -1198,16 +1273,22 @@ static bool test_read_atalk_metadata(struct torture_context *tctx,
 	struct smb2_handle testdirh;
 	bool ret = true;
 	ssize_t len;
+	const char *localdir = NULL;
 
 	torture_comment(tctx, "Checking metadata access\n");
 
-	smb2_util_unlink(tree1, fname);
+	localdir = torture_setting_string(tctx, "localdir", NULL);
+	if (localdir == NULL) {
+		torture_skip(tctx, "Need localdir for test");
+	}
+
+	smb2_util_unlink(tree, fname);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		goto done;
 	}
@@ -1220,42 +1301,122 @@ static bool test_read_atalk_metadata(struct torture_context *tctx,
 		goto done;
 	}
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
-			    0, 60, 0, 4, "AFP");
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 0, 4, "AFP");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
-			    0, 60, 16, 8, "BARRFOOO");
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 16, 8, "BARRFOOO");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
-			    16, 8, 0, 8, "BARRFOOO");
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   16, 8, 0, 3, "AFP");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
 
 	/* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
 
-	len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
 			  AFPINFO_STREAM, 0, 61);
 	CHECK_VALUE(len, 60);
 
-	len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
 			  AFPINFO_STREAM, 59, 2);
-	CHECK_VALUE(len, 1);
+	CHECK_VALUE(len, 2);
 
-	len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
 			  AFPINFO_STREAM, 60, 1);
-	CHECK_VALUE(len, 0);
+	CHECK_VALUE(len, 1);
 
-	len = read_stream(tree1, __location__, tctx, mem_ctx, fname,
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
 			  AFPINFO_STREAM, 61, 1);
 	CHECK_VALUE(len, 0);
 
 done:
-	smb2_deltree(tree1, BASEDIR);
+	smb2_deltree(tree, BASEDIR);
+	talloc_free(mem_ctx);
+	return ret;
+}
+
+static bool test_read_afpinfo(struct torture_context *tctx,
+			      struct smb2_tree *tree)
+{
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\torture_read_metadata";
+	NTSTATUS status;
+	struct smb2_handle testdirh;
+	bool ret = true;
+	ssize_t len;
+	AfpInfo *info;
+	const char *type_creator = "SMB,OLE!";
+
+	torture_comment(tctx, "Checking metadata access\n");
+
+	smb2_util_unlink(tree, fname);
+
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
+	smb2_util_close(tree, testdirh);
+
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
+
+	info = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+	memcpy(info->afpi_FinderInfo, type_creator, 8);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 0, 4, "AFP");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 16, 8, type_creator);
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+	/*
+	 * OS X ignores offset <= 60 and treats the as
+	 * offset=0. Reading from offsets > 60 returns EOF=0.
+	 */
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   16, 8, 0, 8, "AFP\0\0\0\001\0");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+			  AFPINFO_STREAM, 0, 61);
+	torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
+
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+			  AFPINFO_STREAM, 59, 2);
+	torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   59, 2, 0, 2, "AF");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+			  AFPINFO_STREAM, 60, 1);
+	torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   60, 1, 0, 1, "A");
+	torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
+
+	len = read_stream(tree, __location__, tctx, mem_ctx, fname,
+			  AFPINFO_STREAM, 61, 1);
+	torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_write_atalk_metadata(struct torture_context *tctx,
-				      struct smb2_tree *tree1,
-				      struct smb2_tree *tree2)
+				      struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\torture_write_metadata";
@@ -1265,13 +1426,12 @@ static bool test_write_atalk_metadata(struct torture_context *tctx,
 	bool ret = true;
 	AfpInfo *info;
 
-	smb2_util_unlink(tree1, fname);
-
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		goto done;
 	}
@@ -1282,23 +1442,23 @@ static bool test_write_atalk_metadata(struct torture_context *tctx,
 	}
 
 	memcpy(info->afpi_FinderInfo, type_creator, 8);
-	ret = torture_write_afpinfo(tree1, tctx, mem_ctx, fname, info);
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
 			    0, 60, 16, 8, type_creator);
 
 done:
-	smb2_deltree(tree1, BASEDIR);
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
-				      struct smb2_tree *tree1,
-				      struct smb2_tree *tree2)
+				      struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\torture_write_rfork_io";
-	const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM;
+	const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
 	const char *rfork_content = "1234567890";
 	NTSTATUS status;
 	struct smb2_handle testdirh;
@@ -1309,13 +1469,13 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 	union smb_fileinfo finfo;
 	union smb_setfileinfo sinfo;
 
-	smb2_util_unlink(tree1, fname);
+	smb2_util_unlink(tree, fname);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		goto done;
 	}
@@ -1323,12 +1483,12 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 	torture_comment(tctx, "(%s) writing to resource fork\n",
 	    __location__);
 
-	ret &= write_stream(tree1, __location__, tctx, mem_ctx,
-			    fname, AFPRESOURCE_STREAM,
+	ret &= write_stream(tree, __location__, tctx, mem_ctx,
+			    fname, AFPRESOURCE_STREAM_NAME,
 			    10, 10, rfork_content);
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx,
-			    fname, AFPRESOURCE_STREAM,
+	ret &= check_stream(tree, __location__, tctx, mem_ctx,
+			    fname, AFPRESOURCE_STREAM_NAME,
 			    0, 20, 10, 10, rfork_content);
 
 	/* Check size after write */
@@ -1338,7 +1498,7 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 	io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
 		SEC_FILE_WRITE_ATTRIBUTE;
 	io.smb2.in.fname = rfork;
-	status = smb2_create(tree1, mem_ctx, &(io.smb2));
+	status = smb2_create(tree, mem_ctx, &(io.smb2));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	filehandle = io.smb2.out.file.handle;
 
@@ -1348,29 +1508,29 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 	ZERO_STRUCT(finfo);
 	finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
 	finfo.generic.in.file.handle = filehandle;
-	status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+	status = smb2_getinfo_file(tree, mem_ctx, &finfo);
 	CHECK_STATUS(status, NT_STATUS_OK);
 	if (finfo.all_info.out.size != 20) {
 		torture_result(tctx, TORTURE_FAIL,
 			       "(%s) Incorrect resource fork size\n",
 			       __location__);
 		ret = false;
-		smb2_util_close(tree1, filehandle);
+		smb2_util_close(tree, filehandle);
 		goto done;
 	}
-	smb2_util_close(tree1, filehandle);
+	smb2_util_close(tree, filehandle);
 
 	/* Write at large offset */
 
 	torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
 			__location__);
 
-	ret &= write_stream(tree1, __location__, tctx, mem_ctx,
-			    fname, AFPRESOURCE_STREAM,
+	ret &= write_stream(tree, __location__, tctx, mem_ctx,
+			    fname, AFPRESOURCE_STREAM_NAME,
 			    (off_t)1<<32, 10, rfork_content);
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx,
-			    fname, AFPRESOURCE_STREAM,
+	ret &= check_stream(tree, __location__, tctx, mem_ctx,
+			    fname, AFPRESOURCE_STREAM_NAME,
 			    (off_t)1<<32, 10, 0, 10, rfork_content);
 
 	/* Truncate back to size of 1 byte */
@@ -1380,10 +1540,9 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 
 	ZERO_STRUCT(io);
 	io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
-	io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
-		SEC_FILE_WRITE_ATTRIBUTE;
+	io.smb2.in.desired_access = SEC_FILE_ALL;
 	io.smb2.in.fname = rfork;
-	status = smb2_create(tree1, mem_ctx, &(io.smb2));
+	status = smb2_create(tree, mem_ctx, &(io.smb2));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	filehandle = io.smb2.out.file.handle;
 
@@ -1392,10 +1551,10 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 		RAW_SFILEINFO_END_OF_FILE_INFORMATION;
 	sinfo.end_of_file_info.in.file.handle = filehandle;
 	sinfo.end_of_file_info.in.size = 1;
-	status = smb2_setinfo_file(tree1, &sinfo);
+	status = smb2_setinfo_file(tree, &sinfo);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
-	smb2_util_close(tree1, filehandle);
+	smb2_util_close(tree, filehandle);
 
 	/* Now check size */
 	ZERO_STRUCT(io);
@@ -1403,34 +1562,34 @@ static bool test_write_atalk_rfork_io(struct torture_context *tctx,
 	io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
 		SEC_FILE_WRITE_ATTRIBUTE;
 	io.smb2.in.fname = rfork;
-	status = smb2_create(tree1, mem_ctx, &(io.smb2));
+	status = smb2_create(tree, mem_ctx, &(io.smb2));
 	CHECK_STATUS(status, NT_STATUS_OK);
 	filehandle = io.smb2.out.file.handle;
 
 	ZERO_STRUCT(finfo);
 	finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
 	finfo.generic.in.file.handle = filehandle;
-	status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+	status = smb2_getinfo_file(tree, mem_ctx, &finfo);
 	CHECK_STATUS(status, NT_STATUS_OK);
 	if (finfo.all_info.out.size != 1) {
 		torture_result(tctx, TORTURE_FAIL,
 			       "(%s) Incorrect resource fork size\n",
 			       __location__);
 		ret = false;
-		smb2_util_close(tree1, filehandle);
+		smb2_util_close(tree, filehandle);
 		goto done;
 	}
-	smb2_util_close(tree1, filehandle);
+	smb2_util_close(tree, filehandle);
 
 done:
-	smb2_deltree(tree1, BASEDIR);
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_rfork_truncate(struct torture_context *tctx,
-				struct smb2_tree *tree1,
-				struct smb2_tree *tree2)
+				struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\torture_rfork_truncate";
@@ -1443,18 +1602,18 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	struct smb2_handle fh1, fh2, fh3;
 	union smb_setfileinfo sinfo;
 
-	smb2_util_unlink(tree1, fname);
+	smb2_util_unlink(tree, fname);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		goto done;
 	}
 
-	ret &= write_stream(tree1, __location__, tctx, mem_ctx,
+	ret &= write_stream(tree, __location__, tctx, mem_ctx,
 			    fname, AFPRESOURCE_STREAM,
 			    10, 10, rfork_content);
 
@@ -1471,7 +1630,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
 	fh1 = create.out.file.handle;
 
@@ -1483,7 +1642,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
 	fh2 = create.out.file.handle;
 
@@ -1491,7 +1650,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
 	sinfo.end_of_file_info.in.file.handle = fh2;
 	sinfo.end_of_file_info.in.size = 0;
-	status = smb2_setinfo_file(tree1, &sinfo);
+	status = smb2_setinfo_file(tree, &sinfo);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
 
 	/*
@@ -1505,7 +1664,7 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
 
 	/*
@@ -1523,31 +1682,30 @@ static bool test_rfork_truncate(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
 	fh3 = create.out.file.handle;
 
-	status = smb2_util_write(tree1, fh3, "foo", 0, 3);
+	status = smb2_util_write(tree, fh3, "foo", 0, 3);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
 
-	smb2_util_close(tree1, fh3);
-	smb2_util_close(tree1, fh2);
-	smb2_util_close(tree1, fh1);
+	smb2_util_close(tree, fh3);
+	smb2_util_close(tree, fh2);
+	smb2_util_close(tree, fh1);
 
-	ret = check_stream(tree1, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
 			   0, 3, 0, 3, "foo");
 	torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
 
 done:
-	smb2_util_unlink(tree1, fname);
-	smb2_deltree(tree1, BASEDIR);
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_rfork_create(struct torture_context *tctx,
-			      struct smb2_tree *tree1,
-			      struct smb2_tree *tree2)
+			      struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\torture_rfork_create";
@@ -1562,13 +1720,13 @@ static bool test_rfork_create(struct torture_context *tctx,
 	};
 	union smb_fileinfo finfo;
 
-	smb2_util_unlink(tree1, fname);
+	smb2_util_unlink(tree, fname);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		goto done;
 	}
@@ -1584,7 +1742,7 @@ static bool test_rfork_create(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
 
 	torture_comment(tctx, "(%s) create resource fork\n", __location__);
@@ -1597,7 +1755,7 @@ static bool test_rfork_create(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
 	fh1 = create.out.file.handle;
 
@@ -1607,14 +1765,14 @@ static bool test_rfork_create(struct torture_context *tctx,
 	ZERO_STRUCT(finfo);
 	finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
 	finfo.generic.in.file.handle = fh1;
-	status = smb2_getinfo_file(tree1, mem_ctx, &finfo);
+	status = smb2_getinfo_file(tree, mem_ctx, &finfo);
 	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
 	if (finfo.all_info.out.size != 0) {
 		torture_result(tctx, TORTURE_FAIL,
 			       "(%s) Incorrect resource fork size\n",
 			       __location__);
 		ret = false;
-		smb2_util_close(tree1, fh1);
+		smb2_util_close(tree, fh1);
 		goto done;
 	}
 
@@ -1629,25 +1787,15 @@ static bool test_rfork_create(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
 
-	ZERO_STRUCT(create);
-	create.in.fname = fname;
-	create.in.create_disposition = NTCREATEX_DISP_OPEN;
-	create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
-	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
-	status = smb2_create(tree1, mem_ctx, &create);
-	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
-
-	ret = check_stream_list(tree1, tctx, fname, 1, streams,
-				create.out.file.handle);
+	ret = check_stream_list(tree, tctx, fname, 1, streams, false);
 	torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
-	smb2_util_close(tree1, create.out.file.handle);
 
 	torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
 			__location__);
-	smb2_util_close(tree1, fh1);
+
 	ZERO_STRUCT(create);
 	create.in.create_disposition  = NTCREATEX_DISP_OPEN;
 	create.in.desired_access      = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
@@ -1656,19 +1804,18 @@ static bool test_rfork_create(struct torture_context *tctx,
 	create.in.share_access        = NTCREATEX_SHARE_ACCESS_DELETE |
 		NTCREATEX_SHARE_ACCESS_READ |
 		NTCREATEX_SHARE_ACCESS_WRITE;
-	status = smb2_create(tree1, mem_ctx, &create);
+	status = smb2_create(tree, mem_ctx, &create);
 	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
 
 done:
-	smb2_util_unlink(tree1, fname);
-	smb2_deltree(tree1, BASEDIR);
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_adouble_conversion(struct torture_context *tctx,
-				    struct smb2_tree *tree1,
-				    struct smb2_tree *tree2)
+				    struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\test_adouble_conversion";
@@ -1679,12 +1826,18 @@ static bool test_adouble_conversion(struct torture_context *tctx,
 	bool ret = true;
 	const char *data = "This resource fork intentionally left blank";
 	size_t datalen = strlen(data);
+	const char *localdir = NULL;
 
-	smb2_util_unlink(tree1, fname);
+	localdir = torture_setting_string(tctx, "localdir", NULL);
+	if (localdir == NULL) {
+		torture_skip(tctx, "Need localdir for test");
+	}
+
+	smb2_util_unlink(tree, fname);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
 	ret = torture_setup_local_file(tctx, "localdir", fname_local,
 				       NULL, 0);
@@ -1702,19 +1855,18 @@ static bool test_adouble_conversion(struct torture_context *tctx,
 	torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
 	    __location__);
 
-	ret &= check_stream(tree1, __location__, tctx, mem_ctx,
+	ret &= check_stream(tree, __location__, tctx, mem_ctx,
 			    fname, AFPRESOURCE_STREAM,
 			    16, datalen, 0, datalen, data);
 
 done:
-	smb2_deltree(tree1, BASEDIR);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
 
 static bool test_aapl(struct torture_context *tctx,
-		      struct smb2_tree *tree1,
-		      struct smb2_tree *tree2)
+		      struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	const char *fname = BASEDIR "\\test_aapl";
@@ -1737,11 +1889,11 @@ static bool test_aapl(struct torture_context *tctx,
 	union smb_search_data *d;
 	uint64_t rfork_len;
 
-	smb2_deltree(tree1, BASEDIR);
+	smb2_deltree(tree, BASEDIR);
 
-	status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
+	status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	smb2_util_close(tree1, testdirh);
+	smb2_util_close(tree, testdirh);
 
 	ZERO_STRUCT(io);
 	io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
@@ -1771,9 +1923,9 @@ static bool test_aapl(struct torture_context *tctx,
 	status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
-	status = smb2_create(tree1, tctx, &io);
+	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
-	status = smb2_util_close(tree1, io.out.file.handle);
+	status = smb2_util_close(tree, io.out.file.handle);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	/*
@@ -1799,8 +1951,9 @@ static bool test_aapl(struct torture_context *tctx,
 		 * uint32_t ModelStringLen = 10;
 		 * ucs2_t ModelString[5] = "Samba";
 		 */
-		ret = false;
-		goto done;
+		torture_warning(tctx,
+				"(%s) unexpected AAPL context length: %zd, expected 50",
+				__location__, aapl->data.length);
 	}
 
 	aapl_cmd = IVAL(aapl->data.data, 0);
@@ -1838,11 +1991,9 @@ static bool test_aapl(struct torture_context *tctx,
 	aapl_vol_caps = BVAL(aapl->data.data, 24);
 	if (aapl_vol_caps != SMB2_CRTCTX_AAPL_CASE_SENSITIVE) {
 		/* this will fail on a case insensitive fs ... */
-		torture_result(tctx, TORTURE_FAIL,
-			       "(%s) unexpected vol_caps: %d",
-			       __location__, (int)aapl_vol_caps);
-		ret = false;
-		goto done;
+		torture_warning(tctx,
+				"(%s) unexpected vol_caps: %d",
+				__location__, (int)aapl_vol_caps);
 	}
 
 	ret = convert_string_talloc(mem_ctx,
@@ -1861,7 +2012,7 @@ static bool test_aapl(struct torture_context *tctx,
 	 * Now that Requested AAPL extensions are enabled, setup some
 	 * Mac files with metadata and resource fork
 	 */
-	ret = torture_setup_file(mem_ctx, tree1, fname, false);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
 	if (ret == false) {
 		torture_result(tctx, TORTURE_FAIL,
 			       "(%s) torture_setup_file() failed",
@@ -1879,7 +2030,7 @@ static bool test_aapl(struct torture_context *tctx,
 	}
 
 	memcpy(info->afpi_FinderInfo, type_creator, 8);
-	ret = torture_write_afpinfo(tree1, tctx, mem_ctx, fname, info);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
 	if (ret == false) {
 		torture_result(tctx, TORTURE_FAIL,
 			       "(%s) torture_write_afpinfo() failed",
@@ -1887,8 +2038,8 @@ static bool test_aapl(struct torture_context *tctx,
 		goto done;
 	}
 
-	ret = write_stream(tree1, __location__, tctx, mem_ctx,
-			   fname, AFPRESOURCE_STREAM,
+	ret = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
 			   0, 3, "foo");
 	if (ret == false) {
 		torture_result(tctx, TORTURE_FAIL,
@@ -1902,7 +2053,7 @@ static bool test_aapl(struct torture_context *tctx,
 	 */
 
 	ZERO_STRUCT(io);
-	io.in.desired_access = SEC_RIGHTS_DIR_ALL;
+	io.in.desired_access = SEC_RIGHTS_DIR_READ;
 	io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
 	io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
 	io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
@@ -1910,7 +2061,7 @@ static bool test_aapl(struct torture_context *tctx,
 			      NTCREATEX_SHARE_ACCESS_DELETE);
 	io.in.create_disposition = NTCREATEX_DISP_OPEN;
 	io.in.fname = BASEDIR;
-	status = smb2_create(tree1, tctx, &io);
+	status = smb2_create(tree, tctx, &io);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	ZERO_STRUCT(f);
@@ -1920,10 +2071,10 @@ static bool test_aapl(struct torture_context *tctx,
 	f.in.max_response_size	= 0x1000;
 	f.in.level              = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
 
-	status = smb2_find_level(tree1, tree1, &f, &count, &d);
+	status = smb2_find_level(tree, tree, &f, &count, &d);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
-	status = smb2_util_close(tree1, io.out.file.handle);
+	status = smb2_util_close(tree, io.out.file.handle);
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
@@ -1974,6 +2125,8 @@ static bool test_aapl(struct torture_context *tctx,
 	}
 
 done:
+	smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
 	talloc_free(mem_ctx);
 	return ret;
 }
@@ -2426,58 +2579,76 @@ static bool check_stream_list(struct smb2_tree *tree,
 			      const char *fname,
 			      int num_exp,
 			      const char **exp,
-			      struct smb2_handle h)
+			      bool is_dir)
 {
+	bool ret = true;
 	union smb_fileinfo finfo;
 	NTSTATUS status;
 	int i;
 	TALLOC_CTX *tmp_ctx = talloc_new(tctx);
 	char **exp_sort;
 	struct stream_struct *stream_sort;
+	struct smb2_create create;
+	struct smb2_handle h;
+
+	ZERO_STRUCT(h);
+	torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
+
+	ZERO_STRUCT(create);
+	create.in.fname = fname;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
+	create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
+	status = smb2_create(tree, tmp_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
+	h = create.out.file.handle;
 
 	finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
 	finfo.generic.in.file.handle = h;
 
 	status = smb2_getinfo_file(tree, tctx, &finfo);
-	torture_assert_ntstatus_ok(tctx, status, "get stream info");
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
+
+	smb2_util_close(tree, h);
 
-	torture_assert_int_equal(tctx, finfo.stream_info.out.num_streams, num_exp,
-				 "stream count");
+	torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
+				      ret, done, "stream count");
 
 	if (num_exp == 0) {
 		TALLOC_FREE(tmp_ctx);
-		return true;
+		goto done;
 	}
 
 	exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
-	torture_assert(tctx, exp_sort != NULL, __location__);
+	torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
 
 	TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
 
 	stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
 				    finfo.stream_info.out.num_streams *
 				    sizeof(*stream_sort));
-	torture_assert(tctx, stream_sort != NULL, __location__);
+	torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
 
 	TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
 
 	for (i=0; i<num_exp; i++) {
 		torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
 				i, exp_sort[i], stream_sort[i].stream_name.s);
-		torture_assert_str_equal(tctx, stream_sort[i].stream_name.s, exp_sort[i],
-					 "stream name");
+		torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
+					      ret, done, "stream name");
 	}
 
+done:
 	TALLOC_FREE(tmp_ctx);
-	return true;
+	return ret;
 }
 
 /*
   test stream names
 */
 static bool test_stream_names(struct torture_context *tctx,
-			      struct smb2_tree *tree,
-			      struct smb2_tree *tree2)
+			      struct smb2_tree *tree)
 {
 	TALLOC_CTX *mem_ctx = talloc_new(tctx);
 	NTSTATUS status;
@@ -2492,6 +2663,12 @@ static bool test_stream_names(struct torture_context *tctx,
 		":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
 		"::$DATA"
 	};
+	const char *localdir = NULL;
+
+	localdir = torture_setting_string(tctx, "localdir", NULL);
+	if (localdir == NULL) {
+		torture_skip(tctx, "Need localdir for test");
+	}
 
 	sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
 
@@ -2525,35 +2702,829 @@ static bool test_stream_names(struct torture_context *tctx,
 					"data", strlen("data"));
 	CHECK_VALUE(ret, true);
 
+	ret = check_stream_list(tree, tctx, fname, 3, streams, false);
+	CHECK_VALUE(ret, true);
+
+done:
+	status = smb2_util_unlink(tree, fname);
+	smb2_deltree(tree, BASEDIR);
+	talloc_free(mem_ctx);
+
+	return ret;
+}
+
+/* Renaming a directory with open file, should work for OS X AAPL clients */
+static bool test_rename_dir_openfile(struct torture_context *torture,
+				     struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	union smb_open io;
+	union smb_close cl;
+	union smb_setfileinfo sinfo;
+	struct smb2_handle d1, h1;
+	const char *renamedir = BASEDIR "-new";
+	bool server_is_osx = torture_setting_bool(torture, "osx", false);
+
+	smb2_deltree(tree, BASEDIR);
+	smb2_util_rmdir(tree, BASEDIR);
+	smb2_deltree(tree, renamedir);
+
+	ZERO_STRUCT(io.smb2);
+	io.generic.level = RAW_OPEN_SMB2;
+	io.smb2.in.create_flags = 0;
+	io.smb2.in.desired_access = 0x0017019f;
+	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+	io.smb2.in.share_access = 0;
+	io.smb2.in.alloc_size = 0;
+	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	io.smb2.in.security_flags = 0;
+	io.smb2.in.fname = BASEDIR;
+
+	status = smb2_create(tree, torture, &(io.smb2));
+	torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+	d1 = io.smb2.out.file.handle;
+
+	ZERO_STRUCT(io.smb2);
+	io.generic.level = RAW_OPEN_SMB2;
+	io.smb2.in.create_flags = 0;
+	io.smb2.in.desired_access = 0x0017019f;
+	io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
+	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	io.smb2.in.share_access = 0;
+	io.smb2.in.alloc_size = 0;
+	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	io.smb2.in.security_flags = 0;
+	io.smb2.in.fname = BASEDIR "\\file.txt";
+
+	status = smb2_create(tree, torture, &(io.smb2));
+	torture_assert_ntstatus_ok(torture, status, "smb2_create file");
+	h1 = io.smb2.out.file.handle;
+
+	if (!server_is_osx) {
+		torture_comment(torture, "Renaming directory without AAPL, must fail\n");
+
+		ZERO_STRUCT(sinfo);
+		sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+		sinfo.rename_information.in.file.handle = d1;
+		sinfo.rename_information.in.overwrite = 0;
+		sinfo.rename_information.in.root_fid = 0;
+		sinfo.rename_information.in.new_name = renamedir;
+		status = smb2_setinfo_file(tree, &sinfo);
+
+		torture_assert_ntstatus_equal(torture, status,
+					      NT_STATUS_ACCESS_DENIED,
+					      "smb2_setinfo_file");
+
+		ZERO_STRUCT(cl.smb2);
+		cl.smb2.level = RAW_CLOSE_SMB2;
+		cl.smb2.in.file.handle = d1;
+		status = smb2_close(tree, &(cl.smb2));
+		torture_assert_ntstatus_ok(torture, status, "smb2_close");
+		ZERO_STRUCT(d1);
+	}
+
+	torture_comment(torture, "Enabling AAPL\n");
+
+	ret = enable_aapl(torture, tree);
+	torture_assert(torture, ret == true, "enable_aapl failed");
+
+	torture_comment(torture, "Renaming directory with AAPL\n");
+
+	ZERO_STRUCT(io.smb2);
+	io.generic.level = RAW_OPEN_SMB2;
+	io.smb2.in.desired_access = 0x0017019f;
+	io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
+	io.smb2.in.share_access = 0;
+	io.smb2.in.alloc_size = 0;
+	io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
+	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	io.smb2.in.security_flags = 0;
+	io.smb2.in.fname = BASEDIR;
+
+	status = smb2_create(tree, torture, &(io.smb2));
+	torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
+	d1 = io.smb2.out.file.handle;
+
+	ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.handle = d1;
+	sinfo.rename_information.in.overwrite = 0;
+	sinfo.rename_information.in.root_fid = 0;
+	sinfo.rename_information.in.new_name = renamedir;
+
+	status = smb2_setinfo_file(tree, &sinfo);
+	torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
+
+	ZERO_STRUCT(cl.smb2);
+	cl.smb2.level = RAW_CLOSE_SMB2;
+	cl.smb2.in.file.handle = d1;
+	status = smb2_close(tree, &(cl.smb2));
+	torture_assert_ntstatus_ok(torture, status, "smb2_close");
+	ZERO_STRUCT(d1);
+
+	cl.smb2.in.file.handle = h1;
+	status = smb2_close(tree, &(cl.smb2));
+	torture_assert_ntstatus_ok(torture, status, "smb2_close");
+	ZERO_STRUCT(h1);
+
+	torture_comment(torture, "Cleaning up\n");
+
+	if (h1.data) {
+		ZERO_STRUCT(cl.smb2);
+		cl.smb2.level = RAW_CLOSE_SMB2;
+		cl.smb2.in.file.handle = h1;
+		status = smb2_close(tree, &(cl.smb2));
+	}
+
+	smb2_util_unlink(tree, BASEDIR "\\file.txt");
+	smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
+	smb2_deltree(tree, renamedir);
+	smb2_deltree(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_afpinfo_enoent(struct torture_context *tctx,
+				struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+
+	torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
+
 	ZERO_STRUCT(create);
-	create.in.fname = fname;
 	create.in.create_disposition = NTCREATEX_DISP_OPEN;
-	create.in.desired_access = SEC_RIGHTS_FILE_ALL;
-	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
-	create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+	create.in.fname = sname;
+
 	status = smb2_create(tree, mem_ctx, &create);
-	CHECK_STATUS(status, NT_STATUS_OK);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpInfo stream");
 
-	ret = check_stream_list(tree, tctx, fname, 3, streams,
-				create.out.file.handle);
-	CHECK_VALUE(ret, true);
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
 
-	smb2_util_close(tree, create.out.file.handle);
+static bool test_create_delete_on_close(struct torture_context *tctx,
+					struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+	const char *type_creator = "SMB,OLE!";
+	AfpInfo *info = NULL;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+	const char *streams_afpinfo[] = {
+		"::$DATA",
+		AFPINFO_STREAM
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
 
-done:
-	status = smb2_util_unlink(tree, fname);
 	smb2_deltree(tree, BASEDIR);
-	talloc_free(mem_ctx);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
 
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+	create.in.fname = sname;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpInfo stream");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpInfo stream");
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
+
+	info = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+
+	memcpy(info->afpi_FinderInfo, type_creator, 8);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 16, 8, type_creator);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+	smb2_util_close(tree, h1);
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpInfo stream");
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_setinfo_delete_on_close(struct torture_context *tctx,
+					 struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	union smb_setfileinfo sfinfo;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+	const char *type_creator = "SMB,OLE!";
+	AfpInfo *info = NULL;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	info = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+	memcpy(info->afpi_FinderInfo, type_creator, 8);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	/* Delete stream via setinfo delete-on-close */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.disposition_info.in.delete_on_close = 1;
+	sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+	sfinfo.generic.in.file.handle = h1;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpInfo stream");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_setinfo_eof(struct torture_context *tctx,
+			     struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	union smb_setfileinfo sfinfo;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
+	const char *type_creator = "SMB,OLE!";
+	AfpInfo *info = NULL;
+	const char *streams_afpinfo[] = {
+		"::$DATA",
+		AFPINFO_STREAM
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	info = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+	memcpy(info->afpi_FinderInfo, type_creator, 8);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
+
+	/* Test setinfo end-of-file info */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.generic.in.file.handle = h1;
+	sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sfinfo.position_information.in.position = 61;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
+					   ret, done, "set eof 61 failed");
+
+	torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
+
+	/* Truncation returns success, but has no effect */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.generic.in.file.handle = h1;
+	sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sfinfo.position_information.in.position = 1;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status,
+					ret, done, "set eof 1 failed");
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 16, 8, type_creator);
+	torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	/*
+	 * Delete stream via setinfo end-of-file info to 0, should
+	 * return success but stream MUST NOT deleted
+	 */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.generic.in.file.handle = h1;
+	sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sfinfo.position_information.in.position = 0;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
+			   0, 60, 16, 8, type_creator);
+	torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_afpinfo_all0(struct torture_context *tctx,
+			      struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *type_creator = "SMB,OLE!";
+	AfpInfo *info = NULL;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+	const char *streams_afpinfo[] = {
+		"::$DATA",
+		AFPINFO_STREAM
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	info = torture_afpinfo_new(mem_ctx);
+	torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
+	memcpy(info->afpi_FinderInfo, type_creator, 8);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	/* Write all 0 to AFP_AfpInfo */
+	memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
+	ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_create_delete_on_close_resource(struct torture_context *tctx,
+						 struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+	const char *streams_afpresource[] = {
+		"::$DATA",
+		AFPRESOURCE_STREAM
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
+	create.in.fname = sname;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpResource stream");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "Got unexpected AFP_AfpResource stream");
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
+
+	ret = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   0, 10, "1234567890");
+	torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+			   0, 10, 0, 10, "1234567890");
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
+			   0, 10, 0, 10, "1234567890");
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
+						  struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	union smb_setfileinfo sfinfo;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+	const char *streams_afpresource[] = {
+		"::$DATA",
+		AFPRESOURCE_STREAM
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	ret = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   10, 10, "1234567890");
+	torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	/* Try to delete stream via setinfo delete-on-close */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.disposition_info.in.delete_on_close = 1;
+	sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
+	sfinfo.generic.in.file.handle = h1;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
+
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"Got unexpected AFP_AfpResource stream");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
+	return ret;
+}
+
+static bool test_setinfo_eof_resource(struct torture_context *tctx,
+				      struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	struct smb2_create create;
+	union smb_setfileinfo sfinfo;
+	union smb_fileinfo finfo;
+	struct smb2_handle h1;
+	TALLOC_CTX *mem_ctx = talloc_new(tctx);
+	const char *fname = BASEDIR "\\file";
+	const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
+	const char *streams_basic[] = {
+		"::$DATA"
+	};
+
+	torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
+
+	torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
+
+	smb2_deltree(tree, BASEDIR);
+	status = torture_smb2_testdir(tree, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
+	smb2_util_close(tree, h1);
+	ret = torture_setup_file(mem_ctx, tree, fname, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
+
+	ret = write_stream(tree, __location__, tctx, mem_ctx,
+			   fname, AFPRESOURCE_STREAM_NAME,
+			   10, 10, "1234567890");
+	torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
+
+	/* Test setinfo end-of-file info */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.generic.in.file.handle = h1;
+	sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sfinfo.position_information.in.position = 1;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status,
+					ret, done, "set eof 1 failed");
+
+ 	smb2_util_close(tree, h1);
+
+	/* Check size == 1 */
+	ZERO_STRUCT(create);
+	create.in.fname = sname;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	ZERO_STRUCT(finfo);
+	finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+	finfo.generic.in.file.handle = h1;
+	status = smb2_getinfo_file(tree, mem_ctx, &finfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
+
+	smb2_util_close(tree, h1);
+
+	torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
+
+	h1 = create.out.file.handle;
+
+	/*
+	 * Delete stream via setinfo end-of-file info to 0, this
+	 * should delete the stream.
+	 */
+	ZERO_STRUCT(sfinfo);
+	sfinfo.generic.in.file.handle = h1;
+	sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sfinfo.position_information.in.position = 0;
+	status = smb2_setinfo_file(tree, &sfinfo);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
+
+	smb2_util_close(tree, h1);
+
+	ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
+	torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
+
+	ZERO_STRUCT(create);
+	create.in.create_disposition = NTCREATEX_DISP_OPEN;
+	create.in.desired_access = SEC_FILE_ALL;
+	create.in.fname = sname;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
+
+	status = smb2_create(tree, mem_ctx, &create);
+	torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+					   ret, done, "smb2_create failed");
+
+done:
+	smb2_util_unlink(tree, fname);
+	smb2_util_rmdir(tree, BASEDIR);
 	return ret;
 }
 
 /*
- * Note: This test depends on "vfs objects = catia fruit
- * streams_xattr".  Note: To run this test, use
- * "--option=torture:share1=<SHARENAME1>
- * --option=torture:share2=<SHARENAME2>
- * --option=torture:localdir=<SHAREPATH>"
+ * Note: This test depends on "vfs objects = catia fruit streams_xattr".  For
+ * some tests torture must be run on the host it tests and takes an additional
+ * argument with the local path to the share:
+ * "--option=torture:localdir=<SHAREPATH>".
+ *
+ * When running against an OS X SMB server add "--option=torture:osx=true"
  */
 struct torture_suite *torture_vfs_fruit(void)
 {
@@ -2563,14 +3534,24 @@ struct torture_suite *torture_vfs_fruit(void)
 	suite->description = talloc_strdup(suite, "vfs_fruit tests");
 
 	torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
-	torture_suite_add_2ns_smb2_test(suite, "read metadata", test_read_atalk_metadata);
-	torture_suite_add_2ns_smb2_test(suite, "write metadata", test_write_atalk_metadata);
-	torture_suite_add_2ns_smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
-	torture_suite_add_2ns_smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
-	torture_suite_add_2ns_smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
-	torture_suite_add_2ns_smb2_test(suite, "stream names", test_stream_names);
-	torture_suite_add_2ns_smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
-	torture_suite_add_2ns_smb2_test(suite, "opening and creating resource fork", test_rfork_create);
+	torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
+	torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
+	torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
+	torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
+	torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
+	torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
+	torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
+	torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
+	torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
+	torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
+	torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
+	torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
+	torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
+	torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
+	torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
+	torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
+	torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
+	torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
 
 	return suite;
 }
diff --git a/testprogs/blackbox/dfree.sh b/testprogs/blackbox/dfree.sh
index 2da3cbd..64845cd 100755
--- a/testprogs/blackbox/dfree.sh
+++ b/testprogs/blackbox/dfree.sh
@@ -1,2 +1,8 @@
 #!/bin/sh
-echo "1000 10 2048"
+if [ "$1" = "." ] ; then
+    echo "1000 10 2048"
+elif [ "$1" = "subdir1" ] ; then
+    echo "2000 20 4096"
+else
+    echo "4000 40 8192"
+fi

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-samba/samba.git




More information about the Pkg-samba-maint mailing list