⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winsdb.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   WINS database routines   Copyright (C) Andrew Tridgell	2005   Copyright (C) Stefan Metzmacher	2005         This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "nbt_server/nbt_server.h"#include "nbt_server/wins/winsdb.h"#include "lib/ldb/include/ldb.h"#include "lib/ldb/include/ldb_errors.h"#include "librpc/gen_ndr/ndr_nbt.h"#include "system/time.h"#include "ldb_wrap.h"#include "system/network.h"#include "lib/socket/netif.h"#include "param/param.h"uint64_t winsdb_get_maxVersion(struct winsdb_handle *h){	int ret;	struct ldb_context *ldb = h->ldb;	struct ldb_dn *dn;	struct ldb_result *res = NULL;	TALLOC_CTX *tmp_ctx = talloc_new(ldb);	uint64_t maxVersion = 0;	dn = ldb_dn_new(tmp_ctx, ldb, "CN=VERSION");	if (!dn) goto failed;	/* find the record in the WINS database */	ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 			 NULL, NULL, &res);	if (ret != LDB_SUCCESS) goto failed;	talloc_steal(tmp_ctx, res);	if (res->count > 1) goto failed;	if (res->count == 1) {		maxVersion = ldb_msg_find_attr_as_uint64(res->msgs[0], "maxVersion", 0);	}failed:	talloc_free(tmp_ctx);	return maxVersion;}/* if newVersion == 0 return the old maxVersion + 1 and save it if newVersion > 0 return MAX(oldMaxVersion, newMaxVersion) and save it*/uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion){	int trans;	int ret;	struct ldb_dn *dn;	struct ldb_result *res = NULL;	struct ldb_message *msg = NULL;	struct ldb_context *wins_db = h->ldb;	TALLOC_CTX *tmp_ctx = talloc_new(wins_db);	uint64_t oldMaxVersion = 0;	trans = ldb_transaction_start(wins_db);	if (trans != LDB_SUCCESS) goto failed;	dn = ldb_dn_new(tmp_ctx, wins_db, "CN=VERSION");	if (!dn) goto failed;	/* find the record in the WINS database */	ret = ldb_search(wins_db, dn, LDB_SCOPE_BASE, NULL, NULL, &res);	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);	}	if (newMaxVersion == 0) {		newMaxVersion = oldMaxVersion + 1;	} else {		newMaxVersion = MAX(oldMaxVersion, newMaxVersion);	}	msg = ldb_msg_new(tmp_ctx);	if (!msg) goto failed;	msg->dn = dn;	ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);	if (ret != 0) goto failed;	ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion");	if (ret != 0) goto failed;	ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL);	if (ret != 0) goto failed;	ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion);	if (ret != 0) goto failed;	ret = ldb_modify(wins_db, msg);	if (ret != 0) ret = ldb_add(wins_db, msg);	if (ret != 0) goto failed;	trans = ldb_transaction_commit(wins_db);	if (trans != LDB_SUCCESS) goto failed;	talloc_free(tmp_ctx);	return newMaxVersion;failed:	if (trans == LDB_SUCCESS) ldb_transaction_cancel(wins_db);	talloc_free(tmp_ctx);	return 0;}uint64_t winsdb_get_seqnumber(struct winsdb_handle *h){	int ret;	struct ldb_context *ldb = h->ldb;	struct ldb_dn *dn;	struct ldb_result *res = NULL;	TALLOC_CTX *tmp_ctx = talloc_new(ldb);	uint64_t seqnumber = 0;	dn = ldb_dn_new(tmp_ctx, ldb, "@BASEINFO");	if (!dn) goto failed;	/* find the record in the WINS database */	ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 			 NULL, NULL, &res);	if (ret != LDB_SUCCESS) goto failed;	talloc_steal(tmp_ctx, res);	if (res->count > 1) goto failed;	if (res->count == 1) {		seqnumber = ldb_msg_find_attr_as_uint64(res->msgs[0], "sequenceNumber", 0);	}failed:	talloc_free(tmp_ctx);	return seqnumber;}/*  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){	struct ldb_dn *dn;	dn = ldb_dn_new_fmt(mem_ctx, ldb, "type=0x%02X", name->type);	if (ldb_dn_is_valid(dn) && name->name && *name->name) {		ldb_dn_add_child_fmt(dn, "name=%s", name->name);	}	if (ldb_dn_is_valid(dn) && name->scope && *name->scope) {		ldb_dn_add_child_fmt(dn, "scope=%s", name->scope);	}	return dn;}static NTSTATUS winsdb_nbt_name(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct nbt_name **_name){	NTSTATUS status;	struct nbt_name *name;	unsigned int comp_num;	uint32_t cur = 0;	name = talloc(mem_ctx, struct nbt_name);	if (!name) {		status = NT_STATUS_NO_MEMORY;		goto failed;	}	comp_num = ldb_dn_get_comp_num(dn);	if (comp_num > 3) {		status = NT_STATUS_INTERNAL_DB_CORRUPTION;		goto failed;	}	if (comp_num > cur && strcasecmp("scope", ldb_dn_get_component_name(dn, cur)) == 0) {		name->scope	= (const char *)talloc_strdup(name, (char *)ldb_dn_get_component_val(dn, cur)->data);		cur++;	} else {		name->scope	= NULL;	}	if (comp_num > cur && strcasecmp("name", ldb_dn_get_component_name(dn, cur)) == 0) {		name->name	= (const char *)talloc_strdup(name, (char *)ldb_dn_get_component_val(dn, cur)->data);		cur++;	} else {		name->name	= talloc_strdup(name, "");		if (!name->name) {			status = NT_STATUS_NO_MEMORY;			goto failed;		}	}	if (comp_num > cur && strcasecmp("type", ldb_dn_get_component_name(dn, cur)) == 0) {		name->type	= strtoul((char *)ldb_dn_get_component_val(dn, cur)->data, NULL, 0);		cur++;	} else {		status = NT_STATUS_INTERNAL_DB_CORRUPTION;		goto failed;	}	*_name = name;	return NT_STATUS_OK;failed:	talloc_free(name);	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;" are valid records*/static NTSTATUS winsdb_addr_decode(struct winsdb_handle *h, struct winsdb_record *rec, struct ldb_val *val,				   TALLOC_CTX *mem_ctx, struct winsdb_addr **_addr){	NTSTATUS status;	struct winsdb_addr *addr;	const char *address;	const char *wins_owner;	const char *expire_time;	char *p;	addr = talloc(mem_ctx, struct winsdb_addr);	if (!addr) {		status = NT_STATUS_NO_MEMORY;		goto failed;	}	address = (char *)val->data;	p = strchr(address, ';');	if (!p) {		/* support old entries, with only the address */		addr->address		= (const char *)talloc_steal(addr, val->data);		addr->wins_owner	= talloc_reference(addr, rec->wins_owner);		if (!addr->wins_owner) {			status = NT_STATUS_NO_MEMORY;			goto failed;		}		addr->expire_time	= rec->expire_time;		*_addr = addr;		return NT_STATUS_OK;	}	*p = '\0';p++;	addr->address = talloc_strdup(addr, address);	if (!addr->address) {		status = NT_STATUS_NO_MEMORY;		goto failed;	}	if (strncmp("winsOwner:", p, 10) != 0) {		status = NT_STATUS_INTERNAL_DB_CORRUPTION;		goto failed;	}	wins_owner = p + 10;	p = strchr(wins_owner, ';');	if (!p) {		status = NT_STATUS_INTERNAL_DB_CORRUPTION;		goto failed;	}	*p = '\0';p++;	if (strcmp(wins_owner, "0.0.0.0") == 0) {		wins_owner = h->local_owner;	}	addr->wins_owner = talloc_strdup(addr, wins_owner);	if (!addr->wins_owner) {		status = NT_STATUS_NO_MEMORY;		goto failed;	}	if (strncmp("expireTime:", p, 11) != 0) {		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 = ldb_string_to_time(expire_time);	*_addr = addr;	return NT_STATUS_OK;failed:	talloc_free(addr);	return status;}/* encode the winsdb_addr("address") attribute like this: non-static record: "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;" static record: "172.31.1.1"*/static int ldb_msg_add_winsdb_addr(struct ldb_message *msg, struct winsdb_record *rec,				   const char *attr_name, struct winsdb_addr *addr){	struct ldb_val val;	const char *str;	if (rec->is_static) {		str = talloc_strdup(msg, addr->address);		if (!str) return -1;	} else {		char *expire_time;		expire_time = ldb_timestring(msg, addr->expire_time);		if (!expire_time) return -1;		str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s;",				      addr->address, addr->wins_owner,				      expire_time);		talloc_free(expire_time);		if (!str) return -1;	}	val.data = discard_const_p(uint8_t, str);	val.length = strlen(str);	return ldb_msg_add_value(msg, attr_name, &val, NULL);}struct winsdb_addr **winsdb_addr_list_make(TALLOC_CTX *mem_ctx){	struct winsdb_addr **addresses;	addresses = talloc_array(mem_ctx, struct winsdb_addr *, 1);	if (!addresses) return NULL;	addresses[0] = NULL;	return addresses;}static int winsdb_addr_sort_list (struct winsdb_addr **p1, struct winsdb_addr **p2, void *opaque){	struct winsdb_addr *a1 = talloc_get_type(*p1, struct winsdb_addr);	struct winsdb_addr *a2 = talloc_get_type(*p2, struct winsdb_addr);	struct winsdb_handle *h= talloc_get_type(opaque, struct winsdb_handle);	bool a1_owned = false;	bool a2_owned = false;	/*	 * first the owned addresses with the newest to the oldest address	 * then the replica addresses with the newest to the oldest address	 */	if (a2->expire_time != a1->expire_time) {		return a2->expire_time - a1->expire_time;	}	if (strcmp(a2->wins_owner, h->local_owner) == 0) {		a2_owned = true;	}	if (strcmp(a1->wins_owner, h->local_owner) == 0) {		a1_owned = true;	}	return a2_owned - a1_owned;}struct winsdb_addr **winsdb_addr_list_add(struct winsdb_handle *h, const struct winsdb_record *rec,					  struct winsdb_addr **addresses, const char *address,					  const char *wins_owner, time_t expire_time,					  bool is_name_registration){	struct winsdb_addr *old_addr = NULL;	size_t len = 0;	size_t i;	bool found_old_replica = false;	/*	 * count the addresses and maybe	 * find an old entry for the new address	 */	for (i=0; addresses[i]; i++) {		if (old_addr) continue;		if (strcmp(addresses[i]->address, address) == 0) {			old_addr = addresses[i];		}	}	len = i;	/*	 * the address is already there	 * and we can replace it	 */	if (old_addr) {		goto remove_old_addr;	}	/*	 * if we don't have 25 addresses already,	 * we can just add the new address	 */	if (len < 25) {		goto add_new_addr;	}	/*	 * if we haven't found the address,	 * and we have already have 25 addresses	 * if so then we need to do the following:	 * - if it isn't a name registration, then just ignore the new address	 * - if it is a name registration, then first search for 	 *   the oldest replica and if there's no replica address	 *   search the oldest owned address	 */	if (!is_name_registration) {		return addresses;	}	/*	 * find the oldest replica address, if there's no replica	 * record at all, find the oldest owned address	 */	for (i=0; addresses[i]; i++) {		bool cur_is_replica = false;		/* find out if the current address is a replica */		if (strcmp(addresses[i]->wins_owner, h->local_owner) != 0) {			cur_is_replica = true;		}		/*		 * if we already found a replica address and the current address		 * is not a replica, then skip it		 */		if (found_old_replica && !cur_is_replica) continue;		/*		 * if we found the first replica address, reset the address		 * that would be replaced		 */		if (!found_old_replica && cur_is_replica) {			found_old_replica = true;			old_addr = addresses[i];			continue;		}		/*		 * if the first address isn't a replica, just start with 		 * the first one		 */		if (!old_addr) {			old_addr = addresses[i];			continue;		}		/*		 * see if we find an older address		 */		if (addresses[i]->expire_time < old_addr->expire_time) {			old_addr = addresses[i];			continue;		}	}remove_old_addr:	winsdb_addr_list_remove(addresses, old_addr->address);	len --;add_new_addr:	addresses = talloc_realloc(addresses, addresses, struct winsdb_addr *, len + 2);	if (!addresses) return NULL;	addresses[len] = talloc(addresses, struct winsdb_addr);	if (!addresses[len]) {		talloc_free(addresses);		return NULL;	}	addresses[len]->address = talloc_strdup(addresses[len], address);	if (!addresses[len]->address) {		talloc_free(addresses);		return NULL;	}	addresses[len]->wins_owner = talloc_strdup(addresses[len], wins_owner);	if (!addresses[len]->wins_owner) {		talloc_free(addresses);		return NULL;	}	addresses[len]->expire_time = expire_time;	addresses[len+1] = NULL;	ldb_qsort(addresses, len+1 , sizeof(addresses[0]), h, (ldb_qsort_cmp_fn_t)winsdb_addr_sort_list);	return addresses;}void winsdb_addr_list_remove(struct winsdb_addr **addresses, const char *address){	size_t i;	for (i=0; addresses[i]; i++) {		if (strcmp(addresses[i]->address, address) == 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -