r25026: Move param/param.h out of includes.h
[jelmer/samba4-debian.git] / source / torture / rpc / drsuapi.c
index 7bef1e53609d2d66cfdfd7201df13a9f4b9ecc2f..c3ec54cbcdbe6ac5b6eaad921e2ad4ac767d365d 100644 (file)
@@ -5,10 +5,11 @@
 
    Copyright (C) Andrew Tridgell 2003
    Copyright (C) Stefan (metze) Metzmacher 2004
-   
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
+
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/ndr_drsuapi.h"
-
-struct DsPrivate {
-       struct policy_handle bind_handle;
-       struct GUID bind_guid;
-       const char *domain_obj_dn;
-       const char *domain_guid_str;
-       struct GUID domain_guid;
-       struct drsuapi_DsGetDCInfo2 dcinfo;
-};
-
-static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                     struct DsPrivate *priv)
+#include "torture/torture.h"
+#include "librpc/gen_ndr/ndr_drsuapi_c.h"
+#include "torture/rpc/rpc.h"
+#include "dlinklist.h"
+#include "param/param.h"
+
+#define TEST_MACHINE_NAME "torturetest"
+
+bool test_DsBind(struct dcerpc_pipe *p, struct torture_context *tctx,
+                struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsBind r;
-       BOOL ret = True;
+       struct torture_rpc_tcase_data *rpc_tcase;
 
        GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
 
@@ -46,600 +43,249 @@ static BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.bind_info = NULL;
        r.out.bind_handle = &priv->bind_handle;
 
-       printf("testing DsBind\n");
+       status = dcerpc_drsuapi_DsBind(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "DsBind");
+       torture_assert_werr_ok(tctx, r.out.result, "DsBind");
 
-       status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsBind failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       rpc_tcase = (struct torture_rpc_tcase_data *)tctx->active_tcase->data;
 
-       return ret;
+       priv->join = rpc_tcase->join_ctx;
+
+       return true;
 }
 
