summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/include/structs.h1
-rw-r--r--source4/libcli/config.mk8
-rw-r--r--source4/libcli/nbt/libnbt.h11
-rw-r--r--source4/libcli/nbt/nameregister.c134
-rw-r--r--source4/nbt_server/register.c31
5 files changed, 163 insertions, 22 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h
index 69f84ea55e..9c1a1e329f 100644
--- a/source4/include/structs.h
+++ b/source4/include/structs.h
@@ -151,6 +151,7 @@ struct nbt_name_socket;
struct nbt_name_query;
struct nbt_name_status;
struct nbt_name_register;
+struct nbt_name_register_bcast;
struct messaging_context;
struct stream_connection;
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index c801524c2f..d3aa4ff5ab 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -11,14 +11,18 @@ ADD_OBJ_FILES = libcli/util/asn1.o \
ADD_OBJ_FILES = libcli/util/clilsa.o
REQUIRED_SUBSYSTEMS = RPC_NDR_LSA
+[SUBSYSTEM::LIBCLI_COMPOSITE_BASE]
+ADD_OBJ_FILES = \
+ libcli/composite/composite.o
+
[SUBSYSTEM::LIBCLI_COMPOSITE]
ADD_OBJ_FILES = \
- libcli/composite/composite.o \
libcli/composite/loadfile.o \
libcli/composite/savefile.o \
libcli/composite/connect.o \
libcli/composite/sesssetup.o \
libcli/composite/fetchfile.o
+REQUIRED_SUBSYSTEMS = LIBCLI_COMPOSITE_BASE
[SUBSYSTEM::LIBCLI_NBT]
ADD_OBJ_FILES = \
@@ -26,7 +30,7 @@ ADD_OBJ_FILES = \
libcli/nbt/nbtsocket.o \
libcli/nbt/namequery.o \
libcli/nbt/nameregister.o
-REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET
+REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE
[SUBSYSTEM::LIBCLI_RESOLVE]
ADD_OBJ_FILES = \
diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h
index 3bfffa25d0..a3630e2a12 100644
--- a/source4/libcli/nbt/libnbt.h
+++ b/source4/libcli/nbt/libnbt.h
@@ -151,3 +151,14 @@ struct nbt_name_register {
uint8_t rcode;
} out;
};
+
+/* a send 3 times then demand name broadcast name registration */
+struct nbt_name_register_bcast {
+ struct {
+ struct nbt_name name;
+ const char *dest_addr;
+ const char *address;
+ uint16_t nb_flags;
+ uint32_t ttl;
+ } in;
+};
diff --git a/source4/libcli/nbt/nameregister.c b/source4/libcli/nbt/nameregister.c
index 2d1e964977..6d4938cd19 100644
--- a/source4/libcli/nbt/nameregister.c
+++ b/source4/libcli/nbt/nameregister.c
@@ -22,6 +22,8 @@
#include "includes.h"
#include "libcli/nbt/libnbt.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
#include "system/network.h"
/*
@@ -138,3 +140,135 @@ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock,
struct nbt_name_request *req = nbt_name_register_send(nbtsock, io);
return nbt_name_register_recv(req, mem_ctx, io);
}
+
+
+/*
+ a 4 step broadcast registration. 3 lots of name registration requests, followed by
+ a name registration demand
+*/
+struct register_bcast_state {
+ struct nbt_name_socket *nbtsock;
+ struct nbt_name_register *io;
+ int num_sends;
+ struct nbt_name_request *req;
+};
+
+
+/*
+ state handler for 4 stage name registration
+*/
+static void name_register_handler(struct nbt_name_request *req)
+{
+ struct smbcli_composite *c = talloc_get_type(req->async.private, struct smbcli_composite);
+ struct register_bcast_state *state = talloc_get_type(c->private, struct register_bcast_state);
+ NTSTATUS status;
+
+ status = nbt_name_register_recv(state->req, state, state->io);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ /* the registration timed out - good, send the next one */
+ state->num_sends++;
+ if (state->num_sends == 4) {
+ /* all done */
+ c->state = SMBCLI_REQUEST_DONE;
+ c->status = NT_STATUS_OK;
+ goto done;
+ }
+ if (state->num_sends == 3) {
+ state->io->in.register_demand = True;
+ }
+ state->req = nbt_name_register_send(state->nbtsock, state->io);
+ if (state->req == NULL) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ c->status = NT_STATUS_NO_MEMORY;
+ } else {
+ state->req->async.fn = name_register_handler;
+ state->req->async.private = c;
+ }
+ } else if (!NT_STATUS_IS_OK(status)) {
+ c->state = SMBCLI_REQUEST_ERROR;
+ c->status = status;
+ } else {
+ c->state = SMBCLI_REQUEST_ERROR;
+ c->status = NT_STATUS_CONFLICTING_ADDRESSES;
+ DEBUG(3,("Name registration conflict from %s for %s<%02x> with ip %s - rcode %d\n",
+ state->io->out.reply_from,
+ state->io->out.name.name,
+ state->io->out.name.type,
+ state->io->out.reply_addr,
+ state->io->out.rcode));
+ }
+
+done:
+ if (c->state >= SMBCLI_REQUEST_DONE &&
+ c->async.fn) {
+ c->async.fn(c);
+ }
+}
+
+/*
+ the async send call for a 4 stage name registration
+*/
+struct smbcli_composite *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock,
+ struct nbt_name_register_bcast *io)
+{
+ struct smbcli_composite *c;
+ struct register_bcast_state *state;
+
+ c = talloc_zero(nbtsock, struct smbcli_composite);
+ if (c == NULL) goto failed;
+
+ state = talloc(c, struct register_bcast_state);
+ if (state == NULL) goto failed;
+
+ state->io = talloc(state, struct nbt_name_register);
+ if (state->io == NULL) goto failed;
+
+ state->io->in.name = io->in.name;
+ state->io->in.dest_addr = io->in.dest_addr;
+ state->io->in.address = io->in.address;
+ state->io->in.nb_flags = io->in.nb_flags;
+ state->io->in.register_demand = False;
+ state->io->in.broadcast = True;
+ state->io->in.ttl = io->in.ttl;
+ state->io->in.timeout = 1;
+
+ state->num_sends = 0;
+ state->nbtsock = nbtsock;
+
+ state->req = nbt_name_register_send(nbtsock, state->io);
+ if (state->req == NULL) goto failed;
+
+ state->req->async.fn = name_register_handler;
+ state->req->async.private = c;
+
+ c->private = state;
+ c->state = SMBCLI_REQUEST_SEND;
+ c->event_ctx = nbtsock->event_ctx;
+
+ return c;
+
+failed:
+ talloc_free(c);
+ return NULL;
+}
+
+/*
+ broadcast 4 part name register - recv
+*/
+NTSTATUS nbt_name_register_bcast_recv(struct smbcli_composite *c)
+{
+ NTSTATUS status;
+ status = smb_composite_wait(c);
+ talloc_free(c);
+ return status;
+}
+
+/*
+ broadcast 4 part name register - sync interface
+*/
+NTSTATUS nbt_name_register_bcast(struct nbt_name_socket *nbtsock,
+ struct nbt_name_register_bcast *io)
+{
+ struct smbcli_composite *c = nbt_name_register_bcast_send(nbtsock, io);
+ return nbt_name_register_bcast_recv(c);
+}
diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c
index 9a416e37aa..7f7c291cf0 100644
--- a/source4/nbt_server/register.c
+++ b/source4/nbt_server/register.c
@@ -23,6 +23,8 @@
#include "includes.h"
#include "dlinklist.h"
#include "nbt_server/nbt_server.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/composite/composite.h"
/*
start a timer to refresh this name
@@ -35,14 +37,13 @@ static void nbt_start_refresh_timer(struct nbt_iface_name *iname)
/*
a name registration has completed
*/
-static void nbt_register_handler(struct nbt_name_request *req)
+static void nbt_register_handler(struct smbcli_composite *req)
{
struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
NTSTATUS status;
- struct nbt_name_register io;
- status = nbt_name_register_recv(req, iname, &io);
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ status = nbt_name_register_bcast_recv(req);
+ if (NT_STATUS_IS_OK(status)) {
/* good - nobody complained about our registration */
iname->nb_flags |= NBT_NM_ACTIVE;
DEBUG(3,("Registered %s<%02x> on interface %s\n",
@@ -51,19 +52,12 @@ static void nbt_register_handler(struct nbt_name_request *req)
return;
}
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("Error registering %s<%02x> on interface %s - %s\n",
- iname->name.name, iname->name.type, iname->iface->bcast_address,
- nt_errstr(status)));
- return;
- }
-
/* someone must have replied with an objection! */
iname->nb_flags |= NBT_NM_CONFLICT;
-
- DEBUG(1,("Name conflict registering %s<%02x> on interface %s - rcode %d from %s for %s\n",
+
+ DEBUG(1,("Error registering %s<%02x> on interface %s - %s\n",
iname->name.name, iname->name.type, iname->iface->bcast_address,
- io.out.rcode, io.out.reply_from, io.out.reply_addr));
+ nt_errstr(status)));
}
@@ -76,8 +70,8 @@ static void nbt_register_name_iface(struct nbt_interface *iface,
{
struct nbt_iface_name *iname;
const char *scope = lp_netbios_scope();
- struct nbt_name_register io;
- struct nbt_name_request *req;
+ struct nbt_name_register_bcast io;
+ struct smbcli_composite *req;
iname = talloc(iface, struct nbt_iface_name);
if (!iname) return;
@@ -108,12 +102,9 @@ static void nbt_register_name_iface(struct nbt_interface *iface,
io.in.dest_addr = iface->bcast_address;
io.in.address = iface->ip_address;
io.in.nb_flags = nb_flags;
- io.in.register_demand = False;
- io.in.broadcast = True;
io.in.ttl = iname->ttl;
- io.in.timeout = 1;
- req = nbt_name_register_send(iface->nbtsock, &io);
+ req = nbt_name_register_bcast_send(iface->nbtsock, &io);
if (req == NULL) return;
req->async.fn = nbt_register_handler;