diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-16 15:19:49 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:10:44 -0500 |
commit | 12d4b8a95131695724ad3b20c5384a5b2f76f583 (patch) | |
tree | 020eaec246feface50ae95fa48fb38d248aa9477 /source4 | |
parent | a0667e11ae2c92850919a1568ca47fa83d29af6f (diff) | |
download | samba-12d4b8a95131695724ad3b20c5384a5b2f76f583.tar.gz samba-12d4b8a95131695724ad3b20c5384a5b2f76f583.tar.bz2 samba-12d4b8a95131695724ad3b20c5384a5b2f76f583.zip |
r5418: - added version numbers to WINS database records in preparation for adding server side
replication support
- on a WACK registration success, check that the database record
hasn't changed during the WACK processing. If it has, then fail
the registration
(This used to be commit 2acd79b95931b57efae9f7c239bc08dc143f5225)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/nbt_server/winsdb.c | 70 | ||||
-rw-r--r-- | source4/nbt_server/winsdb.h | 6 | ||||
-rw-r--r-- | source4/nbt_server/winsserver.c | 2 | ||||
-rw-r--r-- | source4/nbt_server/winswack.c | 10 |
4 files changed, 84 insertions, 4 deletions
diff --git a/source4/nbt_server/winsdb.c b/source4/nbt_server/winsdb.c index 4eff12901f..66e84c668b 100644 --- a/source4/nbt_server/winsdb.c +++ b/source4/nbt_server/winsdb.c @@ -28,6 +28,62 @@ #include "system/time.h" /* + save the min/max version IDs for the database +*/ +static BOOL winsdb_save_version(struct wins_server *winssrv) +{ + int i, ret = 0; + struct ldb_context *ldb = winssrv->wins_db->ldb; + struct ldb_message *msg = ldb_msg_new(winssrv); + if (msg == NULL) goto failed; + + msg->dn = talloc_strdup(msg, "CN=VERSION"); + if (msg->dn == NULL) goto failed; + + ret |= ldb_msg_add_fmt(ldb, msg, "minVersion", "%llu", winssrv->min_version); + ret |= ldb_msg_add_fmt(ldb, msg, "maxVersion", "%llu", winssrv->max_version); + if (ret != 0) goto failed; + + for (i=0;i<msg->num_elements;i++) { + msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + + ret = ldb_modify(ldb, msg); + if (ret != 0) ret = ldb_add(ldb, msg); + if (ret != 0) goto failed; + + talloc_free(msg); + return True; + +failed: + talloc_free(msg); + return False; +} + +/* + allocate a new version id for a record +*/ +static uint64_t winsdb_allocate_version(struct wins_server *winssrv) +{ + winssrv->max_version++; + if (!winsdb_save_version(winssrv)) { + return 0; + } + return winssrv->max_version; +} + +/* + allocate a new version id for a record +*/ +static void winsdb_remove_version(struct wins_server *winssrv, uint64_t version) +{ + if (version == winssrv->min_version) { + winssrv->min_version++; + winsdb_save_version(winssrv); + } +} + +/* load a WINS entry from the database */ struct winsdb_record *winsdb_load(struct wins_server *winssrv, @@ -60,6 +116,7 @@ struct winsdb_record *winsdb_load(struct wins_server *winssrv, rec->nb_flags = ldb_msg_find_int(res[0], "nbFlags", 0); rec->expire_time = ldap_string_to_time(ldb_msg_find_string(res[0], "expires", NULL)); rec->registered_by = ldb_msg_find_string(res[0], "registeredBy", NULL); + rec->version = ldb_msg_find_uint64(res[0], "version", 0); talloc_steal(rec, rec->registered_by); el = ldb_msg_find_element(res[0], "address"); @@ -109,6 +166,7 @@ static struct ldb_message *winsdb_message(struct wins_server *winssrv, ret |= ldb_msg_add_string(ldb, msg, "registeredBy", rec->registered_by); ret |= ldb_msg_add_string(ldb, msg, "expires", ldap_timestring(msg, rec->expire_time)); + ret |= ldb_msg_add_fmt(ldb, msg, "version", "%llu", rec->version); for (i=0;rec->addresses[i];i++) { ret |= ldb_msg_add_string(ldb, msg, "address", rec->addresses[i]); } @@ -130,6 +188,9 @@ uint8_t winsdb_add(struct wins_server *winssrv, struct winsdb_record *rec) TALLOC_CTX *tmp_ctx = talloc_new(winssrv); int ret; + rec->version = winsdb_allocate_version(winssrv); + if (rec->version == 0) goto failed; + msg = winsdb_message(winssrv, rec, tmp_ctx); if (msg == NULL) goto failed; ret = ldb_add(ldb, msg); @@ -155,6 +216,9 @@ uint8_t winsdb_modify(struct wins_server *winssrv, struct winsdb_record *rec) int ret; int i; + rec->version = winsdb_allocate_version(winssrv); + if (rec->version == 0) goto failed; + msg = winsdb_message(winssrv, rec, tmp_ctx); if (msg == NULL) goto failed; @@ -177,14 +241,16 @@ failed: /* delete a WINS record from the database */ -uint8_t winsdb_delete(struct wins_server *winssrv, struct nbt_name *name) +uint8_t winsdb_delete(struct wins_server *winssrv, struct winsdb_record *rec) { struct ldb_context *ldb = winssrv->wins_db->ldb; TALLOC_CTX *tmp_ctx = talloc_new(winssrv); int ret; const char *dn; - dn = talloc_asprintf(tmp_ctx, "NAME=%s", nbt_name_string(tmp_ctx, name)); + winsdb_remove_version(winssrv, rec->version); + + dn = talloc_asprintf(tmp_ctx, "NAME=%s", nbt_name_string(tmp_ctx, rec->name)); if (dn == NULL) goto failed; ret = ldb_delete(ldb, dn); diff --git a/source4/nbt_server/winsdb.h b/source4/nbt_server/winsdb.h index 0774757ef9..6d395461c6 100644 --- a/source4/nbt_server/winsdb.h +++ b/source4/nbt_server/winsdb.h @@ -35,6 +35,7 @@ struct winsdb_record { time_t expire_time; const char *registered_by; const char **addresses; + uint64_t version; }; struct wins_server { @@ -43,4 +44,9 @@ struct wins_server { uint32_t min_ttl; uint32_t max_ttl; + + /* these are the minimum and maximum record version IDs in the + database. They are needed for replication */ + uint64_t min_version; + uint64_t max_version; }; diff --git a/source4/nbt_server/winsserver.c b/source4/nbt_server/winsserver.c index c1eed0b1fa..6d8770431e 100644 --- a/source4/nbt_server/winsserver.c +++ b/source4/nbt_server/winsserver.c @@ -123,7 +123,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, rcode = wins_register_new(nbtsock, packet, src_address, src_port); goto done; } else if (rec->state != WINS_REC_ACTIVE) { - winsdb_delete(winssrv, rec->name); + winsdb_delete(winssrv, rec); rcode = wins_register_new(nbtsock, packet, src_address, src_port); goto done; } diff --git a/source4/nbt_server/winswack.c b/source4/nbt_server/winswack.c index 190b1cdec7..da8efff8d9 100644 --- a/source4/nbt_server/winswack.c +++ b/source4/nbt_server/winswack.c @@ -57,7 +57,15 @@ static void wins_wack_allow(struct wack_state *state) { uint32_t ttl; time_t now = time(NULL); - struct winsdb_record *rec = state->rec; + struct winsdb_record *rec = state->rec, *rec2; + + rec2 = winsdb_load(state->winssrv, rec->name, state); + if (rec2 == NULL || 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); + return; + } nbtd_name_registration_reply(state->nbtsock, state->request_packet, state->src_address, state->src_port, NBT_RCODE_OK); |