r5294: - added a separate NBT-WINS test for WINS operations (register, refresh, relea...
authorAndrew Tridgell <tridge@samba.org>
Thu, 10 Feb 2005 03:22:47 +0000 (03:22 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:37 +0000 (13:09 -0500)
- change the iface_n_*() functions to return a "const char *" instead of a "struct ipv4_addr"
  I think that in general we should move towards "const char *" for
  all IP addresses, as this makes IPv6 much easier, and is also easier
  to debug. Andrew, when you get a chance, could you fix some of the
  auth code to use strings for IPs ?

- return a NTSTATUS error on bad name queries and node status instead
  of using rcode. This makes the calling code simpler.

- added low level name release code in libcli/nbt/

- use a real IP in the register and wins nbt torture tests, as w2k3
  WINS server silently rejects some operations that don't come from the
  IP being used (eg. it says "yes" to a release, but does not in fact
  release the name)
(This used to be commit bb1ab11d8e0ea0bd9ae34aebeb565d36fe4b495f)

16 files changed:
source4/include/structs.h
source4/ldap_server/ldap_server.c
source4/lib/netif/interface.c
source4/libcli/config.mk
source4/libcli/nbt/libnbt.h
source4/libcli/nbt/namequery.c
source4/libcli/nbt/namerelease.c [new file with mode: 0644]
source4/libcli/resolve/bcast.c
source4/nbt_server/interfaces.c
source4/rpc_server/dcerpc_sock.c
source4/smb_server/smb_server.c
source4/torture/config.mk
source4/torture/nbt/register.c
source4/torture/nbt/wins.c [new file with mode: 0644]
source4/torture/torture.c
source4/utils/nmblookup.c

index 1781ee09ec0eef5f375fe3a6fc2af0ef8354e6dd..f376609302366344b61a2f5045dbf6a07f6a6f4e 100644 (file)
@@ -157,6 +157,7 @@ struct nbt_name_query;
 struct nbt_name_status;
 struct nbt_name_register;
 struct nbt_name_refresh;
+struct nbt_name_release;
 struct nbt_name_register_bcast;
 struct nbt_name_refresh_wins;
 struct nbt_name_register_wins;
index ebc232a4c83045b31050f0f502e0d5c67af409b1..3a0e3d1cde0804c0a5bb2b5b9586ab393997594b 100644 (file)
@@ -533,7 +533,7 @@ static NTSTATUS ldapsrv_init(struct event_context *event_context, const struct m
                   socket per interface and bind to only these.
                */
                for(i = 0; i < num_interfaces; i++) {
-                       const char *address = sys_inet_ntoa(*iface_n_ip(i));
+                       const char *address = iface_n_ip(i);
                        status = add_socket(event_context, model_ops, address, ldap_service);
                        NT_STATUS_NOT_OK_RETURN(status);
                }
index bf1e147e02e8c60a1a97552f2ec95dee063d96e0..31354e359a505aee1f9639258804db8ff7fd5575 100644 (file)
@@ -1,7 +1,9 @@
 /* 
    Unix SMB/CIFS implementation.
+
    multiple interface handling
-   Copyright (C) Andrew Tridgell 1992-1998
+
+   Copyright (C) Andrew Tridgell 1992-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
@@ -275,20 +277,6 @@ BOOL ismyip(struct ipv4_addr ip)
        return False;
 }
 
-/****************************************************************************
-  check if a packet is from a local (known) net
-  **************************************************************************/
-BOOL is_local_net(struct ipv4_addr from)
-{
-       struct interface *i;
-       for (i=local_interfaces;i;i=i->next) {
-               if((from.addr & i->nmask.addr) == 
-                  (i->ip.addr & i->nmask.addr))
-                       return True;
-       }
-       return False;
-}
-
 /****************************************************************************
   how many interfaces do we have
   **************************************************************************/
@@ -305,65 +293,48 @@ int iface_count(void)
 /****************************************************************************
   return IP of the Nth interface
   **************************************************************************/
-struct ipv4_addr *iface_n_ip(int n)
+const char *iface_n_ip(int n)
 {
        struct interface *i;
   
        for (i=local_interfaces;i && n;i=i->next)
                n--;
 
-       if (i) return &i->ip;
+       if (i) {
+               return sys_inet_ntoa(i->ip);
+       }
        return NULL;
 }
 
 /****************************************************************************
   return bcast of the Nth interface
   **************************************************************************/
-struct ipv4_addr *iface_n_bcast(int n)
+const char *iface_n_bcast(int n)
 {
        struct interface *i;
   
        for (i=local_interfaces;i && n;i=i->next)
                n--;
 
-       if (i) return &i->bcast;
+       if (i) {
+               return sys_inet_ntoa(i->bcast);
+       }
        return NULL;
 }
 
 /****************************************************************************
   return netmask of the Nth interface
   **************************************************************************/
-struct ipv4_addr *iface_n_netmask(int n)
+const char *iface_n_netmask(int n)
 {
        struct interface *i;
   
        for (i=local_interfaces;i && n;i=i->next)
                n--;
 
-       if (i) return &i->nmask;
+       if (i) {
+               return sys_inet_ntoa(i->nmask);
+       }
        return NULL;
 }
 
-/* these 3 functions return the ip/bcast/nmask for the interface
-   most appropriate for the given ip address. If they can't find
-   an appropriate interface they return the requested field of the
-   first known interface. */
-
-struct ipv4_addr *iface_ip(struct ipv4_addr ip)
-{
-       struct in_addr in;
-       struct interface *i;
-       in.s_addr = ip.addr;
-       i = iface_find(in, True);
-       return(i ? &i->ip : &local_interfaces->ip);
-}
-
-/*
-  return True if a IP is directly reachable on one of our interfaces
-*/
-BOOL iface_local(struct ipv4_addr ip)
-{
-       struct in_addr in;
-       in.s_addr = ip.addr;
-       return iface_find(in, True) ? True : False;
-}
index 038b8e0ccbef518ea9c3504b6c22fca385958d32..726d3f11845189cee55c9ab17261a92d86c1d674 100644 (file)
@@ -31,7 +31,8 @@ ADD_OBJ_FILES = \
        libcli/nbt/nbtsocket.o \
        libcli/nbt/namequery.o \
        libcli/nbt/nameregister.o \
-       libcli/nbt/namerefresh.o
+       libcli/nbt/namerefresh.o \
+       libcli/nbt/namerelease.o
 REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE LIBEVENTS
 
 [SUBSYSTEM::LIBCLI_RESOLVE]
index 63711490feae209cfd712b4f29cba3243999b00a..5a53510ccf2a1e74afc16144a0d1678cd39a69a4 100644 (file)
@@ -138,7 +138,6 @@ struct nbt_name_query {
                struct nbt_name name;
                int16_t num_addrs;
                const char **reply_addrs;
-               uint8_t rcode;
        } out;
 };
 
@@ -154,7 +153,6 @@ struct nbt_name_status {
                const char *reply_from;
                struct nbt_name name;
                struct nbt_rdata_status status;
-               uint8_t rcode;
        } out;
 };
 
@@ -247,3 +245,21 @@ struct nbt_name_refresh_wins {
 };
 
 
+/* a name release request */
+struct nbt_name_release {
+       struct {
+               struct nbt_name name;
+               const char *dest_addr;
+               const char *address;
+               uint16_t nb_flags;
+               BOOL broadcast;
+               int timeout; /* in seconds */
+               int retries;
+       } in;
+       struct {
+               const char *reply_from;
+               struct nbt_name name;
+               const char *reply_addr;
+               uint8_t rcode;
+       } out;
+};
index 32fcad2052fe41098c07728310e61f4d57285a11..5907c45b875e6a70ca498ab6b2006d2efbe9ae4a 100644 (file)
@@ -84,14 +84,19 @@ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req,
        packet = req->replies[0].packet;
        io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr);
 