-static BOOL test_DsCrackNames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                     struct DsPrivate *priv)
+bool test_DsUnbind(struct dcerpc_pipe *p, struct torture_context *tctx,
+                  struct DsPrivate *priv)
 {
        NTSTATUS status;
-       struct drsuapi_DsCrackNames r;
-       struct drsuapi_DsNameString names[1];
-       BOOL ret = True;
-       const char *dns_domain;
-       const char *nt4_domain;
-       const char *FQDN_1779_name;
-
-       ZERO_STRUCT(r);
-       r.in.bind_handle                = &priv->bind_handle;
-       r.in.level                      = 1;
-       r.in.req.req1.unknown1          = 0x000004e4;
-       r.in.req.req1.unknown2          = 0x00000407;
-       r.in.req.req1.count             = 1;
-       r.in.req.req1.names             = names;
-       r.in.req.req1.format_flags      = DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = talloc_asprintf(mem_ctx, "%s/", lp_realm());
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       dns_domain = r.out.ctr.ctr1->array[0].dns_domain_name;
-       nt4_domain = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_GUID;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       priv->domain_guid_str = r.out.ctr.ctr1->array[0].result_name;
-       GUID_from_string(priv->domain_guid_str, &priv->domain_guid);
-
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = priv->domain_guid_str;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = nt4_domain;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       priv->domain_obj_dn = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, priv->dcinfo.netbios_name);
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       FQDN_1779_name = r.out.ctr.ctr1->array[0].result_name;
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
-       names[0].str = FQDN_1779_name;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_DISPLAY;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_GUID;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL;
-
-       printf("testing DsCrackNames with name '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.site_guid);
-
-       printf("testing DsCrackNames with Site GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
-
-       if (!ret) {
-               return ret;
-       }
-
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid);
-
-       printf("testing DsCrackNames with Computer GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
-
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       struct drsuapi_DsUnbind r;
 
-       if (!ret) {
-               return ret;
-       }
+       r.in.bind_handle = &priv->bind_handle;
+       r.out.bind_handle = &priv->bind_handle;
 
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid);
+       status = dcerpc_drsuapi_DsUnbind(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status,
+                       "dcerpc_drsuapi_DsUnbind failed");
+       torture_assert_werr_ok(tctx, r.out.result, "DsBind failed");
 
-       printf("testing DsCrackNames with Server GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       return true;
+}
 
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+static bool wrap_test_drsuapi(struct torture_context *tctx, 
+                             struct torture_tcase *tcase,
+                             struct torture_test *test)
+{
+       bool (*fn) (struct torture_context *, struct dcerpc_pipe *, struct DsPrivate *);
+       struct torture_rpc_tcase_data *tcase_data = 
+               (struct torture_rpc_tcase_data *)tcase->data;
+       bool ret;
+       struct DsPrivate priv;
 
-       if (!ret) {
-               return ret;
-       }
+       ZERO_STRUCT(priv);
 
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid);
+       fn = test->fn;
 
-       printf("testing DsCrackNames with NTDS GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       if (!test_DsBind(tcase_data->pipe, tctx, &priv))
+               return false;
 
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       ret = fn(tctx, tcase_data->pipe, &priv);
+       
+       if (!test_DsUnbind(tcase_data->pipe, tctx, &priv))
+               return false;
 
-       if (!ret) {
-               return ret;
-       }
+       return ret;
+}
 
-       r.in.req.req1.format_offered    = DRSUAPI_DS_NAME_FORMAT_GUID;
-       r.in.req.req1.format_desired    = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
-       names[0].str = GUID_string2(mem_ctx, &priv->bind_guid);
+static struct torture_test *torture_rpc_tcase_add_drsuapi_test(
+                                       struct torture_rpc_tcase *tcase, 
+                                       const char *name, 
+                                       bool (*fn) (struct torture_context *, struct dcerpc_pipe *, struct DsPrivate *priv))
+{
+       struct torture_test *test;
 
-       printf("testing DsCrackNames with BIND GUID '%s' desired format:%d\n",
-                       names[0].str, r.in.req.req1.format_desired);
+       test = talloc(tcase, struct torture_test);
 
-       status = dcerpc_drsuapi_DsCrackNames(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsCrackNames failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsCrackNames failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       test->name = talloc_strdup(test, name);
+       test->description = NULL;
+       test->run = wrap_test_drsuapi;
+       test->dangerous = false;
+       test->data = NULL;
+       test->fn = fn;
 
-       if (!ret) {
-               return ret;
-       }
+       DLIST_ADD(tcase->tcase.tests, test);
 
-       return ret;
+       return test;
 }
 
-static BOOL test_DsGetDCInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                     struct DsPrivate *priv)
+static bool test_DsGetDomainControllerInfo(struct torture_context *torture, 
+                                          struct dcerpc_pipe *p, 
+                                          struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsGetDomainControllerInfo r;
-       BOOL ret = True;
-
-       r.in.bind_handle = &priv->bind_handle;
-       r.in.level = 1;
-
-       r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_realm());
-       r.in.req.req1.level = 1;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       }
-
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
+       bool found = false;
+       int i, j, k;
+       
+       struct {
+               const char *name;
+               WERROR expected;
+       } names[] = { 
+               {       
+                       .name = torture_join_dom_netbios_name(priv->join),
+                       .expected = WERR_OK
+               },
+               {
+                       .name = torture_join_dom_dns_name(priv->join),
+                       .expected = WERR_OK
+               },
+               {
+                       .name = "__UNKNOWN_DOMAIN__",
+                       .expected = WERR_DS_OBJ_NOT_FOUND
+               },
+               {
+                       .name = "unknown.domain.samba.example.com",
+                       .expected = WERR_DS_OBJ_NOT_FOUND
+               },
+       };
+       int levels[] = {1, 2};
+       int level;
+
+       for (i=0; i < ARRAY_SIZE(levels); i++) {
+               for (j=0; j < ARRAY_SIZE(names); j++) {
+                       level = levels[i];
+                       r.in.bind_handle = &priv->bind_handle;
+                       r.in.level = 1;
+                       
+                       r.in.req.req1.domain_name = names[j].name;
+                       r.in.req.req1.level = level;
+                       
+                       torture_comment(torture,
+                                  "testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
+                              r.in.req.req1.level, r.in.req.req1.domain_name);
+               
+                       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, torture, &r);
+                       torture_assert_ntstatus_ok(torture, status,
+                                  "dcerpc_drsuapi_DsGetDomainControllerInfo with dns domain failed");
+                       torture_assert_werr_equal(torture, 
+                                                                         r.out.result, names[j].expected, 
+                                          "DsGetDomainControllerInfo level with dns domain failed");
+               
+                       if (!W_ERROR_IS_OK(r.out.result)) {
+                               /* If this was an error, we can't read the result structure */
+                               continue;
+                       }
 
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       } else {
-               if (r.out.ctr.ctr2.count > 0) {
-                       priv->dcinfo    = r.out.ctr.ctr2.array[0];
+                       torture_assert_int_equal(torture, 
+                                                r.in.req.req1.level, r.out.level_out, 
+                                                "dcerpc_drsuapi_DsGetDomainControllerInfo level"); 
+
+                       switch (level) {
+                       case 1:
+                               for (k=0; k < r.out.ctr.ctr1.count; k++) {
+                                       if (strcasecmp_m(r.out.ctr.ctr1.array[k].netbios_name, 
+                                                        torture_join_netbios_name(priv->join)) == 0) {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                               break;
+                       case 2:
+                               for (k=0; k < r.out.ctr.ctr2.count; k++) {
+                                       if (strcasecmp_m(r.out.ctr.ctr2.array[k].netbios_name, 
+                                                        torture_join_netbios_name(priv->join)) == 0) {
+                                               found = true;
+                                               priv->dcinfo    = r.out.ctr.ctr2.array[k];
+                                               break;
+                                       }
+                               }
+                               break;
+                       }
+                       torture_assert(torture, found,
+                                "dcerpc_drsuapi_DsGetDomainControllerInfo: Failed to find the domain controller we just created during the join");
                }
        }
 
+       r.in.bind_handle = &priv->bind_handle;
+       r.in.level = 1;
+       
+       r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__"; /* This is clearly ignored for this level */
        r.in.req.req1.level = -1;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with dns domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       }
-
-       r.in.req.req1.domain_name = talloc_strdup(mem_ctx, lp_workgroup());
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+       
+       torture_comment(torture,
+               "testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
+              r.in.req.req1.level, r.in.req.req1.domain_name);
+       
+       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, torture, &r);
+
+       torture_assert_ntstatus_ok(torture, status, 
+                       "dcerpc_drsuapi_DsGetDomainControllerInfo with dns domain failed");
+       torture_assert_werr_ok(torture, r.out.result, 
+                          "DsGetDomainControllerInfo with dns domain failed");
+       
+       {
+               const char *dc_account = talloc_asprintf(torture, "%s\\%s$",
+                                                        torture_join_dom_netbios_name(priv->join), 
+                                                        priv->dcinfo.netbios_name);
+               for (k=0; k < r.out.ctr.ctr01.count; k++) {
+                       if (strcasecmp_m(r.out.ctr.ctr01.array[k].client_account, 
+                                        dc_account)) {
+                               found = true;
+                               break;
+                       }
                }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with netbios domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with netbios domain failed - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
+               torture_assert(torture, found,
+                       "dcerpc_drsuapi_DsGetDomainControllerInfo level: Failed to find the domain controller in last logon records");
        }
 
