r5451: - added separate wrepl_associate(), wrepl_pull_table() and wrepl_pull_names...
authorAndrew Tridgell <tridge@samba.org>
Fri, 18 Feb 2005 23:13:51 +0000 (23:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:10:47 +0000 (13:10 -0500)
  parameters, so callers don't need to deal directly with wins replication packet structures

- converted the NBT-WINSREPLICATION torture test to use the new APIs
(This used to be commit cec1672662b7e5b1bdf843e9dee317aa4b03f719)

source4/include/structs.h
source4/libcli/wins/winsrepl.c
source4/libcli/wins/winsrepl.h
source4/torture/nbt/winsreplication.c

index 0804c90e7994f797d211b742cc190ad43120de56..be52755d798ddbadd67f76adffb153dac4b1afe3 100644 (file)
@@ -181,3 +181,6 @@ struct mutex_ops;
 struct ads_struct;
 
 struct wrepl_packet;
+struct wrepl_associate;
+struct wrepl_pull_table;
+struct wrepl_pull_names;
index 6ee948202faa7cddd362ce633aaacbe5062180d5..bf3593bdf8842bb46279b8bcefdc339952ab865c 100644 (file)
@@ -434,3 +434,271 @@ NTSTATUS wrepl_request(struct wrepl_socket *wrepl_socket,
        struct wrepl_request *req = wrepl_request_send(wrepl_socket, req_packet);
        return wrepl_request_recv(req, mem_ctx, reply_packet);
 }
+
+
+/*
+  setup an association - send
+*/
+struct wrepl_request *wrepl_associate_send(struct wrepl_socket *wrepl_socket,
+                                          struct wrepl_associate *io)
+{
+       struct wrepl_packet *packet;
+       struct wrepl_request *req;
+
+       packet = talloc_zero(wrepl_socket, struct wrepl_packet);
+       if (packet == NULL) return NULL;
+
+       packet->opcode                      = WREPL_OPCODE_BITS;
+       packet->mess_type                   = WREPL_START_ASSOCIATION;
+       packet->message.start.minor_version = 2;
+       packet->message.start.major_version = 5;
+
+       req = wrepl_request_send(wrepl_socket, packet);
+
+       talloc_free(packet);
+
+       return req;     
+}
+
+/*
+  setup an association - recv
+*/
+NTSTATUS wrepl_associate_recv(struct wrepl_request *req,
+                             struct wrepl_associate *io)
+{
+       struct wrepl_packet *packet=NULL;
+       NTSTATUS status;
+       status = wrepl_request_recv(req, req->wrepl_socket, &packet);
+       if (packet->mess_type != WREPL_START_ASSOCIATION_REPLY) {
+               status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+       }
+       if (NT_STATUS_IS_OK(status)) {
+               io->out.assoc_ctx = packet->message.start_reply.assoc_ctx;
+       }
+       talloc_free(packet);
+       return status;
+}
+
+/*
+  setup an association - sync api
+*/
+NTSTATUS wrepl_associate(struct wrepl_socket *wrepl_socket,
+                        struct wrepl_associate *io)
+{
+       struct wrepl_request *req = wrepl_associate_send(wrepl_socket, io);
+       return wrepl_associate_recv(req, io);
+}
+
+
+/*
+  fetch the partner tables - send
+*/
+struct wrepl_request *wrepl_pull_table_send(struct wrepl_socket *wrepl_socket,
+                                           struct wrepl_pull_table *io)
+{
+       struct wrepl_packet *packet;
+       struct wrepl_request *req;
+
+       packet = talloc_zero(wrepl_socket, struct wrepl_packet);
+       if (packet == NULL) return NULL;
+
+       packet->opcode                      = WREPL_OPCODE_BITS;
+       packet->assoc_ctx                   = io->in.assoc_ctx;
+       packet->mess_type                   = WREPL_REPLICATION;
+       packet->message.replication.command = WREPL_REPL_TABLE_QUERY;
+
+       req = wrepl_request_send(wrepl_socket, packet);
+
+       talloc_free(packet);
+
+       return req;     
+}
+
+
+/*
+  fetch the partner tables - recv
+*/
+NTSTATUS wrepl_pull_table_recv(struct wrepl_request *req,
+                              TALLOC_CTX *mem_ctx,
+                              struct wrepl_pull_table *io)
+{
+       struct wrepl_packet *packet=NULL;
+       NTSTATUS status;
+       struct wrepl_table *table;
+       int i;
+
+       status = wrepl_request_recv(req, req->wrepl_socket, &packet);
+       if (packet->mess_type != WREPL_REPLICATION) {
+               status = NT_STATUS_NETWORK_ACCESS_DENIED;
+       } else if (packet->message.replication.command != WREPL_REPL_TABLE_REPLY) {
+               status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+       }
+       if (!NT_STATUS_IS_OK(status)) goto failed;
+
+       table = &packet->message.replication.info.table;
+       io->out.num_partners = table->partner_count;
+       io->out.partners = talloc_steal(mem_ctx, table->partners);
+       for (i=0;i<io->out.num_partners;i++) {
+               talloc_steal(io->out.partners, io->out.partners[i].address);
+       }
+
+failed:
+       talloc_free(packet);
+       return status;
+}
+
+
+/*
+  fetch the partner table - sync api
+*/
+NTSTATUS wrepl_pull_table(struct wrepl_socket *wrepl_socket,
+                         TALLOC_CTX *mem_ctx,
+                         struct wrepl_pull_table *io)
+{
+       struct wrepl_request *req = wrepl_pull_table_send(wrepl_socket, io);
+       return wrepl_pull_table_recv(req, mem_ctx, io);
+}
+
+
+/*
+  fetch the names for a WINS partner - send
+*/
+struct wrepl_request *wrepl_pull_names_send(struct wrepl_socket *wrepl_socket,
+                                           struct wrepl_pull_names *io)
+{
+       struct wrepl_packet *packet;
+       struct wrepl_request *req;
+
+       packet = talloc_zero(wrepl_socket, struct wrepl_packet);
+       if (packet == NULL) return NULL;
+
+       packet->opcode                         = WREPL_OPCODE_BITS;
+       packet->assoc_ctx                      = io->in.assoc_ctx;
+       packet->mess_type                      = WREPL_REPLICATION;
+       packet->message.replication.command    = WREPL_REPL_SEND_REQUEST;
+       packet->message.replication.info.owner = io->in.partner;
+
+       req = wrepl_request_send(wrepl_socket, packet);
+
+       talloc_free(packet);
+
+       return req;     
+}
+
+
+/*
+  extract a nbt_name from a WINS name buffer
+*/
+static NTSTATUS wrepl_extract_name(struct nbt_name *name,
+                                  TALLOC_CTX *mem_ctx,
+                                  uint8_t *namebuf, uint32_t len)
+{
+       char *s;
+
+       /* oh wow, what a nasty bug in windows ... */
+       if (namebuf[0] == 0x1b && len >= 16) {
+               namebuf[0] = namebuf[15];
+               namebuf[15] = 0x1b;
+       }
+
+       if (len < 17) {
+               name->name = talloc_strndup(mem_ctx, namebuf, len);
+               name->type = 0;
+               name->scope = NULL;
+               return NT_STATUS_OK;
+       }
+
+       s = talloc_strndup(mem_ctx, namebuf, 15);
+       trim_string(s, NULL, " ");
+       name->name = s;
+       name->type = namebuf[15];
+       if (len > 18) {
+               name->scope = talloc_strndup(mem_ctx, namebuf+17, len-17);
+       } else {
+               name->scope = NULL;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  fetch the names for a WINS partner - recv
+*/
+NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req,
+                              TALLOC_CTX *mem_ctx,
+                              struct wrepl_pull_names *io)
+{
+       struct wrepl_packet *packet=NULL;
+       NTSTATUS status;
+       int i;
+
+       status = wrepl_request_recv(req, req->wrepl_socket, &packet);
+       if (packet->mess_type != WREPL_REPLICATION ||
+           packet->message.replication.command != WREPL_REPL_SEND_REPLY) {
+               status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+       }
+       if (!NT_STATUS_IS_OK(status)) goto failed;
+
+       io->out.num_names = packet->message.replication.info.reply.num_names;
+
+       status = NT_STATUS_NO_MEMORY;
+
+       io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names);
+       if (io->out.names == NULL) goto failed;
+
+       /* convert the list of names and addresses to a sane format */
+       for (i=0;i<io->out.num_names;i++) {
+               struct wrepl_wins_name *wname = &packet->message.replication.info.reply.names[i];
+               struct wrepl_name *name = &io->out.names[i];
+               status = wrepl_extract_name(&name->name, io->out.names, 
+                                           wname->name, wname->name_len);
+               if (!NT_STATUS_IS_OK(status)) goto failed;
+
+               /* trying to save 1 or 2 bytes on the wire isn't a good idea */
+               if (wname->flags & 2) {
+                       int j;
+
+                       name->num_addresses = wname->addresses.addresses.num_ips;
+                       name->addresses = talloc_array(io->out.names, 
+                                                      struct wrepl_address, 
+                                                      name->num_addresses);
+                       if (name->addresses == NULL) goto failed;
+                       for (j=0;j<name->num_addresses;j++) {
+                               name->addresses[j].owner = 
+                                       talloc_steal(name->addresses, 
+                                                    wname->addresses.addresses.ips[j].owner);
+                               name->addresses[j].address = 
+                                       talloc_steal(name->addresses, 
+                                                    wname->addresses.addresses.ips[j].ip);
+                       }
+               } else {
+                       name->num_addresses = 1;
+                       name->addresses = talloc(io->out.names, struct wrepl_address);
+                       if (name->addresses == NULL) goto failed;
+                       name->addresses[0].owner = talloc_steal(name->addresses, 
+                                                               wname->addresses.address.owner);
+                       name->addresses[0].address = talloc_steal(name->addresses,
+                                                                 wname->addresses.address.ip);
+               }
+       }
+
+       talloc_steal(mem_ctx, io->out.names);
+       status = NT_STATUS_OK;
+
+failed:
+       talloc_free(packet);
+       return status;
+}
+
+
+
+/*
+  fetch the names for a WINS partner - sync api
+*/
+NTSTATUS wrepl_pull_names(struct wrepl_socket *wrepl_socket,
+                         TALLOC_CTX *mem_ctx,
+                         struct wrepl_pull_names *io)
+{
+       struct wrepl_request *req = wrepl_pull_names_send(wrepl_socket, io);
+       return wrepl_pull_names_recv(req, mem_ctx, io);
+}
index 3fd1e5406c566839ba974d3d86dae15c892825a5..79b7f1fd708f5215e83b5e755cf8c427c1f01c05 100644 (file)
@@ -20,6 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "librpc/gen_ndr/ndr_nbt.h"
 #include "librpc/gen_ndr/ndr_winsrepl.h"
 
 /*
@@ -67,3 +68,47 @@ struct wrepl_request {
                void *private;
        } async;
 };
+
+
+/*
+  setup an association
+*/
+struct wrepl_associate {
+       struct {
+               uint32_t assoc_ctx;
+       } out;
+};
+
+/*
+  pull the partner table
+*/
+struct wrepl_pull_table {
+       struct {
+               uint32_t assoc_ctx;
+       } in;
+       struct {
+               uint32_t num_partners;
+               struct wrepl_wins_owner *partners;
+       } out;
+};
+
+/*
+  a full pull replication
+*/
+struct wrepl_pull_names {
+       struct {
+               uint32_t assoc_ctx;
+               struct wrepl_wins_owner partner;
+       } in;
+       struct {
+               uint32_t num_names;
+               struct wrepl_name {
+                       struct nbt_name name;
+                       uint32_t num_addresses;
+                       struct wrepl_address {
+                               const char *owner;
+                               const char *address;
+                       } *addresses;
+               } *names;
+       } out;
+};
index f3446b8e8bb14fca4cd3976de11205f007c09edb..5ba6003b789b0657f0c46bdb99fb780a51bcb550 100644 (file)
                goto done; \
        }} while (0)
 
