diff options
Diffstat (limited to 'source4/wrepl_server')
-rw-r--r-- | source4/wrepl_server/wrepl_in_call.c | 26 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_out_helpers.c | 16 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_server.c | 133 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_server.h | 8 |
4 files changed, 104 insertions, 79 deletions
diff --git a/source4/wrepl_server/wrepl_in_call.c b/source4/wrepl_server/wrepl_in_call.c index 9bd01c14bb..4d5fad8a7c 100644 --- a/source4/wrepl_server/wrepl_in_call.c +++ b/source4/wrepl_server/wrepl_in_call.c @@ -115,7 +115,7 @@ static NTSTATUS wreplsrv_in_table_query(struct wreplsrv_in_call *call) repl_out->command = WREPL_REPL_TABLE_REPLY; return wreplsrv_fill_wrepl_table(service, call, table_out, - our_ip, our_ip, True); + our_ip, True); } static int wreplsrv_in_sort_wins_name(struct wrepl_wins_name *n1, @@ -173,7 +173,6 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) struct wrepl_wins_owner *owner_in = &call->req_packet.message.replication.info.owner; struct wrepl_replication *repl_out = &call->rep_packet.message.replication; struct wrepl_send_reply *reply_out = &call->rep_packet.message.replication.info.reply; - struct wreplsrv_owner local_owner; struct wreplsrv_owner *owner; const char *filter; struct ldb_result *res = NULL; @@ -183,16 +182,7 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) NTSTATUS status; uint32_t i; - if (strcmp(call->wreplconn->our_ip, owner_in->address) == 0) { - ZERO_STRUCT(local_owner); - local_owner.owner.address = service->wins_db->local_owner; - local_owner.owner.min_version = 0; - local_owner.owner.max_version = wreplsrv_local_max_version(service); - local_owner.owner.type = 1; - owner = &local_owner; - } else { - owner = wreplsrv_find_owner(service->table, owner_in->address); - } + owner = wreplsrv_find_owner(service, service->table, owner_in->address); repl_out->command = WREPL_REPL_SEND_REPLY; reply_out->num_names = 0; @@ -203,6 +193,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) * return an empty list. */ if (!owner) { + DEBUG(2,("WINSREPL:reply [0] records unknown owner[%s] to partner[%s]\n", + owner_in->address, call->wreplconn->partner->address)); return NT_STATUS_OK; } @@ -219,6 +211,11 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) * return an empty list. */ if (owner_in->min_version > owner_in->max_version) { + DEBUG(2,("WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s]\n", + owner_in->address, + (long long)owner_in->min_version, + (long long)owner_in->max_version, + call->wreplconn->partner->address)); return NT_STATUS_OK; } @@ -227,6 +224,11 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call) * return an empty list. */ if (owner_in->min_version > owner->owner.max_version) { + DEBUG(2,("WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s]\n", + owner_in->address, + (long long)owner_in->min_version, + (long long)owner_in->max_version, + call->wreplconn->partner->address)); return NT_STATUS_OK; } diff --git a/source4/wrepl_server/wrepl_out_helpers.c b/source4/wrepl_server/wrepl_out_helpers.c index 3b69b40fa0..738d89a55b 100644 --- a/source4/wrepl_server/wrepl_out_helpers.c +++ b/source4/wrepl_server/wrepl_out_helpers.c @@ -552,10 +552,12 @@ static NTSTATUS wreplsrv_pull_cycle_next_owner_do_work(struct wreplsrv_pull_cycl BOOL do_pull = False; for (i=state->current; i < state->table_io.out.num_owners; i++) { - current_owner = wreplsrv_find_owner(state->io->in.partner->pull.table, + current_owner = wreplsrv_find_owner(state->io->in.partner->service, + state->io->in.partner->pull.table, state->table_io.out.owners[i].address); - local_owner = wreplsrv_find_owner(state->io->in.partner->service->table, + local_owner = wreplsrv_find_owner(state->io->in.partner->service, + state->io->in.partner->service->table, state->table_io.out.owners[i].address); /* * this means we are ourself the current owner, @@ -639,12 +641,6 @@ static NTSTATUS wreplsrv_pull_cycle_wait_table_reply(struct wreplsrv_pull_cycle_ /* update partner table */ for (i=0; i < state->table_io.out.num_owners; i++) { - BOOL is_our_addr; - - is_our_addr = wreplsrv_is_our_address(state->io->in.partner->service, - state->table_io.out.owners[i].address); - if (is_our_addr) continue; - status = wreplsrv_add_table(state->io->in.partner->service, state->io->in.partner, &state->io->in.partner->pull.table, @@ -843,7 +839,7 @@ static NTSTATUS wreplsrv_push_notify_update(struct wreplsrv_push_notify_state *s NT_STATUS_HAVE_NO_MEMORY(our_ip); status = wreplsrv_fill_wrepl_table(service, state, table_out, - our_ip, our_ip, state->full_table); + our_ip, state->full_table); NT_STATUS_NOT_OK_RETURN(status); /* queue the request */ @@ -928,7 +924,7 @@ static NTSTATUS wreplsrv_push_notify_inform(struct wreplsrv_push_notify_state *s NT_STATUS_HAVE_NO_MEMORY(our_ip); status = wreplsrv_fill_wrepl_table(service, state, table_out, - our_ip, our_ip, state->full_table); + our_ip, state->full_table); NT_STATUS_NOT_OK_RETURN(status); /* we won't get a reply to a inform message */ diff --git a/source4/wrepl_server/wrepl_server.c b/source4/wrepl_server/wrepl_server.c index e9dbd3b872..0407f7fa6a 100644 --- a/source4/wrepl_server/wrepl_server.c +++ b/source4/wrepl_server/wrepl_server.c @@ -146,83 +146,66 @@ failed: return NT_STATUS_FOOBAR; } -BOOL wreplsrv_is_our_address(struct wreplsrv_service *service, const char *address) -{ - const char *our_address; - - if (lp_interfaces() && lp_bind_interfaces_only()) { - int num_interfaces = iface_count(); - int i; - for(i = 0; i < num_interfaces; i++) { - our_address = iface_n_ip(i); - if (strcasecmp(our_address, address) == 0) { - return True; - } - } - } else { - our_address = lp_socket_address(); - if (strcasecmp(our_address, address) == 0) { - return True; - } - } - - return False; -} - -uint64_t wreplsrv_local_max_version(struct wreplsrv_service *service) -{ - return winsdb_get_maxVersion(service->wins_db); -} - NTSTATUS wreplsrv_fill_wrepl_table(struct wreplsrv_service *service, TALLOC_CTX *mem_ctx, struct wrepl_table *table_out, - const char *our_ip, const char *initiator, BOOL full_table) { struct wreplsrv_owner *cur; - uint64_t local_max_version; uint32_t i = 0; table_out->partner_count = 0; table_out->partners = NULL; table_out->initiator = initiator; - local_max_version = wreplsrv_local_max_version(service); - if (local_max_version > 0) { - table_out->partner_count++; - } + for (cur = service->table; cur; cur = cur->next) { + if (full_table) { + table_out->partner_count++; + continue; + } + + if (strcmp(initiator, cur->owner.address) != 0) continue; - for (cur = service->table; full_table && cur; cur = cur->next) { table_out->partner_count++; + break; } table_out->partners = talloc_array(mem_ctx, struct wrepl_wins_owner, table_out->partner_count); NT_STATUS_HAVE_NO_MEMORY(table_out->partners); - if (local_max_version > 0) { - table_out->partners[i].address = our_ip; - table_out->partners[i].min_version = 0; - table_out->partners[i].max_version = local_max_version; - table_out->partners[i].type = 1; - i++; - } + for (cur = service->table; cur && i < table_out->partner_count; cur = cur->next) { + if (full_table) { + table_out->partners[i] = cur->owner; + i++; + continue; + } + + if (strcmp(initiator, cur->owner.address) != 0) continue; - for (cur = service->table; full_table && cur; cur = cur->next) { table_out->partners[i] = cur->owner; i++; + break; } return NT_STATUS_OK; } -struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_owner *table, const char *wins_owner) +struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_service *service, + struct wreplsrv_owner *table, + const char *wins_owner) { struct wreplsrv_owner *cur; for (cur = table; cur; cur = cur->next) { if (strcmp(cur->owner.address, wins_owner) == 0) { + /* + * if it's our local entry + * update the max version + */ + if (cur == service->owner) { + cur->owner.max_version = winsdb_get_maxVersion(service->wins_db); + } return cur; } } @@ -241,12 +224,11 @@ NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service, struct wreplsrv_owner *table = *_table; struct wreplsrv_owner *cur; - if (strcmp(service->wins_db->local_owner, wins_owner) == 0 || - strcmp("0.0.0.0", wins_owner) == 0) { - return NT_STATUS_OK; + if (!wins_owner || strcmp(wins_owner, "0.0.0.0") == 0) { + wins_owner = service->wins_db->local_owner; } - cur = wreplsrv_find_owner(table, wins_owner); + cur = wreplsrv_find_owner(service, table, wins_owner); /* if it doesn't exists yet, create one */ if (!cur) { @@ -261,7 +243,7 @@ NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service, cur->partner = wreplsrv_find_partner(service, wins_owner); - DLIST_ADD(table, cur); + DLIST_ADD_END(table, cur, struct wreplsrv_owner *); *_table = table; } @@ -270,6 +252,16 @@ NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service, /* if the given version is higher the then current nax_version, update */ if (cur->owner.max_version < version) { cur->owner.max_version = version; + /* if it's for our local db, we need to update the wins.ldb too */ + if (cur == service->owner) { + uint64_t ret; + ret = winsdb_set_maxVersion(service->wins_db, cur->owner.max_version); + if (ret != cur->owner.max_version) { + DEBUG(0,("winsdb_set_maxVersion(%llu) failed: %llu\n", + cur->owner.max_version, ret)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } } return NT_STATUS_OK; @@ -286,6 +278,7 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service) TALLOC_CTX *tmp_ctx = talloc_new(service); struct ldb_context *ldb = service->wins_db->ldb; int i; + struct wreplsrv_owner *local_owner; const char *wins_owner; uint64_t version; const char * const attrs[] = { @@ -294,6 +287,21 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service) NULL }; + /* + * make sure we have our local entry in the list, + * but we set service->owner when we're done + * to avoid to many calls to wreplsrv_local_max_version() + */ + status = wreplsrv_add_table(service, + service, &service->table, + service->wins_db->local_owner, 0); + if (!NT_STATUS_IS_OK(status)) goto failed; + local_owner = wreplsrv_find_owner(service, service->table, service->wins_db->local_owner); + if (!local_owner) { + status = NT_STATUS_INTERNAL_ERROR; + goto failed; + } + /* find the record in the WINS database */ ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, "(objectClass=winsRecord)", attrs, &res); @@ -306,17 +314,28 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service) wins_owner = ldb_msg_find_string(res->msgs[i], "winsOwner", NULL); version = ldb_msg_find_uint64(res->msgs[i], "versionID", 0); - if (wins_owner) { - status = wreplsrv_add_table(service, - service, &service->table, - wins_owner, version); - if (!NT_STATUS_IS_OK(status)) goto failed; - } + status = wreplsrv_add_table(service, + service, &service->table, + wins_owner, version); + if (!NT_STATUS_IS_OK(status)) goto failed; talloc_free(res->msgs[i]); - - /* TODO: what's abut the per address owners? */ } done: + /* + * this makes sure we call wreplsrv_local_max_version() before returning in + * wreplsrv_find_owner() + */ + service->owner = local_owner; + + /* + * this makes sure the maxVersion in the database is updated, + * with the highest version we found, if this is higher than the current stored one + */ + status = wreplsrv_add_table(service, + service, &service->table, + service->wins_db->local_owner, local_owner->owner.max_version); + if (!NT_STATUS_IS_OK(status)) goto failed; + talloc_free(tmp_ctx); return NT_STATUS_OK; failed: diff --git a/source4/wrepl_server/wrepl_server.h b/source4/wrepl_server/wrepl_server.h index c846e08d64..1480d2799a 100644 --- a/source4/wrepl_server/wrepl_server.h +++ b/source4/wrepl_server/wrepl_server.h @@ -276,6 +276,14 @@ struct wreplsrv_service { /* all partners (pull and push) */ struct wreplsrv_partner *partners; + /* + * this is our local wins_owner entry, this is also in the table list + * but we need a pointer to it, because we need to update it on each + * query to wreplsrv_find_owner(), as the local records can be added + * to the wins.ldb from external tools and the winsserver + */ + struct wreplsrv_owner *owner; + /* this is a list of each wins_owner we know about in our database */ struct wreplsrv_owner *table; |