-       r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__";
-       r.in.req.req1.level = 2;
-
-       printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
-                       r.in.req.req1.level, r.in.req.req1.domain_name);
-
-       status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
-                       "    with invalid domain failed - %s\n",
-                       r.in.req.req1.level, errstr);
-               ret = False;
-       } else if (!W_ERROR_EQUAL(r.out.result, WERR_DS_OBJ_NOT_FOUND)) {
-               printf("DsGetDomainControllerInfo level %d\n"
-                       "    with invalid domain not expected error (WERR_DS_OBJ_NOT_FOUND) - %s\n",
-                       r.in.req.req1.level, win_errstr(r.out.result));
-               ret = False;
-       }
 
-       return ret;
+       return true;
 }
 
-static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+static bool test_DsWriteAccountSpn(struct torture_context *tctx, 
+                                  struct dcerpc_pipe *p, 
+                                  struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsWriteAccountSpn r;
        struct drsuapi_DsNameString names[2];
-       BOOL ret = True;
 
        r.in.bind_handle                = &priv->bind_handle;
        r.in.level                      = 1;
 
-       printf("testing DsWriteAccountSpn\n");
-
        r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
        r.in.req.req1.unknown1  = 0;
        r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
        r.in.req.req1.count     = 2;
        r.in.req.req1.spn_names = names;
-       names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
-       names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
-
-       status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       names[0].str = talloc_asprintf(tctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
+       names[1].str = talloc_asprintf(tctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
+
+       status = dcerpc_drsuapi_DsWriteAccountSpn(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, 
+               "dcerpc_drsuapi_DsWriteAccountSpn failed");
+       torture_assert_werr_ok(tctx, r.out.result, "DsWriteAccountSpn failed");
 
        r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
        r.in.req.req1.unknown1  = 0;
 
-       status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-               }
-               printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
-               ret = False;
-       }
+       status = dcerpc_drsuapi_DsWriteAccountSpn(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, 
+               "dcerpc_drsuapi_DsWriteAccountSpn failed");
+       torture_assert_werr_ok(tctx, r.out.result, "DsWriteAccountSpn failed");
 
-       return ret;
+       return true;
 }
 
