s4-winsrepl: don't put in attributes with no elements
[ira/wip.git] / source4 / nbt_server / wins / winsdb.c
index 438fb12b587881e2a36423220220fe2c43631f3e..389995e1bc67c22bc9bd7ef3f4e4e70fafff6955 100644 (file)
@@ -45,10 +45,8 @@ uint64_t winsdb_get_maxVersion(struct winsdb_handle *h)
        if (!dn) goto failed;
 
        /* find the record in the WINS database */
-       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 
-                        NULL, NULL, &res);
+       ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
        if (ret != LDB_SUCCESS) goto failed;
-       talloc_steal(tmp_ctx, res);
        if (res->count > 1) goto failed;
 
        if (res->count == 1) {
@@ -82,14 +80,10 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion)
        if (!dn) goto failed;
 
        /* find the record in the WINS database */
-       ret = ldb_search(wins_db, dn, LDB_SCOPE_BASE, NULL, NULL, &res);
-
+       ret = ldb_search(wins_db, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
        if (ret != LDB_SUCCESS) goto failed;
-       talloc_steal(tmp_ctx, res);
        if (res->count > 1) goto failed;
 
-       talloc_steal(tmp_ctx, res);
-
        if (res->count == 1) {
                oldMaxVersion = ldb_msg_find_attr_as_uint64(res->msgs[0], "maxVersion", 0);
        }
@@ -143,10 +137,8 @@ uint64_t winsdb_get_seqnumber(struct winsdb_handle *h)
        if (!dn) goto failed;
 
        /* find the record in the WINS database */
-       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 
-                        NULL, NULL, &res);
+       ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
        if (ret != LDB_SUCCESS) goto failed;