-/*
-  extract a nbt_name from a name buffer
-*/
-static struct nbt_name *wrepl_extract_name(TALLOC_CTX *mem_ctx, 
-                                          uint8_t *name, uint32_t len)
-{
-       struct nbt_name *ret = talloc_zero(mem_ctx, struct nbt_name);
-
-       /* oh wow, what a nasty bug in windows ... */
-       if (name[0] == 0x1b && len >= 16) {
-               name[0] = name[15];
-               name[15] = 0x1b;
-       }
-
-       if (ret == NULL) return NULL;
-       if (len < 17) {
-               ret->name = talloc_strndup(ret, name, len);
-       } else {
-               char *s = talloc_strndup(ret, name, 15);
-               trim_string(s, NULL, " ");
-               ret->name = s;
-               ret->type = name[15];
-               if (len > 18) {
-                       ret->scope = talloc_strndup(ret, name+17, len-17);
-               }
-       }
-       return ret;
-}
-
 /*
   display a replication entry
 */
-static void display_entry(TALLOC_CTX *mem_ctx, struct wrepl_wins_name *wname)
+static void display_entry(TALLOC_CTX *mem_ctx, struct wrepl_name *name)
 {
-       struct nbt_name *name = wrepl_extract_name(mem_ctx, 
-                                                  wname->name,
-                                                  wname->name_len);
        int i;
-       printf("%s\n", nbt_name_string(mem_ctx, name));
-       if (wname->flags & 2) {
-               for (i=0;i<wname->addresses.addresses.num_ips;i++) {
-                       printf("\t%s %s\n", 
-                              wname->addresses.addresses.ips[i].owner,
-                              wname->addresses.addresses.ips[i].ip);
-               }
-       } else {
+
+       printf("%s\n", nbt_name_string(mem_ctx, &name->name));
+       for (i=0;i<name->num_addresses;i++) {
                printf("\t%s %s\n", 
-                      wname->addresses.address.owner,
-                      wname->addresses.address.ip);
+                      name->addresses[i].owner, name->addresses[i].address);
        }
 }
 
