summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/torture/nbt/winsreplication.c613
1 files changed, 563 insertions, 50 deletions
diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c
index d66be53f5f..94053408eb 100644
--- a/source4/torture/nbt/winsreplication.c
+++ b/source4/torture/nbt/winsreplication.c
@@ -331,15 +331,24 @@ struct test_wrepl_conflict_conn {
struct wrepl_wins_owner a, b, c;
const char *myaddr;
+ const char *myaddr2;
struct nbt_name_socket *nbtsock;
+ struct nbt_name_socket *nbtsock2;
struct nbt_name_socket *nbtsock_srv;
+ struct nbt_name_socket *nbtsock_srv2;
uint32_t addresses_best_num;
struct wrepl_ip *addresses_best;
+ uint32_t addresses_best2_num;
+ struct wrepl_ip *addresses_best2;
+
uint32_t addresses_all_num;
struct wrepl_ip *addresses_all;
+
+ uint32_t addresses_mhomed_num;
+ struct wrepl_ip *addresses_mhomed;
};
static const struct wrepl_ip addresses_A_1[] = {
@@ -452,6 +461,13 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *mem
ctx->myaddr = talloc_strdup(mem_ctx, iface_best_ip(address));
if (!ctx->myaddr) return NULL;
+ for (i = 0; i < iface_count(); i++) {
+ if (strcmp(ctx->myaddr, iface_n_ip(i)) == 0) continue;
+ ctx->myaddr2 = talloc_strdup(mem_ctx, iface_n_ip(i));
+ if (!ctx->myaddr2) return NULL;
+ break;
+ }
+
ctx->nbtsock = nbt_name_socket_init(ctx, NULL);
if (!ctx->nbtsock) return NULL;
@@ -467,21 +483,54 @@ static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *mem
ctx->nbtsock_srv = NULL;
}
+ if (ctx->myaddr2) {
+ ctx->nbtsock2 = nbt_name_socket_init(ctx, NULL);
+ if (!ctx->nbtsock2) return NULL;
+
+ status = socket_listen(ctx->nbtsock2->sock, ctx->myaddr2, 0, 0, 0);
+ if (!NT_STATUS_IS_OK(status)) return NULL;
+
+ ctx->nbtsock_srv2 = nbt_name_socket_init(ctx, ctx->nbtsock_srv->event_ctx);
+ if (!ctx->nbtsock_srv2) return NULL;
+
+ status = socket_listen(ctx->nbtsock_srv2->sock, ctx->myaddr2, lp_nbt_port(), 0, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(ctx->nbtsock_srv2);
+ ctx->nbtsock_srv2 = NULL;
+ }
+ }
+
ctx->addresses_best_num = 1;
ctx->addresses_best = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best_num);
if (!ctx->addresses_best) return NULL;
- ctx->addresses_best[0].owner = ctx->c.address;
+ ctx->addresses_best[0].owner = ctx->b.address;
ctx->addresses_best[0].ip = ctx->myaddr;
ctx->addresses_all_num = iface_count();
ctx->addresses_all = talloc_array(ctx, struct wrepl_ip, ctx->addresses_all_num);
if (!ctx->addresses_all) return NULL;
for (i=0; i < ctx->addresses_all_num; i++) {
- ctx->addresses_all[i].owner = ctx->c.address;
+ ctx->addresses_all[i].owner = ctx->b.address;
ctx->addresses_all[i].ip = talloc_strdup(ctx->addresses_all, iface_n_ip(i));
if (!ctx->addresses_all[i].ip) return NULL;
}
+ if (ctx->nbtsock_srv2) {
+ ctx->addresses_best2_num = 1;
+ ctx->addresses_best2 = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best2_num);
+ if (!ctx->addresses_best2) return NULL;
+ ctx->addresses_best2[0].owner = ctx->b.address;
+ ctx->addresses_best2[0].ip = ctx->myaddr2;
+
+ ctx->addresses_mhomed_num = 2;
+ ctx->addresses_mhomed = talloc_array(ctx, struct wrepl_ip, ctx->addresses_mhomed_num);
+ if (!ctx->addresses_mhomed) return NULL;
+ ctx->addresses_mhomed[0].owner = ctx->b.address;
+ ctx->addresses_mhomed[0].ip = ctx->myaddr;
+ ctx->addresses_mhomed[1].owner = ctx->b.address;
+ ctx->addresses_mhomed[1].ip = ctx->myaddr2;
+ }
+
return ctx;
}
@@ -674,6 +723,84 @@ done:
return ret;
}
+static BOOL test_wrepl_mhomed_merged(struct test_wrepl_conflict_conn *ctx,
+ const struct wrepl_wins_owner *owner1,
+ uint32_t num_ips1, const struct wrepl_ip *ips1,
+ const struct wrepl_wins_owner *owner2,
+ uint32_t num_ips2, const struct wrepl_ip *ips2,
+ const struct wrepl_wins_name *name2)
+{
+ BOOL ret = True;
+ NTSTATUS status;
+ struct wrepl_pull_names pull_names;
+ struct wrepl_name *names;
+ uint32_t flags;
+ uint32_t i, j;
+ uint32_t num_ips = num_ips1 + num_ips2;
+
+ for (i = 0; i < num_ips2; i++) {
+ for (j = 0; j < num_ips1; j++) {
+ if (strcmp(ips2[i].ip,ips1[j].ip) == 0) {
+ num_ips--;
+ break;
+ }
+ }
+ }
+
+ pull_names.in.assoc_ctx = ctx->pull_assoc;
+ pull_names.in.partner = *owner2;
+ 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);
+
+ names = pull_names.out.names;
+
+ flags = WREPL_NAME_FLAGS(names[0].type,
+ names[0].state,
+ names[0].node,
+ names[0].is_static);
+ CHECK_VALUE(names[0].name.type, name2->name->type);
+ CHECK_VALUE_STRING(names[0].name.name, name2->name->name);
+ CHECK_VALUE_STRING(names[0].name.scope, name2->name->scope);
+ CHECK_VALUE(flags, name2->flags | WREPL_TYPE_MHOMED);
+ CHECK_VALUE_UINT64(names[0].version_id, name2->id);
+
+ CHECK_VALUE(names[0].num_addresses, num_ips);
+
+ for (i = 0; i < names[0].num_addresses; i++) {
+ const char *addr = names[0].addresses[i].address;
+ const char *owner = names[0].addresses[i].owner;
+ BOOL found = False;
+
+ for (j = 0; j < num_ips2; j++) {
+ if (strcmp(addr, ips2[j].ip) == 0) {
+ found = True;
+ CHECK_VALUE_STRING(owner, owner2->address);
+ break;
+ }
+ }
+
+ if (found) continue;
+
+ for (j = 0; j < num_ips1; j++) {
+ if (strcmp(addr, ips1[j].ip) == 0) {
+ found = True;
+ CHECK_VALUE_STRING(owner, owner1->address);
+ break;
+ }
+ }
+
+ if (found) continue;
+
+ CHECK_VALUE_STRING(addr, "not found in address list");
+ }
+done:
+ talloc_free(pull_names.out.names);
+ return ret;
+}
+
static BOOL test_wrepl_is_merged(struct test_wrepl_conflict_conn *ctx,
const struct wrepl_wins_name *name1,
const struct wrepl_wins_name *name2)
@@ -5518,7 +5645,9 @@ done:
struct test_conflict_owned_active_vs_replica_struct {
const char *line; /* just better debugging */
+ const char *section; /* just better debugging */
struct nbt_name name;
+ BOOL skip;
struct {
uint32_t nb_flags;
BOOL mhomed;
@@ -5543,6 +5672,7 @@ struct test_conflict_owned_active_vs_replica_struct {
uint32_t num_ips;
const struct wrepl_ip *ips;
BOOL apply_expected;
+ BOOL mhomed_merge;
} replica;
};
@@ -7455,6 +7585,306 @@ static BOOL test_conflict_owned_active_vs_replica(struct test_wrepl_conflict_con
.apply_expected = False
},
},
+/*
+ * some more multi homed test, including merging
+ */
+ /*
+ * mhomed,active vs. mhomed,active with superset ip(s), unchecked
+ */
+ {
+ .line = __location__,
+ .section= "Test Replica vs. owned active: some more MHOMED combinations",
+ .name = _NBT_NAME("_MA_MA_SP_U", 0x00, NULL),
+ .skip = (ctx->addresses_all_num < 3),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 0,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_all_num,
+ .ips = ctx->addresses_all,
+ .apply_expected = True
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with same ips, unchecked
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SM_U", 0x00, NULL),
+ .skip = (ctx->addresses_mhomed_num != 2),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 0,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with subset ip(s), positive response
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SB_P", 0x00, NULL),
+ .skip = (ctx->addresses_mhomed_num != 2),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .mhomed_merge = True
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with subset ip(s), positive response, with all addresses
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SB_A", 0x00, NULL),
+ .skip = (ctx->addresses_all_num < 3),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ .num_ips = ctx->addresses_all_num,
+ .ips = ctx->addresses_all,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .mhomed_merge = True
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with subset ip(s), positive response, with replicas addresses
+ * TODO: here we got a release demand for the replica address from the server after doing
+ * a positive response with the replicas addresses
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SB_C", 0x00, NULL),
+ .skip = (True /*ctx->addresses_all_num < 3*/),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .apply_expected = False
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with subset ip(s), positive response, with other addresses
+ * TODO: here the record is not applied and the old record becomes released
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SB_O", 0x00, NULL),
+
+ .skip = (True /*ctx->addresses_all_num < 3*/),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ .num_ips = ARRAY_SIZE(addresses_B_3_4),
+ .ips = addresses_B_3_4,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .apply_expected = False
+ },
+ },
+ /*
+ * mhomed,active vs. mhomed,active with subset ip(s), negative response
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_MA_MA_SB_N", 0x00, NULL),
+ .skip = (ctx->addresses_mhomed_num != 2),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = False
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .apply_expected = True
+ },
+ },
+/*
+ * some more multi homed and unique test, including merging
+ */
+ /*
+ * mhomed,active vs. unique,active with subset ip(s), positive response
+ */
+ {
+ .line = __location__,
+ .section= "Test Replica vs. owned active: some more UNIQUE,MHOMED combinations",
+ .name = _NBT_NAME("_MA_UA_SB_A", 0x00, NULL),
+ .skip = (ctx->addresses_all_num < 3),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = True,
+ .num_ips = ctx->addresses_mhomed_num,
+ .ips = ctx->addresses_mhomed,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ },
+ .replica= {
+ .type = WREPL_TYPE_UNIQUE,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .mhomed_merge = True
+ },
+ },
+ /*
+ * unique,active vs. unique,active with different ip(s), positive response, with all addresses
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_UA_UA_DI_A", 0x00, NULL),
+ .skip = (ctx->addresses_all_num < 3),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ .num_ips = ctx->addresses_all_num,
+ .ips = ctx->addresses_all,
+ },
+ .replica= {
+ .type = WREPL_TYPE_UNIQUE,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best2_num,
+ .ips = ctx->addresses_best2,
+ .mhomed_merge = True,
+ },
+ },
+ /*
+ * unique,active vs. mhomed,active with different ip(s), positive response, with all addresses
+ */
+ {
+ .line = __location__,
+ .name = _NBT_NAME("_UA_MA_DI_A", 0x00, NULL),
+ .skip = (ctx->addresses_all_num < 3),
+ .wins = {
+ .nb_flags = 0,
+ .mhomed = False,
+ .num_ips = ctx->addresses_best_num,
+ .ips = ctx->addresses_best,
+ .apply_expected = True
+ },
+ .defend = {
+ .timeout = 10,
+ .positive = True,
+ .num_ips = ctx->addresses_all_num,
+ .ips = ctx->addresses_all,
+ },
+ .replica= {
+ .type = WREPL_TYPE_MHOMED,
+ .state = WREPL_STATE_ACTIVE,
+ .node = WREPL_NODE_B,
+ .is_static = False,
+ .num_ips = ctx->addresses_best2_num,
+ .ips = ctx->addresses_best2,
+ .mhomed_merge = True,
+ },
+ },
};
if (!ctx) return False;
@@ -7469,45 +7899,111 @@ static BOOL test_conflict_owned_active_vs_replica(struct test_wrepl_conflict_con
for(i=0; ret && i < ARRAY_SIZE(records); i++) {
struct timeval end;
+ struct test_conflict_owned_active_vs_replica_struct record = records[i];
+ uint32_t j, count = 1;
+ const char *action;
- printf("%s => %s\n", nbt_name_string(ctx, &records[i].name),
- (records[i].replica.apply_expected?"REPLACE":"NOT REPLACE"));
+ if (records[i].wins.mhomed) {
+ count = records[i].wins.num_ips;
+ }
- /* Prepare for the current test */
+ if (records[i].section) {
+ printf("%s\n", records[i].section);
+ }
+
+ if (records[i].skip) {
+ printf("%s => SKIPPED\n", nbt_name_string(ctx, &records[i].name));
+ continue;
+ }
+
+ if (records[i].replica.mhomed_merge) {
+ action = "MHOMED_MERGE";
+ } else if (records[i].replica.apply_expected) {
+ action = "REPLACE";
+ } else {
+ action = "NOT REPLACE";
+ }
+
+ printf("%s => %s\n", nbt_name_string(ctx, &records[i].name), action);
+
+ /* Prepare for multi homed registration */
+ ZERO_STRUCT(records[i].defend);
+ records[i].defend.timeout = 10;
+ records[i].defend.positive = True;
nbt_set_incoming_handler(ctx->nbtsock_srv,
test_conflict_owned_active_vs_replica_handler,
&records[i]);
+ if (ctx->nbtsock_srv2) {
+ nbt_set_incoming_handler(ctx->nbtsock_srv2,
+ test_conflict_owned_active_vs_replica_handler,
+ &records[i]);
+ }
/*
* Setup Register
*/
- name_register->in.name = records[i].name;
- name_register->in.dest_addr = ctx->address;
- name_register->in.address = records[i].wins.ips[0].ip;
- name_register->in.nb_flags = records[i].wins.nb_flags;
- name_register->in.register_demand= False;
- name_register->in.broadcast = False;
- name_register->in.multi_homed = records[i].wins.mhomed;
- name_register->in.ttl = 300000;
- name_register->in.timeout = 70;
- name_register->in.retries = 0;
+ for (j=0; j < count; j++) {
+ struct nbt_name_request *req;
+
+ name_register->in.name = records[i].name;
+ name_register->in.dest_addr = ctx->address;
+ name_register->in.address = records[i].wins.ips[j].ip;
+ name_register->in.nb_flags = records[i].wins.nb_flags;
+ name_register->in.register_demand= False;
+ name_register->in.broadcast = False;
+ name_register->in.multi_homed = records[i].wins.mhomed;
+ name_register->in.ttl = 300000;
+ name_register->in.timeout = 70;
+ name_register->in.retries = 0;
+
+ req = nbt_name_register_send(ctx->nbtsock, name_register);
+
+ /* push the request on the wire */
+ event_loop_once(ctx->nbtsock->event_ctx);
+
+ /*
+ * if we register multiple addresses,
+ * the server will do name queries to see if the old addresses
+ * are still alive
+ */
+ if (j > 0) {
+ end = timeval_current_ofs(records[i].defend.timeout,0);
+ records[i].defend.ret = True;
+ while (records[i].defend.timeout > 0) {
+ event_loop_once(ctx->nbtsock_srv->event_ctx);
+ if (timeval_expired(&end)) break;
+ }
+ ret &= records[i].defend.ret;
+ }
- status = nbt_name_register(ctx->nbtsock, ctx, name_register);
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
- printf("No response from %s for name register\n", ctx->address);
- ret = False;
+ status = nbt_name_register_recv(req, ctx, name_register);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ printf("No response from %s for name register\n", ctx->address);
+ ret = False;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Bad response from %s for name register - %s\n",
+ ctx->address, nt_errstr(status));
+ ret = False;
+ }
+ CHECK_VALUE(name_register->out.rcode, 0);
+ CHECK_VALUE_STRING(name_register->out.reply_from, ctx->address);
+ CHECK_VALUE(name_register->out.name.type, records[i].name.type);
+ CHECK_VALUE_STRING(name_register->out.name.name, records[i].name.name);
+ CHECK_VALUE_STRING(name_register->out.name.scope, records[i].name.scope);
+ CHECK_VALUE_STRING(name_register->out.reply_addr, records[i].wins.ips[j].ip);
}
- if (!NT_STATUS_IS_OK(status)) {
- printf("Bad response from %s for name register - %s\n",
- ctx->address, nt_errstr(status));
- ret = False;
+
+ /* Prepare for the current test */
+ records[i].defend = record.defend;
+ nbt_set_incoming_handler(ctx->nbtsock_srv,
+ test_conflict_owned_active_vs_replica_handler,
+ &records[i]);
+ if (ctx->nbtsock_srv2) {
+ nbt_set_incoming_handler(ctx->nbtsock_srv2,
+ test_conflict_owned_active_vs_replica_handler,
+ &records[i]);
}
- CHECK_VALUE(name_register->out.rcode, 0);
- CHECK_VALUE_STRING(name_register->out.reply_from, ctx->address);
- CHECK_VALUE(name_register->out.name.type, records[i].name.type);
- CHECK_VALUE_STRING(name_register->out.name.name, records[i].name.name);
- CHECK_VALUE_STRING(name_register->out.name.scope, records[i].name.scope);
- CHECK_VALUE_STRING(name_register->out.reply_addr, records[i].wins.ips[0].ip);
/*
* Setup Replica
@@ -7540,10 +8036,19 @@ static BOOL test_conflict_owned_active_vs_replica(struct test_wrepl_conflict_con
}
ret &= records[i].defend.ret;
- ret &= test_wrepl_is_applied(ctx, &ctx->b, wins_name,
- records[i].replica.apply_expected);
+ if (records[i].replica.mhomed_merge) {
+ ret &= test_wrepl_mhomed_merged(ctx, &ctx->c,
+ records[i].wins.num_ips, records[i].wins.ips,
+ &ctx->b,
+ records[i].replica.num_ips, records[i].replica.ips,
+ wins_name);
+ } else {
+ ret &= test_wrepl_is_applied(ctx, &ctx->b, wins_name,
+ records[i].replica.apply_expected);
+ }
- if (records[i].replica.apply_expected) {
+ if (records[i].replica.apply_expected ||
+ records[i].replica.mhomed_merge) {
wins_name->name = &records[i].name;
wins_name->flags = WREPL_NAME_FLAGS(WREPL_TYPE_UNIQUE,
WREPL_STATE_TOMBSTONE,
@@ -7555,25 +8060,33 @@ static BOOL test_conflict_owned_active_vs_replica(struct test_wrepl_conflict_con
ret &= test_wrepl_update_one(ctx, &ctx->b, wins_name);
ret &= test_wrepl_is_applied(ctx, &ctx->b, wins_name, True);
} else {
- release->in.name = records[i].name;
- release->in.dest_addr = ctx->address;
- release->in.address = records[i].wins.ips[0].ip;
- release->in.nb_flags = records[i].wins.nb_flags;
- release->in.broadcast = False;
- release->in.timeout = 30;
- release->in.retries = 0;
-
- status = nbt_name_release(ctx->nbtsock, ctx, release);
- if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
- printf("No response from %s for name release\n", ctx->address);
- return False;
+ for (j=0; j < count; j++) {
+ struct nbt_name_socket *nbtsock = ctx->nbtsock;
+
+ if (ctx->myaddr && strcmp(records[i].wins.ips[j].ip, ctx->myaddr2) == 0) {
+ nbtsock = ctx->nbtsock2;
+ }
+
+ release->in.name = records[i].name;
+ release->in.dest_addr = ctx->address;
+ release->in.address = records[i].wins.ips[j].ip;
+ release->in.nb_flags = records[i].wins.nb_flags;
+ release->in.broadcast = False;
+ release->in.timeout = 30;
+ release->in.retries = 0;
+
+ status = nbt_name_release(nbtsock, ctx, release);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ printf("No response from %s for name release\n", ctx->address);
+ return False;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Bad response from %s for name query - %s\n",
+ ctx->address, nt_errstr(status));
+ return False;
+ }
+ CHECK_VALUE(release->out.rcode, 0);
}
- if (!NT_STATUS_IS_OK(status)) {
- printf("Bad response from %s for name query - %s\n",
- ctx->address, nt_errstr(status));
- return False;
- }
- CHECK_VALUE(release->out.rcode, 0);
}
done: