r12242: - make the push notifications triggered by the change count
[bbaumbach/samba-autobuild/.git] / source4 / wrepl_server / wrepl_server.c
index dd49b37d78be3867d92bf7e23fa26658873f6422..157a39ec85485b58aba6012d69e8cacd71e462a7 100644 (file)
@@ -31,6 +31,7 @@
 #include "wrepl_server/wrepl_server.h"
 #include "nbt_server/wins/winsdb.h"
 #include "ldb/include/ldb.h"
+#include "ldb/include/ldb_errors.h"
 
 /*
   open winsdb
@@ -42,6 +43,21 @@ static NTSTATUS wreplsrv_open_winsdb(struct wreplsrv_service *service)
                return NT_STATUS_INTERNAL_DB_ERROR;
        }
 
+       /* the default renew interval is 6 days */
+       service->config.renew_interval    = lp_parm_int(-1,"wreplsrv","renew_interval", 6*24*60*60);
+
+       /* the default tombstone (extinction) interval is 6 days */
+       service->config.tombstone_interval= lp_parm_int(-1,"wreplsrv","tombstone_interval", 6*24*60*60);
+
+       /* the default tombstone (extinction) timeout is 1 day */
+       service->config.tombstone_timeout = lp_parm_int(-1,"wreplsrv","tombstone_timeout", 1*24*60*60);
+
+       /* the default verify interval is 24 days */
+       service->config.verify_interval   = lp_parm_int(-1,"wreplsrv","verify_interval", 24*24*60*60);
+
+       /* the maximun interval to the next periodic processing event */
+       service->config.periodic_interval = lp_parm_int(-1,"wreplsrv","periodic_interval", 60);
+
        return NT_STATUS_OK;
 }
 
@@ -63,7 +79,7 @@ struct wreplsrv_partner *wreplsrv_find_partner(struct wreplsrv_service *service,
 */
 static NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service)
 {
-       struct ldb_message **res = NULL;
+       struct ldb_result *res = NULL;
        int ret;
        TALLOC_CTX *tmp_ctx = talloc_new(service);
        int i;
@@ -71,24 +87,29 @@ static NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service)
        /* find the record in the WINS database */
        ret = ldb_search(service->wins_db, ldb_dn_explode(tmp_ctx, "CN=PARTNERS"), LDB_SCOPE_ONELEVEL,
                         "(objectClass=wreplPartner)", NULL, &res);
-       if (res != NULL) {
-               talloc_steal(tmp_ctx, res);
-       }
-       if (ret < 0) goto failed;
-       if (ret == 0) goto done;
+       if (ret != LDB_SUCCESS) goto failed;
+       talloc_steal(tmp_ctx, res);
+       if (res->count == 0) goto done;
 
