summaryrefslogtreecommitdiff
path: root/source4/nbt_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/nbt_server')
-rw-r--r--source4/nbt_server/interfaces.c25
-rw-r--r--source4/nbt_server/packet.c3
-rw-r--r--source4/nbt_server/query.c2
-rw-r--r--source4/nbt_server/register.c8
-rw-r--r--source4/nbt_server/winsclient.c141
5 files changed, 145 insertions, 34 deletions
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
index 7572e4e336..3cb690b85d 100644
--- a/source4/nbt_server/interfaces.c
+++ b/source4/nbt_server/interfaces.c
@@ -49,13 +49,14 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
}
/* the request is to us in our role as a B node */
- switch (packet->operation & NBT_OPCODE) {
+ switch ((enum nbt_opcode)(packet->operation & NBT_OPCODE)) {
case NBT_OPCODE_QUERY:
nbtd_request_query(nbtsock, packet, src_address, src_port);
break;
case NBT_OPCODE_REGISTER:
case NBT_OPCODE_REFRESH:
+ case NBT_OPCODE_REFRESH2:
nbtd_request_defense(nbtsock, packet, src_address, src_port);
break;
@@ -165,9 +166,6 @@ static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
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;
@@ -238,21 +236,24 @@ const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx
struct nbtd_server *nbtsrv = iface->nbtsrv;
const char **ret = NULL;
struct nbtd_interface *iface2;
- int count;
+ int count = 0;
- ret = talloc_array(mem_ctx, const char *, 2);
- if (ret == NULL) goto failed;
+ if (iface->ip_address) {
+ ret = talloc_array(mem_ctx, const char *, 2);
+ if (ret == NULL) goto failed;
- ret[0] = talloc_strdup(ret, iface->ip_address);
- if (ret[0] == NULL) goto failed;
- ret[1] = NULL;
+ ret[0] = talloc_strdup(ret, iface->ip_address);
+ if (ret[0] == NULL) goto failed;
+ ret[1] = NULL;
- count = 1;
+ count = 1;
+ }
for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) {
const char **ret2;
- if (strcmp(iface2->ip_address, iface->ip_address) == 0) {
+ if (iface->ip_address &&
+ strcmp(iface2->ip_address, iface->ip_address) == 0) {
continue;
}
diff --git a/source4/nbt_server/packet.c b/source4/nbt_server/packet.c
index ac803f3d5e..a6df618a3f 100644
--- a/source4/nbt_server/packet.c
+++ b/source4/nbt_server/packet.c
@@ -61,7 +61,8 @@ BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock,
/* this uses the fact that iface->nbtsock is our non-broadcast
listen address */
- if (iface->nbtsock == nbtsock) {
+ if (iface->nbtsock == nbtsock &&
+ iface != iface->nbtsrv->bcast_interface) {
return False;
}
diff --git a/source4/nbt_server/query.c b/source4/nbt_server/query.c
index 28406081ea..2bcc2b1892 100644
--- a/source4/nbt_server/query.c
+++ b/source4/nbt_server/query.c
@@ -76,7 +76,7 @@ static void nbtd_name_query_reply(struct nbt_name_socket *nbtsock,
}
DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n",
- name->name, name->type, src_address, addresses[0], src_port));
+ name->name, name->type, addresses[0], src_address, src_port));
nbt_name_reply_send(nbtsock, src_address, src_port, packet);
diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c
index b65bd6d5ac..3b7d57efaf 100644
--- a/source4/nbt_server/register.c
+++ b/source4/nbt_server/register.c
@@ -56,9 +56,10 @@ static void refresh_completion_handler(struct nbt_name_request *req)
iname->nb_flags &= ~NBT_NM_ACTIVE;
if (NT_STATUS_IS_OK(status)) {
- DEBUG(1,("Name conflict from %s refreshing name %s<%02x> on %s - rcode %d\n",
+ DEBUG(1,("Name conflict from %s refreshing name %s<%02x> on %s - %s\n",
io.out.reply_addr, iname->name.name, iname->name.type,
- iname->iface->ip_address, io.out.rcode));
+ iname->iface->ip_address,
+ nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
} else {
DEBUG(1,("Error refreshing name %s<%02x> on %s - %s\n",
iname->name.name, iname->name.type, iname->iface->ip_address,
@@ -92,6 +93,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t
io.in.ttl = iname->ttl;
io.in.register_demand = False;
io.in.broadcast = True;
+ io.in.multi_homed = False;
io.in.timeout = 3;
io.in.retries = 0;
@@ -189,7 +191,7 @@ static void nbtd_register_name_iface(struct nbtd_interface *iface,
/* 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);
+ nbtd_winsclient_register(iname);
return;
}
diff --git a/source4/nbt_server/winsclient.c b/source4/nbt_server/winsclient.c
index 80168c9181..e941d77e28 100644
--- a/source4/nbt_server/winsclient.c
+++ b/source4/nbt_server/winsclient.c
@@ -28,20 +28,33 @@
#include "smbd/service_task.h"
+/* we send WINS client requests using our primary network interface
+*/
+static struct nbt_name_socket *wins_socket(struct nbtd_interface *iface)
+{
+ struct nbtd_server *nbtsrv = iface->nbtsrv;
+ return nbtsrv->interfaces->nbtsock;
+}
+
+
+static void nbtd_wins_refresh(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private);
+
/*
- refresh a WINS name registration
+ retry a WINS name registration
*/
-static void nbtd_refresh_wins_refresh(struct event_context *ev, struct timed_event *te,
- struct timeval t, void *private)
+static void nbtd_wins_register_retry(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);
+ nbtd_winsclient_register(iname);
}
+
/*
called when a wins name refresh has completed
*/
-static void nbtd_refresh_wins_handler(struct composite_context *c)
+static void nbtd_wins_refresh_handler(struct composite_context *c)
{
NTSTATUS status;
struct nbt_name_refresh_wins io;
@@ -51,28 +64,119 @@ static void nbtd_refresh_wins_handler(struct composite_context *c)
status = nbt_name_refresh_wins_recv(c, tmp_ctx, &io);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ /* our WINS server is dead - start registration over
+ from scratch */
+ DEBUG(2,("Failed to refresh %s<%02x> with WINS server %s\n",
+ iname->name.name, iname->name.type, iname->wins_server));
+ nbtd_winsclient_register(iname);
+ 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> - %s\n",
+ io.out.wins_server, iname->name.name, iname->name.type,
+ nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
+ iname->nb_flags |= NBT_NM_CONFLICT;
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ DEBUG(4,("Refreshed name %s<%02x> with WINS server %s\n",
+ iname->name.name, iname->name.type, iname->wins_server));
+ /* 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_wins_refresh,
+ iname);
+
+ talloc_free(tmp_ctx);
+}
+
+
+/*
+ refresh a WINS name registration
+*/
+static void nbtd_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);
+ struct nbtd_interface *iface = iname->iface;
+ struct nbt_name_refresh_wins io;
+ struct composite_context *c;
+ TALLOC_CTX *tmp_ctx = talloc_new(iname);
+
+ /* setup a wins name refresh request */
+ io.in.name = iname->name;
+ io.in.wins_servers = str_list_make(tmp_ctx, iname->wins_server, NULL);
+ io.in.addresses = nbtd_address_list(iface, tmp_ctx);
+ io.in.nb_flags = iname->nb_flags;
+ io.in.ttl = iname->ttl;
+
+ c = nbt_name_refresh_wins_send(wins_socket(iface), &io);
+ if (c == NULL) {
+ talloc_free(tmp_ctx);
+ return;
+ }
+ talloc_steal(c, io.in.addresses);
+
+ c->async.fn = nbtd_wins_refresh_handler;
+ c->async.private = iname;
+
+ talloc_free(tmp_ctx);
+}
+
+
+/*
+ called when a wins name register has completed
+*/
+static void nbtd_wins_register_handler(struct composite_context *c)
+{
+ NTSTATUS status;
+ struct nbt_name_register_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_register_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);
+ int wins_retry_time = lp_parm_int(-1, "nbtd", "wins_retry", 300);
event_add_timed(iname->iface->nbtsrv->task->event_ctx,
iname,
timeval_current_ofs(wins_retry_time, 0),
- nbtd_refresh_wins_refresh,
+ nbtd_wins_register_retry,
iname);
talloc_free(tmp_ctx);
return;
}
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("Name refresh failure with WINS for %s<%02x> - %s\n",
+ DEBUG(1,("Name register 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));
+ DEBUG(1,("WINS server %s rejected name register of %s<%02x> - %s\n",
+ io.out.wins_server, iname->name.name, iname->name.type,
+ nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
iname->nb_flags |= NBT_NM_CONFLICT;
talloc_free(tmp_ctx);
return;
@@ -89,35 +193,38 @@ static void nbtd_refresh_wins_handler(struct composite_context *c)
event_add_timed(iname->iface->nbtsrv->task->event_ctx,
iname,
timeval_add(&iname->registration_time, iname->ttl/2, 0),
- nbtd_refresh_wins_refresh,
+ nbtd_wins_refresh,
iname);
+ DEBUG(3,("Registered %s<%02x> with WINS server %s\n",
+ iname->name.name, iname->name.type, iname->wins_server));
+
talloc_free(tmp_ctx);
}
/*
- refresh a name with our WINS servers
+ register a name with our WINS servers
*/
-void nbtd_winsclient_refresh(struct nbtd_iface_name *iname)
+void nbtd_winsclient_register(struct nbtd_iface_name *iname)
{
struct nbtd_interface *iface = iname->iface;
- struct nbt_name_refresh_wins io;
+ struct nbt_name_register_wins io;
struct composite_context *c;
- /* setup a wins name refresh request */
+ /* setup a wins name register request */
io.in.name = iname->name;
io.in.wins_servers = lp_wins_server_list();
io.in.addresses = nbtd_address_list(iface, iname);
io.in.nb_flags = iname->nb_flags;
io.in.ttl = iname->ttl;
- c = nbt_name_refresh_wins_send(iface->nbtsock, &io);
+ c = nbt_name_register_wins_send(wins_socket(iface), &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.fn = nbtd_wins_register_handler;
c->async.private = iname;
}