r26429: Avoid use of global_smb_iconv_convenience.
[ira/wip.git] / source4 / torture / rap / rap.c
index a74acdb331a4dc2c014d3b8065f76d9b881330fc..d39a83034d98e4e248d3d11498268cb694e44e6b 100644 (file)
@@ -2,10 +2,11 @@
    Unix SMB/CIFS implementation.
    test suite for various RAP operations
    Copyright (C) Volker Lendecke 2004
+   Copyright (C) Tim Potter 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 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 "libcli/libcli.h"
+#include "torture/torture.h"
+#include "torture/util.h"
+#include "libcli/rap/rap.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/libcli.h"
+#include "librpc/ndr/libndr.h"
+#include "param/param.h"
+
+#define RAP_GOTO(call) do { \
+       NTSTATUS _status; \
+       _status = call; \
+       if (!NT_STATUS_IS_OK(_status)) { \
+               result = _status; \
+               goto done; \
+       } \
+} while (0)
+
+#define NDR_GOTO(call) do { \
+       enum ndr_err_code _ndr_err; \
+       _ndr_err = call; \
+       if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
+               result = ndr_map_error2ntstatus(_ndr_err); \
+               goto done; \
+       } \
+} while (0)
+
+#define NDR_RETURN(call) do { \
+       enum ndr_err_code _ndr_err; \
+       _ndr_err = call; \
+       if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
+               return ndr_map_error2ntstatus(_ndr_err); \
+       } \
+} while (0)
 
 struct rap_call {
-       TALLOC_CTX *mem_ctx;
-       uint16 callno;
+       uint16_t callno;
        char *paramdesc;
        const char *datadesc;
 
-       uint16 status;
-       uint16 convert;
+       uint16_t status;
+       uint16_t convert;
        
-       uint16 rcv_paramlen, rcv_datalen;
+       uint16_t rcv_paramlen, rcv_datalen;
 
        struct ndr_push *ndr_push_param;
        struct ndr_push *ndr_push_data;
@@ -39,24 +72,20 @@ struct rap_call {
 
 #define RAPNDR_FLAGS (LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
 
-static struct rap_call *new_rap_cli_call(uint16 callno)
+static struct rap_call *new_rap_cli_call(TALLOC_CTX *mem_ctx, uint16_t callno)
 {
        struct rap_call *call;
-       TALLOC_CTX *mem_ctx = talloc_init("rap_call");
-
-       if (mem_ctx == NULL)
-               return NULL;
 
-       call = talloc_p(mem_ctx, struct rap_call);
+       call = talloc(mem_ctx, struct rap_call);
 
        if (call == NULL)
                return NULL;
 
-       ZERO_STRUCTP(call);
-
        call->callno = callno;
        call->rcv_paramlen = 4;
-       call->mem_ctx = mem_ctx;
+
+       call->paramdesc = NULL;
+       call->datadesc = NULL;
 
        call->ndr_push_param = ndr_push_init_ctx(mem_ctx);
        call->ndr_push_param->flags = RAPNDR_FLAGS;
@@ -67,11 +96,6 @@ static struct rap_call *new_rap_cli_call(uint16 callno)
        return call;
 }
 
-static void destroy_rap_call(struct rap_call *call)
-{
-       talloc_destroy(call->mem_ctx);
-}
-
 static void rap_cli_push_paramdesc(struct rap_call *call, char desc)
 {
        int len = 0;
@@ -79,30 +103,32 @@ static void rap_cli_push_paramdesc(struct rap_call *call, char desc)
        if (call->paramdesc != NULL)
                len = strlen(call->paramdesc);
 
-       call->paramdesc = talloc_realloc(call->mem_ctx,
+       call->paramdesc = talloc_realloc(call,
                                         call->paramdesc,
+                                        char,
                                         len+2);
+
        call->paramdesc[len] = desc;
        call->paramdesc[len+1] = '\0';
 }
 
-static void rap_cli_push_word(struct rap_call *call, uint16 val)
+static void rap_cli_push_word(struct rap_call *call, uint16_t val)
 {
        rap_cli_push_paramdesc(call, 'W');
-       ndr_push_uint16(call->ndr_push_param, val);
+       ndr_push_uint16(call->ndr_push_param, NDR_SCALARS, val);
 }
 
-static void rap_cli_push_dword(struct rap_call *call, uint32 val)
+static void rap_cli_push_dword(struct rap_call *call, uint32_t val)
 {
        rap_cli_push_paramdesc(call, 'D');
-       ndr_push_uint32(call->ndr_push_param, val);
+       ndr_push_uint32(call->ndr_push_param, NDR_SCALARS, val);
 }
 
 static void rap_cli_push_rcvbuf(struct rap_call *call, int len)
 {
        rap_cli_push_paramdesc(call, 'r');
        rap_cli_push_paramdesc(call, 'L');
-       ndr_push_uint16(call->ndr_push_param, len);
+       ndr_push_uint16(call->ndr_push_param, NDR_SCALARS, len);
        call->rcv_datalen = len;
 }
 
@@ -110,7 +136,13 @@ static void rap_cli_expect_multiple_entries(struct rap_call *call)
 {
        rap_cli_push_paramdesc(call, 'e');
        rap_cli_push_paramdesc(call, 'h');
-       call->rcv_paramlen += 4; /* uint16 entry count, uint16 total */
+       call->rcv_paramlen += 4; /* uint16_t entry count, uint16_t total */
+}
+
+static void rap_cli_expect_word(struct rap_call *call)
+{
+       rap_cli_push_paramdesc(call, 'h');
+       call->rcv_paramlen += 2;
 }
 
 static void rap_cli_push_string(struct rap_call *call, const char *str)
@@ -129,42 +161,41 @@ static void rap_cli_expect_format(struct rap_call *call, const char *format)
 }
 
 static NTSTATUS rap_pull_string(TALLOC_CTX *mem_ctx, struct ndr_pull *ndr,
-                               uint16 convert, char **dest)
+                               uint16_t convert, char **dest)
 {
-       uint16 string_offset;
-       uint16 ignore;
-       char *p;
+       uint16_t string_offset;
+       uint16_t ignore;
+       const char *p;
        size_t len;
 
-       NDR_CHECK(ndr_pull_uint16(ndr, &string_offset));
-       NDR_CHECK(ndr_pull_uint16(ndr, &ignore));
+       NDR_RETURN(ndr_pull_uint16(ndr, NDR_SCALARS, &string_offset));
+       NDR_RETURN(ndr_pull_uint16(ndr, NDR_SCALARS, &ignore));
 
        string_offset -= convert;
 
        if (string_offset+1 > ndr->data_size)
                return NT_STATUS_INVALID_PARAMETER;
 
-       p = ndr->data + string_offset;
+       p = (const char *)(ndr->data + string_offset);
        len = strnlen(p, ndr->data_size-string_offset);
 
        if ( string_offset + len + 1 >  ndr->data_size )
                return NT_STATUS_INVALID_PARAMETER;
 
-       *dest = talloc_zero(mem_ctx, len+1);
-       pull_ascii(*dest, p, len+1, len, 0);
+       *dest = talloc_zero_array(mem_ctx, char, len+1);
+       pull_string(lp_iconv_convenience(global_loadparm), *dest, p, len+1, len, STR_ASCII);
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS rap_cli_do_call(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
-                               struct rap_call *call)
+static NTSTATUS rap_cli_do_call(struct smbcli_tree *tree, struct rap_call *call)
 {
        NTSTATUS result;
        DATA_BLOB param_blob;
        struct ndr_push *params;
        struct smb_trans2 trans;
 
-       params = ndr_push_init_ctx(mem_ctx);
+       params = ndr_push_init_ctx(call);
 
        if (params == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -172,7 +203,7 @@ static NTSTATUS rap_cli_do_call(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
        params->flags = RAPNDR_FLAGS;
 
        trans.in.max_param = call->rcv_paramlen;
-       trans.in.max_data = call->rcv_datalen;
+       trans.in.max_data = smb_raw_max_trans_data(tree, call->rcv_paramlen);
        trans.in.max_setup = 0;
        trans.in.flags = 0;
        trans.in.timeout = 0;
@@ -180,48 +211,43 @@ static NTSTATUS rap_cli_do_call(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
        trans.in.setup = NULL;
        trans.in.trans_name = "\\PIPE\\LANMAN";
 
-       NDR_CHECK(ndr_push_uint16(params, call->callno));
-       NDR_CHECK(ndr_push_string(params, NDR_SCALARS, call->paramdesc));
-       NDR_CHECK(ndr_push_string(params, NDR_SCALARS, call->datadesc));
+       NDR_RETURN(ndr_push_uint16(params, NDR_SCALARS, call->callno));
+       if (call->paramdesc)
+               NDR_RETURN(ndr_push_string(params, NDR_SCALARS, call->paramdesc));
+       if (call->datadesc)
+               NDR_RETURN(ndr_push_string(params, NDR_SCALARS, call->datadesc));
 
        param_blob = ndr_push_blob(call->ndr_push_param);
-       NDR_CHECK(ndr_push_bytes(params, param_blob.data,
+       NDR_RETURN(ndr_push_bytes(params, param_blob.data,
                                 param_blob.length));
 
        trans.in.params = ndr_push_blob(params);
        trans.in.data = data_blob(NULL, 0);
 
-       result = smb_raw_trans(cli->tree, call->mem_ctx, &trans);
+       result = smb_raw_trans(tree, call, &trans);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       call->ndr_pull_param = ndr_pull_init_blob(&trans.out.params,
-                                                 call->mem_ctx);
+       call->ndr_pull_param = ndr_pull_init_blob(&trans.out.params, call);
        call->ndr_pull_param->flags = RAPNDR_FLAGS;
 
-       call->ndr_pull_data = ndr_pull_init_blob(&trans.out.data,
-                                                call->mem_ctx);
+       call->ndr_pull_data = ndr_pull_init_blob(&trans.out.data, call);
        call->ndr_pull_data->flags = RAPNDR_FLAGS;
 
        return result;
 }
 
-#define NDR_OK(call) do { NTSTATUS _status; \
-                             _status = call; \
-                             if (!NT_STATUS_IS_OK(_status)) \
-                               goto done; \
-                        } while (0)
 
-static NTSTATUS smbcli_rap_netshareenum(struct smbcli_state *cli,
-                                    TALLOC_CTX *mem_ctx,
-                                    struct rap_NetShareEnum *r)
+static NTSTATUS smbcli_rap_netshareenum(struct smbcli_tree *tree,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct rap_NetShareEnum *r)
 {
        struct rap_call *call;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        int i;
 
-       call = new_rap_cli_call(0);
+       call = new_rap_cli_call(tree, RAP_WshareEnum);
 
        if (call == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -239,36 +265,37 @@ static NTSTATUS smbcli_rap_netshareenum(struct smbcli_state *cli,
                break;
        }
 
-       result = rap_cli_do_call(cli, mem_ctx, call);
+       result = rap_cli_do_call(tree, call);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.status));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.convert));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.count));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.available));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.status));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.convert));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.count));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.available));
 
-       r->out.info = talloc_array_p(mem_ctx, union rap_shareenum_info,
-                                    r->out.count);
+       r->out.info = talloc_array(mem_ctx, union rap_shareenum_info, r->out.count);
 
-       if (r->out.info == NULL)
-               return NT_STATUS_NO_MEMORY;
+       if (r->out.info == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        for (i=0; i<r->out.count; i++) {
                switch(r->in.level) {
                case 0:
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
-                                             r->out.info[i].info0.name, 13));
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                             (uint8_t *)r->out.info[i].info0.name, 13));
                        break;
                case 1:
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
-                                             r->out.info[i].info1.name, 13));
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
-                                             &r->out.info[i].info1.pad, 1));
-                       NDR_OK(ndr_pull_uint16(call->ndr_pull_data,
-                                              &r->out.info[i].info1.type));
-                       NDR_OK(rap_pull_string(mem_ctx, call->ndr_pull_data,
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                             (uint8_t *)r->out.info[i].info1.name, 13));
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                             (uint8_t *)&r->out.info[i].info1.pad, 1));
+                       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_data,
+                                              NDR_SCALARS, &r->out.info[i].info1.type));
+                       RAP_GOTO(rap_pull_string(mem_ctx, call->ndr_pull_data,
                                               r->out.convert,
                                               &r->out.info[i].info1.comment));
                        break;