-       talloc_steal(tmp_ctx, res);
        if (res->count > 1) goto failed;
 
        if (res->count == 1) {
@@ -161,7 +153,8 @@ failed:
 /*
   return a DN for a nbt_name
 */
-static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct nbt_name *name)
+static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+                               const struct nbt_name *name)
 {
        struct ldb_dn *dn;
 
@@ -576,7 +569,7 @@ const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **a
   load a WINS entry from the database
 */
 NTSTATUS winsdb_lookup(struct winsdb_handle *h, 
-                      struct nbt_name *name,
+                      const struct nbt_name *name,
                       TALLOC_CTX *mem_ctx,
                       struct winsdb_record **_rec)
 {
@@ -589,10 +582,10 @@ NTSTATUS winsdb_lookup(struct winsdb_handle *h,
        time_t now = time(NULL);
 
        /* find the record in the WINS database */
-       ret = ldb_search(wins_db, winsdb_dn(tmp_ctx, wins_db, name), LDB_SCOPE_BASE, 
-                        NULL, NULL, &res);
+       ret = ldb_search(wins_db, tmp_ctx, &res,
+                        winsdb_dn(tmp_ctx, wins_db, name),
+                        LDB_SCOPE_BASE, NULL, NULL);
 
-       talloc_steal(tmp_ctx, res);
        if (ret != LDB_SUCCESS || res->count > 1) {
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
@@ -621,7 +614,6 @@ NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_
        struct ldb_message_element *el;
        struct nbt_name *name;
        uint32_t i, j, num_values;
-       bool we_are_owner = false;
 
        rec = talloc(mem_ctx, struct winsdb_record);
        if (rec == NULL) {
@@ -682,26 +674,6 @@ NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_
                goto failed;
        }
 
-       if (strcmp(rec->wins_owner, h->local_owner) == 0) {
-               we_are_owner = true;
-       }
-
-       /* 
-        * see if it has already expired
-        * 
-        * NOTE: only expire owned records this way!
-        *       w2k3 resolves expired replicas
-        *       which are in active state
-        */
-       if (!rec->is_static &&
-           rec->expire_time <= now &&
-           rec->state == WREPL_STATE_ACTIVE &&
-           we_are_owner) {
-               DEBUG(5,("WINS: expiring name %s (expired at %s)\n", 
-                        nbt_name_string(mem_ctx, rec->name), timestring(mem_ctx, rec->expire_time)));
-               rec->state = WREPL_STATE_RELEASED;
-       }
-
        rec->addresses     = talloc_array(rec, struct winsdb_addr *, num_values+1);
        if (rec->addresses == NULL) {
                status = NT_STATUS_NO_MEMORY;
@@ -709,12 +681,26 @@ NTSTATUS winsdb_record(struct winsdb_handle *h, struct ldb_message *msg, TALLOC_
        }
 
        for (i=0,j=0;i<num_values;i++) {
+               bool we_are_owner = false;
+
                status = winsdb_addr_decode(h, rec, &el->values[i], rec->addresses, &rec->addresses[j]);
                if (!NT_STATUS_IS_OK(status)) goto failed;
 
+               if (strcmp(rec->addresses[j]->wins_owner, h->local_owner) == 0) {
+                       we_are_owner = true;
+               }
+
                /*
                 * the record isn't static and is active
-                * then don't add the address if it's expired
+                * then don't add the address if it's expired,
+                * but only if we're the owner of the address
+                *
+                * This is important for SGROUP records,
+                * because each server thinks he's the owner of the
+                * record and the record isn't replicated on a
+                * name_refresh. So addresses owned by another owner
+                * could expire, but we still need to return them
+                * (as windows does).
                 */
                if (!rec->is_static &&
                    rec->addresses[j]->expire_time <= now &&
@@ -760,8 +746,9 @@ failed:
 /*
   form a ldb_message from a winsdb_record
 */
-struct ldb_message *winsdb_message(struct ldb_context *ldb, 
-                                  struct winsdb_record *rec, TALLOC_CTX *mem_ctx)
+static struct ldb_message *winsdb_message(struct ldb_context *ldb,
+                                         struct winsdb_record *rec,
+                                         TALLOC_CTX *mem_ctx)
 {
        int i, ret=0;
        size_t addr_count;
@@ -807,11 +794,11 @@ struct ldb_message *winsdb_message(struct ldb_context *ldb,
        for (i=0;rec->addresses[i];i++) {
                ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]);
        }
-       ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL);
        if (rec->registered_by) {
+               ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL);
                ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by);
-               if (ret != 0) goto failed;
        }
+       if (ret != 0) goto failed;
        return msg;
 
 failed:
@@ -945,7 +932,8 @@ failed:
        return NBT_RCODE_SVR;
 }
 
-static bool winsdb_check_or_add_module_list(struct loadparm_context *lp_ctx, struct winsdb_handle *h)
+static bool winsdb_check_or_add_module_list(struct tevent_context *ev_ctx, 
+                                           struct loadparm_context *lp_ctx, struct winsdb_handle *h)
 {
        int trans;
        int ret;
@@ -963,9 +951,8 @@ static bool winsdb_check_or_add_module_list(struct loadparm_context *lp_ctx, str
        if (!dn) goto failed;
 
        /* find the record in the WINS database */
-       ret = ldb_search(h->ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &res);
+       ret = ldb_search(h->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
        if (ret != LDB_SUCCESS) goto failed;
-       talloc_steal(tmp_ctx, res);
 
        if (res->count > 0) goto skip;
 
@@ -992,7 +979,7 @@ static bool winsdb_check_or_add_module_list(struct loadparm_context *lp_ctx, str
                flags |= LDB_FLG_NOSYNC;
        }
 
-       h->ldb = ldb_wrap_connect(h, lp_ctx, lock_path(h, lp_ctx, lp_wins_url(lp_ctx)),
+       h->ldb = ldb_wrap_connect(h, ev_ctx, lp_ctx, lock_path(h, lp_ctx, lp_wins_url(lp_ctx)),
                                  NULL, NULL, flags, NULL);
        if (!h->ldb) goto failed;
 
@@ -1010,39 +997,36 @@ failed:
        return false;
 }
 
-struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
+struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx, 
+                                    struct tevent_context *ev_ctx,
+                                    struct loadparm_context *lp_ctx,
+                                    const char *owner,
                                     enum winsdb_handle_caller caller)
 {
        struct winsdb_handle *h = NULL;
-       const char *owner;
        unsigned int flags = 0;
        bool ret;
        int ldb_err;
 
-       h = talloc(mem_ctx, struct winsdb_handle);
+       h = talloc_zero(mem_ctx, struct winsdb_handle);
        if (!h) return NULL;
 
        if (lp_parm_bool(lp_ctx, NULL,"winsdb", "nosync", false)) {
                flags |= LDB_FLG_NOSYNC;
        }
 
-       h->ldb = ldb_wrap_connect(h, lp_ctx, lock_path(h, lp_ctx, lp_wins_url(lp_ctx)),
+       h->ldb = ldb_wrap_connect(h, ev_ctx, lp_ctx, lock_path(h, lp_ctx, lp_wins_url(lp_ctx)),
                                  NULL, NULL, flags, NULL);
        if (!h->ldb) goto failed;       
 
        h->caller = caller;
        h->hook_script = lp_wins_hook(lp_ctx);
 
-       owner = lp_parm_string(lp_ctx, NULL, "winsdb", "local_owner");
-       if (!owner) {
-               owner = iface_n_ip(0);
-       }
-
        h->local_owner = talloc_strdup(h, owner);
        if (!h->local_owner) goto failed;
 
        /* make sure the module list is available and used */
-       ret = winsdb_check_or_add_module_list(lp_ctx, h);
+       ret = winsdb_check_or_add_module_list(ev_ctx, lp_ctx, h);
        if (!ret) goto failed;
 
        ldb_err = ldb_set_opaque(h->ldb, "winsdb_handle", h);