summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/structs.h1
-rw-r--r--source4/ldap_server/ldap_server.c2
-rw-r--r--source4/lib/netif/interface.c59
-rw-r--r--source4/libcli/config.mk3
-rw-r--r--source4/libcli/nbt/libnbt.h20
-rw-r--r--source4/libcli/nbt/namequery.c16
-rw-r--r--source4/libcli/nbt/namerelease.c129
-rw-r--r--source4/libcli/resolve/bcast.c3
-rw-r--r--source4/nbt_server/interfaces.c8
-rw-r--r--source4/rpc_server/dcerpc_sock.c2
-rw-r--r--source4/smb_server/smb_server.c2
-rw-r--r--source4/torture/config.mk3
-rw-r--r--source4/torture/nbt/register.c82
-rw-r--r--source4/torture/nbt/wins.c219
-rw-r--r--source4/torture/torture.c1
-rw-r--r--source4/utils/nmblookup.c6
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;
}