summaryrefslogtreecommitdiff
path: root/source4/wrepl_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/wrepl_server')
-rw-r--r--source4/wrepl_server/wrepl_in_call.c26
-rw-r--r--source4/wrepl_server/wrepl_out_helpers.c16
-rw-r--r--source4/wrepl_server/wrepl_server.c133
-rw-r--r--source4/wrepl_server/wrepl_server.h8
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;