nmbd_winsserver.c

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

C
2,043
字号
		DEBUG( 3, ( "wins_process_multihomed_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;	}	/*	 * Reject if the name exists and is a GROUP name and is active.	 */	if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {		DEBUG(3,("wins_process_multihomed_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) && (is_myname(namerec->name.name)) ) {		if(!ismyip(from_ip)) {			DEBUG(3,("wins_process_multihomed_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. Ensure the IP is in the record and			 *  update the ttl. Update the version ID to force replication.			 */			update_name_ttl(namerec, ttl);			if(!find_ip_in_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);				add_ip_to_name_record(namerec, from_ip);			}			wins_hook("refresh", namerec, ttl);			send_wins_name_registration_response(0, ttl, p);			return;		}	}	/*	 * If the name exists and is active, check if the IP address is already registered	 * to that name. If so then update the ttl and reply success.	 */	if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {		update_name_ttl(namerec, ttl);		/*		 * If it's a replica, we need to become the wins owner		 * to force the replication		 */		if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {			get_global_id_and_update(&namerec->data.id, True);			update_wins_owner(namerec, our_fake_ip);			update_wins_flag(namerec, WINS_ACTIVE);		}    		wins_hook("refresh", namerec, ttl);		send_wins_name_registration_response(0, ttl, p);		return;	}	/*	 * If the name exists do a query to the owner	 * to see if they still want 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.		 *		 * Note that this packet is sent to the current owner of the name,		 * not the person who sent the packet 		 */		pull_ascii_nstring( qname, sizeof(qname), question->name);		query_name_from_wins_server( namerec->data.ip[0],				qname,				question->name_type, 				wins_multihomed_register_query_success,				wins_multihomed_register_query_fail,				userdata );		return;	}	/*	 * Name did not exist - add it.	 */	pull_ascii_nstring( qname, sizeof(qname), question->name);	add_name_to_subnet( subrec, qname, 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 the special name query for *<1b>.***********************************************************************/   static void process_wins_dmb_query_request(struct subnet_record *subrec,                                             struct packet_struct *p){  	struct name_record *namerec = NULL;	char *prdata;	int num_ips;	/*	 * Go through all the ACTIVE names in the WINS db looking for those	 * ending in <1b>. Use this to calculate the number of IP	 * addresses we need to return.	 */	num_ips = 0;	for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );			namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {		if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )			num_ips += namerec->data.num_ips;	}	if(num_ips == 0) {		/*		 * There are no 0x1b names registered. Return name query fail.		 */		send_wins_name_query_response(NAM_ERR, p, NULL);		return;	}	if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {		DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));		return;	}	/*	 * Go through all the names again in the WINS db looking for those	 * ending in <1b>. Add their IP addresses into the list we will	 * return.	 */ 	num_ips = 0;	for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );			namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {		if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {			int i;			for(i = 0; i < namerec->data.num_ips; i++) {				set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);				putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);				num_ips++;			}		}	}	/*	 * Send back the reply containing the IP list.	 */	reply_netbios_packet(p,                                /* Packet to reply to. */				0,                             /* Result code. */				WINS_QUERY,                    /* nmbd type code. */				NMB_NAME_QUERY_OPCODE,         /* opcode. */				lp_min_wins_ttl(),             /* ttl. */				prdata,                        /* data to send. */				num_ips*6);                    /* data length. */	SAFE_FREE(prdata);}/****************************************************************************Send a WINS name query response.**************************************************************************/void send_wins_name_query_response(int rcode, struct packet_struct *p,                                           struct name_record *namerec){	char rdata[6];	char *prdata = rdata;	int reply_data_len = 0;	int ttl = 0;	int i;	memset(rdata,'\0',6);	if(rcode == 0) {		ttl = (namerec->data.death_time != PERMANENT_TTL) ?  namerec->data.death_time - p->timestamp : lp_max_wins_ttl();		/* Copy all known ip addresses into the return data. */		/* Optimise for the common case of one IP address so we don't need a malloc. */		if( namerec->data.num_ips == 1 ) {			prdata = rdata;		} else {			if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {				DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));				return;			}		}		for(i = 0; i < namerec->data.num_ips; i++) {			set_nb_flags(&prdata[i*6],namerec->data.nb_flags);			putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);		}		sort_query_replies(prdata, i, p->ip);		reply_data_len = namerec->data.num_ips * 6;	}	reply_netbios_packet(p,                                /* Packet to reply to. */				rcode,                         /* Result code. */				WINS_QUERY,                    /* nmbd type code. */				NMB_NAME_QUERY_OPCODE,         /* opcode. */				ttl,                           /* ttl. */				prdata,                        /* data to send. */				reply_data_len);               /* data length. */	if(prdata != rdata) {		SAFE_FREE(prdata);	}}/*********************************************************************** Deal with a name query.***********************************************************************/void wins_process_name_query_request(struct subnet_record *subrec,                                      struct packet_struct *p){	struct nmb_packet *nmb = &p->packet.nmb;	struct nmb_name *question = &nmb->question.question_name;	struct name_record *namerec = NULL;	unstring qname;	DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 		nmb_namestr(question), inet_ntoa(p->ip) ));	/*	 * Special name code. If the queried name is *<1b> then search	 * the entire WINS database and return a list of all the IP addresses	 * registered to any <1b> name. This is to allow domain master browsers	 * to discover other domains that may not have a presence on their subnet.	 */	pull_ascii_nstring(qname, sizeof(qname), question->name);	if(strequal( qname, "*") && (question->name_type == 0x1b)) {		process_wins_dmb_query_request( subrec, p);		return;	}	namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);	if(namerec != NULL) {		/*		 * If the name is not anymore in active state then reply not found.		 * it's fair even if we keep it in the cache for days.		 */		if (!WINS_STATE_ACTIVE(namerec)) {			DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",				nmb_namestr(question) ));			send_wins_name_query_response(NAM_ERR, p, namerec);			return;		}		/* 		 * If it's a DNSFAIL_NAME then reply name not found.		 */		if( namerec->data.source == DNSFAIL_NAME ) {			DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",				nmb_namestr(question) ));			send_wins_name_query_response(NAM_ERR, p, namerec);			return;		}		/*		 * If the name has expired then reply name not found.		 */		if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {			DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",					nmb_namestr(question) ));			send_wins_name_query_response(NAM_ERR, p, namerec);			return;		}		DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",				nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));		send_wins_name_query_response(0, p, namerec);		return;	}	/* 	 * Name not found in WINS - try a dns query if it's a 0x20 name.	 */	if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {		DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",				nmb_namestr(question) ));		queue_dns_query(p, question, &namerec);		return;	}	/*	 * Name not found - return error.	 */	send_wins_name_query_response(NAM_ERR, p, NULL);}/****************************************************************************Send a WINS name release response.**************************************************************************/static void send_wins_name_release_response(int rcode, struct packet_struct *p){	struct nmb_packet *nmb = &p->packet.nmb;	char rdata[6];	memcpy(&rdata[0], &nmb->additional->rdata[0], 6);	reply_netbios_packet(p,                               /* Packet to reply to. */				rcode,                        /* Result code. */				NMB_REL,                      /* nmbd type code. */				NMB_NAME_RELEASE_OPCODE,      /* opcode. */				0,                            /* ttl. */				rdata,                        /* data to send. */				6);                           /* data length. */}/*********************************************************************** Deal with a name release.***********************************************************************/void wins_process_name_release_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);	struct name_record *namerec = NULL;	struct in_addr from_ip;	BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;	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_name_release_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));

⌨️ 快捷键说明

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