diff options
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/ldap_server/ldap_server.c | 2 | ||||
-rw-r--r-- | source4/lib/netif/interface.c | 59 | ||||
-rw-r--r-- | source4/libcli/config.mk | 3 | ||||
-rw-r--r-- | source4/libcli/nbt/libnbt.h | 20 | ||||
-rw-r--r-- | source4/libcli/nbt/namequery.c | 16 | ||||
-rw-r--r-- | source4/libcli/nbt/namerelease.c | 129 | ||||
-rw-r--r-- | source4/libcli/resolve/bcast.c | 3 | ||||
-rw-r--r-- | source4/nbt_server/interfaces.c | 8 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_sock.c | 2 | ||||
-rw-r--r-- | source4/smb_server/smb_server.c | 2 | ||||
-rw-r--r-- | source4/torture/config.mk | 3 | ||||
-rw-r--r-- | source4/torture/nbt/register.c | 82 | ||||
-rw-r--r-- | source4/torture/nbt/wins.c | 219 | ||||
-rw-r--r-- | source4/torture/torture.c | 1 | ||||
-rw-r--r-- | source4/utils/nmblookup.c | 6 |
16 files changed, 419 insertions, 137 deletions
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 @@ -276,20 +278,6 @@ BOOL ismyip(struct ipv4_addr ip) } /**************************************************************************** - 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 **************************************************************************/ int iface_count(void) @@ -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<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; diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c index 3cb690b85d..c84f630400 100644 --- a/source4/nbt_server/interfaces.c +++ b/source4/nbt_server/interfaces.c @@ -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); diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c index 62f8c91d11..3f99b59a4d 100644 --- a/source4/rpc_server/dcerpc_sock.c +++ b/source4/rpc_server/dcerpc_sock.c @@ -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); } diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 10635f739d..11fe965a92 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -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); } diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 15661eb785..75bca5239d 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -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 diff --git a/source4/torture/nbt/register.c b/source4/torture/nbt/register.c index 6094d9fcaf..a8be5dbb9a 100644 --- a/source4/torture/nbt/register.c +++ b/source4/torture/nbt/register.c @@ -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 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<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; } |