@@ -278,21 +305,21 @@ static NTSTATUS smbcli_rap_netshareenum(struct smbcli_state *cli,
        result = NT_STATUS_OK;
 
  done:
-       destroy_rap_call(call);
-
+       talloc_free(call);
        return result;
 }
 
-static BOOL test_netshareenum(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_netshareenum(struct smbcli_tree *tree)
 {
        struct rap_NetShareEnum r;
        int i;
+       TALLOC_CTX *tmp_ctx = talloc_new(tree);
 
        r.in.level = 1;
        r.in.bufsize = 8192;
 
-       if (!NT_STATUS_IS_OK(smbcli_rap_netshareenum(cli, mem_ctx, &r)))
-               return False;
+       if (!NT_STATUS_IS_OK(smbcli_rap_netshareenum(tree, tmp_ctx, &r)))
+               return false;
 
        for (i=0; i<r.out.count; i++) {
                printf("%s %d %s\n", r.out.info[i].info1.name,
@@ -300,18 +327,20 @@ static BOOL test_netshareenum(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                       r.out.info[i].info1.comment);
        }
 
-       return True;
+       talloc_free(tmp_ctx);
+
+       return true;
 }
 
-static NTSTATUS smbcli_rap_netserverenum2(struct smbcli_state *cli,
-                                      TALLOC_CTX *mem_ctx,
-                                      struct rap_NetServerEnum2 *r)
+static NTSTATUS smbcli_rap_netserverenum2(struct smbcli_tree *tree,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct rap_NetServerEnum2 *r)
 {
        struct rap_call *call;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        int i;
 
-       call = new_rap_cli_call(104);
+       call = new_rap_cli_call(mem_ctx, RAP_NetServerEnum2);
 
        if (call == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -331,40 +360,41 @@ static NTSTATUS smbcli_rap_netserverenum2(struct smbcli_state *cli,
                break;
        }
 
-       result = rap_cli_do_call(cli, mem_ctx, call);
+       result = rap_cli_do_call(tree, call);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
        result = NT_STATUS_INVALID_PARAMETER;
 
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.status));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.convert));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.count));
-       NDR_OK(ndr_pull_uint16(call->ndr_pull_param, &r->out.available));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.status));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.convert));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.count));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.available));
 
