s4-smbtorture: Make test names lowercase and dot-separated.
[metze/samba/wip.git] / source4 / torture / nbt / wins.c
index 44ac61fe460b1e67f6e7f1db645e2de080d4819c..0ddaa8a05a1ea2fcb432ab35666fae820b14d31b 100644 (file)
@@ -7,7 +7,7 @@
    
    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 "lib/util/dlinklist.h"
+#include "lib/events/events.h"
 #include "lib/socket/socket.h"
 #include "libcli/resolve/resolve.h"
 #include "system/network.h"
 #include "lib/socket/netif.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
 #include "torture/torture.h"
+#include "torture/nbt/proto.h"
+#include "param/param.h"
 
-#define CHECK_VALUE(v, correct) do { \
-       if ((v) != (correct)) { \
-               printf("(%s) Incorrect value %s=%d (0x%X) - should be %d (0x%X)\n", \
-                      __location__, #v, v, v, correct, correct); \
-               ret = False; \
-       }} while (0)
-
-#define CHECK_STRING(v, correct) do { \
-       if ((v) != (correct) && \
-           ((v)==NULL || (correct)==NULL || strcasecmp_m(v, correct) != 0)) { \
-               printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
-                      __location__, #v, v, correct); \
-               ret = False; \
-       }} while (0)
-
-#define CHECK_NAME(_name, correct) do { \
-       CHECK_STRING((_name).name, (correct).name); \
-       CHECK_VALUE((uint8_t)(_name).type, (uint8_t)(correct).type); \
-       CHECK_STRING((_name).scope, (correct).scope); \
+#define CHECK_VALUE(tctx, v, correct) \
+       torture_assert_int_equal(tctx, v, correct, "Incorrect value")
+
+#define CHECK_STRING(tctx, v, correct) \
+       torture_assert_casestr_equal(tctx, v, correct, "Incorrect value")
+
+#define CHECK_NAME(tctx, _name, correct) do { \
+       CHECK_STRING(tctx, (_name).name, (correct).name); \
+       CHECK_VALUE(tctx, (uint8_t)(_name).type, (uint8_t)(correct).type); \
+       CHECK_STRING(tctx, (_name).scope, (correct).scope); \
 } while (0)
 
 
 /*
   test operations against a WINS server
 */
-static BOOL nbt_test_wins_name(TALLOC_CTX *mem_ctx, const char *address,
-                              struct nbt_name *name, uint16_t nb_flags)
+static bool nbt_test_wins_name(struct torture_context *tctx, const char *address,
+                              struct nbt_name *name, uint16_t nb_flags,
+                              bool try_low_port,
+                              uint8_t register_rcode)
 {
        struct nbt_name_register_wins io;
+       struct nbt_name_register name_register;
        struct nbt_name_query query;
        struct nbt_name_refresh_wins refresh;
        struct nbt_name_release release;
+       struct nbt_name_request *req;
        NTSTATUS status;
-       struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
-       BOOL ret = True;
-       const char *myaddress = talloc_strdup(mem_ctx, iface_best_ip(address));
+       struct nbt_name_socket *nbtsock = torture_init_nbt_socket(tctx);
+       const char *myaddress;
        struct socket_address *socket_address;
+       struct interface *ifaces;
+       bool low_port = try_low_port;
+
+       load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces);
 
-       socket_address = socket_address_from_strings(mem_ctx, 
+       myaddress = talloc_strdup(tctx, iface_best_ip(ifaces, address));
+
+       socket_address = socket_address_from_strings(tctx, 
                                                     nbtsock->sock->backend_name,
-                                                    myaddress, 0);
-       if (!socket_address) {
-               return False;
-       }
+                                                    myaddress, lpcfg_nbt_port(tctx->lp_ctx));
+       torture_assert(tctx, socket_address != NULL, 
+                                  "Error getting address");
 
        /* we do the listen here to ensure the WINS server receives the packets from
           the right IP */
        status = socket_listen(nbtsock->sock, socket_address, 0, 0);