+       if ((packet->operation & NBT_RCODE) != 0) {
+               status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
+               talloc_free(req);
+               return status;
+       }
+
        if (packet->ancount != 1 ||
            packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
            packet->answers[0].rr_class != NBT_QCLASS_IP) {
                talloc_free(req);
-               return NT_STATUS_INVALID_NETWORK_RESPONSE;
+               return status;
        }
 
-       io->out.rcode = packet->operation & NBT_RCODE;
        io->out.name = packet->answers[0].name;
        io->out.num_addrs = packet->answers[0].rdata.netbios.length / 6;
        io->out.reply_addrs = talloc_array(mem_ctx, const char *, io->out.num_addrs);
@@ -178,6 +183,12 @@ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
        packet = req->replies[0].packet;
        io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr);
 
+       if ((packet->operation & NBT_RCODE) != 0) {
+               status = nbt_rcode_to_ntstatus(packet->operation & NBT_RCODE);
+               talloc_free(req);
+               return status;
+       }
+
        if (packet->ancount != 1 ||
            packet->answers[0].rr_type != NBT_QTYPE_STATUS ||
            packet->answers[0].rr_class != NBT_QCLASS_IP) {
@@ -185,7 +196,6 @@ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req,
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
 
-       io->out.rcode = packet->operation & NBT_RCODE;
        io->out.name = packet->answers[0].name;
        talloc_steal(mem_ctx, io->out.name.name);
        talloc_steal(mem_ctx, io->out.name.scope);
diff --git a/source4/libcli/nbt/namerelease.c b/source4/libcli/nbt/namerelease.c
new file mode 100644 (file)
index 0000000..208c73d
--- /dev/null
@@ -0,0 +1,129 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   send out a name release request
+
+   Copyright (C) Andrew Tridgell 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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "libcli/nbt/libnbt.h"
+
+/*
+  send a nbt name release request
+*/
+struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock,
+                                              struct nbt_name_release *io)
+{
+       struct nbt_name_request *req;
+       struct nbt_name_packet *packet;
+
+       packet = talloc_zero(nbtsock, struct nbt_name_packet);
+       if (packet == NULL) return NULL;
+
+       packet->qdcount = 1;
+       packet->arcount = 1;
+       packet->operation = NBT_OPCODE_RELEASE;
+       if (io->in.broadcast) {
+               packet->operation |= NBT_FLAG_BROADCAST;
+       }
+
+       packet->questions = talloc_array(packet, struct nbt_name_question, 1);
+       if (packet->questions == NULL) goto failed;
+
+       packet->questions[0].name           = io->in.name;
+       packet->questions[0].question_type  = NBT_QTYPE_NETBIOS;
+       packet->questions[0].question_class = NBT_QCLASS_IP;
+
+       packet->additional = talloc_array(packet, struct nbt_res_rec, 1);
+       if (packet->additional == NULL) goto failed;
+
+       packet->additional[0].name                   = io->in.name;
+       packet->additional[0].rr_type                = NBT_QTYPE_NETBIOS;
+       packet->additional[0].rr_class               = NBT_QCLASS_IP;
+       packet->additional[0].ttl                    = 0;
+       packet->additional[0].rdata.netbios.length   = 6;
+       packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional,
+                                                                    struct nbt_rdata_address, 1);
+       if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed;
+       packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags;
+       packet->additional[0].rdata.netbios.addresses[0].ipaddr = 
+               talloc_strdup(packet->additional, io->in.address);
+       
+       req = nbt_name_request_send(nbtsock, io->in.dest_addr, lp_nbt_port(), packet,
+                                   io->in.timeout, io->in.retries, False);
+       if (req == NULL) goto failed;
+
+       talloc_free(packet);
+       return req;
+
+failed:
+       talloc_free(packet);
+       return NULL;    
+}
+
+/*
+  wait for a release reply
+*/
+NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, 
+                              TALLOC_CTX *mem_ctx, struct nbt_name_release *io)
+{
+       NTSTATUS status;
+       struct nbt_name_packet *packet;
+
+       status = nbt_name_request_recv(req);
+       if (!NT_STATUS_IS_OK(status) ||
+           req->num_replies == 0) {
+               talloc_free(req);
+               return status;
+       }
+       
+       packet = req->replies[0].packet;
+       io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].reply_addr);
+
+       if (packet->ancount != 1 ||
+           packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
+           packet->answers[0].rr_class != NBT_QCLASS_IP) {
+               talloc_free(req);
+               return NT_STATUS_INVALID_NETWORK_RESPONSE;
+       }
+
+       io->out.rcode = packet->operation & NBT_RCODE;
+       io->out.name = packet->answers[0].name;
+       if (packet->answers[0].rdata.netbios.length < 6) {
+               talloc_free(req);
+               return NT_STATUS_INVALID_NETWORK_RESPONSE;
+       }
+       io->out.reply_addr = talloc_steal(mem_ctx, 
+                                         packet->answers[0].rdata.netbios.addresses[0].ipaddr);
+       talloc_steal(mem_ctx, io->out.name.name);
+       talloc_steal(mem_ctx, io->out.name.scope);
+
+       talloc_free(req);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  synchronous name release request
+*/
+NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, 
+                          TALLOC_CTX *mem_ctx, struct nbt_name_release *io)
+{
+       struct nbt_name_request *req = nbt_name_release_send(nbtsock, io);
+       return nbt_name_release_recv(req, mem_ctx, io);
+}
index 5fb6e6dd5ca60b6889ef173f63e03534001b72ee..c47bba38c542ab75529479739ec2c1207c358a79 100644 (file)
@@ -40,8 +40,7 @@ struct composite_context *resolve_name_bcast_send(struct nbt_name *name,
        if (address_list == NULL) return NULL;
 
        for (i=0;i<num_interfaces;i++) {
-               struct ipv4_addr *ip = iface_n_bcast(i);
-               address_list[i] = talloc_strdup(address_list, sys_inet_ntoa(*ip));
+               address_list[i] = talloc_strdup(address_list, iface_n_bcast(i));
                if (address_list[i] == NULL) {
                        talloc_free(address_list);
                        return NULL;
index 3cb690b85df0a15e2e346388f1b830b67f7674c1..c84f63040072218947ad693aa755c0c6c2ee3ddc 100644 (file)
@@ -191,7 +191,7 @@ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
                   for non-WINS queries not made on a specific
                   interface */
                if (num_interfaces > 0) {
-                       primary_address = sys_inet_ntoa(*iface_n_ip(0));
+                       primary_address = iface_n_ip(0);
                } else {
                        primary_address = sys_inet_ntoa(interpret_addr2(
                                                                lp_netbios_name()));
@@ -208,9 +208,9 @@ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
        }
 
        for (i=0; i<num_interfaces; i++) {
-               const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i)));
-               const char *bcast   = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i)));
-               const char *netmask = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_netmask(i)));
+               const char *address = talloc_strdup(tmp_ctx, iface_n_ip(i));
+               const char *bcast   = talloc_strdup(tmp_ctx, iface_n_bcast(i));
+               const char *netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
 
                status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
                NT_STATUS_NOT_OK_RETURN(status);
