diff options
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/config.mk | 8 | ||||
-rw-r--r-- | source4/libcli/nbt/libnbt.h | 11 | ||||
-rw-r--r-- | source4/libcli/nbt/nameregister.c | 134 |
3 files changed, 151 insertions, 2 deletions
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); +} |