+       talloc_free(socket_address);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("socket_listen for WINS failed: %s\n", nt_errstr(status));
-               return False;
+               low_port = false;
+               socket_address = socket_address_from_strings(tctx,
+                                                            nbtsock->sock->backend_name,
+                                                            myaddress, 0);
+               torture_assert(tctx, socket_address != NULL,
+                              "Error getting address");
+
+               status = socket_listen(nbtsock->sock, socket_address, 0, 0);
+               talloc_free(socket_address);
+               torture_assert_ntstatus_ok(tctx, status,
+                                          "socket_listen for WINS failed");
        }
-       talloc_free(socket_address);
 
-       printf("Testing name registration to WINS with name %s at %s nb_flags=0x%x\n", 
-              nbt_name_string(mem_ctx, name), myaddress, nb_flags);
+       torture_comment(tctx, "Testing name registration to WINS with name %s at %s nb_flags=0x%x\n", 
+              nbt_name_string(tctx, name), myaddress, nb_flags);
 
-       printf("release the name\n");
+       torture_comment(tctx, "release the name\n");
        release.in.name = *name;
+       release.in.dest_port = lpcfg_nbt_port(tctx->lp_ctx);
        release.in.dest_addr = address;
        release.in.address = myaddress;
        release.in.nb_flags = nb_flags;
-       release.in.broadcast = False;
+       release.in.broadcast = false;
        release.in.timeout = 3;
        release.in.retries = 0;
 
-       status = nbt_name_release(nbtsock, mem_ctx, &release);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name release\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name query - %s\n",
-                      address, nt_errstr(status));
-               return False;
+       status = nbt_name_release(nbtsock, tctx, &release);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
+       CHECK_VALUE(tctx, release.out.rcode, 0);
+
+       if (nb_flags & NBT_NM_GROUP) {
+               /* ignore this for group names */
+       } else if (!low_port) {
+               torture_comment(tctx, "no low port - skip: register the name with a wrong address\n");
+       } else {
+               torture_comment(tctx, "register the name with a wrong address (makes the next request slow!)\n");
+               io.in.name = *name;
+               io.in.wins_port = lpcfg_nbt_port(tctx->lp_ctx);
+               io.in.wins_servers = const_str_list(
+                       str_list_make_single(tctx, address));
+               io.in.addresses = const_str_list(
+                       str_list_make_single(tctx, "127.64.64.1"));
+               io.in.nb_flags = nb_flags;
+               io.in.ttl = 300000;
+
+               status = nbt_name_register_wins(nbtsock, tctx, &io);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               talloc_asprintf(tctx, "No response from %s for name register\n",
+                                               address));
+               }
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "Bad response from %s for name register\n",
+                                       address));
+
+               CHECK_STRING(tctx, io.out.wins_server, address);
+               CHECK_VALUE(tctx, io.out.rcode, 0);
+
+               torture_comment(tctx, "register the name correct address\n");
+               name_register.in.name           = *name;
+               name_register.in.dest_port      = lpcfg_nbt_port(tctx->lp_ctx);
+               name_register.in.dest_addr      = address;
+               name_register.in.address        = myaddress;
+               name_register.in.nb_flags       = nb_flags;
+               name_register.in.register_demand= false;
+               name_register.in.broadcast      = false;
+               name_register.in.multi_homed    = true;
+               name_register.in.ttl            = 300000;
+               name_register.in.timeout        = 3;
+               name_register.in.retries        = 2;
+
+               /*
+                * test if the server ignores resent requests
+                */
+               req = nbt_name_register_send(nbtsock, &name_register);
+               while (true) {
+                       event_loop_once(nbtsock->event_ctx);
+                       if (req->state != NBT_REQUEST_WAIT) {
+                               break;
+                       }
+                       if (req->received_wack) {
+                               /*
+                                * if we received the wack response
+                                * we resend the request and the
+                                * server should ignore that
+                                * and not handle it as new request
+                                */
+                               req->state = NBT_REQUEST_SEND;
+                               DLIST_ADD_END(nbtsock->send_queue, req,
+                                             struct nbt_name_request *);
+                               EVENT_FD_WRITEABLE(nbtsock->fde);
+                               break;
+                       }
+               }
+
+               status = nbt_name_register_recv(req, tctx, &name_register);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               talloc_asprintf(tctx, "No response from %s for name register\n",
+                                               address));
+               }
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "Bad response from %s for name register\n",
+                                       address));
+
+               CHECK_VALUE(tctx, name_register.out.rcode, 0);
+               CHECK_STRING(tctx, name_register.out.reply_addr, myaddress);
        }