-static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+static bool test_DsReplicaGetInfo(struct torture_context *tctx, 
+                                 struct dcerpc_pipe *p, 
+                                 struct DsPrivate *priv)
 {
        NTSTATUS status;
        struct drsuapi_DsReplicaGetInfo r;
-       BOOL ret = True;
        int i;
        struct {
-               int32 level;
-               int32 infotype;
+               int32_t level;
+               int32_t infotype;
                const char *obj_dn;
        } array[] = {
                {       
@@ -696,7 +342,7 @@ static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        "__IGNORED__"
                },{
                        DRSUAPI_DS_REPLICA_GET_INFO2,
-                       DRSUAPI_DS_REPLICA_INFO_CURSURS05,
+                       DRSUAPI_DS_REPLICA_INFO_CURSORS05,
                        NULL
                },{
                        DRSUAPI_DS_REPLICA_GET_INFO2,
@@ -710,7 +356,8 @@ static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        for (i=0; i < ARRAY_SIZE(array); i++) {
                const char *object_dn;
 
-               printf("testing DsReplicaGetInfo level %d infotype %d\n",
+               torture_comment(tctx, 
+                       "testing DsReplicaGetInfo level %d infotype %d\n",
                        array[i].level, array[i].infotype);
 
                object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
@@ -733,164 +380,285 @@ static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        break;
                }
 
-               status = dcerpc_drsuapi_DsReplicaGetInfo(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       const char *errstr = nt_errstr(status);
-                       if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                               errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-                       }
-                       if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
-                               printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
-                               ret = False;
-                       } else {
-                               printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
-                                       array[i].level, array[i].infotype);
-                       }
-               } else if (!W_ERROR_IS_OK(r.out.result)) {
-                       printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
-                       ret = False;
-               }
+               status = dcerpc_drsuapi_DsReplicaGetInfo(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, 
+                       "dcerpc_drsuapi_DsReplicaGetInfo failed");
+               torture_assert_werr_ok(tctx, r.out.result, 
+                                      "DsReplicaGetInfo failed");
        }
 
-       return ret;
+       return true;
 }
 