-       for (i=0; i < ret; i++) {
+       for (i=0; i < res->count; i++) {
                struct wreplsrv_partner *partner;
 
-               partner = talloc(service, struct wreplsrv_partner);
+               partner = talloc_zero(service, struct wreplsrv_partner);
                if (partner == NULL) goto failed;
 
-               partner->address        = ldb_msg_find_string(res[i], "address", NULL);
+               partner->service                = service;
+               partner->address                = ldb_msg_find_string(res->msgs[i], "address", NULL);
                if (!partner->address) goto failed;
-               partner->name           = ldb_msg_find_string(res[i], "name", partner->address);
-               partner->type           = ldb_msg_find_int(res[i], "type", WINSREPL_PARTNER_BOTH);
-               partner->pull.interval  = ldb_msg_find_int(res[i], "pullInterval", WINSREPL_DEFAULT_PULL_INTERVAL);
-               partner->our_address    = ldb_msg_find_string(res[i], "ourAddress", NULL);
+               partner->name                   = ldb_msg_find_string(res->msgs[i], "name", partner->address);
+               partner->type                   = ldb_msg_find_uint(res->msgs[i], "type", WINSREPL_PARTNER_BOTH);
+               partner->pull.interval          = ldb_msg_find_uint(res->msgs[i], "pullInterval",
+                                                                   WINSREPL_DEFAULT_PULL_INTERVAL);
+               partner->pull.retry_interval    = ldb_msg_find_uint(res->msgs[i], "pullRetryInterval",
+                                                                   WINSREPL_DEFAULT_PULL_RETRY_INTERVAL);
+               partner->our_address            = ldb_msg_find_string(res->msgs[i], "ourAddress", NULL);
+               partner->push.change_count      = ldb_msg_find_uint(res->msgs[i], "pushChangeCount",
+                                                                   WINSREPL_DEFAULT_PUSH_CHANGE_COUNT);
+               partner->push.use_inform        = ldb_msg_find_uint(res->msgs[i], "pushUseInform", False);
 
                talloc_steal(partner, partner->address);
                talloc_steal(partner, partner->name);
@@ -104,12 +125,35 @@ 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)
 {
        int ret;
        struct ldb_context *ldb = service->wins_db;
        struct ldb_dn *dn;
-       struct ldb_message **res = NULL;
+       struct ldb_result *res = NULL;
        TALLOC_CTX *tmp_ctx = talloc_new(service);
        uint64_t maxVersion = 0;
 
@@ -119,14 +163,12 @@ uint64_t wreplsrv_local_max_version(struct wreplsrv_service *service)
        /* find the record in the WINS database */
        ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 
                         NULL, NULL, &res);
-       if (res != NULL) {
-               talloc_steal(tmp_ctx, res);
-       }
-       if (ret < 0) goto failed;
-       if (ret > 1) goto failed;
+       if (ret != LDB_SUCCESS) goto failed;
+       talloc_steal(tmp_ctx, res);
+       if (res->count > 1) goto failed;
 
-       if (ret == 1) {
-               maxVersion = ldb_msg_find_uint64(res[0], "maxVersion", 0);
+       if (res->count == 1) {
+               maxVersion = ldb_msg_find_uint64(res->msgs[0], "maxVersion", 0);
        }
 
 failed:
@@ -134,6 +176,49 @@ failed:
        return maxVersion;
 }
 
+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; full_table && cur; cur = cur->next) {
+               table_out->partner_count++;
+       }
+
+       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; full_table && cur; cur = cur->next) {
+               table_out->partners[i] = cur->owner;
+               i++;
+       }
+
+       return NT_STATUS_OK;
+}
+
 struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_owner *table, const char *wins_owner)
 {
        struct wreplsrv_owner *cur;
@@ -151,9 +236,9 @@ struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_owner *table, const c
  update the wins_owner_table max_version, if the given version is the highest version
  if no entry for the wins_owner exists yet, create one
 */
-static NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service,
-                                  TALLOC_CTX *mem_ctx, struct wreplsrv_owner **_table,
-                                  const char *wins_owner, uint64_t version)
+NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service,
+                           TALLOC_CTX *mem_ctx, struct wreplsrv_owner **_table,
+                           const char *wins_owner, uint64_t version)
 {
        struct wreplsrv_owner *table = *_table;
        struct wreplsrv_owner *cur;
@@ -196,7 +281,7 @@ static NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service,
 */
 static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
 {
-       struct ldb_message **res = NULL;
+       struct ldb_result *res = NULL;
        int ret;
        NTSTATUS status;
        TALLOC_CTX *tmp_ctx = talloc_new(service);
@@ -212,16 +297,14 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
        /* find the record in the WINS database */
        ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE,
                         "(objectClass=winsRecord)", attrs, &res);
-       if (res != NULL) {
-               talloc_steal(tmp_ctx, res);
-       }
        status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-       if (ret < 0) goto failed;
-       if (ret == 0) goto done;
+       if (ret != LDB_SUCCESS) goto failed;
+       talloc_steal(tmp_ctx, res);
+       if (res->count == 0) goto done;
 
-       for (i=0; i < ret; i++) {
-               wins_owner     = ldb_msg_find_string(res[i], "winsOwner", NULL);
-               version        = ldb_msg_find_uint64(res[i], "versionID", 0);
+       for (i=0; i < res->count; i++) {
+               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,
@@ -229,7 +312,7 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
                                                    wins_owner, version);
                        if (!NT_STATUS_IS_OK(status)) goto failed;
                }
-               talloc_free(res[i]);
+               talloc_free(res->msgs[i]);
 
                /* TODO: what's abut the per address owners? */
        }
@@ -301,6 +384,12 @@ static void wreplsrv_task_init(struct task_server *task)
                return;
        }
 
+       status = wreplsrv_setup_periodic(service);
+       if (!NT_STATUS_IS_OK(status)) {
+               task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_periodic() failed");
+               return;
+       }
+
        irpc_add_name(task->msg_ctx, "wrepl_server");
 }
 
@@ -309,6 +398,10 @@ static void wreplsrv_task_init(struct task_server *task)
  */
 static NTSTATUS wreplsrv_init(struct event_context *event_ctx, const struct model_ops *model_ops)
 {
+       if (!lp_wins_support()) {
+               return NT_STATUS_OK;
+       }
+
        return task_server_startup(event_ctx, model_ops, wreplsrv_task_init);
 }