-       CHECK_VALUE(release.out.rcode, 0);
 
-       printf("register the name\n");
+       torture_comment(tctx, "register the name correct address\n");
        io.in.name = *name;
-       io.in.wins_servers = str_list_make(mem_ctx, address, NULL);
-       io.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
+       io.in.wins_port = lpcfg_nbt_port(tctx->lp_ctx);
+       io.in.wins_servers = (const char **)str_list_make_single(tctx, address);
+       io.in.addresses = (const char **)str_list_make_single(tctx, myaddress);
        io.in.nb_flags = nb_flags;
        io.in.ttl = 300000;
        
-       status = nbt_name_register_wins(nbtsock, mem_ctx, &io);
-       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name register\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name register - %s\n",
-                      address, nt_errstr(status));
-               return False;
-       }
+       status = nbt_name_register_wins(nbtsock, tctx, &io);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name register", address));
        
-       CHECK_STRING(io.out.wins_server, address);
-       CHECK_VALUE(io.out.rcode, 0);
+       CHECK_STRING(tctx, io.out.wins_server, address);
+       CHECK_VALUE(tctx, io.out.rcode, register_rcode);
+
+       if (register_rcode != NBT_RCODE_OK) {
+               return true;
+       }
 
        if (name->type != NBT_NAME_MASTER &&
            name->type != NBT_NAME_LOGON && 
            name->type != NBT_NAME_BROWSER && 
            (nb_flags & NBT_NM_GROUP)) {
-               printf("Try to register as non-group\n");
+               torture_comment(tctx, "Try to register as non-group\n");
                io.in.nb_flags &= ~NBT_NM_GROUP;
-               status = nbt_name_register_wins(nbtsock, mem_ctx, &io);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("Bad response from %s for name register - %s\n",
-                              address, nt_errstr(status));
-                       return False;
-               }
-               CHECK_VALUE(io.out.rcode, NBT_RCODE_ACT);
+               status = nbt_name_register_wins(nbtsock, tctx, &io);
+               torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name register\n",
+                       address));
+               CHECK_VALUE(tctx, io.out.rcode, NBT_RCODE_ACT);
        }
 
-       printf("query the name to make sure its there\n");
+       torture_comment(tctx, "query the name to make sure its there\n");
        query.in.name = *name;
        query.in.dest_addr = address;
-       query.in.broadcast = False;
-       query.in.wins_lookup = True;
+       query.in.dest_port = lpcfg_nbt_port(tctx->lp_ctx);
+       query.in.broadcast = false;
+       query.in.wins_lookup = true;
        query.in.timeout = 3;
        query.in.retries = 0;
 
-       status = nbt_name_query(nbtsock, mem_ctx, &query);
+       status = nbt_name_query(nbtsock, tctx, &query);
        if (name->type == NBT_NAME_MASTER) {
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-                       printf("Bad response from %s for name query - %s\n",
-                              address, nt_errstr(status));
-                       return False;
-               }
-               return ret;
-       }
-       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name query\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name query - %s\n",
-                      address, nt_errstr(status));
-               return False;
+               torture_assert_ntstatus_equal(
+                         tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, 
+                         talloc_asprintf(tctx, "Bad response from %s for name query", address));
+               return true;
        }
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
        
-       CHECK_NAME(query.out.name, *name);
-       CHECK_VALUE(query.out.num_addrs, 1);
+       CHECK_NAME(tctx, query.out.name, *name);
+       CHECK_VALUE(tctx, query.out.num_addrs, 1);
        if (name->type != NBT_NAME_LOGON &&
            (nb_flags & NBT_NM_GROUP)) {
-               CHECK_STRING(query.out.reply_addrs[0], "255.255.255.255");
+               CHECK_STRING(tctx, query.out.reply_addrs[0], "255.255.255.255");
        } else {
-               CHECK_STRING(query.out.reply_addrs[0], myaddress);
+               CHECK_STRING(tctx, query.out.reply_addrs[0], myaddress);
        }
 
 
