From b9bb7f596de51496c18580863efbb8ac17c78970 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 03:22:47 +0000 Subject: r5294: - added a separate NBT-WINS test for WINS operations (register, refresh, release and query) - 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) --- source4/include/structs.h | 1 + source4/ldap_server/ldap_server.c | 2 +- source4/lib/netif/interface.c | 59 +++------- source4/libcli/config.mk | 3 +- source4/libcli/nbt/libnbt.h | 20 +++- source4/libcli/nbt/namequery.c | 16 ++- source4/libcli/nbt/namerelease.c | 129 ++++++++++++++++++++++ source4/libcli/resolve/bcast.c | 3 +- source4/nbt_server/interfaces.c | 8 +- source4/rpc_server/dcerpc_sock.c | 2 +- source4/smb_server/smb_server.c | 2 +- source4/torture/config.mk | 3 +- source4/torture/nbt/register.c | 82 ++------------ source4/torture/nbt/wins.c | 219 ++++++++++++++++++++++++++++++++++++++ source4/torture/torture.c | 1 + source4/utils/nmblookup.c | 6 +- 16 files changed, 419 insertions(+), 137 deletions(-) create mode 100644 source4/libcli/nbt/namerelease.c create mode 100644 source4/torture/nbt/wins.c (limited to 'source4') diff --git a/source4/include/structs.h b/source4/include/structs.h index 1781ee09ec..f376609302 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -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; diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index ebc232a4c8..3a0e3d1cde 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -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); } diff --git a/source4/lib/netif/interface.c b/source4/lib/netif/interface.c index bf1e147e02..31354e359a 100644 --- a/source4/lib/netif/interface.c +++ b/source4/lib/netif/interface.c @@ -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; -} diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 038b8e0ccb..726d3f1184 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -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] diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h index 63711490fe..5a53510ccf 100644 --- a/source4/libcli/nbt/libnbt.h +++ b/source4/libcli/nbt/libnbt.h @@ -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; +}; diff --git a/source4/libcli/nbt/namequery.c b/source4/libcli/nbt/namequery.c index 32fcad2052..5907c45b87 100644 --- a/source4/libcli/nbt/namequery.c +++ b/source4/libcli/nbt/namequery.c @@ -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 index 0000000000..208c73d386 --- /dev/null +++ b/source4/libcli/nbt/namerelease.c @@ -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); +} diff --git a/source4/libcli/resolve/bcast.c b/source4/libcli/resolve/bcast.c index 5fb6e6dd5c..c47bba38c5 100644 --- a/source4/libcli/resolve/bcast.c +++ b/source4/libcli/resolve/bcast.c @@ -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 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; isock, 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 index 0000000000..62efcd3e97 --- /dev/null +++ b/source4/torture/nbt/wins.c @@ -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; +} diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 8fd9d9f1ef..12b1214723 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -2430,6 +2430,7 @@ static struct { /* nbt tests */ {"NBT-REGISTER", torture_nbt_register, 0}, + {"NBT-WINS", torture_nbt_wins, 0}, {NULL, NULL, 0}}; diff --git a/source4/utils/nmblookup.c b/source4/utils/nmblookup.c index 36550b8933..e4cf87802d 100644 --- a/source4/utils/nmblookup.c +++ b/source4/utils/nmblookup.c @@ -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\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