diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-01-31 03:14:15 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:24 -0500 |
commit | 5e6082b4b0e8d47d8634cf1b0c5bb460d0b6dbd1 (patch) | |
tree | 9d9e7ff4684f3ba69a32621e0e5f4418e570490c /source4/libcli/nbt | |
parent | 5269fb13a92850b5f22bf9f7640568d5946a43d5 (diff) | |
download | samba-5e6082b4b0e8d47d8634cf1b0c5bb460d0b6dbd1.tar.gz samba-5e6082b4b0e8d47d8634cf1b0c5bb460d0b6dbd1.tar.bz2 samba-5e6082b4b0e8d47d8634cf1b0c5bb460d0b6dbd1.zip |
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.
(This used to be commit d656fba6f1a2e9d8c03893741327e5fb59c5271e)
Diffstat (limited to 'source4/libcli/nbt')
-rw-r--r-- | source4/libcli/nbt/libnbt.h | 11 | ||||
-rw-r--r-- | source4/libcli/nbt/nameregister.c | 134 |
2 files changed, 145 insertions, 0 deletions
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); +} |