-       query.in.name.name = strupper_talloc(mem_ctx, name->name);
+       query.in.name.name = strupper_talloc(tctx, name->name);
        if (query.in.name.name &&
            strcmp(query.in.name.name, name->name) != 0) {
-               printf("check case sensitivity\n");
-               status = nbt_name_query(nbtsock, mem_ctx, &query);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-                       printf("No response from %s for name query\n", address);
-                       return False;
-               }
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-                       printf("Bad response from %s for name query - %s\n",
-                              address, nt_errstr(status));
-                       return False;
-               }
+               torture_comment(tctx, "check case sensitivity\n");
+               status = nbt_name_query(nbtsock, tctx, &query);
+               torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, talloc_asprintf(tctx, "Bad response from %s for name query", address));
        }
 
        query.in.name = *name;
        if (name->scope) {
-               query.in.name.scope = strupper_talloc(mem_ctx, name->scope);
+               query.in.name.scope = strupper_talloc(tctx, name->scope);
        }
        if (query.in.name.scope &&
            strcmp(query.in.name.scope, name->scope) != 0) {
-               printf("check case sensitivity on scope\n");
-               status = nbt_name_query(nbtsock, mem_ctx, &query);
-               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-                       printf("No response from %s for name query\n", address);
-                       return False;
-               }
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-                       printf("Bad response from %s for name query - %s\n",
-                              address, nt_errstr(status));
-                       return False;
-               }
+               torture_comment(tctx, "check case sensitivity on scope\n");
+               status = nbt_name_query(nbtsock, tctx, &query);
+               torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, talloc_asprintf(tctx, "Bad response from %s for name query", address));
        }
 
-       printf("refresh the name\n");
+       torture_comment(tctx, "refresh the name\n");
        refresh.in.name = *name;
-       refresh.in.wins_servers = str_list_make(mem_ctx, address, NULL);
-       refresh.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
+       refresh.in.wins_port = lpcfg_nbt_port(tctx->lp_ctx);
+       refresh.in.wins_servers = (const char **)str_list_make_single(tctx, address);
+       refresh.in.addresses = (const char **)str_list_make_single(tctx, myaddress);
        refresh.in.nb_flags = nb_flags;
        refresh.in.ttl = 12345;
        
-       status = nbt_name_refresh_wins(nbtsock, mem_ctx, &refresh);
+       status = nbt_name_refresh_wins(nbtsock, tctx, &refresh);
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name refresh\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name refresh - %s\n",
-                      address, nt_errstr(status));
-               return False;
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "No response from %s for name refresh",
+                                       address));
        }
-       
-       CHECK_STRING(refresh.out.wins_server, address);
-       CHECK_VALUE(refresh.out.rcode, 0);
+       torture_assert_ntstatus_ok(tctx, status,
+               talloc_asprintf(tctx, "Bad response from %s for name refresh",
+                               address));
+
+       CHECK_STRING(tctx, refresh.out.wins_server, address);
+       CHECK_VALUE(tctx, refresh.out.rcode, 0);
 
        printf("release the name\n");
        release.in.name = *name;
+       release.in.dest_port = lpcfg_nbt_port(tctx->lp_ctx);
        release.in.dest_addr = address;
        release.in.address = myaddress;
        release.in.nb_flags = nb_flags;
-       release.in.broadcast = False;
+       release.in.broadcast = false;
        release.in.timeout = 3;
        release.in.retries = 0;
 
-       status = nbt_name_release(nbtsock, mem_ctx, &release);
+       status = nbt_name_release(nbtsock, tctx, &release);
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name release\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name query - %s\n",
-                      address, nt_errstr(status));
-               return False;
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "No response from %s for name release",
+                                       address));
        }
+       torture_assert_ntstatus_ok(tctx, status,
+               talloc_asprintf(tctx, "Bad response from %s for name release",
+                               address));
+
+       CHECK_NAME(tctx, release.out.name, *name);
+       CHECK_VALUE(tctx, release.out.rcode, 0);
+
+       if (nb_flags & NBT_NM_GROUP) {
+               /* ignore this for group names */
+       } else if (!low_port) {
+               torture_comment(tctx, "no low port - skip: register the name with a wrong address\n");
+       } else {
+               torture_comment(tctx, "register the name with a wrong address (makes the next request slow!)\n");
+               io.in.name = *name;
+               io.in.wins_port = lpcfg_nbt_port(tctx->lp_ctx);
+               io.in.wins_servers = const_str_list(
+                       str_list_make_single(tctx, address));
+               io.in.addresses = const_str_list(
+                       str_list_make_single(tctx, "127.64.64.1"));
+               io.in.nb_flags = nb_flags;
+               io.in.ttl = 300000;
        
-       CHECK_NAME(release.out.name, *name);
-       CHECK_VALUE(release.out.rcode, 0);
+               status = nbt_name_register_wins(nbtsock, tctx, &io);
+               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       torture_assert_ntstatus_ok(tctx, status,
+                               talloc_asprintf(tctx, "No response from %s for name register\n",
+                                               address));
+               }
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "Bad response from %s for name register\n",
+                                       address));
+
+               CHECK_STRING(tctx, io.out.wins_server, address);
+               CHECK_VALUE(tctx, io.out.rcode, 0);
+       }
 