index 62f8c91d11322b3dada265e80534c2bce41a0d43..3f99b59a4daa40ef5ab2fc8bef4bceebb3da13fe 100644 (file)
@@ -246,7 +246,7 @@ static NTSTATUS add_socket_rpc_tcp(struct dcesrv_context *dce_ctx, struct dcesrv
                int num_interfaces = iface_count();
                int i;
                for(i = 0; i < num_interfaces; i++) {
-                       const char *address = sys_inet_ntoa(*iface_n_ip(i));
+                       const char *address = iface_n_ip(i);
                        status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
                        NT_STATUS_NOT_OK_RETURN(status);
                }
index 10635f739df1e9abd5e7dbcc9f21f9802d5238ab..11fe965a92390a609dd006f6f49adb9c0dfed1d5 100644 (file)
@@ -795,7 +795,7 @@ static NTSTATUS smbsrv_init(struct event_context *event_context, const struct mo
                   socket per interface and bind to only these.
                */
                for(i = 0; i < num_interfaces; i++) {
-                       const char *address = sys_inet_ntoa(*iface_n_ip(i));
+                       const char *address = iface_n_ip(i);
                        status = smb_add_socket(event_context, model_ops, address);
                        NT_STATUS_NOT_OK_RETURN(status);
                }
index 15661eb7854ba33c0fe04cae32a9c2bc163ba2b9..75bca5239d90cd10f09243bb16ba53b03b3063da 100644 (file)
@@ -171,7 +171,8 @@ REQUIRED_SUBSYSTEMS = \
 [SUBSYSTEM::TORTURE_NBT]
 ADD_OBJ_FILES = \
                torture/nbt/query.o \
-               torture/nbt/register.o
+               torture/nbt/register.o \
+               torture/nbt/wins.o
 REQUIRED_SUBSYSTEMS = \
                LIBSMB
 # End SUBSYSTEM TORTURE_NBT
index 6094d9fcaf51b652b5ccbc5401461837e085c5ff..a8be5dbb9a1f9ce7aee4f6e9c61e612eef3d35e4 100644 (file)
@@ -38,9 +38,6 @@
                ret = False; \
        }} while (0)
 
