From d656fba6f1a2e9d8c03893741327e5fb59c5271e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 31 Jan 2005 03:14:15 +0000 Subject: [PATCH] r5117: used a composite function to add 4 stage name registration. We send 3 broadcast name registration demands per name per interface at 1 second intervals, then send a name overwrite request and demand. Any name conflict replies are reported. --- source/include/structs.h | 1 + source/libcli/config.mk | 8 +- source/libcli/nbt/libnbt.h | 11 +++ source/libcli/nbt/nameregister.c | 134 +++++++++++++++++++++++++++++++ source/nbt_server/register.c | 31 +++---- 5 files changed, 163 insertions(+), 22 deletions(-) diff --git a/source/include/structs.h b/source/include/structs.h index 69f84ea55e1..9c1a1e329fd 100644 --- a/source/include/structs.h +++ b/source/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/source/libcli/config.mk b/source/libcli/config.mk index c801524c2ff..d3aa4ff5ab2 100644 --- a/source/libcli/config.mk +++ b/source/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/source/libcli/nbt/libnbt.h b/source/libcli/nbt/libnbt.h index 3bfffa25d05..a3630e2a12a 100644 --- a/source/libcli/nbt/libnbt.h +++ b/source/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/source/libcli/nbt/nameregister.c b/source/libcli/nbt/nameregister.c index 2d1e964977d..6d4938cd194 100644 --- a/source/libcli/nbt/nameregister.c +++ b/source/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/source/nbt_server/register.c b/source/nbt_server/register.c index 9a416e37aa0..7f7c291cf0f 100644 --- a/source/nbt_server/register.c +++ b/source/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; -- 2.34.1