1
0
mirror of https://github.com/samba-team/samba.git synced 2025-09-13 17:44:21 +03:00

r11040: r10357@SERNOX: metze | 2005-09-20 21:28:11 +0200

- 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 82bad3f3ef)
This commit is contained in:
Stefan Metzmacher
2005-10-14 12:55:59 +00:00
committed by Gerald (Jerry) Carter
parent 8755cd4a9c
commit 676b220f3e
5 changed files with 115 additions and 63 deletions

View File

@@ -83,7 +83,7 @@ static struct ldb_dn *winsdb_dn(TALLOC_CTX *mem_ctx, struct nbt_name *name)
{ {
struct ldb_dn *dn; 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) { if (dn && name->name && *name->name) {
dn = ldb_dn_string_compose(mem_ctx, dn, "name=%s", 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; 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; struct nbt_name *name;
uint32_t cur = 0; uint32_t cur = 0;
name = talloc(mem_ctx, struct nbt_name); 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) { if (dn->comp_num > 3) {
status = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto failed; goto failed;
} }
@@ -117,26 +122,31 @@ struct nbt_name *winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
cur++; cur++;
} else { } else {
name->name = talloc_strdup(name, ""); 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) { 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++; cur++;
} else { } else {
status = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto failed; goto failed;
} }
return name; *_name = name;
return NT_STATUS_OK;
failed: failed:
talloc_free(name); talloc_free(name);
return NULL; return status;
} }
/* /*
decode the winsdb_addr("address") attribute: decode the winsdb_addr("address") attribute:
"172.31.1.1" or "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 are valid records
*/ */
static BOOL winsdb_remove_version(struct wins_server *winssrv, uint64_t version) 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) 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; struct winsdb_addr *addr;
char *address; char *address;
char *wins_owner; char *wins_owner;
@@ -254,7 +265,10 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_
char *p; char *p;
addr = talloc(mem_ctx, struct winsdb_addr); addr = talloc(mem_ctx, struct winsdb_addr);
if (!addr) return NULL; if (!addr) {
status = NT_STATUS_NO_MEMORY;
goto failed;
}
address = (char *)val->data; 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->address = talloc_steal(addr, val->data);
addr->wins_owner = rec->wins_owner; addr->wins_owner = rec->wins_owner;
addr->expire_time = rec->expire_time; addr->expire_time = rec->expire_time;
return addr; *_addr = addr;
return NT_STATUS_OK;
} }
*p = '\0';p++; *p = '\0';p++;
addr->address = talloc_strdup(addr, address); addr->address = talloc_strdup(addr, address);
if (!addr->address) { if (!addr->address) {
talloc_free(addr); status = NT_STATUS_NO_MEMORY;
return NULL; goto failed;
} }
if (strncmp("winsOwner:", p, 10) != 0) { if (strncmp("winsOwner:", p, 10) != 0) {
/* invalid record */ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
talloc_free(addr); goto failed;
return NULL;
} }
wins_owner = p + 10; wins_owner = p + 10;
p = strchr(wins_owner, ';'); p = strchr(wins_owner, ';');
if (!p) { if (!p) {
/* invalid record */ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
talloc_free(addr); goto failed;
return NULL;
} }
*p = '\0';p++; *p = '\0';p++;
addr->wins_owner = talloc_strdup(addr, wins_owner); addr->wins_owner = talloc_strdup(addr, wins_owner);
if (!addr->wins_owner) { if (!addr->wins_owner) {
talloc_free(addr); status = NT_STATUS_NO_MEMORY;
return NULL; goto failed;
} }
if (strncmp("expireTime:", p, 11) != 0) { if (strncmp("expireTime:", p, 11) != 0) {
/* invalid record */ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
talloc_free(addr); goto failed;
return NULL;
} }
expire_time = p + 11; 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); 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: 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, static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg,
const char *attr_name, struct winsdb_addr *addr) 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; struct ldb_val val;
const char *str; 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, addr->address, addr->wins_owner,
ldap_timestring(msg, addr->expire_time)); ldap_timestring(msg, addr->expire_time));
if (!str) return -1; 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 load a WINS entry from the database
*/ */
struct winsdb_record *winsdb_load(struct wins_server *winssrv, NTSTATUS winsdb_lookup(struct ldb_context *wins_db,
struct nbt_name *name, TALLOC_CTX *mem_ctx) struct nbt_name *name,
TALLOC_CTX *mem_ctx,
struct winsdb_record **_rec)
{ {
NTSTATUS status;
struct ldb_message **res = NULL; struct ldb_message **res = NULL;
int ret; int ret;
struct winsdb_record *rec; struct winsdb_record *rec;
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
/* find the record in the WINS database */ /* 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); NULL, NULL, &res);
if (res != NULL) { if (res != NULL) {
talloc_steal(tmp_ctx, res); 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); status = winsdb_record(res[0], name, tmp_ctx, &rec);
if (rec == NULL) goto failed; if (!NT_STATUS_IS_OK(status)) goto failed;
rec->name = name;
/* see if it has already expired */ /* see if it has already expired */
if (rec->state == WINS_REC_ACTIVE && 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_steal(mem_ctx, rec);
talloc_free(tmp_ctx); talloc_free(tmp_ctx);
return rec; *_rec = rec;
return NT_STATUS_OK;
failed: failed:
talloc_free(tmp_ctx); 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 winsdb_record *rec;
struct ldb_message_element *el; struct ldb_message_element *el;
uint32_t i; uint32_t i;
rec = talloc(mem_ctx, struct winsdb_record); 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 */ /* parse it into a more convenient winsdb_record structure */
rec->name = name; 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; if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL;
el = ldb_msg_find_element(msg, "address"); 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); 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++) { for (i=0;i<el->num_values;i++) {
rec->addresses[i] = winsdb_addr_decode(rec, rec->addresses, &el->values[i]); status = winsdb_addr_decode(rec, &el->values[i], rec->addresses, &rec->addresses[i]);
if (rec->addresses[i] == NULL) goto failed; if (!NT_STATUS_IS_OK(status)) goto failed;
} }
rec->addresses[i] = NULL; rec->addresses[i] = NULL;
return rec; *_rec = rec;
return NT_STATUS_OK;
failed: 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); talloc_free(rec);
return NULL; return status;
} }
/* /*

View File

@@ -110,6 +110,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet, struct nbt_name_packet *packet,
const struct nbt_peer_socket *src) const struct nbt_peer_socket *src)
{ {
NTSTATUS status;
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
struct nbtd_interface); struct nbtd_interface);
struct wins_server *winssrv = iface->nbtsrv->winssrv; struct wins_server *winssrv = iface->nbtsrv->winssrv;
@@ -125,10 +126,13 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
goto done; goto done;
} }
rec = winsdb_load(winssrv, name, packet); status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
if (rec == NULL) { if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
rcode = wins_register_new(nbtsock, packet, src); rcode = wins_register_new(nbtsock, packet, src);
goto done; goto done;
} else if (!NT_STATUS_IS_OK(status)) {
rcode = NBT_RCODE_SVR;
goto done;
} else if (rec->state != WINS_REC_ACTIVE) { } else if (rec->state != WINS_REC_ACTIVE) {
winsdb_delete(winssrv, rec); winsdb_delete(winssrv, rec);
rcode = wins_register_new(nbtsock, packet, src); 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, struct nbt_name_packet *packet,
const struct nbt_peer_socket *src) const struct nbt_peer_socket *src)
{ {
NTSTATUS status;
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
struct nbtd_interface); struct nbtd_interface);
struct wins_server *winssrv = iface->nbtsrv->winssrv; 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; struct winsdb_record *rec;
const char **addresses; const char **addresses;
rec = winsdb_load(winssrv, name, packet); status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
if (rec == NULL || rec->state != WINS_REC_ACTIVE) { if (!NT_STATUS_IS_OK(status) || rec->state != WINS_REC_ACTIVE) {
nbtd_negative_name_query_reply(nbtsock, packet, src); nbtd_negative_name_query_reply(nbtsock, packet, src);
return; return;
} }
@@ -212,14 +217,15 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
struct nbt_name_packet *packet, struct nbt_name_packet *packet,
const struct nbt_peer_socket *src) const struct nbt_peer_socket *src)
{ {
NTSTATUS status;
struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
struct nbtd_interface); struct nbtd_interface);
struct wins_server *winssrv = iface->nbtsrv->winssrv; struct wins_server *winssrv = iface->nbtsrv->winssrv;
struct nbt_name *name = &packet->questions[0].name; struct nbt_name *name = &packet->questions[0].name;
struct winsdb_record *rec; struct winsdb_record *rec;
rec = winsdb_load(winssrv, name, packet); status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
if (rec == NULL || if (!NT_STATUS_IS_OK(status) ||
rec->state != WINS_REC_ACTIVE || rec->state != WINS_REC_ACTIVE ||
IS_GROUP_NAME(name, rec->nb_flags)) { IS_GROUP_NAME(name, rec->nb_flags)) {
goto done; goto done;

View File

@@ -54,12 +54,13 @@ static void wins_wack_deny(struct wack_state *state)
*/ */
static void wins_wack_allow(struct wack_state *state) static void wins_wack_allow(struct wack_state *state)
{ {
NTSTATUS status;
uint32_t ttl; uint32_t ttl;
time_t now = time(NULL); time_t now = time(NULL);
struct winsdb_record *rec = state->rec, *rec2; struct winsdb_record *rec = state->rec, *rec2;
rec2 = winsdb_load(state->winssrv, rec->name, state); status = winsdb_lookup(state->winssrv->wins_db, rec->name, state, &rec2);
if (rec2 == NULL || rec2->version != rec->version) { if (!NT_STATUS_IS_OK(status) || rec2->version != rec->version) {
DEBUG(1,("WINS: record %s changed during WACK - failing registration\n", DEBUG(1,("WINS: record %s changed during WACK - failing registration\n",
nbt_name_string(state, rec->name))); nbt_name_string(state, rec->name)));
wins_wack_deny(state); wins_wack_deny(state);

View File

@@ -263,8 +263,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
return NT_STATUS_OK; return NT_STATUS_OK;
} }
filter = talloc_asprintf(call, "(&(winsOwner=%s)(objectClass=wins)(active=1)(version>=%llu)(version<=%llu))", filter = talloc_asprintf(call, "(&(winsOwner=%s)(objectClass=winsRecord)(state>=%u)(versionID>=%llu)(versionID<=%llu))",
owner->owner.address, owner_in->min_version, owner_in->max_version); owner->owner.address, WINS_REC_ACTIVE, owner_in->min_version, owner_in->max_version);
NT_STATUS_HAVE_NO_MEMORY(filter); NT_STATUS_HAVE_NO_MEMORY(filter);
ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &res); ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &res);
if (res != NULL) { if (res != NULL) {
@@ -277,13 +277,8 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
NT_STATUS_HAVE_NO_MEMORY(names); NT_STATUS_HAVE_NO_MEMORY(names);
for (i=0; i < ret; i++) { for (i=0; i < ret; i++) {
rec = winsdb_record(res[i], call); status = winsdb_record(res[i], NULL, call, &rec);
NT_STATUS_HAVE_NO_MEMORY(rec); NT_STATUS_NOT_OK_RETURN(status);
rec->name = winsdb_nbt_name(names, res[i]->dn);
if (!rec->name) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
status = wreplsrv_record2wins_name(names, &names[i], rec); status = wreplsrv_record2wins_name(names, &names[i], rec);
NT_STATUS_NOT_OK_RETURN(status); NT_STATUS_NOT_OK_RETURN(status);

View File

@@ -205,13 +205,13 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
uint64_t version; uint64_t version;
const char * const attrs[] = { const char * const attrs[] = {
"winsOwner", "winsOwner",
"version", "versionID",
NULL NULL
}; };
/* find the record in the WINS database */ /* find the record in the WINS database */
ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE, ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE,
"(objectClass=wins)", attrs, &res); "(objectClass=winsRecord)", attrs, &res);
if (res != NULL) { if (res != NULL) {
talloc_steal(tmp_ctx, res); talloc_steal(tmp_ctx, res);
} }
@@ -221,7 +221,7 @@ static NTSTATUS wreplsrv_load_table(struct wreplsrv_service *service)
for (i=0; i < ret; i++) { for (i=0; i < ret; i++) {
wins_owner = ldb_msg_find_string(res[i], "winsOwner", NULL); 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) { if (wins_owner) {
status = wreplsrv_add_table(service, status = wreplsrv_add_table(service,