📄 winsreplication.c
字号:
{ .owner = TEST_OWNER_B_ADDRESS, .ip = TEST_ADDRESS_B_PREFIX".3" }, { .owner = TEST_OWNER_B_ADDRESS, .ip = TEST_ADDRESS_B_PREFIX".4" }, { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".1" }, { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".2" }};static const struct wrepl_ip addresses_X_1_2[] = { { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".1" }, { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".2" }};static const struct wrepl_ip addresses_X_3_4[] = { { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".3" }, { .owner = TEST_OWNER_X_ADDRESS, .ip = TEST_ADDRESS_X_PREFIX".4" }};static struct test_wrepl_conflict_conn *test_create_conflict_ctx( struct torture_context *tctx, const char *address){ struct test_wrepl_conflict_conn *ctx; struct wrepl_associate associate; struct wrepl_pull_table pull_table; struct socket_address *nbt_srv_addr; NTSTATUS status; uint32_t i; struct interface *ifaces; ctx = talloc_zero(tctx, struct test_wrepl_conflict_conn); if (!ctx) return NULL; ctx->address = address; ctx->pull = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); if (!ctx->pull) return NULL; torture_comment(tctx, "Setup wrepl conflict pull connection\n"); status = wrepl_connect(ctx->pull, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, ctx->address), ctx->address); if (!NT_STATUS_IS_OK(status)) return NULL; status = wrepl_associate(ctx->pull, &associate); if (!NT_STATUS_IS_OK(status)) return NULL; ctx->pull_assoc = associate.out.assoc_ctx; ctx->a.address = TEST_OWNER_A_ADDRESS; ctx->a.max_version = 0; ctx->a.min_version = 0; ctx->a.type = 1; ctx->b.address = TEST_OWNER_B_ADDRESS; ctx->b.max_version = 0; ctx->b.min_version = 0; ctx->b.type = 1; ctx->x.address = TEST_OWNER_X_ADDRESS; ctx->x.max_version = 0; ctx->x.min_version = 0; ctx->x.type = 1; ctx->c.address = address; ctx->c.max_version = 0; ctx->c.min_version = 0; ctx->c.type = 1; pull_table.in.assoc_ctx = ctx->pull_assoc; status = wrepl_pull_table(ctx->pull, ctx->pull, &pull_table); if (!NT_STATUS_IS_OK(status)) return NULL; for (i=0; i < pull_table.out.num_partners; i++) { if (strcmp(TEST_OWNER_A_ADDRESS,pull_table.out.partners[i].address)==0) { ctx->a.max_version = pull_table.out.partners[i].max_version; ctx->a.min_version = pull_table.out.partners[i].min_version; } if (strcmp(TEST_OWNER_B_ADDRESS,pull_table.out.partners[i].address)==0) { ctx->b.max_version = pull_table.out.partners[i].max_version; ctx->b.min_version = pull_table.out.partners[i].min_version; } if (strcmp(TEST_OWNER_X_ADDRESS,pull_table.out.partners[i].address)==0) { ctx->x.max_version = pull_table.out.partners[i].max_version; ctx->x.min_version = pull_table.out.partners[i].min_version; } if (strcmp(address,pull_table.out.partners[i].address)==0) { ctx->c.max_version = pull_table.out.partners[i].max_version; ctx->c.min_version = pull_table.out.partners[i].min_version; } } talloc_free(pull_table.out.partners); ctx->nbtsock = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); if (!ctx->nbtsock) return NULL; load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces); ctx->myaddr = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_best_ip(ifaces, address), 0); if (!ctx->myaddr) return NULL; for (i = 0; i < iface_count(ifaces); i++) { if (strcmp(ctx->myaddr->addr, iface_n_ip(ifaces, i)) == 0) continue; ctx->myaddr2 = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_n_ip(ifaces, i), 0); if (!ctx->myaddr2) return NULL; break; } status = socket_listen(ctx->nbtsock->sock, ctx->myaddr, 0, 0); if (!NT_STATUS_IS_OK(status)) return NULL; ctx->nbtsock_srv = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); if (!ctx->nbtsock_srv) return NULL; /* Make a port 137 version of ctx->myaddr */ nbt_srv_addr = socket_address_from_strings(tctx, ctx->nbtsock_srv->sock->backend_name, ctx->myaddr->addr, lp_nbt_port(tctx->lp_ctx)); if (!nbt_srv_addr) return NULL; /* And if possible, bind to it. This won't work unless we are root or in sockewrapper */ status = socket_listen(ctx->nbtsock_srv->sock, nbt_srv_addr, 0, 0); talloc_free(nbt_srv_addr); if (!NT_STATUS_IS_OK(status)) { /* this isn't fatal */ talloc_free(ctx->nbtsock_srv); ctx->nbtsock_srv = NULL; } if (ctx->myaddr2 && ctx->nbtsock_srv) { ctx->nbtsock2 = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); if (!ctx->nbtsock2) return NULL; status = socket_listen(ctx->nbtsock2->sock, ctx->myaddr2, 0, 0); if (!NT_STATUS_IS_OK(status)) return NULL; ctx->nbtsock_srv2 = nbt_name_socket_init(ctx, ctx->nbtsock_srv->event_ctx, lp_iconv_convenience(tctx->lp_ctx)); if (!ctx->nbtsock_srv2) return NULL; /* Make a port 137 version of ctx->myaddr2 */ nbt_srv_addr = socket_address_from_strings(tctx, ctx->nbtsock_srv->sock->backend_name, ctx->myaddr2->addr, lp_nbt_port(tctx->lp_ctx)); if (!nbt_srv_addr) return NULL; /* And if possible, bind to it. This won't work unless we are root or in sockewrapper */ status = socket_listen(ctx->nbtsock_srv2->sock, ctx->myaddr2, 0, 0); talloc_free(nbt_srv_addr); if (!NT_STATUS_IS_OK(status)) { /* this isn't fatal */ 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->b.address; ctx->addresses_best[0].ip = ctx->myaddr->addr; ctx->addresses_all_num = iface_count(ifaces); 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->b.address; ctx->addresses_all[i].ip = talloc_strdup(ctx->addresses_all, iface_n_ip(ifaces, 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->addr; 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->addr; ctx->addresses_mhomed[1].owner = ctx->b.address; ctx->addresses_mhomed[1].ip = ctx->myaddr2->addr; } return ctx;}static bool test_wrepl_update_one(struct torture_context *tctx, struct test_wrepl_conflict_conn *ctx, const struct wrepl_wins_owner *owner, const struct wrepl_wins_name *name){ struct wrepl_socket *wrepl_socket; struct wrepl_associate associate; struct wrepl_packet update_packet, repl_send; struct wrepl_table *update; struct wrepl_wins_owner wrepl_wins_owners[1]; struct wrepl_packet *repl_recv; struct wrepl_wins_owner *send_request; struct wrepl_send_reply *send_reply; struct wrepl_wins_name wrepl_wins_names[1]; uint32_t assoc_ctx; NTSTATUS status; wrepl_socket = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); status = wrepl_connect(wrepl_socket, lp_resolve_context(tctx->lp_ctx), wrepl_best_ip(tctx->lp_ctx, ctx->address), ctx->address); CHECK_STATUS(tctx, status, NT_STATUS_OK); status = wrepl_associate(wrepl_socket, &associate); CHECK_STATUS(tctx, status, NT_STATUS_OK); assoc_ctx = associate.out.assoc_ctx; /* now send a WREPL_REPL_UPDATE message */ ZERO_STRUCT(update_packet); update_packet.opcode = WREPL_OPCODE_BITS; update_packet.assoc_ctx = assoc_ctx; update_packet.mess_type = WREPL_REPLICATION; update_packet.message.replication.command = WREPL_REPL_UPDATE; update = &update_packet.message.replication.info.table; update->partner_count = ARRAY_SIZE(wrepl_wins_owners); update->partners = wrepl_wins_owners; update->initiator = "0.0.0.0"; wrepl_wins_owners[0] = *owner; status = wrepl_request(wrepl_socket, wrepl_socket, &update_packet, &repl_recv); CHECK_STATUS(tctx, status, NT_STATUS_OK); CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_REPLICATION); CHECK_VALUE(tctx, repl_recv->message.replication.command, WREPL_REPL_SEND_REQUEST); send_request = &repl_recv->message.replication.info.owner; ZERO_STRUCT(repl_send); repl_send.opcode = WREPL_OPCODE_BITS; repl_send.assoc_ctx = assoc_ctx; repl_send.mess_type = WREPL_REPLICATION; repl_send.message.replication.command = WREPL_REPL_SEND_REPLY; send_reply = &repl_send.message.replication.info.reply; send_reply->num_names = ARRAY_SIZE(wrepl_wins_names); send_reply->names = wrepl_wins_names; wrepl_wins_names[0] = *name; status = wrepl_request(wrepl_socket, wrepl_socket, &repl_send, &repl_recv); CHECK_STATUS(tctx, status, NT_STATUS_OK); CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_STOP_ASSOCIATION); CHECK_VALUE(tctx, repl_recv->message.stop.reason, 0); talloc_free(wrepl_socket); return true;}static bool test_wrepl_is_applied(struct torture_context *tctx, struct test_wrepl_conflict_conn *ctx, const struct wrepl_wins_owner *owner, const struct wrepl_wins_name *name, bool expected){ NTSTATUS status; struct wrepl_pull_names pull_names; struct wrepl_name *names; pull_names.in.assoc_ctx = ctx->pull_assoc; 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(tctx, status, NT_STATUS_OK); torture_assert(tctx, pull_names.out.num_names == (expected?1:0), talloc_asprintf(tctx, "Invalid number of records returned - expected %d got %d", expected, pull_names.out.num_names)); names = pull_names.out.names; if (expected) { uint32_t flags = WREPL_NAME_FLAGS(names[0].type, names[0].state, names[0].node, names[0].is_static); CHECK_VALUE(tctx, names[0].name.type, name->name->type); CHECK_VALUE_STRING(tctx, names[0].name.name, name->name->name); CHECK_VALUE_STRING(tctx, names[0].name.scope, name->name->scope); CHECK_VALUE(tctx, flags, name->flags); CHECK_VALUE_UINT64(tctx, names[0].version_id, name->id); if (flags & 2) { CHECK_VALUE(tctx, names[0].num_addresses, name->addresses.addresses.num_ips); } else { CHECK_VALUE(tctx, names[0].num_addresses, 1); CHECK_VALUE_STRING(tctx, names[0].addresses[0].address, name->addresses.ip); } } talloc_free(pull_names.out.names); return true;}static bool test_wrepl_mhomed_merged(struct torture_context *tctx, 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){ 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(tctx, status, NT_STATUS_OK); CHECK_VALUE(tctx, 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(tctx, names[0].name.type, name2->name->type); CHECK_VALUE_STRING(tctx, names[0].name.name, name2->name->name); CHECK_VALUE_STRING(tctx, names[0].name.scope, name2->name->scope); CHECK_VALUE(tctx, flags, name2->flags | WREPL_TYPE_MHOMED); CHECK_VALUE_UINT64(tctx, names[0].version_id, name2->id); CHECK_VALUE(tctx, 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(tctx, 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(tctx, owner, owner1->address); break; } } if (found) continue; CHECK_VALUE_STRING(tctx, addr, "not found in address list"); } talloc_free(pull_names.out.names); return true;}static bool test_wrepl_sgroup_merged(struct torture_context *tctx, struct test_wrepl_conflict_conn *ctx, struct wrepl_wins_owner *merge_owner, struct wrepl_wins_owner *owner1, uint32_t num_ips1, const struct wrepl_ip *ips1, struct wrepl_wins_owner *owner2, uint32_t num_ips2, const struct wrepl_ip *ips2, const struct wrepl_wins_name *name2){ NTSTATUS status; struct wrepl_pull_names pull_names; struct wrepl_name *names; struct wrepl_name *name = NULL; uint32_t flags; uint32_t i, j; uint32_t num_ips = num_ips1 + num_ips2; if (!merge_owner) { merge_owner = &ctx->c; } for (i = 0; i < num_ips1; i++) { if (owner1 != &ctx->c && strcmp(ips1[i].owner,owner2->address) == 0) { num_ips--; continue; } for (j = 0; j < num_ips2; j++) { if (strcmp(ips1[i].ip,ips2[j].ip) == 0) { num_ips--; break; } } } pull_names.in.assoc_ctx = ctx->pull_assoc; pull_names.in.partner = *merge_owner; pull_names.in.partner.min_version = pull_names.in.partner.max_version; pull_names.in.partner.max_version = 0; status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names); CHECK_STATUS(tctx, status, NT_STATUS_OK); names = pull_names.out.names; for (i = 0; i < pull_names.out.num_names; i++) { if (names[i].name.type != name2->name->type) continue; if (!names[i].name.name) continue; if (strcmp(names[i].name.name, name2->name->name) != 0) continue; if (names[i].name.scope) continue; name = &names[i]; } if (pull_names.out.num_names > 0) { merge_owner->max_version = names[pull_names.out.num_names-1].version_id; } if (!name) { torture_comment(tctx, "%s: Name '%s' not found\n", __location__, nbt_name_string(ctx, name2->name)); return false; } flags = WREPL_NAME_FLAGS(name->type, name->state, name->node, name->is_static); CHECK_VALUE(tctx, name->name.type, name2->name->type); CHECK_VALUE_STRING(tctx, name->name.name, name2->name->name); CHECK_VALUE_STRING(tctx, name->name.scope, name2->name->scope); CHECK_VALUE(tctx, flags, name2->flags); CHECK_VALUE(tctx, name->num_addresses, num_ips); for (i = 0; i < name->num_addresses; i++) { const char *addr = name->addresses[i].address; const char *owner = name->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(tctx, owner, ips2[j].owner); break; } } if (found) continue; for (j = 0; j < num_ips1; j++) { if (strcmp(addr, ips1[j].ip) == 0) { found = true; if (owner1 == &ctx->c) { CHECK_VALUE_STRING(tctx, owner, owner1->address); } else { CHECK_VALUE_STRING(tctx, owner, ips1[j].owner); } break; } } if (found) continue; CHECK_VALUE_STRING(tctx, addr, "not found in address list");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -