Author: tridge Date: 2005-02-16 15:19:49 +0000 (Wed, 16 Feb 2005) New Revision: 5418
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=5418 Log: - 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 Modified: branches/SAMBA_4_0/source/nbt_server/winsdb.c branches/SAMBA_4_0/source/nbt_server/winsdb.h branches/SAMBA_4_0/source/nbt_server/winsserver.c branches/SAMBA_4_0/source/nbt_server/winswack.c Changeset: Modified: branches/SAMBA_4_0/source/nbt_server/winsdb.c =================================================================== --- branches/SAMBA_4_0/source/nbt_server/winsdb.c 2005-02-16 11:09:10 UTC (rev 5417) +++ branches/SAMBA_4_0/source/nbt_server/winsdb.c 2005-02-16 15:19:49 UTC (rev 5418) @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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); Modified: branches/SAMBA_4_0/source/nbt_server/winsdb.h =================================================================== --- branches/SAMBA_4_0/source/nbt_server/winsdb.h 2005-02-16 11:09:10 UTC (rev 5417) +++ branches/SAMBA_4_0/source/nbt_server/winsdb.h 2005-02-16 15:19:49 UTC (rev 5418) @@ -35,6 +35,7 @@ time_t expire_time; const char *registered_by; const char **addresses; + uint64_t version; }; struct wins_server { @@ -43,4 +44,9 @@ 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; }; Modified: branches/SAMBA_4_0/source/nbt_server/winsserver.c =================================================================== --- branches/SAMBA_4_0/source/nbt_server/winsserver.c 2005-02-16 11:09:10 UTC (rev 5417) +++ branches/SAMBA_4_0/source/nbt_server/winsserver.c 2005-02-16 15:19:49 UTC (rev 5418) @@ -123,7 +123,7 @@ 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; } Modified: branches/SAMBA_4_0/source/nbt_server/winswack.c =================================================================== --- branches/SAMBA_4_0/source/nbt_server/winswack.c 2005-02-16 11:09:10 UTC (rev 5417) +++ branches/SAMBA_4_0/source/nbt_server/winswack.c 2005-02-16 15:19:49 UTC (rev 5418) @@ -57,8 +57,16 @@ { 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);