diff options
-rw-r--r-- | source4/torture/nbt/winsreplication.c | 400 |
1 files changed, 388 insertions, 12 deletions
diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index eb9f7038b0..87c7b13e85 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -40,6 +40,12 @@ goto done; \ }} while (0) +#define _NBT_NAME(n,t,s) {\ + .name = n,\ + .type = t,\ + .scope = s\ +} + /* test how assoc_ctx's are only usable on the connection they are created on. @@ -295,6 +301,19 @@ static const struct wrepl_ip addresses_A_2[] = { } }; +static const struct wrepl_ip addresses_B_1[] = { + { + .owner = TEST_OWNER_B_ADDRESS, + .ip = TEST_ADDRESS_B_PREFIX".1" + } +}; +static const struct wrepl_ip addresses_B_2[] = { + { + .owner = TEST_OWNER_B_ADDRESS, + .ip = TEST_ADDRESS_B_PREFIX".2" + } +}; + static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *mem_ctx, const char *address) { @@ -350,8 +369,9 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *mem return ctx; } -static BOOL test_wrepl_update_one_A(struct test_wrepl_conflict_conn *ctx, - const struct wrepl_wins_name *name) +static BOOL test_wrepl_update_one(struct test_wrepl_conflict_conn *ctx, + const struct wrepl_wins_owner *owner, + const struct wrepl_wins_name *name) { BOOL ret = True; struct wrepl_socket *wrepl_socket; @@ -387,7 +407,7 @@ static BOOL test_wrepl_update_one_A(struct test_wrepl_conflict_conn *ctx, update->partners = wrepl_wins_owners; update->initiator = "0.0.0.0"; - wrepl_wins_owners[0] = ctx->a; + wrepl_wins_owners[0] = *owner; status = wrepl_request(wrepl_socket, wrepl_socket, &update_packet, &repl_recv); @@ -419,21 +439,22 @@ done: return ret; } -static BOOL test_wrepl_is_applied_A(struct test_wrepl_conflict_conn *ctx, - const struct wrepl_wins_name *name) +static BOOL test_wrepl_is_applied(struct test_wrepl_conflict_conn *ctx, + const struct wrepl_wins_owner *owner, + const struct wrepl_wins_name *name, + BOOL expected) { BOOL ret = True; NTSTATUS status; struct wrepl_pull_names pull_names; - ctx->a.min_version = ctx->a.max_version; - pull_names.in.assoc_ctx = ctx->pull_assoc; - pull_names.in.partner = ctx->a; + pull_names.in.partner = *owner; + pull_names.in.partner.min_version = pull_names.in.partner.max_version; status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names); CHECK_STATUS(status, NT_STATUS_OK); - CHECK_VALUE(pull_names.out.num_names, 1); + CHECK_VALUE(pull_names.out.num_names, (expected?1:0)); done: talloc_free(pull_names.out.names); @@ -481,6 +502,20 @@ static BOOL test_conflict_same_owner(struct test_wrepl_conflict_conn *ctx) .num_ips = ARRAY_SIZE(addresses_A_2), .ips = addresses_A_2, },{ + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = True, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + },{ + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_2), + .ips = addresses_A_2, + },{ .type = WREPL_TYPE_SGROUP, .state = WREPL_STATE_TOMBSTONE, .node = WREPL_NODE_B, @@ -495,7 +530,7 @@ static BOOL test_conflict_same_owner(struct test_wrepl_conflict_conn *ctx) .num_ips = ARRAY_SIZE(addresses_A_1), .ips = addresses_A_1, },{ - /* the last one should always be a tomstone record! */ + /* the last one should always be a unique,tomstone record! */ .type = WREPL_TYPE_UNIQUE, .state = WREPL_STATE_TOMBSTONE, .node = WREPL_NODE_B, @@ -539,13 +574,353 @@ static BOOL test_conflict_same_owner(struct test_wrepl_conflict_conn *ctx) } wins_name_cur->unknown = "255.255.255.255"; - ret &= test_wrepl_update_one_A(ctx, wins_name_cur); - ret &= test_wrepl_is_applied_A(ctx, wins_name_cur); + ret &= test_wrepl_update_one(ctx, &ctx->a,wins_name_cur); + ret &= test_wrepl_is_applied(ctx, &ctx->a, wins_name_cur, True); } } return ret; } +static BOOL test_conflict_different_owner(struct test_wrepl_conflict_conn *ctx) +{ + BOOL ret = True; + struct wrepl_wins_name wins_name1; + struct wrepl_wins_name wins_name2; + struct wrepl_wins_name *wins_name_r1; + struct wrepl_wins_name *wins_name_r2; + uint32_t i; + struct { + struct nbt_name name; + struct { + struct wrepl_wins_owner *owner; + enum wrepl_name_type type; + enum wrepl_name_state state; + enum wrepl_name_node node; + BOOL is_static; + uint32_t num_ips; + const struct wrepl_ip *ips; + BOOL apply_expected; + } r1, r2; + } records[] = { + /* + * NOTE: the first record and the last applied one + * needs to be from the same owner, + * to not conflict in the next smbtorture run!!! + */ + + /* + * unique,active vs. unique,active the same ip + * => should be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + } + }, + + /* + * unique,active vs. unique,tombstone the same ips + * => should NOT be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = False + } + }, + + /* + * unique,tombstone vs. unique,active the same ips + * => should NOT be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + } + }, + + /* + * unique,tombstone vs. unique,tombstone the same ips + * => should be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + } + }, + + /* + * unique,active vs. unique,active the different ips + * => should be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + } + }, + + /* + * unique,active vs. unique,tombstone the different ips + * => should NOT be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = False + } + }, + + /* + * unique,tombstone vs. unique,active the different ips + * => should be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + } + }, + + /* + * unique,tombstone vs. unique,tombstone the different ips + * => should be replaced + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_1), + .ips = addresses_B_1, + .apply_expected = True + } + }, + + /* + * This should be the last record in this array, + * we need to make sure the we leave a tombstoned unique entry + * owned by OWNER_A + */ + { + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + }, + .r2 = { + .owner = &ctx->a, + .type = WREPL_TYPE_UNIQUE, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_1), + .ips = addresses_A_1, + .apply_expected = True + } + }}; /* do not add entries here, this should be the last record! */ + + if (!ctx) return False; + + wins_name_r1 = &wins_name1; + wins_name_r2 = &wins_name2; + + for(i=0; ret && i < ARRAY_SIZE(records); i++) { + + /* + * Setup R1 + */ + wins_name_r1->name = &records[i].name; + wins_name_r1->flags = WREPL_NAME_FLAGS(records[i].r1.type, + records[i].r1.state, + records[i].r1.node, + records[i].r1.is_static); + wins_name_r1->id = ++records[i].r1.owner->max_version; + if (wins_name_r1->flags & 2) { + wins_name_r1->addresses.addresses.num_ips = records[i].r1.num_ips; + wins_name_r1->addresses.addresses.ips = discard_const(records[i].r1.ips); + } else { + wins_name_r1->addresses.ip = records[i].r1.ips[0].ip; + } + wins_name_r1->unknown = "255.255.255.255"; + + /* now apply R1 */ + ret &= test_wrepl_update_one(ctx, records[i].r1.owner, wins_name_r1); + ret &= test_wrepl_is_applied(ctx, records[i].r1.owner, + wins_name_r1, records[i].r1.apply_expected); + + /* + * Setup R2 + */ + wins_name_r2->name = &records[i].name; + wins_name_r2->flags = WREPL_NAME_FLAGS(records[i].r2.type, + records[i].r2.state, + records[i].r2.node, + records[i].r2.is_static); + wins_name_r2->id = ++records[i].r2.owner->max_version; + if (wins_name_r2->flags & 2) { + wins_name_r2->addresses.addresses.num_ips = records[i].r2.num_ips; + wins_name_r2->addresses.addresses.ips = discard_const(records[i].r2.ips); + } else { + wins_name_r2->addresses.ip = records[i].r2.ips[0].ip; + } + wins_name_r2->unknown = "255.255.255.255"; + + /* now apply R2 */ + ret &= test_wrepl_update_one(ctx, records[i].r2.owner, wins_name_r2); + ret &= test_wrepl_is_applied(ctx, records[i].r2.owner, + wins_name_r2, records[i].r2.apply_expected); + + if (!ret) { + printf("%s: failed with index: %u\n", __location__, i); + return ret; + } + } + + return ret; +} + /* test WINS replication operations */ @@ -577,6 +952,7 @@ BOOL torture_nbt_winsreplication(void) ctx = test_create_conflict_ctx(mem_ctx, address); ret &= test_conflict_same_owner(ctx); + ret &= test_conflict_different_owner(ctx); talloc_free(mem_ctx); |