r11040: r10357@SERNOX: metze | 2005-09-20 21:28:11 +0200
authorStefan Metzmacher <metze@samba.org>
Fri, 14 Oct 2005 12:55:59 +0000 (12:55 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:42:34 +0000 (13:42 -0500)
 - as the old records are broken sinse the last winsdb_dn() changes, (the dn components order was reversed)
   we can use nicer attribute and objectClass names...

 - use much more verbose error handling for winsdb_*
 - print a debug message when we found a corrupted record

 metze
(This used to be commit 82bad3f3efec5b706a65e65054787f1486d7c875)

source4/nbt_server/wins/winsdb.c
source4/nbt_server/wins/winsserver.c
source4/nbt_server/wins/winswack.c
source4/wrepl_server/wrepl_in_call.c
source4/wrepl_server/wrepl_server.c

index 551bc8572755cd69f55d6e0129022a628da2ae34..ff3c787eb036f64abdb9de274d60859e781fcc18 100644 (file)
@@ -83,7 +83,7 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name)
 {
        struct ldb_dn *dn;
 
-       dn = ldb_dn_string_compose(mem_ctx, NULL, "type=%02x", name->type);
+       dn = ldb_dn_string_compose(mem_ctx, NULL, "type=0x%02X", name->type);
        if (dn && name->name && *name->name) {
                dn = ldb_dn_string_compose(mem_ctx, dn, "name=%s", name->name);
        }
@@ -93,15 +93,20 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name)
        return dn;
 }
 
-struct nbt_name *winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
+static NTSTATUS winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct nbt_name **_name)
 {
+       NTSTATUS status;
        struct nbt_name *name;
        uint32_t cur = 0;
 
        name = talloc(mem_ctx, struct nbt_name);
-       if (!name) goto failed;
+       if (!name) {
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
+       }
 
        if (dn->comp_num > 3) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
        }
 
@@ -117,26 +122,31 @@ struct nbt_name *winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
                cur++;
        } else {
                name->name      = talloc_strdup(name, "");
-               if (!name->name) goto failed;
+               if (!name->name) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto failed;
+               }
        }
 
        if (dn->comp_num > cur && strcasecmp("type", dn->components[cur].name) == 0) {
-               name->type      = strtoul((char *)dn->components[cur].value.data, NULL, 16);
+               name->type      = strtoul((char *)dn->components[cur].value.data, NULL, 0);
                cur++;
        } else {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
        }
 
-       return name;
+       *_name = name;
+       return NT_STATUS_OK;
 failed:
        talloc_free(name);
-       return NULL;
+       return status;
 }
 
 /*
  decode the winsdb_addr("address") attribute:
  "172.31.1.1" or 
- "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z"
+ "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;"
  are valid records
 */
 static BOOL winsdb_remove_version(struct wins_server *winssrv, uint64_t version)
@@ -247,6 +257,7 @@ const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **a
 */
 static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_CTX *mem_ctx, struct ldb_val *val)
 {
+       NTSTATUS status;
        struct winsdb_addr *addr;
        char *address;
        char *wins_owner;
@@ -254,7 +265,10 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_
        char *p;
 
        addr = talloc(mem_ctx, struct winsdb_addr);
-       if (!addr) return NULL;
+       if (!addr) {
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
+       }
 
        address = (char *)val->data;
 
@@ -264,52 +278,60 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_
                addr->address           = talloc_steal(addr, val->data);
                addr->wins_owner        = rec->wins_owner;
                addr->expire_time       = rec->expire_time;
-               return addr;
+               *_addr = addr;
+               return NT_STATUS_OK;
        }
 
        *p = '\0';p++;
        addr->address = talloc_strdup(addr, address);
        if (!addr->address) {
-               talloc_free(addr);
-               return NULL;
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
        }
 
        if (strncmp("winsOwner:", p, 10) != 0) {
-               /* invalid record */
-               talloc_free(addr);
-               return NULL;
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
        }
        wins_owner = p + 10;
        p = strchr(wins_owner, ';');
        if (!p) {
-               /* invalid record */
-               talloc_free(addr);
-               return NULL;
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
        }
 
        *p = '\0';p++;
        addr->wins_owner = talloc_strdup(addr, wins_owner);
        if (!addr->wins_owner) {
-               talloc_free(addr);
-               return NULL;
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
        }
 
        if (strncmp("expireTime:", p, 11) != 0) {
-               /* invalid record */
-               talloc_free(addr);
-               return NULL;
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
        }
 
        expire_time = p + 11;
+       p = strchr(expire_time, ';');
+       if (!p) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
+       }
 
+       *p = '\0';p++;
        addr->expire_time = ldap_string_to_time(expire_time);
 
-       return addr;
+       *_addr = addr;
+       return NT_STATUS_OK;
+failed:
+       talloc_free(addr);
+       return status;
 }
 
 /*
  encode the winsdb_addr("address") attribute like this:
- "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z"
+ "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;"
 */
 static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg, 
                                   const char *attr_name, struct winsdb_addr *addr)
@@ -317,7 +339,7 @@ static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *
        struct ldb_val val;
        const char *str;
 
-       str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s",
+       str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s;",
                              addr->address, addr->wins_owner,
                              ldap_timestring(msg, addr->expire_time));
        if (!str) return -1;
@@ -435,25 +457,33 @@ const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **a
 /*
   load a WINS entry from the database
 */
-struct winsdb_record *winsdb_load(struct wins_server *winssrv, 
-                                 struct nbt_name *name, TALLOC_CTX *mem_ctx)
+NTSTATUS winsdb_lookup(struct ldb_context *wins_db, 
+                      struct nbt_name *name,
+                      TALLOC_CTX *mem_ctx,
+                      struct winsdb_record **_rec)
 {
+       NTSTATUS status;
        struct ldb_message **res = NULL;
        int ret;
        struct winsdb_record *rec;
        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 
        /* find the record in the WINS database */
-       ret = ldb_search(winssrv->wins_db, winsdb_dn(tmp_ctx, name), LDB_SCOPE_BASE, 
+       ret = ldb_search(wins_db, winsdb_dn(tmp_ctx, name), LDB_SCOPE_BASE, 
                         NULL, NULL, &res);
        if (res != NULL) {
                talloc_steal(tmp_ctx, res);
        }
-       if (ret != 1) goto failed;
+       if (ret == 0) {
+               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               goto failed;
+       } else if (ret != 1) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
+       }
 
-       rec = winsdb_record(res[0], tmp_ctx);
-       if (rec == NULL) goto failed;
-       rec->name           = name;
+       status = winsdb_record(res[0], name, tmp_ctx, &rec);
+       if (!NT_STATUS_IS_OK(status)) goto failed;
 
        /* see if it has already expired */
        if (rec->state == WINS_REC_ACTIVE &&
@@ -465,21 +495,31 @@ struct winsdb_record *winsdb_load(struct wins_server *winssrv,
 
        talloc_steal(mem_ctx, rec);
        talloc_free(tmp_ctx);
-       return rec;
+       *_rec = rec;
+       return NT_STATUS_OK;
 
 failed:
        talloc_free(tmp_ctx);
-       return NULL;
+       return status;
 }
 
-struct winsdb_record *winsdb_record(struct ldb_message *msg, TALLOC_CTX *mem_ctx)
+NTSTATUS winsdb_record(struct ldb_message *msg, struct nbt_name *name, TALLOC_CTX *mem_ctx, struct winsdb_record **_rec)
 {
+       NTSTATUS status;
        struct winsdb_record *rec;
        struct ldb_message_element *el;
        uint32_t i;
 
        rec = talloc(mem_ctx, struct winsdb_record);
-       if (rec == NULL) goto failed;
+       if (rec == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
+       }
+
+       if (!name) {
+               status = winsdb_nbt_name(rec, msg->dn, &name);
+               if (!NT_STATUS_IS_OK(status)) goto failed;
+       }
 
        /* parse it into a more convenient winsdb_record structure */
        rec->name           = name;
@@ -494,21 +534,31 @@ struct winsdb_record *winsdb_record(struct ldb_message *msg, TALLOC_CTX *mem_ctx
        if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL;
 
        el = ldb_msg_find_element(msg, "address");
-       if (el == NULL) goto failed;
+       if (el == NULL) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto failed;
+       }
 
        rec->addresses     = talloc_array(rec, struct winsdb_addr *, el->num_values+1);
-       if (rec->addresses == NULL) goto failed;
+       if (rec->addresses == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto failed;
+       }
 
        for (i=0;i<el->num_values;i++) {
-               rec->addresses[i] = winsdb_addr_decode(rec, rec->addresses, &el->values[i]);
-               if (rec->addresses[i] == NULL) goto failed;
+               status = winsdb_addr_decode(rec, &el->values[i], rec->addresses, &rec->addresses[i]);
+               if (!NT_STATUS_IS_OK(status)) goto failed;
        }
        rec->addresses[i] = NULL;
 
-       return rec;
+       *_rec = rec;
+       return NT_STATUS_OK;
 failed:
+       if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status)) {
+               DEBUG(1,("winsdb_record: corrupted record: %s\n", ldb_dn_linearize(rec, msg->dn)));
+       }
        talloc_free(rec);
-       return NULL;
+       return status;
 }
 
 /*
index 37b59cdc7f52853406291e76f6a75e3de681be3b..d5043caa298428986d8e296c26d2510c53877d50 100644 (file)
@@ -110,6 +110,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
                                     struct nbt_name_packet *packet, 
                                     const struct nbt_peer_socket *src)
 {
+       NTSTATUS status;
        struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
@@ -125,10 +126,13 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
                goto done;
        }
 
-       rec = winsdb_load(winssrv, name, packet);
-       if (rec == NULL) {
+       status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
+       if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
                rcode = wins_register_new(nbtsock, packet, src);
                goto done;
+       } else if (!NT_STATUS_IS_OK(status)) {
+               rcode = NBT_RCODE_SVR;
+               goto done;
        } else if (rec->state != WINS_REC_ACTIVE) {
                winsdb_delete(winssrv, rec);
                rcode = wins_register_new(nbtsock, packet, src);
@@ -182,6 +186,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
                                  struct nbt_name_packet *packet, 
                                  const struct nbt_peer_socket *src)
 {
+       NTSTATUS status;
        struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
@@ -189,8 +194,8 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
        struct winsdb_record *rec;
        const char **addresses;
 
-       rec = winsdb_load(winssrv, name, packet);
-       if (rec == NULL || rec->state != WINS_REC_ACTIVE) {
+       status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
+       if (!NT_STATUS_IS_OK(status) || rec->state != WINS_REC_ACTIVE) {
                nbtd_negative_name_query_reply(nbtsock, packet, src);
                return;
        }
@@ -212,14 +217,15 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
                                    struct nbt_name_packet *packet, 
                                    const struct nbt_peer_socket *src)
 {
+       NTSTATUS status;
        struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
                                                       struct nbtd_interface);
        struct wins_server *winssrv = iface->nbtsrv->winssrv;
        struct nbt_name *name = &packet->questions[0].name;
        struct winsdb_record *rec;
 
-       rec = winsdb_load(winssrv, name, packet);
-       if (rec == NULL || 
+       status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
+       if (!NT_STATUS_IS_OK(status) || 
            rec->state != WINS_REC_ACTIVE || 
            IS_GROUP_NAME(name, rec->nb_flags)) {
                goto done;
index defa3ad09ab0a61145a9ec942c3d7121a2b1efbe..64336992f6d870aa6772b0a98a3c73b5f3c50582 100644 (file)
@@ -54,12 +54,13 @@ static void wins_wack_deny(struct wack_state *state)
 */
 static void wins_wack_allow(struct wack_state *state)
 {
+       NTSTATUS status;
        uint32_t ttl;
        time_t now = time(NULL);
        struct winsdb_record *rec = state->rec, *rec2;
 
-       rec2 = winsdb_load(state->winssrv, rec->name, state);
-       if (rec2 == NULL || rec2->version != rec->version) {
+       status = winsdb_lookup(state->winssrv->wins_db, rec->name, state, &rec2);
+       if (!NT_STATUS_IS_OK(status) || rec2->version != rec->version) {
                DEBUG(1,("WINS: record %s changed during WACK - failing registration\n",
                         nbt_name_string(state, rec->name)));
                wins_wack_deny(state);
index ab86aa209f5e0dae1a4db8e9d347ecd289449439..4472a0fede29d872aa463481cb895380457bf6a1 100644 (file)
@@ -263,8 +263,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
                return NT_STATUS_OK;
        }
 
-       filter = talloc_asprintf(call, "(&(winsOwner=%s)(objectClass=wins)(active=1)(version>=%llu)(version<=%llu))",
-                                owner->owner.address, owner_in->min_version, owner_in->max_version);
+       filter = talloc_asprintf(call, "(&(winsOwner=%s)(objectClass=winsRecord)(state>=%u)(versionID>=%llu)(versionID<=%llu))",
+                                owner->owner.address, WINS_REC_ACTIVE, owner_in->min_version, owner_in->max_version);
        NT_STATUS_HAVE_NO_MEMORY(filter);
        ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &res);
        if (res != NULL) {
@@ -277,13 +277,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
        NT_STATUS_HAVE_NO_MEMORY(names);
 
        for (i=0; i < ret; i++) {
-               rec = winsdb_record(res[i], call);
-               NT_STATUS_HAVE_NO_MEMORY(rec);
-
-               rec->name       = winsdb_nbt_name(names, res[i]->dn);
-               if (!rec->name) {
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
+               status = winsdb_record(res[i], NULL, call, &rec);
+               NT_STATUS_NOT_OK_RETURN(status);
 
                status = wreplsrv_record2wins_name(names, &names[i], rec);
                NT_STATUS_NOT_OK_RETURN(status);
index 866090f40051825a4ee1f871f52cee193ec394ae..dd49b37d78be3867d92bf7e23fa26658873f6422 100644 (file)
@@ -205,13 +205,13 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
        uint64_t version;
        const char * const attrs[] = {
                "winsOwner",
-               "version",
+               "versionID",
                NULL
        };
 
        /* find the record in the WINS database */
        ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE,
-                        "(objectClass=wins)", attrs, &res);
+                        "(objectClass=winsRecord)", attrs, &res);
        if (res != NULL) {
                talloc_steal(tmp_ctx, res);
        }
@@ -221,7 +221,7 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
 
        for (i=0; i < ret; i++) {
                wins_owner     = ldb_msg_find_string(res[i], "winsOwner", NULL);
-               version        = ldb_msg_find_uint64(res[i], "version", 0);
+               version        = ldb_msg_find_uint64(res[i], "versionID", 0);
 
                if (wins_owner) { 
                        status = wreplsrv_add_table(service,