@@ -100,9 +62,10 @@ static BOOL nbt_test_wins_replication(TALLOC_CTX *mem_ctx, const char *address)
        BOOL ret = True;
        struct wrepl_socket *wrepl_socket;
        NTSTATUS status;
-       struct wrepl_packet request, *reply;
        int i, j;
-       struct wrepl_table *table;
+       struct wrepl_associate associate;
+       struct wrepl_pull_table pull_table;
+       struct wrepl_pull_names pull_names;
 
        wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
        
@@ -111,60 +74,37 @@ static BOOL nbt_test_wins_replication(TALLOC_CTX *mem_ctx, const char *address)
 
        printf("Send a start association request\n");
 
-       ZERO_STRUCT(request);
-       request.opcode                      = WREPL_OPCODE_BITS;
-       request.mess_type                   = WREPL_START_ASSOCIATION;
-       request.message.start.minor_version = 2;
-       request.message.start.major_version = 5;
-       request.padding                     = data_blob_talloc_zero(mem_ctx, 0);
-
-       status = wrepl_request(wrepl_socket, mem_ctx, &request, &reply);
+       status = wrepl_associate(wrepl_socket, &associate);
        CHECK_STATUS(status, NT_STATUS_OK);
-       CHECK_VALUE(reply->mess_type, WREPL_START_ASSOCIATION_REPLY);
 