-       r->out.info = talloc_array_p(mem_ctx, union rap_server_info,
-                                    r->out.count);
+       r->out.info = talloc_array(mem_ctx, union rap_server_info, r->out.count);
 
-       if (r->out.info == NULL)
-               return NT_STATUS_NO_MEMORY;
+       if (r->out.info == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
 
        for (i=0; i<r->out.count; i++) {
                switch(r->in.level) {
                case 0:
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
-                                             r->out.info[i].info0.name, 16));
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                             (uint8_t *)r->out.info[i].info0.name, 16));
                        break;
                case 1:
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
-                                             r->out.info[i].info1.name, 16));
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                             (uint8_t *)r->out.info[i].info1.name, 16));
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
                                              &r->out.info[i].info1.version_major, 1));
-                       NDR_OK(ndr_pull_bytes(call->ndr_pull_data,
+                       NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
                                              &r->out.info[i].info1.version_minor, 1));
-                       NDR_OK(ndr_pull_uint32(call->ndr_pull_data,
-                                              &r->out.info[i].info1.servertype));
-                       NDR_OK(rap_pull_string(mem_ctx, call->ndr_pull_data,
+                       NDR_GOTO(ndr_pull_uint32(call->ndr_pull_data,
+                                              NDR_SCALARS, &r->out.info[i].info1.servertype));
+                       RAP_GOTO(rap_pull_string(mem_ctx, call->ndr_pull_data,
                                               r->out.convert,
                                               &r->out.info[i].info1.comment));
                }
@@ -373,15 +403,15 @@ static NTSTATUS smbcli_rap_netserverenum2(struct smbcli_state *cli,
        result = NT_STATUS_OK;
 
  done:
-       destroy_rap_call(call);
-
+       talloc_free(call);
        return result;
 }
 
-static BOOL test_netserverenum(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_netserverenum(struct smbcli_tree *tree)
 {
        struct rap_NetServerEnum2 r;
        int i;
+       TALLOC_CTX *tmp_ctx = talloc_new(tree);
 
        r.in.level = 0;
        r.in.bufsize = 8192;
@@ -389,8 +419,8 @@ static BOOL test_netserverenum(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        r.in.servertype = 0x80000000;
        r.in.domain = NULL;
 
-       if (!NT_STATUS_IS_OK(smbcli_rap_netserverenum2(cli, mem_ctx, &r)))
-               return False;
+       if (!NT_STATUS_IS_OK(smbcli_rap_netserverenum2(tree, tmp_ctx, &r)))
+               return false;
 
        for (i=0; i<r.out.count; i++) {
                switch (r.in.level) {
@@ -405,41 +435,166 @@ static BOOL test_netserverenum(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                }
        }
 
-       return True;
+       talloc_free(tmp_ctx);
+
+       return true;
 }
 
+_PUBLIC_ NTSTATUS smbcli_rap_netservergetinfo(struct smbcli_tree *tree,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct rap_WserverGetInfo *r)
+{
+       struct rap_call *call;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+       if (!(call = new_rap_cli_call(mem_ctx, RAP_WserverGetInfo))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       rap_cli_push_word(call, r->in.level);
+       rap_cli_push_rcvbuf(call, r->in.bufsize);
+       rap_cli_expect_word(call);
 
+       switch(r->in.level) {
+       case 0:
+               rap_cli_expect_format(call, "B16");
+               break;
+       case 1:
+               rap_cli_expect_format(call, "B16BBDz");
+               break;
+       default:
+               result = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       result = rap_cli_do_call(tree, call);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
 
-static BOOL test_rap(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.status));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.convert));
+       NDR_GOTO(ndr_pull_uint16(call->ndr_pull_param, NDR_SCALARS, &r->out.available));
+
+       switch(r->in.level) {
+       case 0:
+               NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                     (uint8_t *)r->out.info.info0.name, 16));
+               break;
+       case 1:
+               NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                     (uint8_t *)r->out.info.info1.name, 16));
+               NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                     &r->out.info.info1.version_major, 1));
+               NDR_GOTO(ndr_pull_bytes(call->ndr_pull_data,
+                                     &r->out.info.info1.version_minor, 1));
+               NDR_GOTO(ndr_pull_uint32(call->ndr_pull_data,
+                                      NDR_SCALARS, &r->out.info.info1.servertype));
+               RAP_GOTO(rap_pull_string(mem_ctx, call->ndr_pull_data,
+                                      r->out.convert,
+                                      &r->out.info.info1.comment));
+       }
+ done:
+       talloc_free(call);
+       return result;
+}
+
+static bool test_netservergetinfo(struct smbcli_tree *tree)
 {
-       BOOL res = True;
+       struct rap_WserverGetInfo r;
+       bool res = true;
+       TALLOC_CTX *mem_ctx;
 
-       if (!test_netserverenum(cli, mem_ctx))
-               res = False;
+       if (!(mem_ctx = talloc_new(tree))) {
+               return false;
+       }
 
-       if (!test_netshareenum(cli, mem_ctx))
-               res = False;
+       r.in.bufsize = 0xffff;
 
+       r.in.level = 0;
+       res &= NT_STATUS_IS_OK(smbcli_rap_netservergetinfo(tree, mem_ctx, &r));
+       r.in.level = 1;
+       res &= NT_STATUS_IS_OK(smbcli_rap_netservergetinfo(tree, mem_ctx, &r));
+
+       talloc_free(mem_ctx);
        return res;
 }
 
