2 Unix SMB/CIFS implementation.
4 WINS replication testing
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/nbt/libnbt.h"
25 #include "libcli/wrepl/winsrepl.h"
27 #define CHECK_STATUS(status, correct) do { \
28 if (!NT_STATUS_EQUAL(status, correct)) { \
29 printf("(%s) Incorrect status %s - should be %s\n", \
30 __location__, nt_errstr(status), nt_errstr(correct)); \
35 #define CHECK_VALUE(v, correct) do { \
36 if ((v) != (correct)) { \
37 printf("(%s) Incorrect value %s=%d - should be %d\n", \
38 __location__, #v, v, correct); \
43 #define _NBT_NAME(n,t,s) {\
50 test how assoc_ctx's are only usable on the connection
53 static BOOL test_assoc_ctx1(TALLOC_CTX *mem_ctx, const char *address)
56 struct wrepl_request *req;
57 struct wrepl_socket *wrepl_socket1;
58 struct wrepl_associate associate1;
59 struct wrepl_socket *wrepl_socket2;
60 struct wrepl_associate associate2;
61 struct wrepl_pull_table pull_table;
62 struct wrepl_packet *rep_packet;
63 struct wrepl_associate_stop assoc_stop;
66 if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
67 printf("winsrepl: cross connection assoc_ctx usage disabled - enable dangerous tests to use\n");
71 printf("Test if assoc_ctx is only valid on the conection it was created on\n");
73 wrepl_socket1 = wrepl_socket_init(mem_ctx, NULL);
74 wrepl_socket2 = wrepl_socket_init(mem_ctx, NULL);
76 printf("Setup 2 wrepl connections\n");
77 status = wrepl_connect(wrepl_socket1, NULL, address);
78 CHECK_STATUS(status, NT_STATUS_OK);
80 status = wrepl_connect(wrepl_socket2, NULL, address);
81 CHECK_STATUS(status, NT_STATUS_OK);
83 printf("Send a start association request (conn1)\n");
84 status = wrepl_associate(wrepl_socket1, &associate1);
85 CHECK_STATUS(status, NT_STATUS_OK);
87 printf("association context (conn1): 0x%x\n", associate1.out.assoc_ctx);
89 printf("Send a start association request (conn2)\n");
90 status = wrepl_associate(wrepl_socket2, &associate2);
91 CHECK_STATUS(status, NT_STATUS_OK);
93 printf("association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
95 printf("Send a replication table query, with assoc 1 (conn2), the anwser should be on conn1\n");
96 pull_table.in.assoc_ctx = associate1.out.assoc_ctx;
97 req = wrepl_pull_table_send(wrepl_socket2, &pull_table);
98 req->send_only = True;
99 status = wrepl_request_recv(req, mem_ctx, &rep_packet);
100 CHECK_STATUS(status, NT_STATUS_OK);
102 printf("Send a association request (conn2), to make sure the last request was ignored\n");
103 status = wrepl_associate(wrepl_socket2, &associate2);
104 CHECK_STATUS(status, NT_STATUS_OK);
106 printf("Send a replication table query, with invalid assoc (conn1), receive answer from conn2\n");
107 pull_table.in.assoc_ctx = 0;
108 req = wrepl_pull_table_send(wrepl_socket1, &pull_table);
109 status = wrepl_request_recv(req, mem_ctx, &rep_packet);
110 CHECK_STATUS(status, NT_STATUS_OK);
112 printf("Send a association request (conn1), to make sure the last request was handled correct\n");
113 status = wrepl_associate(wrepl_socket1, &associate2);
114 CHECK_STATUS(status, NT_STATUS_OK);
116 assoc_stop.in.assoc_ctx = associate1.out.assoc_ctx;
117 assoc_stop.in.reason = 4;
118 printf("Send a association stop request (conn1), reson: %u\n", assoc_stop.in.reason);
119 status = wrepl_associate_stop(wrepl_socket1, &assoc_stop);
120 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
122 assoc_stop.in.assoc_ctx = associate2.out.assoc_ctx;
123 assoc_stop.in.reason = 0;
124 printf("Send a association stop request (conn2), reson: %u\n", assoc_stop.in.reason);
125 status = wrepl_associate_stop(wrepl_socket2, &assoc_stop);
126 CHECK_STATUS(status, NT_STATUS_OK);
129 printf("Close 2 wrepl connections\n");
130 talloc_free(wrepl_socket1);
131 talloc_free(wrepl_socket2);
136 test if we always get back the same assoc_ctx
138 static BOOL test_assoc_ctx2(TALLOC_CTX *mem_ctx, const char *address)
141 struct wrepl_socket *wrepl_socket;
142 struct wrepl_associate associate;
146 printf("Test if we always get back the same assoc_ctx\n");
148 wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
150 printf("Setup wrepl connections\n");
151 status = wrepl_connect(wrepl_socket, NULL, address);
152 CHECK_STATUS(status, NT_STATUS_OK);
155 printf("Send 1st start association request\n");
156 status = wrepl_associate(wrepl_socket, &associate);
157 CHECK_STATUS(status, NT_STATUS_OK);
158 assoc_ctx1 = associate.out.assoc_ctx;
159 printf("1st association context: 0x%x\n", associate.out.assoc_ctx);
161 printf("Send 2nd start association request\n");
162 status = wrepl_associate(wrepl_socket, &associate);
163 CHECK_VALUE(associate.out.assoc_ctx, assoc_ctx1);
164 CHECK_STATUS(status, NT_STATUS_OK);
165 printf("2nd association context: 0x%x\n", associate.out.assoc_ctx);
167 printf("Send 3rd start association request\n");
168 status = wrepl_associate(wrepl_socket, &associate);
169 CHECK_VALUE(associate.out.assoc_ctx, assoc_ctx1);
170 CHECK_STATUS(status, NT_STATUS_OK);
171 printf("3rd association context: 0x%x\n", associate.out.assoc_ctx);
174 printf("Close wrepl connections\n");
175 talloc_free(wrepl_socket);
181 display a replication entry
183 static void display_entry(TALLOC_CTX *mem_ctx, struct wrepl_name *name)
187 printf("%s\n", nbt_name_string(mem_ctx, &name->name));
188 printf("\tTYPE:%u STATE:%u NODE:%u STATIC:%u VERSION_ID: %llu\n",
189 name->type, name->state, name->node, name->is_static, name->version_id);
190 printf("\tRAW_FLAGS: 0x%08X OWNER: %-15s\n",
191 name->raw_flags, name->owner);
192 for (i=0;i<name->num_addresses;i++) {
193 printf("\tADDR: %-15s OWNER: %-15s\n",
194 name->addresses[i].address, name->addresses[i].owner);
199 test a full replication dump from a WINS server
201 static BOOL test_wins_replication(TALLOC_CTX *mem_ctx, const char *address)
204 struct wrepl_socket *wrepl_socket;
207 struct wrepl_associate associate;
208 struct wrepl_pull_table pull_table;
209 struct wrepl_pull_names pull_names;
211 printf("Test one pull replication cycle\n");
213 wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
215 printf("Setup wrepl connections\n");
216 status = wrepl_connect(wrepl_socket, NULL, address);
217 CHECK_STATUS(status, NT_STATUS_OK);
219 printf("Send a start association request\n");
221 status = wrepl_associate(wrepl_socket, &associate);
222 CHECK_STATUS(status, NT_STATUS_OK);
224 printf("association context: 0x%x\n", associate.out.assoc_ctx);
226 printf("Send a replication table query\n");
227 pull_table.in.assoc_ctx = associate.out.assoc_ctx;
229 status = wrepl_pull_table(wrepl_socket, mem_ctx, &pull_table);
230 if (NT_STATUS_EQUAL(NT_STATUS_NETWORK_ACCESS_DENIED,status)) {
231 struct wrepl_packet packet;
232 struct wrepl_request *req;
235 packet.opcode = WREPL_OPCODE_BITS;
236 packet.assoc_ctx = associate.out.assoc_ctx;
237 packet.mess_type = WREPL_STOP_ASSOCIATION;
238 packet.message.stop.reason = 0;
240 req = wrepl_request_send(wrepl_socket, &packet);
243 printf("failed - We are not a valid pull partner for the server\n");
247 CHECK_STATUS(status, NT_STATUS_OK);
249 printf("Found %d replication partners\n", pull_table.out.num_partners);
251 for (i=0;i<pull_table.out.num_partners;i++) {
252 struct wrepl_wins_owner *partner = &pull_table.out.partners[i];
253 printf("%s max_version=%6llu min_version=%6llu type=%d\n",
255 partner->max_version,
256 partner->min_version,
259 pull_names.in.assoc_ctx = associate.out.assoc_ctx;
260 pull_names.in.partner = *partner;
262 status = wrepl_pull_names(wrepl_socket, mem_ctx, &pull_names);
263 CHECK_STATUS(status, NT_STATUS_OK);
265 printf("Received %d names\n", pull_names.out.num_names);
267 for (j=0;j<pull_names.out.num_names;j++) {
268 display_entry(mem_ctx, &pull_names.out.names[j]);
273 printf("Close wrepl connections\n");
274 talloc_free(wrepl_socket);
278 struct test_wrepl_conflict_conn {
280 struct wrepl_socket *pull;
283 #define TEST_OWNER_A_ADDRESS "127.65.65.1"
284 #define TEST_ADDRESS_A_PREFIX "127.0.65"
285 #define TEST_OWNER_B_ADDRESS "127.66.66.1"
286 #define TEST_ADDRESS_B_PREFIX "127.0.66"
288 struct wrepl_wins_owner a, b;
291 static const struct wrepl_ip addresses_A_1[] = {
293 .owner = TEST_OWNER_A_ADDRESS,
294 .ip = TEST_ADDRESS_A_PREFIX".1"
297 static const struct wrepl_ip addresses_A_2[] = {
299 .owner = TEST_OWNER_A_ADDRESS,
300 .ip = TEST_ADDRESS_A_PREFIX".2"
304 static const struct wrepl_ip addresses_B_1[] = {
306 .owner = TEST_OWNER_B_ADDRESS,
307 .ip = TEST_ADDRESS_B_PREFIX".1"
310 static const struct wrepl_ip addresses_B_2[] = {
312 .owner = TEST_OWNER_B_ADDRESS,
313 .ip = TEST_ADDRESS_B_PREFIX".2"
317 static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *mem_ctx,
320 struct test_wrepl_conflict_conn *ctx;
321 struct wrepl_associate associate;
322 struct wrepl_pull_table pull_table;
326 ctx = talloc_zero(mem_ctx, struct test_wrepl_conflict_conn);
327 if (!ctx) return NULL;
329 ctx->address = address;
330 ctx->pull = wrepl_socket_init(ctx, NULL);
331 if (!ctx->pull) return NULL;
333 printf("Setup wrepl conflict pull connection\n");
334 status = wrepl_connect(ctx->pull, NULL, ctx->address);
335 if (!NT_STATUS_IS_OK(status)) return NULL;
337 status = wrepl_associate(ctx->pull, &associate);
338 if (!NT_STATUS_IS_OK(status)) return NULL;
340 ctx->pull_assoc = associate.out.assoc_ctx;
342 ctx->a.address = TEST_OWNER_A_ADDRESS;
343 ctx->a.max_version = 0;
344 ctx->a.min_version = 0;
347 ctx->b.address = TEST_OWNER_B_ADDRESS;
348 ctx->b.max_version = 0;
349 ctx->b.min_version = 0;
352 pull_table.in.assoc_ctx = ctx->pull_assoc;
353 status = wrepl_pull_table(ctx->pull, ctx->pull, &pull_table);
354 if (!NT_STATUS_IS_OK(status)) return NULL;
356 for (i=0; i < pull_table.out.num_partners; i++) {
357 if (strcmp(TEST_OWNER_A_ADDRESS,pull_table.out.partners[i].address)==0) {
358 ctx->a.max_version = pull_table.out.partners[i].max_version;
359 ctx->a.min_version = pull_table.out.partners[i].min_version;
361 if (strcmp(TEST_OWNER_B_ADDRESS,pull_table.out.partners[i].address)==0) {
362 ctx->b.max_version = pull_table.out.partners[i].max_version;
363 ctx->b.min_version = pull_table.out.partners[i].min_version;
367 talloc_free(pull_table.out.partners);
372 static BOOL test_wrepl_update_one(struct test_wrepl_conflict_conn *ctx,
373 const struct wrepl_wins_owner *owner,
374 const struct wrepl_wins_name *name)
377 struct wrepl_socket *wrepl_socket;
378 struct wrepl_associate associate;
379 struct wrepl_packet update_packet, repl_send;
380 struct wrepl_table *update;
381 struct wrepl_wins_owner wrepl_wins_owners[1];
382 struct wrepl_packet *repl_recv;
383 struct wrepl_wins_owner *send_request;
384 struct wrepl_send_reply *send_reply;
385 struct wrepl_wins_name wrepl_wins_names[1];
389 wrepl_socket = wrepl_socket_init(ctx, NULL);
391 status = wrepl_connect(wrepl_socket, NULL, ctx->address);
392 CHECK_STATUS(status, NT_STATUS_OK);
394 status = wrepl_associate(wrepl_socket, &associate);
395 CHECK_STATUS(status, NT_STATUS_OK);
396 assoc_ctx = associate.out.assoc_ctx;
398 /* now send a WREPL_REPL_UPDATE message */
399 ZERO_STRUCT(update_packet);
400 update_packet.opcode = WREPL_OPCODE_BITS;
401 update_packet.assoc_ctx = assoc_ctx;
402 update_packet.mess_type = WREPL_REPLICATION;
403 update_packet.message.replication.command = WREPL_REPL_UPDATE;
404 update = &update_packet.message.replication.info.table;
406 update->partner_count = ARRAY_SIZE(wrepl_wins_owners);
407 update->partners = wrepl_wins_owners;
408 update->initiator = "0.0.0.0";
410 wrepl_wins_owners[0] = *owner;
412 status = wrepl_request(wrepl_socket, wrepl_socket,
413 &update_packet, &repl_recv);
414 CHECK_STATUS(status, NT_STATUS_OK);
415 CHECK_VALUE(repl_recv->mess_type, WREPL_REPLICATION);
416 CHECK_VALUE(repl_recv->message.replication.command, WREPL_REPL_SEND_REQUEST);
417 send_request = &repl_recv->message.replication.info.owner;
419 ZERO_STRUCT(repl_send);
420 repl_send.opcode = WREPL_OPCODE_BITS;
421 repl_send.assoc_ctx = assoc_ctx;
422 repl_send.mess_type = WREPL_REPLICATION;
423 repl_send.message.replication.command = WREPL_REPL_SEND_REPLY;
424 send_reply = &repl_send.message.replication.info.reply;
426 send_reply->num_names = ARRAY_SIZE(wrepl_wins_names);
427 send_reply->names = wrepl_wins_names;
429 wrepl_wins_names[0] = *name;
431 status = wrepl_request(wrepl_socket, wrepl_socket,
432 &repl_send, &repl_recv);
433 CHECK_STATUS(status, NT_STATUS_OK);
434 CHECK_VALUE(repl_recv->mess_type, WREPL_STOP_ASSOCIATION);
435 CHECK_VALUE(repl_recv->message.stop.reason, 0);
438 talloc_free(wrepl_socket);
442 static BOOL test_wrepl_is_applied(struct test_wrepl_conflict_conn *ctx,
443 const struct wrepl_wins_owner *owner,
444 const struct wrepl_wins_name *name,
449 struct wrepl_pull_names pull_names;
451 pull_names.in.assoc_ctx = ctx->pull_assoc;
452 pull_names.in.partner = *owner;
453 pull_names.in.partner.min_version = pull_names.in.partner.max_version;
455 status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
456 CHECK_STATUS(status, NT_STATUS_OK);
457 CHECK_VALUE(pull_names.out.num_names, (expected?1:0));
460 talloc_free(pull_names.out.names);
464 static BOOL test_conflict_same_owner(struct test_wrepl_conflict_conn *ctx)
467 struct nbt_name name;
468 struct wrepl_wins_name wins_name1;
469 struct wrepl_wins_name wins_name2;
470 struct wrepl_wins_name *wins_name_tmp;
471 struct wrepl_wins_name *wins_name_last;
472 struct wrepl_wins_name *wins_name_cur;
474 uint8_t types[] = { 0x00, 0x1C };
476 enum wrepl_name_type type;
477 enum wrepl_name_state state;
478 enum wrepl_name_node node;
481 const struct wrepl_ip *ips;
484 .type = WREPL_TYPE_GROUP,
485 .state = WREPL_STATE_ACTIVE,
486 .node = WREPL_NODE_B,
488 .num_ips = ARRAY_SIZE(addresses_A_1),
489 .ips = addresses_A_1,
491 .type = WREPL_TYPE_UNIQUE,
492 .state = WREPL_STATE_ACTIVE,
493 .node = WREPL_NODE_B,
495 .num_ips = ARRAY_SIZE(addresses_A_1),
496 .ips = addresses_A_1,
498 .type = WREPL_TYPE_UNIQUE,
499 .state = WREPL_STATE_ACTIVE,
500 .node = WREPL_NODE_B,
502 .num_ips = ARRAY_SIZE(addresses_A_2),
503 .ips = addresses_A_2,
505 .type = WREPL_TYPE_UNIQUE,
506 .state = WREPL_STATE_ACTIVE,
507 .node = WREPL_NODE_B,
509 .num_ips = ARRAY_SIZE(addresses_A_1),
510 .ips = addresses_A_1,
512 .type = WREPL_TYPE_UNIQUE,
513 .state = WREPL_STATE_ACTIVE,
514 .node = WREPL_NODE_B,
516 .num_ips = ARRAY_SIZE(addresses_A_2),
517 .ips = addresses_A_2,
519 .type = WREPL_TYPE_SGROUP,
520 .state = WREPL_STATE_TOMBSTONE,
521 .node = WREPL_NODE_B,
523 .num_ips = ARRAY_SIZE(addresses_A_2),
524 .ips = addresses_A_2,
526 .type = WREPL_TYPE_MHOMED,
527 .state = WREPL_STATE_TOMBSTONE,
528 .node = WREPL_NODE_B,
530 .num_ips = ARRAY_SIZE(addresses_A_1),
531 .ips = addresses_A_1,
533 /* the last one should always be a unique,tomstone record! */
534 .type = WREPL_TYPE_UNIQUE,
535 .state = WREPL_STATE_TOMBSTONE,
536 .node = WREPL_NODE_B,
538 .num_ips = ARRAY_SIZE(addresses_A_1),
539 .ips = addresses_A_1,
543 if (!ctx) return False;
545 name.name = "_SAME_OWNER_A";
549 wins_name_tmp = NULL;
550 wins_name_last = &wins_name2;
551 wins_name_cur = &wins_name1;
553 for (j=0; ret && j < ARRAY_SIZE(types); j++) {
554 name.type = types[j];
555 printf("Test Replica Conflicts with same owner[%s] for %s\n",
556 nbt_name_string(ctx, &name), ctx->a.address);
558 for(i=0; ret && i < ARRAY_SIZE(records); i++) {
559 wins_name_tmp = wins_name_last;
560 wins_name_last = wins_name_cur;
561 wins_name_cur = wins_name_tmp;
563 wins_name_cur->name = &name;
564 wins_name_cur->flags = WREPL_NAME_FLAGS(records[i].type,
567 records[i].is_static);
568 wins_name_cur->id = ++ctx->a.max_version;
569 if (wins_name_cur->flags & 2) {
570 wins_name_cur->addresses.addresses.num_ips = records[i].num_ips;
571 wins_name_cur->addresses.addresses.ips = discard_const(records[i].ips);
573 wins_name_cur->addresses.ip = records[i].ips[0].ip;
575 wins_name_cur->unknown = "255.255.255.255";
577 ret &= test_wrepl_update_one(ctx, &ctx->a,wins_name_cur);
578 ret &= test_wrepl_is_applied(ctx, &ctx->a, wins_name_cur, True);
584 static BOOL test_conflict_different_owner(struct test_wrepl_conflict_conn *ctx)
587 struct wrepl_wins_name wins_name1;
588 struct wrepl_wins_name wins_name2;
589 struct wrepl_wins_name *wins_name_r1;
590 struct wrepl_wins_name *wins_name_r2;
593 struct nbt_name name;
595 struct wrepl_wins_owner *owner;
596 enum wrepl_name_type type;
597 enum wrepl_name_state state;
598 enum wrepl_name_node node;
601 const struct wrepl_ip *ips;
606 * NOTE: the first record and the last applied one
607 * needs to be from the same owner,
608 * to not conflict in the next smbtorture run!!!
612 * unique,active vs. unique,active the same ip
613 * => should be replaced
616 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
619 .type = WREPL_TYPE_UNIQUE,
620 .state = WREPL_STATE_ACTIVE,
621 .node = WREPL_NODE_B,
623 .num_ips = ARRAY_SIZE(addresses_A_1),
624 .ips = addresses_A_1,
625 .apply_expected = True
629 .type = WREPL_TYPE_UNIQUE,
630 .state = WREPL_STATE_ACTIVE,
631 .node = WREPL_NODE_B,
633 .num_ips = ARRAY_SIZE(addresses_A_1),
634 .ips = addresses_A_1,
635 .apply_expected = True
640 * unique,active vs. unique,tombstone the same ips
641 * => should NOT be replaced
644 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
647 .type = WREPL_TYPE_UNIQUE,
648 .state = WREPL_STATE_ACTIVE,
649 .node = WREPL_NODE_B,
651 .num_ips = ARRAY_SIZE(addresses_B_1),
652 .ips = addresses_B_1,
653 .apply_expected = True
657 .type = WREPL_TYPE_UNIQUE,
658 .state = WREPL_STATE_TOMBSTONE,
659 .node = WREPL_NODE_B,
661 .num_ips = ARRAY_SIZE(addresses_B_1),
662 .ips = addresses_B_1,
663 .apply_expected = False
668 * unique,tombstone vs. unique,active the same ips
669 * => should NOT be replaced
672 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
675 .type = WREPL_TYPE_UNIQUE,
676 .state = WREPL_STATE_TOMBSTONE,
677 .node = WREPL_NODE_B,
679 .num_ips = ARRAY_SIZE(addresses_B_1),
680 .ips = addresses_B_1,
681 .apply_expected = True
685 .type = WREPL_TYPE_UNIQUE,
686 .state = WREPL_STATE_ACTIVE,
687 .node = WREPL_NODE_B,
689 .num_ips = ARRAY_SIZE(addresses_B_1),
690 .ips = addresses_B_1,
691 .apply_expected = True
696 * unique,tombstone vs. unique,tombstone the same ips
697 * => should be replaced
700 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
703 .type = WREPL_TYPE_UNIQUE,
704 .state = WREPL_STATE_TOMBSTONE,
705 .node = WREPL_NODE_B,
707 .num_ips = ARRAY_SIZE(addresses_A_1),
708 .ips = addresses_A_1,
709 .apply_expected = True
713 .type = WREPL_TYPE_UNIQUE,
714 .state = WREPL_STATE_TOMBSTONE,
715 .node = WREPL_NODE_B,
717 .num_ips = ARRAY_SIZE(addresses_A_1),
718 .ips = addresses_A_1,
719 .apply_expected = True
724 * unique,active vs. unique,active the different ips
725 * => should be replaced
728 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
731 .type = WREPL_TYPE_UNIQUE,
732 .state = WREPL_STATE_ACTIVE,
733 .node = WREPL_NODE_B,
735 .num_ips = ARRAY_SIZE(addresses_A_1),
736 .ips = addresses_A_1,
737 .apply_expected = True
741 .type = WREPL_TYPE_UNIQUE,
742 .state = WREPL_STATE_ACTIVE,
743 .node = WREPL_NODE_B,
745 .num_ips = ARRAY_SIZE(addresses_B_1),
746 .ips = addresses_B_1,
747 .apply_expected = True
752 * unique,active vs. unique,tombstone the different ips
753 * => should NOT be replaced
756 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
759 .type = WREPL_TYPE_UNIQUE,
760 .state = WREPL_STATE_ACTIVE,
761 .node = WREPL_NODE_B,
763 .num_ips = ARRAY_SIZE(addresses_B_1),
764 .ips = addresses_B_1,
765 .apply_expected = True
769 .type = WREPL_TYPE_UNIQUE,
770 .state = WREPL_STATE_TOMBSTONE,
771 .node = WREPL_NODE_B,
773 .num_ips = ARRAY_SIZE(addresses_A_1),
774 .ips = addresses_A_1,
775 .apply_expected = False
780 * unique,tombstone vs. unique,active the different ips
781 * => should be replaced
784 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
787 .type = WREPL_TYPE_UNIQUE,
788 .state = WREPL_STATE_TOMBSTONE,
789 .node = WREPL_NODE_B,
791 .num_ips = ARRAY_SIZE(addresses_B_1),
792 .ips = addresses_B_1,
793 .apply_expected = True
797 .type = WREPL_TYPE_UNIQUE,
798 .state = WREPL_STATE_ACTIVE,
799 .node = WREPL_NODE_B,
801 .num_ips = ARRAY_SIZE(addresses_A_1),
802 .ips = addresses_A_1,
803 .apply_expected = True
808 * unique,tombstone vs. unique,tombstone the different ips
809 * => should be replaced
812 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
815 .type = WREPL_TYPE_UNIQUE,
816 .state = WREPL_STATE_TOMBSTONE,
817 .node = WREPL_NODE_B,
819 .num_ips = ARRAY_SIZE(addresses_A_1),
820 .ips = addresses_A_1,
821 .apply_expected = True
825 .type = WREPL_TYPE_UNIQUE,
826 .state = WREPL_STATE_TOMBSTONE,
827 .node = WREPL_NODE_B,
829 .num_ips = ARRAY_SIZE(addresses_B_1),
830 .ips = addresses_B_1,
831 .apply_expected = True
836 * This should be the last record in this array,
837 * we need to make sure the we leave a tombstoned unique entry
841 .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
844 .type = WREPL_TYPE_UNIQUE,
845 .state = WREPL_STATE_TOMBSTONE,
846 .node = WREPL_NODE_B,
848 .num_ips = ARRAY_SIZE(addresses_A_1),
849 .ips = addresses_A_1,
850 .apply_expected = True
854 .type = WREPL_TYPE_UNIQUE,
855 .state = WREPL_STATE_TOMBSTONE,
856 .node = WREPL_NODE_B,
858 .num_ips = ARRAY_SIZE(addresses_A_1),
859 .ips = addresses_A_1,
860 .apply_expected = True
862 }}; /* do not add entries here, this should be the last record! */
864 if (!ctx) return False;
866 wins_name_r1 = &wins_name1;
867 wins_name_r2 = &wins_name2;
869 for(i=0; ret && i < ARRAY_SIZE(records); i++) {
874 wins_name_r1->name = &records[i].name;
875 wins_name_r1->flags = WREPL_NAME_FLAGS(records[i].r1.type,
878 records[i].r1.is_static);
879 wins_name_r1->id = ++records[i].r1.owner->max_version;
880 if (wins_name_r1->flags & 2) {
881 wins_name_r1->addresses.addresses.num_ips = records[i].r1.num_ips;
882 wins_name_r1->addresses.addresses.ips = discard_const(records[i].r1.ips);
884 wins_name_r1->addresses.ip = records[i].r1.ips[0].ip;
886 wins_name_r1->unknown = "255.255.255.255";
889 ret &= test_wrepl_update_one(ctx, records[i].r1.owner, wins_name_r1);
890 ret &= test_wrepl_is_applied(ctx, records[i].r1.owner,
891 wins_name_r1, records[i].r1.apply_expected);
896 wins_name_r2->name = &records[i].name;
897 wins_name_r2->flags = WREPL_NAME_FLAGS(records[i].r2.type,
900 records[i].r2.is_static);
901 wins_name_r2->id = ++records[i].r2.owner->max_version;
902 if (wins_name_r2->flags & 2) {
903 wins_name_r2->addresses.addresses.num_ips = records[i].r2.num_ips;
904 wins_name_r2->addresses.addresses.ips = discard_const(records[i].r2.ips);
906 wins_name_r2->addresses.ip = records[i].r2.ips[0].ip;
908 wins_name_r2->unknown = "255.255.255.255";
911 ret &= test_wrepl_update_one(ctx, records[i].r2.owner, wins_name_r2);
912 ret &= test_wrepl_is_applied(ctx, records[i].r2.owner,
913 wins_name_r2, records[i].r2.apply_expected);
916 printf("%s: failed with index: %u\n", __location__, i);
925 test WINS replication operations
927 BOOL torture_nbt_winsreplication(void)
930 struct nbt_name name;
931 TALLOC_CTX *mem_ctx = talloc_new(NULL);
934 struct test_wrepl_conflict_conn *ctx;
936 make_nbt_name_server(&name, lp_parm_string(-1, "torture", "host"));
938 /* do an initial name resolution to find its IP */
939 status = resolve_name(&name, mem_ctx, &address, NULL);
940 if (!NT_STATUS_IS_OK(status)) {
941 printf("Failed to resolve %s - %s\n",
942 name.name, nt_errstr(status));
943 talloc_free(mem_ctx);
947 ret &= test_assoc_ctx1(mem_ctx, address);
948 ret &= test_assoc_ctx2(mem_ctx, address);
950 ret &= test_wins_replication(mem_ctx, address);
952 ctx = test_create_conflict_ctx(mem_ctx, address);
954 ret &= test_conflict_same_owner(ctx);
955 ret &= test_conflict_different_owner(ctx);
957 talloc_free(mem_ctx);