+       torture_comment(tctx, "refresh the name with the correct address\n");
+       refresh.in.name = *name;
+       refresh.in.wins_port = lpcfg_nbt_port(tctx->lp_ctx);
+       refresh.in.wins_servers = const_str_list(
+                       str_list_make_single(tctx, address));
+       refresh.in.addresses = const_str_list(
+                       str_list_make_single(tctx, myaddress));
+       refresh.in.nb_flags = nb_flags;
+       refresh.in.ttl = 12345;
 
-       printf("release again\n");
-       status = nbt_name_release(nbtsock, mem_ctx, &release);
+       status = nbt_name_refresh_wins(nbtsock, tctx, &refresh);
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               printf("No response from %s for name release\n", address);
-               return False;
-       }
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Bad response from %s for name query - %s\n",
-                      address, nt_errstr(status));
-               return False;
+               torture_assert_ntstatus_ok(tctx, status,
+                       talloc_asprintf(tctx, "No response from %s for name refresh",
+                                       address));
        }
+       torture_assert_ntstatus_ok(tctx, status,
+               talloc_asprintf(tctx, "Bad response from %s for name refresh",
+                               address));
+
+       CHECK_STRING(tctx, refresh.out.wins_server, address);
+       CHECK_VALUE(tctx, refresh.out.rcode, 0);
+
+       torture_comment(tctx, "release the name\n");
+       release.in.name = *name;
+       release.in.dest_port = lpcfg_nbt_port(tctx->lp_ctx);
+       release.in.dest_addr = address;
+       release.in.address = myaddress;
+       release.in.nb_flags = nb_flags;
+       release.in.broadcast = false;
+       release.in.timeout = 3;
+       release.in.retries = 0;
+
+       status = nbt_name_release(nbtsock, tctx, &release);
+       torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
        
-       CHECK_NAME(release.out.name, *name);
-       CHECK_VALUE(release.out.rcode, 0);
+       CHECK_NAME(tctx, release.out.name, *name);
+       CHECK_VALUE(tctx, release.out.rcode, 0);
+
+       torture_comment(tctx, "release again\n");
+       status = nbt_name_release(nbtsock, tctx, &release);
+       torture_assert_ntstatus_ok(tctx, status, 
+                               talloc_asprintf(tctx, "Bad response from %s for name query",
+                      address));
+       
+       CHECK_NAME(tctx, release.out.name, *name);
+       CHECK_VALUE(tctx, release.out.rcode, 0);
 
 
-       printf("query the name to make sure its gone\n");
+       torture_comment(tctx, "query the name to make sure its gone\n");
        query.in.name = *name;
-       status = nbt_name_query(nbtsock, mem_ctx, &query);
+       status = nbt_name_query(nbtsock, tctx, &query);
        if (name->type != NBT_NAME_LOGON &&
            (nb_flags & NBT_NM_GROUP)) {
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("ERROR: Name query failed after group release - %s\n",
-                              nt_errstr(status));
-                       return False;
-               }
+               torture_assert_ntstatus_ok(tctx, status, 
+                               "ERROR: Name query failed after group release");
        } else {
-               if (NT_STATUS_IS_OK(status)) {
-                       printf("ERROR: Name query success after release\n");
-                       return False;
-               }
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-                       printf("Incorrect response to name query - %s\n", nt_errstr(status));
-                       return False;
-               }
+               torture_assert_ntstatus_equal(tctx, status, 
+                                                                         NT_STATUS_OBJECT_NAME_NOT_FOUND,
+                               "Incorrect response to name query");
        }
        
-       return ret;
+       return true;
 }
 
 