-BOOL torture_raw_rap(void)
+static bool test_rap(struct smbcli_tree *tree)
+{
+       bool res = true;
+
+       res &= test_netserverenum(tree);
+       res &= test_netshareenum(tree);
+       res &= test_netservergetinfo(tree);
+
+       return res;
+}
+
+bool torture_rap_basic(struct torture_context *torture)
 {
        struct smbcli_state *cli;
-       BOOL ret = True;
+       bool ret = true;
        TALLOC_CTX *mem_ctx;
 
-       if (!torture_open_connection(&cli)) {
-               return False;
+       if (!torture_open_connection(&cli, torture, 0)) {
+               return false;
        }
 
-       mem_ctx = talloc_init("torture_raw_rap");
+       mem_ctx = talloc_init("torture_rap_basic");
 
-       if (!test_rap(cli, mem_ctx)) {
-               ret = False;
+       if (!test_rap(cli->tree)) {
+               ret = false;
        }
 
        torture_close_connection(cli);
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
+
        return ret;
 }
+
+bool torture_rap_scan(struct torture_context *torture)
+{
+       TALLOC_CTX *mem_ctx;
+       struct smbcli_state *cli;
+       int callno;
+
+       mem_ctx = talloc_init("torture_rap_scan");
+
+       if (!torture_open_connection(&cli, torture, 0)) {
+               return false;
+       }
+       
+       for (callno = 0; callno < 0xffff; callno++) {
+               struct rap_call *call = new_rap_cli_call(mem_ctx, callno);
+               NTSTATUS result;
+
+               result = rap_cli_do_call(cli->tree, call);
+
+               if (!NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER))
+                       continue;
+
+               printf("callno %d is RAP call\n", callno);
+       }
+
+       torture_close_connection(cli);
+
+       return true;
+}
+
+NTSTATUS torture_rap_init(void)
+{
+       struct torture_suite *suite = torture_suite_create(
+                                                                       talloc_autofree_context(),
+                                                                       "RAP");
+
+       torture_suite_add_simple_test(suite, "BASIC", torture_rap_basic);
+       torture_suite_add_simple_test(suite, "SCAN", torture_rap_scan);
+
+       suite->description = talloc_strdup(suite, 
+                                               "Remote Administration Protocol tests");
+
+       torture_register_suite(suite);
+
+       return NT_STATUS_OK;
+}