diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-06 08:25:53 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:34 -0500 |
commit | a75e9a3ee91b83af9c0fa25e407bf63cd67cd343 (patch) | |
tree | 21fde192c87ce7cab8ade46b57134cf43a037181 /source4/nbt_server | |
parent | e0caea68f5ac9f9fee1006b472bb49c2f81b21ac (diff) | |
download | samba-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/nbt_server')
-rw-r--r-- | source4/nbt_server/config.mk | 1 | ||||
-rw-r--r-- | source4/nbt_server/defense.c | 8 | ||||
-rw-r--r-- | source4/nbt_server/interfaces.c | 78 | ||||
-rw-r--r-- | source4/nbt_server/nbt_server.c | 5 | ||||
-rw-r--r-- | source4/nbt_server/nbt_server.h | 28 | ||||
-rw-r--r-- | source4/nbt_server/nodestatus.c | 10 | ||||
-rw-r--r-- | source4/nbt_server/packet.c | 6 | ||||
-rw-r--r-- | source4/nbt_server/query.c | 48 | ||||
-rw-r--r-- | source4/nbt_server/register.c | 43 | ||||
-rw-r--r-- | source4/nbt_server/winsclient.c | 123 | ||||
-rw-r--r-- | source4/nbt_server/winsserver.c | 1 |
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" /* |