-#define BOGUS_ADDRESS1 "255.255.255.254"
-#define BOGUS_ADDRESS2 "255.255.255.253"
-
 /*
   test that a server responds correctly to attempted registrations of its name
 */
@@ -51,12 +48,15 @@ static BOOL nbt_register_own(TALLOC_CTX *mem_ctx, struct nbt_name *name,
        NTSTATUS status;
        struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
        BOOL ret = True;
+       const char *myaddress = iface_n_ip(0);
+
+       socket_listen(nbtsock->sock, myaddress, 0, 0, 0);
 
        printf("Testing name defense to name registration\n");
 
        io.in.name = *name;
        io.in.dest_addr = address;
-       io.in.address = BOGUS_ADDRESS1;
+       io.in.address = myaddress;
        io.in.nb_flags = NBT_NODE_B | NBT_NM_ACTIVE;
        io.in.register_demand = False;
        io.in.broadcast = True;
@@ -81,7 +81,7 @@ static BOOL nbt_register_own(TALLOC_CTX *mem_ctx, struct nbt_name *name,
        CHECK_VALUE(io.out.rcode, NBT_RCODE_ACT);
 
        /* check a register demand */
-       io.in.address = BOGUS_ADDRESS2;
+       io.in.address = myaddress;
        io.in.register_demand = True;
 
        status = nbt_name_register(nbtsock, mem_ctx, &io);
@@ -113,14 +113,17 @@ static BOOL nbt_refresh_own(TALLOC_CTX *mem_ctx, struct nbt_name *name,
        NTSTATUS status;
        struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
        BOOL ret = True;
+       const char *myaddress = iface_n_ip(0);
+
+       socket_listen(nbtsock->sock, myaddress, 0, 0, 0);
 
        printf("Testing name defense to name refresh\n");
 
        io.in.name = *name;
        io.in.dest_addr = address;
-       io.in.address = BOGUS_ADDRESS1;
+       io.in.address = myaddress;
        io.in.nb_flags = NBT_NODE_B | NBT_NM_ACTIVE;
-       io.in.broadcast = True;
+       io.in.broadcast = False;
        io.in.ttl = 1234;
        io.in.timeout = 3;
        io.in.retries = 0;
@@ -144,70 +147,6 @@ static BOOL nbt_refresh_own(TALLOC_CTX *mem_ctx, struct nbt_name *name,
 }
 
 
-/*
-  register names with a WINS server
-*/
-static BOOL nbt_register_wins(TALLOC_CTX *mem_ctx, struct nbt_name *name, 
-                             const char *address)
-{
-       struct nbt_name_refresh_wins io;
-       struct nbt_name_query q;
-       NTSTATUS status;
-       struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
-       BOOL ret = True;
-
-       printf("Testing name registration to WINS\n");
-
-       io.in.name.name = talloc_asprintf(mem_ctx, "_TORTURE-%5u", 
-                                         (unsigned)(random() % (100000)));
-       io.in.name.type = NBT_NAME_CLIENT;
-       io.in.name.scope = NULL;
-       io.in.wins_servers = str_list_make(mem_ctx, address, NULL);
-       io.in.addresses = str_list_make(mem_ctx, BOGUS_ADDRESS1, NULL);
-       io.in.nb_flags = NBT_NODE_M | NBT_NM_ACTIVE;
-       io.in.ttl = 12345;
-       
-       status = nbt_name_refresh_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;
-       }
-       
-       CHECK_STRING(io.out.wins_server, address);
-       CHECK_VALUE(io.out.rcode, 0);
-
-       /* query the name to make sure its there */
-       q.in.name = io.in.name;
-       q.in.dest_addr = address;
-       q.in.broadcast = False;
-       q.in.wins_lookup = True;
-       q.in.timeout = 3;
-       q.in.retries = 0;
-
-       status = nbt_name_query(nbtsock, mem_ctx, &q);
-       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;
-       }
-       
-       CHECK_STRING(q.out.name.name, q.in.name.name);
-       CHECK_VALUE(q.out.name.type, q.in.name.type);
-       CHECK_VALUE(q.out.num_addrs, 1);
-       CHECK_STRING(q.out.reply_addrs[0], BOGUS_ADDRESS1);
-
-       return ret;
-}
-
 
 /*
   test name registration to a server
@@ -235,7 +174,6 @@ BOOL torture_nbt_register(void)
 
        ret &= nbt_register_own(mem_ctx, &name, address);
        ret &= nbt_refresh_own(mem_ctx, &name, address);
-       ret &= nbt_register_wins(mem_ctx, &name, address);
 
        talloc_free(mem_ctx);
 
diff --git a/source4/torture/nbt/wins.c b/source4/torture/nbt/wins.c
new file mode 100644 (file)
index 0000000..62efcd3
--- /dev/null
@@ -0,0 +1,219 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   NBT WINS server testing
+
+   Copyright (C) Andrew Tridgell 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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "libcli/nbt/libnbt.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+
+#define CHECK_VALUE(v, correct) do { \
+       if ((v) != (correct)) { \
+               printf("(%s) Incorrect value %s=%d - should be %d\n", \
+                      __location__, #v, v, correct); \
+               ret = False; \
+       }} while (0)
+
+#define CHECK_STRING(v, correct) do { \
+       if (StrCaseCmp(v, correct) != 0) { \
+               printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
+                      __location__, #v, v, correct); \
+               ret = False; \
+       }} while (0)
+
+
+/*
+  test operations against a WINS server
+*/
+static BOOL nbt_test_wins(TALLOC_CTX *mem_ctx, struct nbt_name *name, 
+                             const char *address)
+{
+       struct nbt_name_register_wins io;
+       struct nbt_name_query query;
+       struct nbt_name_refresh_wins refresh;
+       struct nbt_name_release release;
+       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_n_ip(0));
+       const char *tname = talloc_asprintf(mem_ctx, "_TORTURE-%5u", 
+                                         (unsigned)(random() % (100000)));
+
+       /* we do the listen here to ensure the WINS server receives the packets from
+          the right IP */
+       socket_listen(nbtsock->sock, myaddress, 0, 0, 0);
+
+       printf("Testing name registration to WINS with name '%s' at %s\n", tname, myaddress);
+
+       io.in.name.name = tname;
+       io.in.name.type = NBT_NAME_CLIENT;
+       io.in.name.scope = NULL;
+       io.in.wins_servers = str_list_make(mem_ctx, address, NULL);
+       io.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
+       io.in.nb_flags = NBT_NODE_H;
+       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;
+       }
+       
+       CHECK_STRING(io.out.wins_server, address);
+       CHECK_VALUE(io.out.rcode, 0);
+
+       printf("query the name to make sure its there\n");
+       query.in.name = io.in.name;
+       query.in.dest_addr = address;
+       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);
+       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;
+       }
+       
+       CHECK_STRING(query.out.name.name, tname);
+       CHECK_VALUE(query.out.name.type, NBT_NAME_CLIENT);
+       CHECK_VALUE(query.out.num_addrs, 1);
+       CHECK_STRING(query.out.reply_addrs[0], myaddress);
+
+       printf("refresh the name\n");
+       refresh.in.name.name = tname;
+       refresh.in.name.type = NBT_NAME_CLIENT;
+       refresh.in.name.scope = NULL;
+       refresh.in.wins_servers = str_list_make(mem_ctx, address, NULL);
+       refresh.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
+       refresh.in.nb_flags = NBT_NODE_H;
+       refresh.in.ttl = 12345;
+       
+       status = nbt_name_refresh_wins(nbtsock, mem_ctx, &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;
+       }
+       
+       CHECK_STRING(io.out.wins_server, address);
+       CHECK_VALUE(io.out.rcode, 0);
+
+       printf("release the name\n");
+       release.in.name = io.in.name;
+       release.in.dest_addr = address;
+       release.in.address = myaddress;
+       release.in.nb_flags = NBT_NODE_H;
+       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;
+       }
+       
+       CHECK_STRING(release.out.name.name, tname);
+       CHECK_VALUE(release.out.name.type, NBT_NAME_CLIENT);
+       CHECK_VALUE(release.out.rcode, 0);
+
+       printf("release again\n");
+       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;
+       }
+       
+       CHECK_STRING(release.out.name.name, tname);
+       CHECK_VALUE(release.out.name.type, NBT_NAME_CLIENT);
+       CHECK_VALUE(release.out.rcode, 0);
+
+
+       printf("query the name to make sure its gone\n");
+       status = nbt_name_query(nbtsock, mem_ctx, &query);
+       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;
+       }
+       
+       return ret;
+}
+
+
+/*
+  test WINS operations
+*/
+BOOL torture_nbt_wins(void)
+{
+       const char *address;
+       struct nbt_name name;
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+       NTSTATUS status;
+       BOOL ret = True;
+       
+       name.name = lp_parm_string(-1, "torture", "host");
+       name.type = NBT_NAME_SERVER;
+       name.scope = NULL;
+
+       /* do an initial name resolution to find its IP */
+       status = resolve_name(&name, mem_ctx, &address);
+       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, &name, address);
+
+       talloc_free(mem_ctx);
+
+       return ret;
+}
index 8fd9d9f1eff8c2b28382decb78d3d63fd9dc50c2..12b12147234509610b60fa0233593475f5a8fa72 100644 (file)
@@ -2430,6 +2430,7 @@ static struct {
 
        /* nbt tests */
        {"NBT-REGISTER", torture_nbt_register, 0},
+       {"NBT-WINS", torture_nbt_wins, 0},
 
        {NULL, NULL, 0}};
 
index 36550b893331e82e1aa42d34963ef7d7d8d58fdd..e4cf87802d8b65d2659b9a2732b9679888b4f368 100644 (file)
@@ -156,10 +156,6 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
        status = nbt_name_query(nbtsock, nbtsock, &io);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       if (io.out.rcode != 0) {
-               return nbt_rcode_to_ntstatus(io.out.rcode);
-       }
-               
        for (i=0;i<io.out.num_addrs;i++) {
                printf("%s %s<%02x>\n",
                       io.out.reply_addrs[i],
@@ -221,7 +217,7 @@ static void process_one(const char *name)
        } else {
                int i, num_interfaces = iface_count();
                for (i=0;i<num_interfaces;i++) {
-                       const char *bcast = sys_inet_ntoa(*iface_n_bcast(i));
+                       const char *bcast = iface_n_bcast(i);
                        status = do_node_query(nbtsock, bcast, node_name, node_type, True);
                        if (NT_STATUS_IS_OK(status)) break;
                }