nmbd_winsserver.c

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

C
2,043
字号
		return;	}  	DEBUG(3,("wins_process_name_release_request: %s name release for name %s \IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));    	/*	 * Deal with policy regarding 0x1d names.	 */	if(!releasing_group_name && (question->name_type == 0x1d)) {		DEBUG(3,("wins_process_name_release_request: Ignoring request \to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));		send_wins_name_release_response(0, p);		return;	}	/*	 * See if the name already exists.	 */    	namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);	if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {		send_wins_name_release_response(NAM_ERR, p);		return;	}	/* 	 * Check that the sending machine has permission to release this name.	 * If it's a group name not ending in 0x1c then just say yes and let	 * the group time out.	 */	if(releasing_group_name && (question->name_type != 0x1c)) {		send_wins_name_release_response(0, p);		return;	}	/* 	 * Check that the releasing node is on the list of IP addresses	 * for this name. Disallow the release if not.	 */	if(!find_ip_in_name_record(namerec, from_ip)) {		DEBUG(3,("wins_process_name_release_request: Refusing request to \release name %s as IP %s is not one of the known IP's for this name.\n",			nmb_namestr(question), inet_ntoa(from_ip) ));		send_wins_name_release_response(NAM_ERR, p);		return;	}	/*	 * Check if the record is active. IF it's already released	 * or tombstoned, refuse the release.	 */	if (!WINS_STATE_ACTIVE(namerec)) {		DEBUG(3,("wins_process_name_release_request: Refusing request to \release name %s as this record is not active anymore.\n", nmb_namestr(question) ));		send_wins_name_release_response(NAM_ERR, p);		return;	}    	/*	 * Check if the record is a 0x1c group	 * and has more then one ip	 * remove only this address.	 */	if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {		remove_ip_from_name_record(namerec, from_ip);		DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",				inet_ntoa(from_ip),nmb_namestr(question)));		wins_hook("delete", namerec, 0);		send_wins_name_release_response(0, p);		return;	}	/* 	 * Send a release response.	 * Flag the name as released and update the ttl	 */	namerec->data.wins_flags |= WINS_RELEASED;	update_name_ttl(namerec, EXTINCTION_INTERVAL);	wins_hook("delete", namerec, 0);	send_wins_name_release_response(0, p);}/******************************************************************* WINS time dependent processing.******************************************************************/void initiate_wins_processing(time_t t){	static time_t lasttime = 0;	struct name_record *namerec;	struct name_record *next_namerec;	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");	if (!lasttime)		lasttime = t;	if (t - lasttime < 20)		return;	lasttime = t;	if(!lp_we_are_a_wins_server())		return;	for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );	     namerec;	     namerec = next_namerec ) {		next_namerec = (struct name_record *)ubi_trNext( namerec );		if( (namerec->data.death_time != PERMANENT_TTL)		     && (namerec->data.death_time < t) ) {			if( namerec->data.source == SELF_NAME ) {				DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n", 				           wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );				namerec->data.death_time += 300;				namerec->subnet->namelist_changed = True;				continue;			} else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {				DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n",						nmb_namestr(&namerec->name)));				remove_name_from_namelist( wins_server_subnet, namerec );				continue;			}			/* handle records, samba is the wins owner */			if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {				switch (namerec->data.wins_flags | WINS_STATE_MASK) {					case WINS_ACTIVE:						namerec->data.wins_flags&=~WINS_STATE_MASK;						namerec->data.wins_flags|=WINS_RELEASED;						namerec->data.death_time = t + EXTINCTION_INTERVAL;						DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));						break;					case WINS_RELEASED:						namerec->data.wins_flags&=~WINS_STATE_MASK;						namerec->data.wins_flags|=WINS_TOMBSTONED;						namerec->data.death_time = t + EXTINCTION_TIMEOUT;						get_global_id_and_update(&namerec->data.id, True);						DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));						break;					case WINS_TOMBSTONED:						DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));						remove_name_from_namelist( wins_server_subnet, namerec );						break;				}			} else {				switch (namerec->data.wins_flags | WINS_STATE_MASK) {					case WINS_ACTIVE:						/* that's not as MS says it should be */						namerec->data.wins_flags&=~WINS_STATE_MASK;						namerec->data.wins_flags|=WINS_TOMBSTONED;						namerec->data.death_time = t + EXTINCTION_TIMEOUT;						DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));					case WINS_TOMBSTONED:						DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));						remove_name_from_namelist( wins_server_subnet, namerec );						break;					case WINS_RELEASED:						DEBUG(0,("initiate_wins_processing: %s is in released state and\we are not the wins owner !\n", nmb_namestr(&namerec->name)));						break;				}			}		}	}	if(wins_server_subnet->namelist_changed)		wins_write_database(True);	wins_server_subnet->namelist_changed = False;}/******************************************************************* Write out the current WINS database.******************************************************************/void wins_write_database(BOOL background){	struct name_record *namerec;	pstring fname, fnamenew;	XFILE *fp;   	if(!lp_we_are_a_wins_server())		return;	/* We will do the writing in a child process to ensure that the parent doesn't block while this is done */	if (background) {		CatchChild();		if (sys_fork()) {			return;		}	}	slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);	all_string_sub(fname,"//", "/", 0);	slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());	if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {		DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));		if (background) {			_exit(0);		}		return;	}	DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));	x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); 	for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {		int i;		struct tm *tm;		DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));		if( namerec->data.death_time != PERMANENT_TTL ) {			char *ts, *nl;			tm = localtime(&namerec->data.death_time);			ts = asctime(tm);			nl = strrchr( ts, '\n' );		if( NULL != nl ) {				*nl = '\0';		}			DEBUGADD(4,("TTL = %s  ", ts ));		} else {			DEBUGADD(4,("TTL = PERMANENT                 "));		}	for (i = 0; i < namerec->data.num_ips; i++) {			DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));	}		DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));		if( namerec->data.source == REGISTER_NAME ) {			unstring name;			pull_ascii_nstring(name, sizeof(name), namerec->name.name);			x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */				(int)namerec->data.death_time);			for (i = 0; i < namerec->data.num_ips; i++)				x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );			x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );		}	}  	x_fclose(fp);	chmod(fnamenew,0644);	unlink(fname);	rename(fnamenew,fname);	if (background) {		_exit(0);	}}#if 0	Until winsrepl is done./**************************************************************************** Process a internal Samba message receiving a wins record.***************************************************************************/void nmbd_wins_new_entry(int msg_type, struct process_id src,			 void *buf, size_t len){	WINS_RECORD *record;	struct name_record *namerec = NULL;	struct name_record *new_namerec = NULL;	struct nmb_name question;	BOOL overwrite=False;	struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");	int i;	if (buf==NULL) {		return;	}		/* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */	record=(WINS_RECORD *)buf;		make_nmb_name(&question, record->name, record->type);	namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);	/* record doesn't exist, add it */	if (namerec == NULL) {		DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 			  record->name, record->type, inet_ntoa(record->wins_ip)));		new_namerec=add_name_to_subnet( wins_server_subnet,						record->name,						record->type,						record->nb_flags, 						EXTINCTION_INTERVAL,						REGISTER_NAME,						record->num_ips,						record->ip);		if (new_namerec!=NULL) {				update_wins_owner(new_namerec, record->wins_ip);				update_wins_flag(new_namerec, record->wins_flags);				new_namerec->data.id=record->id;				wins_server_subnet->namelist_changed = True;			}	}	/* check if we have a conflict */	if (namerec != NULL) {		/* both records are UNIQUE */		if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {			/* the database record is a replica */			if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {				if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {					if (ip_equal(namerec->data.wins_ip, record->wins_ip))						overwrite=True;				} else					overwrite=True;			} else {			/* we are the wins owner of the database record */				/* the 2 records have the same IP address */				if (ip_equal(namerec->data.ip[0], record->ip[0])) {					if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)						get_global_id_and_update(&namerec->data.id, True);					else						overwrite=True;								} else {				/* the 2 records have different IP address */					if (namerec->data.wins_flags&WINS_ACTIVE) {						if (record->wins_flags&WINS_TOMBSTONED)							get_global_id_and_update(&namerec->data.id, True);						if (record->wins_flags&WINS_ACTIVE)							/* send conflict challenge to the replica node */							;					} else						overwrite=True;				}			}		}				/* the replica is a standard group */		if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {			/* if the database record is unique and active force a name release */			if (namerec->data.wins_flags&WINS_UNIQUE)				/* send a release name to the unique node */				;			overwrite=True;				}			/* the replica is a special group */		if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {			if (namerec->data.wins_flags&WINS_ACTIVE) {				for (i=0; i<record->num_ips; i++)					if(!find_ip_in_name_record(namerec, record->ip[i]))						add_ip_to_name_record(namerec, record->ip[i]);			} else {				overwrite=True;			}		}				/* the replica is a multihomed host */				/* I'm giving up on multi homed. Too much complex to understand */				if (record->wins_flags&WINS_MHOMED) {			if (! (namerec->data.wins_flags&WINS_ACTIVE)) {				if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))					overwrite=True;			}			else {				if (ip_equal(record->wins_ip, namerec->data.wins_ip))					overwrite=True;								if (ip_equal(namerec->data.wins_ip, our_fake_ip))					if (namerec->data.wins_flags&WINS_UNIQUE)						get_global_id_and_update(&namerec->data.id, True);							}						if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)				if (namerec->data.wins_flags&WINS_UNIQUE ||				    namerec->data.wins_flags&WINS_MHOMED)					if (ip_equal(record->wins_ip, namerec->data.wins_ip))						overwrite=True;						}		if (overwrite == False)			DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 				  record->name, record->type, inet_ntoa(record->wins_ip)));		else {			DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 				  record->name, record->type, inet_ntoa(record->wins_i

⌨️ 快捷键说明

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