r5117: used a composite function to add 4 stage name registration. We send 3
authorAndrew Tridgell <tridge@samba.org>
Mon, 31 Jan 2005 03:14:15 +0000 (03:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:09:24 +0000 (13:09 -0500)
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
source/libcli/config.mk
source/libcli/nbt/libnbt.h
source/libcli/nbt/nameregister.c
source/nbt_server/register.c

index 69f84ea55e1476682c48d2b60a0030defa78c1c3..9c1a1e329fde265bb98cb47602baf54b7ed74675 100644 (file)
@@ -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;
index c801524c2ffa1ef8691681ab4c311027a6b14849..d3aa4ff5ab293848fab4537ca069d1603f4a9d60 100644 (file)
@@ -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 = \
index 3bfffa25d059e3abae0b642b430873bbde609a2b..a3630e2a12a95f59d065059cfae1ce8691d05c6a 100644 (file)
@@ -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;
+};
index 2d1e964977d5181e92cbfdef5fcb9d5caebaca78..6d4938cd1944e0ca962c8715e1089121541b3206 100644 (file)
@@ -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);
+}
index 9a416e37aa0751b6df2306a889be3a8b9b5d8c78..7f7c291cf0f3ba92f6246db0c5fd8ebe802ceb8b 100644 (file)
@@ -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;