+static char *test_nbt_wins_scope_string(TALLOC_CTX *mem_ctx, uint8_t count)
+{
+       char *res;
+       uint8_t i;
+
+       res = talloc_array(mem_ctx, char, count+1);
+       if (res == NULL) {
+               return NULL;
+       }
+
+       for (i=0; i < count; i++) {
+               switch (i) {
+               case 63:
+               case 63 + 1 + 63:
+               case 63 + 1 + 63 + 1 + 63:
+                       res[i] = '.';
+                       break;
+               default:
+                       res[i] = '0' + (i%10);
+                       break;
+               }
+       }
+
+       res[count] = '\0';
+
+       talloc_set_name_const(res, res);
+
+       return res;
+}
 
 /*
   test operations against a WINS server
 */
-static BOOL nbt_test_wins(TALLOC_CTX *mem_ctx, const char *address)
+static bool nbt_test_wins(struct torture_context *tctx)
 {
        struct nbt_name name;
-       BOOL ret = True;
        uint32_t r = (uint32_t)(random() % (100000));
+       const char *address;
+       bool ret = true;
+
+       if (!torture_nbt_get_name(tctx, &name, &address))
+               return false;
 
-       name.name = talloc_asprintf(mem_ctx, "_TORTURE-%5u", r);
+       name.name = talloc_asprintf(tctx, "_TORTURE-%5u", r);
 
        name.type = NBT_NAME_CLIENT;
        name.scope = NULL;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, true, NBT_RCODE_OK);
 
        name.type = NBT_NAME_MASTER;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK);
 
        name.type = NBT_NAME_SERVER;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, true, NBT_RCODE_OK);
 
        name.type = NBT_NAME_LOGON;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK);
 
        name.type = NBT_NAME_BROWSER;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK);
 
        name.type = NBT_NAME_PDC;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, true, NBT_RCODE_OK);
 
        name.type = 0xBF;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, true, NBT_RCODE_OK);
 
        name.type = 0xBE;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
        name.scope = "example";
        name.type = 0x72;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, true, NBT_RCODE_OK);
 
        name.scope = "example";
        name.type = 0x71;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H | NBT_NM_GROUP, false, NBT_RCODE_OK);
 
        name.scope = "foo.example.com";
        name.type = 0x72;
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
-       name.name = talloc_asprintf(mem_ctx, "_T\01-%5u.foo", r);
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       name.name = talloc_asprintf(tctx, "_T\01-%5u.foo", r);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
        name.name = "";
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
-       name.name = talloc_asprintf(mem_ctx, ".");
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       name.name = talloc_asprintf(tctx, ".");
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
 
-       name.name = talloc_asprintf(mem_ctx, "%5u-\377\200\300FOO", r);
-       ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
+       name.name = talloc_asprintf(tctx, "%5u-\377\200\300FOO", r);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
+
+       name.scope = test_nbt_wins_scope_string(tctx, 237);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_OK);
+
+       name.scope = test_nbt_wins_scope_string(tctx, 238);
+       ret &= nbt_test_wins_name(tctx, address, &name,
+                                 NBT_NODE_H, false, NBT_RCODE_SVR);
 
        return ret;
 }
@@ -369,28 +531,11 @@ static BOOL nbt_test_wins(TALLOC_CTX *mem_ctx, const char *address)
 /*
   test WINS operations
 */
-BOOL torture_nbt_wins(struct torture_context *torture)
+struct torture_suite *torture_nbt_wins(TALLOC_CTX *mem_ctx)
 {
-       const char *address;
-       struct nbt_name name;
-       TALLOC_CTX *mem_ctx = talloc_new(NULL);
-       NTSTATUS status;
-       BOOL ret = True;
-       
-       make_nbt_name_server(&name, lp_parm_string(-1, "torture", "host"));
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "wins");
 
-       /* do an initial name resolution to find its IP */
-       status = resolve_name(&name, mem_ctx, &address, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Failed to resolve %s - %s\n",
-                      name.name, nt_errstr(status));
-               talloc_free(mem_ctx);
-               return False;
-       }
-
-       ret &= nbt_test_wins(mem_ctx, address);
+       torture_suite_add_simple_test(suite, "wins", nbt_test_wins);
 
-       talloc_free(mem_ctx);
-
-       return ret;
+       return suite;
 }