-       request.assoc_ctx = reply->message.start_reply.assoc_ctx;
-       printf("association context: 0x%x\n", request.assoc_ctx);
+       printf("association context: 0x%x\n", associate.out.assoc_ctx);
 
        printf("Send a replication table query\n");
-       request.mess_type = WREPL_REPLICATION;
-       request.message.replication.command = WREPL_REPL_TABLE_QUERY;
+       pull_table.in.assoc_ctx = associate.out.assoc_ctx;
 
-       status = wrepl_request(wrepl_socket, mem_ctx, &request, &reply);
+       status = wrepl_pull_table(wrepl_socket, mem_ctx, &pull_table);
        CHECK_STATUS(status, NT_STATUS_OK);
-       if (reply->mess_type == WREPL_STOP_ASSOCIATION) {
-               printf("server refused table query - reason %d\n",
-                      reply->message.stop.reason);
-               ret = False;
-               goto done;
-       }
-       CHECK_VALUE(reply->mess_type, WREPL_REPLICATION);
-       CHECK_VALUE(reply->message.replication.command, WREPL_REPL_TABLE_REPLY);        
-
-       table = &reply->message.replication.info.table;
 
-       printf("Found %d replication partners\n", table->partner_count);
+       printf("Found %d replication partners\n", pull_table.out.num_partners);
 
-       for (i=0;i<table->partner_count;i++) {
+       for (i=0;i<pull_table.out.num_partners;i++) {
+               struct wrepl_wins_owner *partner = &pull_table.out.partners[i];
                printf("%s   max_version=%6llu   min_version=%6llu type=%d\n",
-                      table->partners[i].address, 
-                      table->partners[i].max_version, 
-                      table->partners[i].min_version, 
-                      table->partners[i].type);
-
-               request.message.replication.command = WREPL_REPL_SEND_REQUEST;
-               request.message.replication.info.owner = table->partners[i];
-
-               status = wrepl_request(wrepl_socket, mem_ctx, &request, &reply);
+                      partner->address, 
+                      partner->max_version, 
+                      partner->min_version, 
+                      partner->type);
+
+               pull_names.in.assoc_ctx = associate.out.assoc_ctx;
+               pull_names.in.partner = *partner;
+               
+               status = wrepl_pull_names(wrepl_socket, mem_ctx, &pull_names);
                CHECK_STATUS(status, NT_STATUS_OK);
-               CHECK_VALUE(reply->mess_type, WREPL_REPLICATION);
-               CHECK_VALUE(reply->message.replication.command, WREPL_REPL_SEND_REPLY);
 
-               printf("Received %d names\n", 
-                      reply->message.replication.info.reply.num_names);
+               printf("Received %d names\n", pull_names.out.num_names);
 
-               for (j=0;j<reply->message.replication.info.reply.num_names;j++) {
-                       display_entry(mem_ctx,
-                                     &reply->message.replication.info.reply.names[j]);
+               for (j=0;j<pull_names.out.num_names;j++) {
+                       display_entry(mem_ctx, &pull_names.out.names[j]);
                }
        }