-static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+static bool test_DsReplicaSync(struct torture_context *tctx,
+                              struct dcerpc_pipe *p, 
+                              struct DsPrivate *priv)
 {
        NTSTATUS status;
-       BOOL ret = True;
        int i;
        struct drsuapi_DsReplicaSync r;
-       struct drsuapi_DsReplicaSyncRequest1Info info1;
-
+       struct drsuapi_DsReplicaObjectIdentifier nc;
+       struct GUID null_guid;
+       struct dom_sid null_sid;
        struct {
-               int32 level;
+               int32_t level;
        } array[] = {
                {       
                        1
                }
        };
 
+       ZERO_STRUCT(null_guid);
+       ZERO_STRUCT(null_sid);
+
        r.in.bind_handle        = &priv->bind_handle;
 
        for (i=0; i < ARRAY_SIZE(array); i++) {
-               printf("testing DsReplicaGetInfo level %d\n",
-                       array[i].level);
+               torture_comment(tctx, "testing DsReplicaSync level %d\n",
+                               array[i].level);
 
                r.in.level = array[i].level;
                switch(r.in.level) {
                case 1:
-                       r.in.req.req1.info                      = &info1;
-                       r.in.req.req1.info->unknown1            = 32;
-                       r.in.req.req1.info->unknown2            = 120;
-                       ZERO_STRUCT(r.in.req.req1.info->guid1);
-                       ZERO_ARRAY(r.in.req.req1.info->unknown3);
-                       r.in.req.req1.info->nc_dn               = priv->domain_obj_dn;
-                       r.in.req.req1.guid1                     = priv->dcinfo.ntds_guid;
-                       r.in.req.req1.string1                   = NULL;
-                       r.in.req.req1.unknown1                  = 16;
+                       nc.guid                                 = null_guid;
+                       nc.sid                                  = null_sid;
+                       nc.dn                                   = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req1.naming_context            = &nc;
+                       r.in.req.req1.source_dsa_guid           = priv->dcinfo.ntds_guid;
+                       r.in.req.req1.other_info                = NULL;
+                       r.in.req.req1.options                   = 16;
                        break;
                }
 
-               status = dcerpc_drsuapi_DsReplicaSync(p, mem_ctx, &r);
-               if (!NT_STATUS_IS_OK(status)) {
-                       const char *errstr = nt_errstr(status);
-                       if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                               errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
-                       }
-                       printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
-                       ret = False;
-               } else if (!W_ERROR_IS_OK(r.out.result)) {
-                       printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
-                       ret = False;
-               }
+               status = dcerpc_drsuapi_DsReplicaSync(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, 
+                       "dcerpc_drsuapi_DsReplicaSync failed");
+               torture_assert_werr_ok(tctx, r.out.result, 
+                                      "DsReplicaSync failed");
        }
 
-       return ret;
+       return true;
 }
 
-static BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
-                       struct DsPrivate *priv)
+static bool test_DsReplicaUpdateRefs(struct torture_context *tctx, 
+                                    struct dcerpc_pipe *p, 
+                                    struct DsPrivate *priv)
 {
        NTSTATUS status;
-       struct drsuapi_DsUnbind r;
-       BOOL ret = True;
+       int i;
+       struct drsuapi_DsReplicaUpdateRefs r;
+       struct drsuapi_DsReplicaObjectIdentifier nc;
+       struct GUID null_guid;
+       struct dom_sid null_sid;
+       struct {
+               int32_t level;
+       } array[] = {
+               {       
+                       1
+               }
+       };
 
-       r.in.bind_handle = &priv->bind_handle;
-       r.out.bind_handle = &priv->bind_handle;
+       ZERO_STRUCT(null_guid);
+       ZERO_STRUCT(null_sid);
 
-       printf("testing DsUnbind\n");
+       r.in.bind_handle        = &priv->bind_handle;
 
-       status = dcerpc_drsuapi_DsUnbind(p, mem_ctx, &r);
-       if (!NT_STATUS_IS_OK(status)) {
-               const char *errstr = nt_errstr(status);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
+       for (i=0; i < ARRAY_SIZE(array); i++) {
+               torture_comment(tctx, "testing DsReplicaUpdateRefs level %d\n",
+                       array[i].level);
+
+               r.in.level = array[i].level;
+               switch(r.in.level) {
+               case 1:
+                       nc.guid                         = null_guid;
+                       nc.sid                          = null_sid;
+                       nc.dn                           = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req1.naming_context    = &nc;
+                       r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(tctx, "__some_dest_dsa_guid_string._msdn.%s",
+                                                                               priv->domain_dns_name);
+                       r.in.req.req1.dest_dsa_guid     = null_guid;
+                       r.in.req.req1.options           = 0;
+                       break;
                }
-               printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
-               ret = False;
-       } else if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("DsBind failed - %s\n", win_errstr(r.out.result));
-               ret = False;
+
+               status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, 
+                       "dcerpc_drsuapi_DsReplicaUpdateRefs failed");
+               torture_assert_werr_ok(tctx, r.out.result, 
+                       "DsReplicaUpdateRefs failed");
        }
 
-       return ret;
+       return true;
 }
 
