s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[ira/wip.git] / source4 / wrepl_server / wrepl_apply_records.c
index 17777f4dcffc974d7e0fca083f3c03dac6560ccc..4eed36bb674606b67de4dd0673ea4e0ad4f4030e 100644 (file)
@@ -29,6 +29,7 @@
 #include "libcli/wrepl/winsrepl.h"
 #include "system/time.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
+#include "param/param.h"
 
 enum _R_ACTION {
        R_INVALID,
@@ -892,7 +893,7 @@ struct r_do_challenge_state {
 static void r_do_late_release_demand_handler(struct irpc_request *ireq)
 {
        NTSTATUS status;
-       struct r_do_challenge_state *state = talloc_get_type(ireq->async.private,
+       struct r_do_challenge_state *state = talloc_get_type(ireq->async.private_data,
                                                             struct r_do_challenge_state);
 
        status = irpc_call_recv(ireq);
@@ -930,7 +931,7 @@ static NTSTATUS r_do_late_release_demand(struct r_do_challenge_state *state)
        NT_STATUS_HAVE_NO_MEMORY(ireq);
 
        ireq->async.fn          = r_do_late_release_demand_handler;
-       ireq->async.private     = state;
+       ireq->async.private_data= state;
 
        return NT_STATUS_OK;
 }
@@ -953,7 +954,7 @@ _UA_MA_DI_A<00>: C:BEST vs. B:BEST2 (C:ALL) => B:MHOMED => MHOMED_MERGE
 static void r_do_challenge_handler(struct irpc_request *ireq)
 {
        NTSTATUS status;
-       struct r_do_challenge_state *state = talloc_get_type(ireq->async.private,
+       struct r_do_challenge_state *state = talloc_get_type(ireq->async.private_data,
                                                             struct r_do_challenge_state);
        bool old_is_subset = false;
        bool new_is_subset = false;
@@ -1075,7 +1076,7 @@ static NTSTATUS r_do_challenge(struct wreplsrv_partner *partner,
        NT_STATUS_HAVE_NO_MEMORY(ireq);
 
        ireq->async.fn          = r_do_challenge_handler;
-       ireq->async.private     = state;
+       ireq->async.private_data= state;
 
        talloc_steal(partner, state);
        return NT_STATUS_OK;
@@ -1089,7 +1090,7 @@ struct r_do_release_demand_state {
 static void r_do_release_demand_handler(struct irpc_request *ireq)
 {
        NTSTATUS status;
-       struct r_do_release_demand_state *state = talloc_get_type(ireq->async.private,
+       struct r_do_release_demand_state *state = talloc_get_type(ireq->async.private_data,
                                                  struct r_do_release_demand_state);
 
        status = irpc_call_recv(ireq);
@@ -1151,7 +1152,7 @@ static NTSTATUS r_do_release_demand(struct wreplsrv_partner *partner,
        NT_STATUS_HAVE_NO_MEMORY(ireq);
 
        ireq->async.fn          = r_do_release_demand_handler;
-       ireq->async.private     = state;
+       ireq->async.private_data= state;
 
        talloc_steal(partner, state);
        return NT_STATUS_OK;
@@ -1190,7 +1191,9 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
        uint8_t ret;
        size_t len;
        bool changed_old_addrs = false;
+       bool skip_replica_owned_by_us = false;
        bool become_owner = true;
+       bool propagate = lpcfg_parm_bool(partner->service->task->lp_ctx, NULL, "wreplsrv", "propagate name releases", false);
        const char *local_owner = partner->service->wins_db->local_owner;
 
        merge = talloc(mem_ctx, struct winsdb_record);
@@ -1251,6 +1254,23 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
        }
 
        for (i=0; i < replica->num_addresses; i++) {
+               if (propagate &&
+                   strcmp(replica->addresses[i].owner, local_owner) == 0) {
+                       const struct winsdb_addr *a;
+
+                       /*
+                        * NOTE: this is different to the windows behavior
+                        *       and off by default, but it better propagated
+                        *       name releases
+                        */
+                       a = winsdb_addr_list_check(merge->addresses,
+                                                  replica->addresses[i].address);
+                       if (!a) {
+                               /* don't add addresses owned by us */
+                               skip_replica_owned_by_us = true;
+                       }
+                       continue;
+               }
                merge->addresses = winsdb_addr_list_add(partner->service->wins_db,
                                                        merge, merge->addresses,
                                                        replica->addresses[i].address,
@@ -1265,6 +1285,15 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
                become_owner = false;
        }
 
+       /*
+        * when we notice another server believes an address
+        * is owned by us and that's not the case
+        * we propagate the result
+        */
+       if (skip_replica_owned_by_us) {
+               become_owner = true;
+       }
+
        /* if we're the owner of the old record, we'll be the owner of the new one too */
        if (strcmp(rec->wins_owner, local_owner)==0) {
                become_owner = true;
@@ -1283,7 +1312,25 @@ static NTSTATUS r_do_sgroup_merge(struct wreplsrv_partner *partner,
         * will be owner of the merge result, otherwise we take the ownership
         */
        if (become_owner) {
+               time_t lh = 0;
+
                modify_flags = WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;
+
+               /*
+                * if we're the owner, the expire time becomes the highest
+                * expire time of owned addresses
+                */
+               len = winsdb_addr_list_length(merge->addresses);
+
+               for (i=0; i < len; i++) {
+                       if (strcmp(merge->addresses[i]->wins_owner, local_owner)==0) {
+                               lh = MAX(lh, merge->addresses[i]->expire_time);
+                       }
+               }
+
+               if (lh != 0) {
+                       merge->expire_time = lh;
+               }
        }
 
        ret = winsdb_modify(partner->service->wins_db, merge, modify_flags);
@@ -1311,6 +1358,20 @@ static NTSTATUS wreplsrv_apply_one_record(struct wreplsrv_partner *partner,
        bool replica_vs_replica = false;
        bool local_vs_replica = false;
 
+       if (replica->name.scope) {
+               TALLOC_CTX *parent;
+               const char *scope;
+
+               /*
+                * Windows 2008 truncates the scope to 237 bytes,
+                * so we do...
+                */
+               parent = talloc_parent(replica->name.scope);
+               scope = talloc_strndup(parent, replica->name.scope, 237);
+               NT_STATUS_HAVE_NO_MEMORY(scope);
+               replica->name.scope = scope;
+       }
+
        status = winsdb_lookup(partner->service->wins_db,
                               &replica->name, mem_ctx, &rec);
        if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {