nmbd_winsserver.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,043 行 · 第 1/5 页

C
2,043
字号
	 */	if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {		DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \a dns lookup - removing it.\n", nmb_namestr(question) ));		remove_name_from_namelist( subrec, namerec );		namerec = NULL;	}	/*	 * Reject if the name exists and is not a REGISTER_NAME.	 * (ie. Don't allow any static names to be overwritten.	 */	if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {		DEBUG( 3, ( "wins_process_name_registration_request: Attempt \to register name %s. Name already exists in WINS with source type %d.\n",			nmb_namestr(question), namerec->data.source ));		send_wins_name_registration_response(RFS_ERR, 0, p);		return;	}	/*	 * Special policy decisions based on MS documentation.	 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.	 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.	 */	/*	 * A group name is always added as the local broadcast address, except	 * for group names ending in 0x1c.	 * Group names with type 0x1c are registered with individual IP addresses.	 */	if(registering_group_name && (question->name_type != 0x1c)) {		from_ip = *interpret_addr2("255.255.255.255");	}	/*	 * Ignore all attempts to register a unique 0x1d name, although return success.	 */	if(!registering_group_name && (question->name_type == 0x1d)) {		DEBUG(3,("wins_process_name_registration_request: Ignoring request \to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));		send_wins_name_registration_response(0, ttl, p);		return;	}	/*	 * Next two cases are the 'if statement' mentioned above.	 */	if((namerec != NULL) && NAME_GROUP(namerec)) {		if(registering_group_name) {			/*			 * If we are adding a group name, the name exists and is also a group entry just add this			 * IP address to it and update the ttl.			 */			DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",				inet_ntoa(from_ip), nmb_namestr(question) ));			/* 			 * Check the ip address is not already in the group.			 */			if(!find_ip_in_name_record(namerec, from_ip)) {				add_ip_to_name_record(namerec, from_ip);				/* we need to update the record for replication */				get_global_id_and_update(&namerec->data.id, True);				/*				 * if the record is a replica, we must change				 * the wins owner to us to make the replication updates				 * it on the other wins servers.				 * And when the partner will receive this record,				 * it will update its own record.				 */				update_wins_owner(namerec, our_fake_ip);			}			update_name_ttl(namerec, ttl);			wins_hook("refresh", namerec, ttl);			send_wins_name_registration_response(0, ttl, p);			return;		} else {			/*			 * If we are adding a unique name, the name exists in the WINS db 			 * and is a group name then reject the registration.			 *			 * explanation: groups have a higher priority than unique names.			 */			DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));			send_wins_name_registration_response(RFS_ERR, 0, p);			return;		} 	}	/*	 * From here on down we know that if the name exists in the WINS db it is	 * a unique name, not a group name.	 */	/* 	 * If the name exists and is one of our names then check the	 * registering IP address. If it's not one of ours then automatically	 * reject without doing the query - we know we will reject it.	 */	if ( namerec != NULL ) {		pull_ascii_nstring(name, sizeof(name), namerec->name.name);	} else {		name[0] = '\0';	}			if( is_myname(name) ) {		if(!ismyip(from_ip)) {			DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));			send_wins_name_registration_response(RFS_ERR, 0, p);			return;		} else {			/*			 * It's one of our names and one of our IP's - update the ttl.			 */			update_name_ttl(namerec, ttl);			wins_hook("refresh", namerec, ttl);			send_wins_name_registration_response(0, ttl, p);			return;		}	}	/*	 * If the name exists and it is a unique registration and the registering IP 	 * is the same as the (single) already registered IP then just update the ttl.	 *	 * But not if the record is an active replica. IF it's a replica, it means it can be	 * the same client which has moved and not yet expired. So we don't update	 * the ttl in this case and go beyond to do a WACK and query the old client	 */	if( !registering_group_name			&& (namerec != NULL)			&& (namerec->data.num_ips == 1)			&& ip_equal( namerec->data.ip[0], from_ip )			&& ip_equal(namerec->data.wins_ip, our_fake_ip) ) {		update_name_ttl( namerec, ttl );		wins_hook("refresh", namerec, ttl);		send_wins_name_registration_response( 0, ttl, p );		return;	}	/*	 * Finally if the name exists do a query to the registering machine 	 * to see if they still claim to have the name.	 */	if( namerec != NULL ) {		long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];		struct userdata_struct *userdata = (struct userdata_struct *)ud;		/*		 * First send a WACK to the registering machine.		 */		send_wins_wack_response(60, p);		/*		 * When the reply comes back we need the original packet.		 * Lock this so it won't be freed and then put it into		 * the userdata structure.		 */		p->locked = True;		userdata = (struct userdata_struct *)ud;		userdata->copy_fn = NULL;		userdata->free_fn = NULL;		userdata->userdata_len = sizeof(struct packet_struct *);		memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );		/*		 * Use the new call to send a query directly to an IP address.		 * This sends the query directly to the IP address, and ensures		 * the recursion desired flag is not set (you were right Luke :-).		 * This function should *only* be called from the WINS server		 * code. JRA.		 */		pull_ascii_nstring(name, sizeof(name), question->name);		query_name_from_wins_server( *namerec->data.ip,				name,				question->name_type, 				wins_register_query_success,				wins_register_query_fail,				userdata );		return;	}	/*	 * Name did not exist - add it.	 */	pull_ascii_nstring(name, sizeof(name), question->name);	add_name_to_subnet( subrec, name, question->name_type,			nb_flags, ttl, REGISTER_NAME, 1, &from_ip);	if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {		get_global_id_and_update(&namerec->data.id, True);		update_wins_owner(namerec, our_fake_ip);		update_wins_flag(namerec, WINS_ACTIVE);		wins_hook("add", namerec, ttl);	}	send_wins_name_registration_response(0, ttl, p);}/*********************************************************************** Deal with a mutihomed name query success to the machine that requested the multihomed name registration. We have a locked pointer to the original packet stashed away in the userdata pointer.************************************************************************/static void wins_multihomed_register_query_success(struct subnet_record *subrec,                                             struct userdata_struct *userdata,                                             struct nmb_name *question_name,                                             struct in_addr ip,                                             struct res_rec *answers){	struct packet_struct *orig_reg_packet;	struct nmb_packet *nmb;	struct name_record *namerec = NULL;	struct in_addr from_ip;	int ttl;	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");	memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));	nmb = &orig_reg_packet->packet.nmb;	putip((char *)&from_ip,&nmb->additional->rdata[2]);	ttl = get_ttl_from_packet(nmb);	/*	 * We want to just add the new IP, as we now know the requesting	 * machine claims to own it. But we can't just do that as an arbitary	 * amount of time may have taken place between the name query	 * request and this response. So we check that	 * the name still exists and is in the same state - if so	 * we just add the extra IP and update the ttl.	 */	namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);	if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {		DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \a subsequent IP address.\n", nmb_namestr(question_name) ));		send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);		orig_reg_packet->locked = False;		free_packet(orig_reg_packet);		return;	}	if(!find_ip_in_name_record(namerec, from_ip)) {		add_ip_to_name_record(namerec, from_ip);	}	get_global_id_and_update(&namerec->data.id, True);	update_wins_owner(namerec, our_fake_ip);	update_wins_flag(namerec, WINS_ACTIVE);	update_name_ttl(namerec, ttl);	wins_hook("add", namerec, ttl);	send_wins_name_registration_response(0, ttl, orig_reg_packet);	orig_reg_packet->locked = False;	free_packet(orig_reg_packet);}/*********************************************************************** Deal with a name registration request query failure to a client that owned the name. We have a locked pointer to the original packet stashed away in the userdata pointer.************************************************************************/static void wins_multihomed_register_query_fail(struct subnet_record *subrec,                                          struct response_record *rrec,                                          struct nmb_name *question_name,                                          int rcode){	struct userdata_struct *userdata = rrec->userdata;	struct packet_struct *orig_reg_packet;	memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));	DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));	send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);	orig_reg_packet->locked = False;	free_packet(orig_reg_packet);	return;}/*********************************************************************** Deal with a multihomed name registration request to a WINS server. These cannot be group name registrations.***********************************************************************/void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,                                                        struct packet_struct *p){	struct nmb_packet *nmb = &p->packet.nmb;	struct nmb_name *question = &nmb->question.question_name;	BOOL bcast = nmb->header.nm_flags.bcast;	uint16 nb_flags = get_nb_flags(nmb->additional->rdata);	int ttl = get_ttl_from_packet(nmb);	struct name_record *namerec = NULL;	struct in_addr from_ip;	BOOL group = (nb_flags & NB_GROUP) ? True : False;	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");	unstring qname;	putip((char *)&from_ip,&nmb->additional->rdata[2]);	if(bcast) {		/*		 * We should only get unicast name registration packets here.		 * Anyone trying to register broadcast should not be going to a WINS		 * server. Log an error here.		 */		DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",			nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));		return;	}	/*	 * Only unique names should be registered multihomed.	 */	if(group) {		DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",			nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));		return;	}	DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));	/*	 * Deal with policy regarding 0x1d names.	 */	if(question->name_type == 0x1d) {		DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));		send_wins_name_registration_response(0, ttl, p);  		return;	}	/*	 * See if the name already exists.	 */	namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);	/*	 * if the record exists but NOT in active state,	 * consider it dead.	 */	if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {		DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));		remove_name_from_namelist(subrec, namerec);		namerec = NULL;	}  	/*	 * Deal with the case where the name found was a dns entry.	 * Remove it as we now have a NetBIOS client registering the	 * name.	 */	if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {		DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \- removing it.\n", nmb_namestr(question) ));		remove_name_from_namelist( subrec, namerec);		namerec = NULL;	}	/*	 * Reject if the name exists and is not a REGISTER_NAME.	 * (ie. Don't allow any static names to be overwritten.	 */	if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {

⌨️ 快捷键说明

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