-BOOL torture_rpc_drsuapi(void)
+static bool test_DsGetNCChanges(struct torture_context *tctx, 
+                               struct dcerpc_pipe *p, 
+                               struct DsPrivate *priv)
 {
-        NTSTATUS status;
-        struct dcerpc_pipe *p;
-       TALLOC_CTX *mem_ctx;
-       BOOL ret = True;
-       struct DsPrivate priv;
+       NTSTATUS status;
+       int i;
+       struct drsuapi_DsGetNCChanges r;
+       struct drsuapi_DsReplicaObjectIdentifier nc;
+       struct GUID null_guid;
+       struct dom_sid null_sid;
+       struct {
+               int32_t level;
+       } array[] = {
+               {       
+                       5
+               },
+               {       
+                       8
+               }
+       };
 
-       status = torture_rpc_connection(&p, 
-                                       DCERPC_DRSUAPI_NAME,
-                                       DCERPC_DRSUAPI_UUID,
-                                       DCERPC_DRSUAPI_VERSION);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
+       ZERO_STRUCT(null_guid);
+       ZERO_STRUCT(null_sid);
 
-       printf("Connected to DRAUAPI pipe\n");
+       for (i=0; i < ARRAY_SIZE(array); i++) {
+               torture_comment(tctx, "testing DsGetNCChanges level %d\n",
+                       array[i].level);
 
-       mem_ctx = talloc_init("torture_rpc_drsuapi");
+               r.in.bind_handle        = &priv->bind_handle;
+               r.in.level              = &array[i].level;
+
+               switch (*r.in.level) {
+               case 5:
+                       nc.guid = null_guid;
+                       nc.sid  = null_sid;
+                       nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req5.destination_dsa_guid              = GUID_random();
+                       r.in.req.req5.source_dsa_invocation_id          = null_guid;
+                       r.in.req.req5.naming_context                    = &nc;
+                       r.in.req.req5.highwatermark.tmp_highest_usn     = 0;
+                       r.in.req.req5.highwatermark.reserved_usn        = 0;
+                       r.in.req.req5.highwatermark.highest_usn         = 0;
+                       r.in.req.req5.uptodateness_vector               = NULL;
+                       r.in.req.req5.replica_flags                     = 0;
+                       if (lp_parm_bool(-1, "drsuapi", "compression", false)) {
+                               r.in.req.req5.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
+                       }
+                       r.in.req.req5.max_object_count                  = 0;
+                       r.in.req.req5.max_ndr_size                      = 0;
+                       r.in.req.req5.unknown4                          = 0;
+                       r.in.req.req5.h1                                = 0;
 
-       ZERO_STRUCT(priv);
+                       break;
+               case 8:
+                       nc.guid = null_guid;
+                       nc.sid  = null_sid;
+                       nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
+
+                       r.in.req.req8.destination_dsa_guid              = GUID_random();
+                       r.in.req.req8.source_dsa_invocation_id          = null_guid;
+                       r.in.req.req8.naming_context                    = &nc;
+                       r.in.req.req8.highwatermark.tmp_highest_usn     = 0;
+                       r.in.req.req8.highwatermark.reserved_usn        = 0;
+                       r.in.req.req8.highwatermark.highest_usn         = 0;
+                       r.in.req.req8.uptodateness_vector               = NULL;
+                       r.in.req.req8.replica_flags                     = 0;
+                       if (lp_parm_bool(-1, "drsuapi", "compression", false)) {
+                               r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
+                       }
+                       if (lp_parm_bool(-1, "drsuapi", "neighbour_writeable",true)) {
+                               r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
+                       }
+                       r.in.req.req8.replica_flags                     |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
+                                                                       | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
+                                                                       ;
+                       r.in.req.req8.max_object_count                  = 402;
+                       r.in.req.req8.max_ndr_size                      = 402116;
+                       r.in.req.req8.unknown4                          = 0;
+                       r.in.req.req8.h1                                = 0;
+                       r.in.req.req8.unique_ptr1                       = 0;
+                       r.in.req.req8.unique_ptr2                       = 0;
+                       r.in.req.req8.mapping_ctr.num_mappings          = 0;
+                       r.in.req.req8.mapping_ctr.mappings              = NULL;
 
-       if (!test_DsBind(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+                       break;
+               }
 
-       if (!test_DsGetDCInfo(p, mem_ctx, &priv)) {
-               ret = False;
+               status = dcerpc_drsuapi_DsGetNCChanges(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, 
+                       "dcerpc_drsuapi_DsGetNCChanges failed");
+               torture_assert_werr_ok(tctx, r.out.result, 
+                                      "DsGetNCChanges failed");
        }
 
-       if (!test_DsCrackNames(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+       return true;
+}
 
-       if (!test_DsWriteAccountSpn(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+bool test_QuerySitesByCost(struct torture_context *tctx, struct dcerpc_pipe *p, 
+                          struct DsPrivate *priv)
+{
+       NTSTATUS status;
+       struct drsuapi_QuerySitesByCost r;
 
-       if (!test_DsReplicaGetInfo(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+       const char *my_site = "Default-First-Site-Name";
+       const char *remote_site1 = "smbtorture-nonexisting-site1";
+       const char *remote_site2 = "smbtorture-nonexisting-site2";
 
-       if (!test_DsReplicaSync(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+       r.in.bind_handle = &priv->bind_handle;
+       r.in.level = 1;
+       r.in.req.req1.site_from = talloc_strdup(tctx, my_site);
+       r.in.req.req1.num_req = 2;
+       r.in.req.req1.site_to = talloc_zero_array(tctx, const char *, r.in.req.req1.num_req);
+       r.in.req.req1.site_to[0] = talloc_strdup(tctx, remote_site1);
+       r.in.req.req1.site_to[1] = talloc_strdup(tctx, remote_site2);
+       r.in.req.req1.flags = 0;
+
+       status = dcerpc_drsuapi_QuerySitesByCost(p, tctx, &r);
+       torture_assert_ntstatus_ok(tctx, status, "drsuapi_QuerySitesByCost");
+       torture_assert_werr_ok(tctx, r.out.result, "QuerySitesByCost failed");
+
+       torture_assert_werr_equal(tctx, r.out.ctr.ctr1.info[0].error_code, 
+                                 WERR_DS_OBJ_NOT_FOUND, "expected not found error");
+       torture_assert_werr_equal(tctx, r.out.ctr.ctr1.info[1].error_code, 
+                                 WERR_DS_OBJ_NOT_FOUND, "expected not found error");
+
+       torture_assert_int_equal(tctx, r.out.ctr.ctr1.info[0].site_cost,
+                                (uint32_t) -1, "unexpected site cost");
+         
+       torture_assert_int_equal(tctx, r.out.ctr.ctr1.info[1].site_cost, 
+                                (uint32_t) -1, "unexpected site cost");
+
+       return true;
+}
 
-       if (!test_DsUnbind(p, mem_ctx, &priv)) {
-               ret = False;
-       }
+struct torture_suite *torture_rpc_drsuapi(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "DRSUAPI");
+       struct torture_test *test;
+       struct torture_rpc_tcase *tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "drsuapi", 
+                                                                           &ndr_table_drsuapi, TEST_MACHINE_NAME);
+
+       torture_rpc_tcase_add_drsuapi_test(tcase, "QuerySitesByCost", test_QuerySitesByCost);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsGetDomainControllerInfo", test_DsGetDomainControllerInfo);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsCrackNames", test_DsCrackNames);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsWriteAccountSpn", test_DsWriteAccountSpn);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsReplicaGetInfo", test_DsReplicaGetInfo);
+       test = torture_rpc_tcase_add_drsuapi_test(tcase, "DsReplicaSync", test_DsReplicaSync);
+       test->dangerous = true;
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsReplicaUpdateRefs", test_DsReplicaUpdateRefs);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsGetNCChange", test_DsGetNCChanges);
+
+       return suite;
+}
 
-       talloc_destroy(mem_ctx);
+struct torture_suite *torture_rpc_drsuapi_cracknames(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "CRACKNAMES");
+       struct torture_rpc_tcase *tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "drsuapi", 
+                                                                           &ndr_table_drsuapi, TEST_MACHINE_NAME);
 
-        torture_rpc_close(p);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsGetDomainControllerInfo", test_DsGetDomainControllerInfo);
+       torture_rpc_tcase_add_drsuapi_test(tcase, "DsCrackNames", test_DsCrackNames);
 
-       return ret;
+       return suite;
 }
+