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

📄 winsserver.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
	switch (rec->type) {	case WREPL_TYPE_UNIQUE:	case WREPL_TYPE_MHOMED:		/* 		 * if its an active unique name, and the registration is for a group, then		 * see if the unique name owner still wants the name		 * TODO: is this correct?		 */		if (new_type == WREPL_TYPE_GROUP || new_type == WREPL_TYPE_GROUP) {			wins_register_wack(nbtsock, packet, rec, src, new_type);			return;		}		/* 		 * if the registration is for an address that is currently active, then 		 * just update the expiry time of the record and the address		 */		winsdb_addr = winsdb_addr_list_check(rec->addresses, address);		if (winsdb_addr) {			rcode = wins_update_ttl(nbtsock, packet, rec, winsdb_addr, src);			goto done;		}		/*		 * we have to do a WACK to see if the current owner is willing		 * to give up its claim		 */		wins_register_wack(nbtsock, packet, rec, src, new_type);		return;	case WREPL_TYPE_GROUP:		/* this should not be reached as normal groups are handled above */		DEBUG(0,("BUG at %s\n",__location__));		rcode = NBT_RCODE_ACT;		goto done;	case WREPL_TYPE_SGROUP:		/* if the new record isn't also a special group, refuse the registration */ 		if (new_type != WREPL_TYPE_SGROUP) {			DEBUG(2,("WINS: Attempt to register name %s as non special group(%u)"				 " while a special group is already there\n",				 nbt_name_string(packet, name), new_type));			rcode = NBT_RCODE_ACT;			goto done;		}		/* 		 * if the registration is for an address that is currently active, then 		 * just update the expiry time of the record and the address		 */		winsdb_addr = winsdb_addr_list_check(rec->addresses, address);		if (winsdb_addr) {			rcode = wins_update_ttl(nbtsock, packet, rec, winsdb_addr, src);			goto done;		}		rcode = wins_sgroup_merge(nbtsock, packet, rec, address, src);		goto done;	}done:	nbtd_name_registration_reply(nbtsock, packet, src, rcode);}static uint32_t ipv4_match_bits(struct in_addr ip1, struct in_addr ip2){	uint32_t i, j, match=0;	uint8_t *p1, *p2;	p1 = (uint8_t *)&ip1.s_addr;	p2 = (uint8_t *)&ip2.s_addr;	for (i=0; i<4; i++) {		if (p1[i] != p2[i]) break;		match += 8;	}	if (i==4) return match;	for (j=0; j<8; j++) {		if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))			break;		match++;	}	return match;}static int nbtd_wins_randomize1Clist_sort(void *p1,/* (const char **) */					  void *p2,/* (const char **) */					  struct socket_address *src){	const char *a1 = (const char *)*(const char **)p1;	const char *a2 = (const char *)*(const char **)p2;	uint32_t match_bits1;	uint32_t match_bits2;	match_bits1 = ipv4_match_bits(interpret_addr2(a1), interpret_addr2(src->addr));	match_bits2 = ipv4_match_bits(interpret_addr2(a2), interpret_addr2(src->addr));	return match_bits2 - match_bits1;}static void nbtd_wins_randomize1Clist(struct loadparm_context *lp_ctx,				      const char **addresses, struct socket_address *src){	const char *mask;	const char *tmp;	uint32_t num_addrs;	uint32_t idx, sidx;	int r;	for (num_addrs=0; addresses[num_addrs]; num_addrs++) { /* noop */ }	if (num_addrs <= 1) return; /* nothing to do */	/* first sort the addresses depending on the matching to the client */	ldb_qsort(addresses, num_addrs , sizeof(addresses[0]),		  src, (ldb_qsort_cmp_fn_t)nbtd_wins_randomize1Clist_sort);	mask = lp_parm_string(lp_ctx, NULL, "nbtd", "wins_randomize1Clist_mask");	if (!mask) {		mask = "255.255.255.0";	}	/* 	 * choose a random address to be the first in the response to the client,	 * preferr the addresses inside the nbtd:wins_randomize1Clist_mask netmask	 */	r = random();	idx = sidx = r % num_addrs;	while (1) {		bool same;		/* if the current one is in the same subnet, use it */		same = iface_same_net(addresses[idx], src->addr, mask);		if (same) {			sidx = idx;			break;		}		/* we need to check for idx == 0, after checking for the same net */		if (idx == 0) break;		/* 		 * if we haven't found an address in the same subnet, search in ones		 * which match the client more		 *		 * some notes:		 *		 * it's not "idx = idx % r" but "idx = r % idx"		 * because in "a % b" b is the allowed range		 * and b-1 is the maximum possible result, so it must be decreasing		 * and the above idx == 0 check breaks the while(1) loop.		 */		idx = r % idx;	}	/* note sidx == 0 is also valid here ... */	tmp		= addresses[0];	addresses[0]	= addresses[sidx];	addresses[sidx]	= tmp;}/*  query a name*/static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,				  struct nbt_name_socket *nbtsock, 				  struct nbt_name_packet *packet, 				  struct socket_address *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;	struct winsdb_record *rec_1b = NULL;	const char **addresses;	const char **addresses_1b = NULL;	uint16_t nb_flags = 0;	if (name->type == NBT_NAME_MASTER) {		goto notfound;	}	/*	 * w2k3 returns the first address of the 0x1B record as first address	 * to a 0x1C query	 *	 * since Windows 2000 Service Pack 2 there's on option to trigger this behavior:	 *	 * HKEY_LOCAL_MACHINE\System\CurrentControlset\Services\WINS\Parameters\Prepend1BTo1CQueries	 * Typ: Daten REG_DWORD	 * Value: 0 = deactivated, 1 = activated	 */	if (name->type == NBT_NAME_LOGON && 	    lp_parm_bool(lp_ctx, NULL, "nbtd", "wins_prepend1Bto1Cqueries", true)) {		struct nbt_name name_1b;		name_1b = *name;		name_1b.type = NBT_NAME_PDC;		status = winsdb_lookup(winssrv->wins_db, &name_1b, packet, &rec_1b);		if (NT_STATUS_IS_OK(status)) {			addresses_1b = winsdb_addr_string_list(packet, rec_1b->addresses);		}	}	status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);	if (!NT_STATUS_IS_OK(status)) {		if (!lp_wins_dns_proxy(lp_ctx)) {			goto notfound;		}		if (name->type != NBT_NAME_CLIENT && name->type != NBT_NAME_SERVER) {			goto notfound;		}		nbtd_wins_dns_proxy_query(nbtsock, packet, src);		return;	}	/*	 * for group's we always reply with	 * 255.255.255.255 as address, even if	 * the record is released or tombstoned	 */	if (rec->type == WREPL_TYPE_GROUP) {		addresses = str_list_add(NULL, "255.255.255.255");		talloc_steal(packet, addresses);		if (!addresses) {			goto notfound;		}		nb_flags |= NBT_NM_GROUP;		goto found;	}	if (rec->state != WREPL_STATE_ACTIVE) {		goto notfound;	}	addresses = winsdb_addr_string_list(packet, rec->addresses);	if (!addresses) {		goto notfound;	}	/* 	 * if addresses_1b isn't NULL, we have a 0x1C query and need to return the	 * first 0x1B address as first address	 */	if (addresses_1b && addresses_1b[0]) {		const char **addresses_1c = addresses;		uint32_t i;		uint32_t num_addrs;		addresses = str_list_add(NULL, addresses_1b[0]);		if (!addresses) {			goto notfound;		}		talloc_steal(packet, addresses);		num_addrs = 1;		for (i=0; addresses_1c[i]; i++) {			if (strcmp(addresses_1b[0], addresses_1c[i]) == 0) continue;			/*			 * stop when we already have 25 addresses			 */			if (num_addrs >= 25) break;			num_addrs++;						addresses = str_list_add(addresses, addresses_1c[i]);			if (!addresses) {				goto notfound;			}		}	}	if (rec->type == WREPL_TYPE_SGROUP) {		nb_flags |= NBT_NM_GROUP;	} else {		nb_flags |= (rec->node <<13);	}	/*	 * since Windows 2000 Service Pack 2 there's on option to trigger this behavior:	 *	 * HKEY_LOCAL_MACHINE\System\CurrentControlset\Services\WINS\Parameters\Randomize1CList	 * Typ: Daten REG_DWORD	 * Value: 0 = deactivated, 1 = activated	 */	if (name->type == NBT_NAME_LOGON && 	    lp_parm_bool(lp_ctx, NULL, "nbtd", "wins_randomize1Clist", false)) {		nbtd_wins_randomize1Clist(lp_ctx, addresses, src);	}found:	nbtd_name_query_reply(nbtsock, packet, src, name, 			      0, nb_flags, addresses);	return;notfound:	nbtd_negative_name_query_reply(nbtsock, packet, src);}/*  release a name*/static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, 				    struct nbt_name_packet *packet, 				    struct socket_address *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;	uint32_t modify_flags = 0;	uint8_t ret;	if (name->type == NBT_NAME_MASTER) {		goto done;	}	status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);	if (!NT_STATUS_IS_OK(status)) {		goto done;	}	if (rec->is_static) {		if (rec->type == WREPL_TYPE_UNIQUE || rec->type == WREPL_TYPE_MHOMED) {			goto done;		}		nbtd_name_release_reply(nbtsock, packet, src, NBT_RCODE_ACT);		return;	}	if (rec->state != WREPL_STATE_ACTIVE) {		goto done;	}	/* 	 * TODO: do we need to check if	 *       src->addr matches packet->additional[0].rdata.netbios.addresses[0].ipaddr	 *       here?	 */	/* 	 * we only allow releases from an owner - other releases are	 * silently ignored	 */	if (!winsdb_addr_list_check(rec->addresses, src->addr)) {		int i;		DEBUG(4,("WINS: silently ignoring attempted name release on %s from %s\n", nbt_name_string(rec, rec->name), src->addr));		DEBUGADD(4, ("Registered Addresses: \n"));		for (i=0; rec->addresses && rec->addresses[i]; i++) {			DEBUGADD(4, ("%s\n", rec->addresses[i]->address));		}		goto done;	}	DEBUG(4,("WINS: released name %s from %s\n", nbt_name_string(rec, rec->name), src->addr));	switch (rec->type) {	case WREPL_TYPE_UNIQUE:		rec->state = WREPL_STATE_RELEASED;		break;	case WREPL_TYPE_GROUP:		rec->state = WREPL_STATE_RELEASED;		break;	case WREPL_TYPE_SGROUP:		winsdb_addr_list_remove(rec->addresses, src->addr);		/* TODO: do we need to take the ownership here? */		if (winsdb_addr_list_length(rec->addresses) == 0) {			rec->state = WREPL_STATE_RELEASED;		}		break;	case WREPL_TYPE_MHOMED:		winsdb_addr_list_remove(rec->addresses, src->addr);		/* TODO: do we need to take the ownership here? */		if (winsdb_addr_list_length(rec->addresses) == 0) {			rec->state = WREPL_STATE_RELEASED;		}		break;	}	if (rec->state == WREPL_STATE_RELEASED) {		/*		 * if we're not the owner, we need to take the owner ship		 * and make the record tombstone, but expire after		 * tombstone_interval + tombstone_timeout and not only after tombstone_timeout		 * like for normal tombstone records.		 * This is to replicate the record directly to the original owner,		 * where the record is still active		 */ 		if (strcmp(rec->wins_owner, winssrv->wins_db->local_owner) == 0) {			rec->expire_time= time(NULL) + winssrv->config.tombstone_interval;		} else {			rec->state	= WREPL_STATE_TOMBSTONE;			rec->expire_time= time(NULL) + 					  winssrv->config.tombstone_interval +					  winssrv->config.tombstone_timeout;			modify_flags	= WINSDB_FLAG_ALLOC_VERSION | WINSDB_FLAG_TAKE_OWNERSHIP;		}	}	ret = winsdb_modify(winssrv->wins_db, rec, modify_flags);	if (ret != NBT_RCODE_OK) {		DEBUG(1,("WINS: FAILED: released name %s at %s: error:%u\n",			nbt_name_string(rec, rec->name), src->addr, ret));	}done:	/* we match w2k3 by always giving a positive reply to name releases. */	nbtd_name_release_reply(nbtsock, packet, src, NBT_RCODE_OK);}/*  answer a name query*/void nbtd_winsserver_request(struct nbt_name_socket *nbtsock, 			     struct nbt_name_packet *packet, 			     struct socket_address *src){	struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 						       struct nbtd_interface);	struct wins_server *winssrv = iface->nbtsrv->winssrv;	if ((packet->operation & NBT_FLAG_BROADCAST) || winssrv == NULL) {		return;	}	switch (packet->operation & NBT_OPCODE) {	case NBT_OPCODE_QUERY:		nbtd_winsserver_query(iface->nbtsrv->task->lp_ctx, nbtsock, packet, src);		break;	case NBT_OPCODE_REGISTER:	case NBT_OPCODE_REFRESH:	case NBT_OPCODE_REFRESH2:	case NBT_OPCODE_MULTI_HOME_REG:		nbtd_winsserver_register(nbtsock, packet, src);		break;	case NBT_OPCODE_RELEASE:		nbtd_winsserver_release(nbtsock, packet, src);		break;	}}/*  startup the WINS server, if configured*/NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv){	uint32_t tmp;	const char *owner;	if (!lp_wins_support(nbtsrv->task->lp_ctx)) {		nbtsrv->winssrv = NULL;		return NT_STATUS_OK;	}	nbtsrv->winssrv = talloc_zero(nbtsrv, struct wins_server);	NT_STATUS_HAVE_NO_MEMORY(nbtsrv->winssrv);	nbtsrv->winssrv->config.max_renew_interval = lp_max_wins_ttl(nbtsrv->task->lp_ctx);	nbtsrv->winssrv->config.min_renew_interval = lp_min_wins_ttl(nbtsrv->task->lp_ctx);	tmp = lp_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv", "tombstone_interval", 6*24*60*60);	nbtsrv->winssrv->config.tombstone_interval = tmp;	tmp = lp_parm_int(nbtsrv->task->lp_ctx, NULL, "wreplsrv"," tombstone_timeout", 1*24*60*60);	nbtsrv->winssrv->config.tombstone_timeout = tmp;	owner = lp_parm_string(nbtsrv->task->lp_ctx, NULL, "winsdb", "local_owner");	if (owner == NULL) {		struct interface *ifaces;		load_interfaces(nbtsrv->task, lp_interfaces(nbtsrv->task->lp_ctx), &ifaces);		owner = iface_n_ip(ifaces, 0);	}	nbtsrv->winssrv->wins_db     = winsdb_connect(nbtsrv->winssrv, nbtsrv->task->event_ctx, 						      nbtsrv->task->lp_ctx,						      owner, WINSDB_HANDLE_CALLER_NBTD);	if (!nbtsrv->winssrv->wins_db) {		return NT_STATUS_INTERNAL_DB_ERROR;	}	irpc_add_name(nbtsrv->task->msg_ctx, "wins_server");	return NT_STATUS_OK;}

⌨️ 快捷键说明

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