summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-02-06 08:25:53 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:34 -0500
commita75e9a3ee91b83af9c0fa25e407bf63cd67cd343 (patch)
tree21fde192c87ce7cab8ade46b57134cf43a037181 /source4
parente0caea68f5ac9f9fee1006b472bb49c2f81b21ac (diff)
downloadsamba-a75e9a3ee91b83af9c0fa25e407bf63cd67cd343.tar.gz
samba-a75e9a3ee91b83af9c0fa25e407bf63cd67cd343.tar.bz2
samba-a75e9a3ee91b83af9c0fa25e407bf63cd67cd343.zip
r5251: - renamed the nbtd server side structures to have a nbtd_ prefix, to
be consistent with the function names - added WINS client support to the NBT server. It will do initial WINS registration, and WINS refresh, automatically failing over to secondary WINS servers and handling multi-homed servers where we need to register multiple IPs. - added support for multi-homed name query replies, which are essential for multi-homed registration as the WINS server will query us to ensure we have the names when doing the secondary IPs in multi-homed registration (This used to be commit a1553fa8054dc7d33f5d77f8f95d3ffd90392b2a)
Diffstat (limited to 'source4')
-rw-r--r--source4/nbt_server/config.mk1
-rw-r--r--source4/nbt_server/defense.c8
-rw-r--r--source4/nbt_server/interfaces.c78
-rw-r--r--source4/nbt_server/nbt_server.c5
-rw-r--r--source4/nbt_server/nbt_server.h28
-rw-r--r--source4/nbt_server/nodestatus.c10
-rw-r--r--source4/nbt_server/packet.c6
-rw-r--r--source4/nbt_server/query.c48
-rw-r--r--source4/nbt_server/register.c43
-rw-r--r--source4/nbt_server/winsclient.c123
-rw-r--r--source4/nbt_server/winsserver.c1
11 files changed, 287 insertions, 64 deletions
diff --git a/source4/nbt_server/config.mk b/source4/nbt_server/config.mk
index 34ed8878e8..8054ebc4de 100644
--- a/source4/nbt_server/config.mk
+++ b/source4/nbt_server/config.mk
@@ -11,6 +11,7 @@ ADD_OBJ_FILES = \
nbt_server/query.o \
nbt_server/nodestatus.o \
nbt_server/winsserver.o \
+ nbt_server/winsclient.o \
nbt_server/defense.o \
nbt_server/packet.o
REQUIRED_SUBSYSTEMS = \
diff --git a/source4/nbt_server/defense.c b/source4/nbt_server/defense.c
index e2095f22bd..86cf587235 100644
--- a/source4/nbt_server/defense.c
+++ b/source4/nbt_server/defense.c
@@ -43,7 +43,7 @@ static void nbtd_name_defense_reply(struct nbt_name_socket *nbtsock,
packet->ancount = 1;
packet->operation =
NBT_FLAG_REPLY |
- (request_packet->operation & NBT_OPCODE) |
+ NBT_OPCODE_REGISTER |
NBT_FLAG_AUTHORITIVE |
NBT_FLAG_RECURSION_DESIRED |
NBT_FLAG_RECURSION_AVAIL |
@@ -84,10 +84,10 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet,
const char *src_address, int src_port)
{
- struct nbt_iface_name *iname;
+ struct nbtd_iface_name *iname;
struct nbt_name *name;
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
- struct nbt_interface);
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
+ struct nbtd_interface);
NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
NBT_ASSERT_PACKET(packet, src_address, packet->arcount == 1);
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
index bb599b4fcd..b99c17089c 100644
--- a/source4/nbt_server/interfaces.c
+++ b/source4/nbt_server/interfaces.c
@@ -33,9 +33,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet,
const char *src_address, int src_port)
{
- /* if its a WINS query then direct to our WINS server */
+ /* if its a WINS query then direct to our WINS server if we
+ are running one */
if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
- !(packet->operation & NBT_FLAG_BROADCAST)) {
+ !(packet->operation & NBT_FLAG_BROADCAST) &&
+ lp_wins_support()) {
nbtd_query_wins(nbtsock, packet, src_address, src_port);
return;
}
@@ -56,6 +58,10 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
case NBT_OPCODE_REFRESH:
nbtd_request_defense(nbtsock, packet, src_address, src_port);
break;
+
+ default:
+ nbtd_bad_packet(packet, src_address, "Unexpected opcode");
+ break;
}
}
@@ -64,11 +70,11 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
/*
find a registered name on an interface
*/
-struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface,
- struct nbt_name *name,
- uint16_t nb_flags)
+struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
+ struct nbt_name *name,
+ uint16_t nb_flags)
{
- struct nbt_iface_name *iname;
+ struct nbtd_iface_name *iname;
for (iname=iface->names;iname;iname=iname->next) {
if (iname->name.type == name->type &&
StrCaseCmp(name->name, iname->name.name) == 0 &&
@@ -82,13 +88,13 @@ struct nbt_iface_name *nbtd_find_iname(struct nbt_interface *iface,
/*
start listening on the given address
*/
-static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
+static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
const char *bind_address,
const char *address,
const char *bcast,
const char *netmask)
{
- struct nbt_interface *iface;
+ struct nbtd_interface *iface;
NTSTATUS status;
struct nbt_name_socket *bcast_nbtsock;
@@ -100,7 +106,7 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
to interfaces
*/
- iface = talloc(nbtsrv, struct nbt_interface);
+ iface = talloc(nbtsrv, struct nbtd_interface);
NT_STATUS_HAVE_NO_MEMORY(iface);
iface->nbtsrv = nbtsrv;
@@ -151,9 +157,30 @@ static NTSTATUS nbtd_add_socket(struct nbt_server *nbtsrv,
/*
+ setup a socket for talking to our WINS servers
+*/
+static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
+{
+ struct nbtd_interface *iface;
+
+ iface = talloc_zero(nbtsrv, struct nbtd_interface);
+ NT_STATUS_HAVE_NO_MEMORY(iface);
+
+ iface->nbtsrv = nbtsrv;
+
+ iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(iface->nbtsock);
+
+ DLIST_ADD(nbtsrv->wins_interface, iface);
+
+ return NT_STATUS_OK;
+}
+
+
+/*
setup our listening sockets on the configured network interfaces
*/
-NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
+NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
{
int num_interfaces = iface_count();
int i;
@@ -194,7 +221,38 @@ NTSTATUS nbtd_startup_interfaces(struct nbt_server *nbtsrv)
NT_STATUS_NOT_OK_RETURN(status);
}
+ if (lp_wins_server_list()) {
+ status = nbtd_add_wins_socket(nbtsrv);
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
+
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
+
+
+/*
+ form a list of addresses that we should use in name query replies
+*/
+const char **nbtd_address_list(struct nbtd_server *nbtsrv, TALLOC_CTX *mem_ctx)
+{
+ const char **ret = NULL;
+ struct nbtd_interface *iface;
+ int count = 0;
+
+ for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
+ const char **ret2 = talloc_realloc(mem_ctx, ret, const char *, count+2);
+ if (ret2 == NULL) goto failed;
+ ret = ret2;
+ ret[count] = talloc_strdup(ret, iface->ip_address);
+ if (ret[count] == NULL) goto failed;
+ count++;
+ }
+ ret[count] = NULL;
+ return ret;
+
+failed:
+ talloc_free(ret);
+ return NULL;
+}
diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c
index d312269a19..73724720e5 100644
--- a/source4/nbt_server/nbt_server.c
+++ b/source4/nbt_server/nbt_server.c
@@ -31,10 +31,10 @@
*/
static void nbtd_task_init(struct task_server *task)
{
- struct nbt_server *nbtsrv;
+ struct nbtd_server *nbtsrv;
NTSTATUS status;
- nbtsrv = talloc(task, struct nbt_server);
+ nbtsrv = talloc(task, struct nbtd_server);
if (nbtsrv == NULL) {
task_terminate(task, "nbtd: out of memory");
return;
@@ -43,6 +43,7 @@ static void nbtd_task_init(struct task_server *task)
nbtsrv->task = task;
nbtsrv->interfaces = NULL;
nbtsrv->bcast_interface = NULL;
+ nbtsrv->wins_interface = NULL;
/* start listening on the configured network interfaces */
status = nbtd_startup_interfaces(nbtsrv);
diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h
index d7c85d77f2..3def958cc4 100644
--- a/source4/nbt_server/nbt_server.h
+++ b/source4/nbt_server/nbt_server.h
@@ -25,39 +25,47 @@
/*
a list of our registered names on each interface
*/
-struct nbt_iface_name {
- struct nbt_iface_name *next, *prev;
- struct nbt_interface *iface;
+struct nbtd_iface_name {
+ struct nbtd_iface_name *next, *prev;
+ struct nbtd_interface *iface;
struct nbt_name name;
uint16_t nb_flags;
struct timeval registration_time;
uint32_t ttl;
+
+ /* if registered with a wins server, then this lists the server being
+ used */
+ char *wins_server;
};
/* a list of network interfaces we are listening on */
-struct nbt_interface {
- struct nbt_interface *next, *prev;
- struct nbt_server *nbtsrv;
+struct nbtd_interface {
+ struct nbtd_interface *next, *prev;
+ struct nbtd_server *nbtsrv;
const char *ip_address;
const char *bcast_address;
const char *netmask;
struct nbt_name_socket *nbtsock;
- struct nbt_iface_name *names;
+ struct nbtd_iface_name *names;
};
/*
top level context structure for the nbt server
*/
-struct nbt_server {
+struct nbtd_server {
struct task_server *task;
/* the list of local network interfaces */
- struct nbt_interface *interfaces;
+ struct nbtd_interface *interfaces;
/* broadcast interface used for receiving packets only */
- struct nbt_interface *bcast_interface;
+ struct nbtd_interface *bcast_interface;
+
+ /* wins client interface - used for registering and refreshing
+ our names with a WINS server */
+ struct nbtd_interface *wins_interface;
};
diff --git a/source4/nbt_server/nodestatus.c b/source4/nbt_server/nodestatus.c
index 0d0fbb8086..ba6c3ea77b 100644
--- a/source4/nbt_server/nodestatus.c
+++ b/source4/nbt_server/nodestatus.c
@@ -32,11 +32,11 @@ static void nbtd_node_status_reply(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *request_packet,
const char *src_address, int src_port,
struct nbt_name *name,
- struct nbt_interface *iface)
+ struct nbtd_interface *iface)
{
struct nbt_name_packet *packet;
uint32_t name_count;
- struct nbt_iface_name *iname;
+ struct nbtd_iface_name *iname;
/* work out how many names to send */
name_count = 0;
@@ -100,9 +100,9 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock,
const char *src_address, int src_port)
{
struct nbt_name *name;
- struct nbt_iface_name *iname;
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
- struct nbt_interface);
+ struct nbtd_iface_name *iname;
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
+ struct nbtd_interface);
NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_STATUS);
diff --git a/source4/nbt_server/packet.c b/source4/nbt_server/packet.c
index bb9e2459b1..ac803f3d5e 100644
--- a/source4/nbt_server/packet.c
+++ b/source4/nbt_server/packet.c
@@ -45,9 +45,9 @@ BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet,
const char *src_address, int src_port)
{
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
- struct nbt_interface);
- struct nbt_server *nbtsrv = iface->nbtsrv;
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
+ struct nbtd_interface);
+ struct nbtd_server *nbtsrv = iface->nbtsrv;
/* if its not a broadcast then its not considered a self packet */
if (!(packet->operation & NBT_FLAG_BROADCAST)) {
diff --git a/source4/nbt_server/query.c b/source4/nbt_server/query.c
index bf2c75f2d1..80ea3d6ab8 100644
--- a/source4/nbt_server/query.c
+++ b/source4/nbt_server/query.c
@@ -32,9 +32,16 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *request_packet,
const char *src_address, int src_port,
struct nbt_name *name, uint32_t ttl,
- uint16_t nb_flags, const char *address)
+ uint16_t nb_flags, const char **addresses)
{
struct nbt_name_packet *packet;
+ size_t num_addresses = str_list_length(addresses);
+ int i;
+
+ if (num_addresses == 0) {
+ DEBUG(3,("No addresses in name query reply - failing\n"));
+ return;
+ }
packet = talloc_zero(nbtsock, struct nbt_name_packet);
if (packet == NULL) return;
@@ -55,17 +62,21 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
packet->answers[0].rr_type = NBT_QTYPE_NETBIOS;
packet->answers[0].rr_class = NBT_QCLASS_IP;
packet->answers[0].ttl = ttl;
- packet->answers[0].rdata.netbios.length = 6;
- packet->answers[0].rdata.netbios.addresses = talloc_array(packet->answers,
- struct nbt_rdata_address, 1);
+ packet->answers[0].rdata.netbios.length = num_addresses*6;
+ packet->answers[0].rdata.netbios.addresses =
+ talloc_array(packet->answers, struct nbt_rdata_address, num_addresses);
if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
- packet->answers[0].rdata.netbios.addresses[0].nb_flags = nb_flags;
- packet->answers[0].rdata.netbios.addresses[0].ipaddr =
- talloc_strdup(packet->answers, address);
- if (packet->answers[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
+
+ for (i=0;i<num_addresses;i++) {
+ struct nbt_rdata_address *addr =
+ &packet->answers[0].rdata.netbios.addresses[i];
+ addr->nb_flags = nb_flags;
+ addr->ipaddr = talloc_strdup(packet->answers, addresses[i]);
+ if (addr->ipaddr == NULL) goto failed;
+ }
DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n",
- name->name, name->type, src_address, address, src_port));
+ name->name, name->type, src_address, addresses[0], src_port));
nbt_name_reply_send(nbtsock, src_address, src_port, packet);
@@ -81,10 +92,10 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet,
const char *src_address, int src_port)
{
- struct nbt_iface_name *iname;
+ struct nbtd_iface_name *iname;
struct nbt_name *name;
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private,
- struct nbt_interface);
+ struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
+ struct nbtd_interface);
/* see if its a node status query */
if (packet->qdcount == 1 &&
@@ -100,14 +111,23 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
/* see if we have the requested name on this interface */
name = &packet->questions[0].name;
- iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE);
+ iname = nbtd_find_iname(iface, name, 0);
if (iname == NULL) {
DEBUG(7,("Query for %s<%02x> from %s - not found on %s\n",
name->name, name->type, src_address, iface->ip_address));
return;
}
+ /* if the name is not yet active and its a broadcast query then
+ ignore it for now */
+ if (!(iname->nb_flags & NBT_NM_ACTIVE) &&
+ (packet->operation & NBT_FLAG_BROADCAST)) {
+ DEBUG(7,("Query for %s<%02x> from %s - name not active yet on %s\n",
+ name->name, name->type, src_address, iface->ip_address));
+ return;
+ }
+
nbtd_name_query_reply(nbtsock, packet, src_address, src_port,
&iname->name, iname->ttl, iname->nb_flags,
- iface->ip_address);
+ nbtd_address_list(iface->nbtsrv, packet));
}
diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c
index e033797164..b65bd6d5ac 100644
--- a/source4/nbt_server/register.c
+++ b/source4/nbt_server/register.c
@@ -29,14 +29,15 @@
#include "libcli/composite/composite.h"
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname);
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
/*
a name refresh request has completed
*/
static void refresh_completion_handler(struct nbt_name_request *req)
{
- struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
+ struct nbtd_iface_name *iname = talloc_get_type(req->async.private,
+ struct nbtd_iface_name);
NTSTATUS status;
struct nbt_name_refresh io;
TALLOC_CTX *tmp_ctx = talloc_new(iname);
@@ -74,8 +75,8 @@ static void refresh_completion_handler(struct nbt_name_request *req)
static void name_refresh_handler(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private)
{
- struct nbt_iface_name *iname = talloc_get_type(private, struct nbt_iface_name);
- struct nbt_interface *iface = iname->iface;
+ struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
+ struct nbtd_interface *iface = iname->iface;
struct nbt_name_register io;
struct nbt_name_request *req;
@@ -92,6 +93,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
io.in.register_demand = False;
io.in.broadcast = True;
io.in.timeout = 3;
+ io.in.retries = 0;
req = nbt_name_register_send(iface->nbtsock, &io);
if (req == NULL) return;
@@ -104,7 +106,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
/*
start a timer to refresh this name
*/
-static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
+static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
{
uint32_t refresh_time;
uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
@@ -123,8 +125,8 @@ static void nbtd_start_refresh_timer(struct nbt_iface_name *iname)
*/
static void nbtd_register_handler(struct composite_context *req)
{
- struct nbt_iface_name *iname = talloc_get_type(req->async.private,
- struct nbt_iface_name);
+ struct nbtd_iface_name *iname = talloc_get_type(req->async.private,
+ struct nbtd_iface_name);
NTSTATUS status;
status = nbt_name_register_bcast_recv(req);
@@ -150,16 +152,16 @@ static void nbtd_register_handler(struct composite_context *req)
/*
register a name on a network interface
*/
-static void nbtd_register_name_iface(struct nbt_interface *iface,
+static void nbtd_register_name_iface(struct nbtd_interface *iface,
const char *name, enum nbt_name_type type,
uint16_t nb_flags)
{
- struct nbt_iface_name *iname;
+ struct nbtd_iface_name *iname;
const char *scope = lp_netbios_scope();
struct nbt_name_register_bcast io;
struct composite_context *req;
- iname = talloc(iface, struct nbt_iface_name);
+ iname = talloc(iface, struct nbtd_iface_name);
if (!iname) return;
iname->iface = iface;
@@ -173,8 +175,9 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
iname->nb_flags = nb_flags;
iname->ttl = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
iname->registration_time = timeval_zero();
+ iname->wins_server = NULL;
- DLIST_ADD_END(iface->names, iname, struct nbt_iface_name *);
+ DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
if (nb_flags & NBT_NM_PERMANENT) {
/* permanent names are not announced and are immediately active */
@@ -183,6 +186,13 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
return;
}
+ /* if this is the wins interface, then we need to do a special
+ wins name registration */
+ if (iface == iface->nbtsrv->wins_interface) {
+ nbtd_winsclient_refresh(iname);
+ return;
+ }
+
/* setup a broadcast name registration request */
io.in.name = iname->name;
io.in.dest_addr = iface->bcast_address;
@@ -201,11 +211,11 @@ static void nbtd_register_name_iface(struct nbt_interface *iface,
/*
register one name on all our interfaces
*/
-static void nbtd_register_name(struct nbt_server *nbtsrv,
+static void nbtd_register_name(struct nbtd_server *nbtsrv,
const char *name, enum nbt_name_type type,
uint16_t nb_flags)
{
- struct nbt_interface *iface;
+ struct nbtd_interface *iface;
/* register with all the local interfaces */
for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
@@ -218,14 +228,17 @@ static void nbtd_register_name(struct nbt_server *nbtsrv,
nb_flags | NBT_NM_PERMANENT);
}
- /* TODO: register with our WINS servers */
+ /* register with our WINS servers */
+ if (nbtsrv->wins_interface) {
+ nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
+ }
}
/*
register our names on all interfaces
*/
-void nbtd_register_names(struct nbt_server *nbtsrv)
+void nbtd_register_names(struct nbtd_server *nbtsrv)
{
uint16_t nb_flags = NBT_NODE_M;
const char **aliases;
diff --git a/source4/nbt_server/winsclient.c b/source4/nbt_server/winsclient.c
new file mode 100644
index 0000000000..572d46ba4b
--- /dev/null
+++ b/source4/nbt_server/winsclient.c
@@ -0,0 +1,123 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ wins client name registration and refresh
+
+ 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 "nbt_server/nbt_server.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
+#include "lib/events/events.h"
+#include "smbd/service_task.h"
+
+
+/*
+ refresh a WINS name registration
+*/
+static void nbtd_refresh_wins_refresh(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private)
+{
+ struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
+ nbtd_winsclient_refresh(iname);
+}
+
+/*
+ called when a wins name refresh has completed
+*/
+static void nbtd_refresh_wins_handler(struct composite_context *c)
+{
+ NTSTATUS status;
+ struct nbt_name_refresh_wins io;
+ struct nbtd_iface_name *iname = talloc_get_type(c->async.private,
+ struct nbtd_iface_name);
+ TALLOC_CTX *tmp_ctx = talloc_new(iname);
+
+ status = nbt_name_refresh_wins_recv(c, tmp_ctx, &io);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ /* none of the WINS servers responded - try again
+ periodically */
+ int wins_retry_time = lp_parm_int(-1, "nbt", "wins_retry", 300);
+ event_add_timed(iname->iface->nbtsrv->task->event_ctx,
+ iname,
+ timeval_current_ofs(wins_retry_time, 0),
+ nbtd_refresh_wins_refresh,
+ iname);
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1,("Name refresh failure with WINS for %s<%02x> - %s\n",
+ iname->name.name, iname->name.type, nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ if (io.out.rcode != 0) {
+ DEBUG(1,("WINS server %s rejected name refresh of %s<%02x> - rcode %d\n",
+ io.out.wins_server, iname->name.name, iname->name.type, io.out.rcode));
+ iname->nb_flags |= NBT_NM_CONFLICT;
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ /* success - start a periodic name refresh */
+ iname->nb_flags |= NBT_NM_ACTIVE;
+ if (iname->wins_server) {
+ talloc_free(iname->wins_server);
+ }
+ iname->wins_server = talloc_steal(iname, io.out.wins_server);
+
+ iname->registration_time = timeval_current();
+ event_add_timed(iname->iface->nbtsrv->task->event_ctx,
+ iname,
+ timeval_add(&iname->registration_time, iname->ttl/2, 0),
+ nbtd_refresh_wins_refresh,
+ iname);
+
+ talloc_free(tmp_ctx);
+}
+
+/*
+ refresh a name with our WINS servers
+*/
+void nbtd_winsclient_refresh(struct nbtd_iface_name *iname)
+{
+ struct nbtd_interface *iface = iname->iface;
+ struct nbt_name_refresh_wins io;
+ struct composite_context *c;
+
+ /* setup a wins name refresh request */
+ io.in.name = iname->name;
+ io.in.wins_servers = lp_wins_server_list();
+ io.in.addresses = nbtd_address_list(iface->nbtsrv, iname);
+ io.in.nb_flags = iname->nb_flags;
+ io.in.ttl = iname->ttl;
+
+ c = nbt_name_refresh_wins_send(iface->nbtsock, &io);
+ if (c == NULL) {
+ talloc_free(io.in.addresses);
+ return;
+ }
+ talloc_steal(c, io.in.addresses);
+
+ c->async.fn = nbtd_refresh_wins_handler;
+ c->async.private = iname;
+}
diff --git a/source4/nbt_server/winsserver.c b/source4/nbt_server/winsserver.c
index 44216a1cb5..5940303f66 100644
--- a/source4/nbt_server/winsserver.c
+++ b/source4/nbt_server/winsserver.c
@@ -21,7 +21,6 @@
*/
#include "includes.h"
-#include "dlinklist.h"
#include "nbt_server/nbt_server.h"
/*