diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-10 03:22:47 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:37 -0500 |
commit | b9bb7f596de51496c18580863efbb8ac17c78970 (patch) | |
tree | e8ea83908a7a2e259e97b309595208481ef70b3d /source4 | |
parent | 57f69e6f37949636ae14c646517792fa40c9c75b (diff) | |
download | samba-b9bb7f596de51496c18580863efbb8ac17c78970.tar.gz samba-b9bb7f596de51496c18580863efbb8ac17c78970.tar.bz2 samba-b9bb7f596de51496c18580863efbb8ac17c78970.zip |
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)
Diffstat (limited to 'source4')
-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; } |