nmbd_winsserver.c

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

C
2,043
字号
/*    Unix SMB/CIFS implementation.   NBT netbios routines and daemon - version 2   Copyright (C) Jeremy Allison 1994-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 2 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, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */#include "includes.h"#define WINS_LIST "wins.dat"#define WINS_VERSION 1/**************************************************************************** Change the wins owner address in the record.*****************************************************************************/static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip){	if (namerec==NULL)		return;	namerec->data.wins_ip=wins_ip;}/**************************************************************************** Create the wins flags based on the nb flags and the input value.*****************************************************************************/static void update_wins_flag(struct name_record *namerec, int flags){	if (namerec==NULL)		return;	namerec->data.wins_flags=0x0;	/* if it's a group, it can be a normal or a special one */	if (namerec->data.nb_flags & NB_GROUP) {		if (namerec->name.name_type==0x1C) {			namerec->data.wins_flags|=WINS_SGROUP;		} else {			if (namerec->data.num_ips>1) {				namerec->data.wins_flags|=WINS_SGROUP;			} else {				namerec->data.wins_flags|=WINS_NGROUP;			}		}	} else {		/* can be unique or multi-homed */		if (namerec->data.num_ips>1) {			namerec->data.wins_flags|=WINS_MHOMED;		} else {			namerec->data.wins_flags|=WINS_UNIQUE;	}	}	/* the node type are the same bits */	namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;	/* the static bit is elsewhere */	if (namerec->data.death_time == PERMANENT_TTL) {		namerec->data.wins_flags|=WINS_STATIC;	}	/* and add the given bits */	namerec->data.wins_flags|=flags;	DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", 		 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));}/**************************************************************************** Return the general ID value and increase it if requested.*****************************************************************************/static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update){	/*	 * it's kept as a static here, to prevent people from messing	 * with the value directly	 */	static SMB_BIG_UINT general_id = 1;	DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));		*current_id = general_id;		if (update) {		general_id++;	}}/**************************************************************************** Possibly call the WINS hook external program when a WINS change is made.*****************************************************************************/static void wins_hook(const char *operation, struct name_record *namerec, int ttl){	pstring command;	char *cmd = lp_wins_hook();	char *p, *namestr;	int i;	if (!cmd || !*cmd) return;	for (p=namerec->name.name; *p; p++) {		if (!(isalnum((int)*p) || strchr_m("._-",*p))) {			DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));			return;		}	}		/* Use the name without the nametype (and scope) appended */	namestr = nmb_namestr(&namerec->name);	if ((p = strchr(namestr, '<'))) {		*p = 0;	}	p = command;	p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", 		      cmd,		      operation, 		      namestr,		      namerec->name.name_type,		      ttl);	for (i=0;i<namerec->data.num_ips;i++) {		p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));	}	DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));	smbrun(command, NULL);}/****************************************************************************Determine if this packet should be allocated to the WINS server.*****************************************************************************/BOOL packet_is_for_wins_server(struct packet_struct *packet){	struct nmb_packet *nmb = &packet->packet.nmb;	/* Only unicast packets go to a WINS server. */	if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {		DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));		return False;	}	/* Check for node status requests. */	if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {		return False;	}	switch(nmb->header.opcode) { 		/*		 * A WINS server issues WACKS, not receives them.		 */		case NMB_WACK_OPCODE:			DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));			return False;		/*		 * A WINS server only processes registration and		 * release requests, not responses.		 */		case NMB_NAME_REG_OPCODE:		case NMB_NAME_MULTIHOMED_REG_OPCODE:		case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */		case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */			if(nmb->header.response) {				DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));				return False;			}			break;		case NMB_NAME_RELEASE_OPCODE:			if(nmb->header.response) {				DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));				return False;			}			break;		/*		 * Only process unicast name queries with rd = 1.		 */		case NMB_NAME_QUERY_OPCODE:			if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {				DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));				return False;			}			break;	}	return True;}/****************************************************************************Utility function to decide what ttl to give a register/refresh request.*****************************************************************************/static int get_ttl_from_packet(struct nmb_packet *nmb){	int ttl = nmb->additional->ttl;	if (ttl < lp_min_wins_ttl()) {		ttl = lp_min_wins_ttl();	}	if (ttl > lp_max_wins_ttl()) {		ttl = lp_max_wins_ttl();	}	return ttl;}/****************************************************************************Load or create the WINS database.*****************************************************************************/BOOL initialise_wins(void){	time_t time_now = time(NULL);	XFILE *fp;	pstring line;	if(!lp_we_are_a_wins_server()) {		return True;	}	add_samba_names_to_subnet(wins_server_subnet);	if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {		DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",			WINS_LIST, strerror(errno) ));		return True;	}	while (!x_feof(fp)) {		pstring name_str, ip_str, ttl_str, nb_flags_str;		unsigned int num_ips;		pstring name;		struct in_addr *ip_list;		int type = 0;		int nb_flags;		int ttl;		const char *ptr;		char *p;		BOOL got_token;		BOOL was_ip;		int i;		unsigned int hash;		int version;		/* Read a line from the wins.dat file. Strips whitespace			from the beginning and end of the line.  */		if (!fgets_slash(line,sizeof(pstring),fp))			continue;      		if (*line == '#')			continue;		if (strncmp(line,"VERSION ", 8) == 0) {			if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||						version != WINS_VERSION) {				DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));				x_fclose(fp);				return True;			}			continue;		}		ptr = line;		/* 		 * Now we handle multiple IP addresses per name we need		 * to iterate over the line twice. The first time to		 * determine how many IP addresses there are, the second		 * time to actually parse them into the ip_list array.		 */		if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {			DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));			continue;		}		if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {			DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));			continue;		}		/*		 * Determine the number of IP addresses per line.		 */		num_ips = 0;		do {			got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));			was_ip = False;			if(got_token && strchr(ip_str, '.')) {				num_ips++;				was_ip = True;			}		} while( got_token && was_ip);		if(num_ips == 0) {			DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));			continue;		}		if(!got_token) {			DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));			continue;		}		/* Allocate the space for the ip_list. */		if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {			DEBUG(0,("initialise_wins: Malloc fail !\n"));			return False;		} 		/* Reset and re-parse the line. */		ptr = line;		next_token(&ptr,name_str,NULL,sizeof(name_str)); 		next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));		for(i = 0; i < num_ips; i++) {			next_token(&ptr, ip_str, NULL, sizeof(ip_str));			ip_list[i] = *interpret_addr2(ip_str);		}		next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));		/* 		 * Deal with SELF or REGISTER name encoding. Default is REGISTER		 * for compatibility with old nmbds.		 */		if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {			DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));			SAFE_FREE(ip_list);			continue;		}      		if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {			nb_flags_str[strlen(nb_flags_str)-1] = '\0';		}      		/* Netbios name. # divides the name from the type (hex): netbios#xx */		pstrcpy(name,name_str);      		if((p = strchr(name,'#')) != NULL) {			*p = 0;			sscanf(p+1,"%x",&type);		}      		/* Decode the netbios flags (hex) and the time-to-live (in seconds). */		sscanf(nb_flags_str,"%x",&nb_flags);		sscanf(ttl_str,"%d",&ttl);		/* add all entries that have 60 seconds or more to live */		if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {			if(ttl != PERMANENT_TTL) {				ttl -= time_now;			}    			DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",				name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));			(void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 					ttl, REGISTER_NAME, num_ips, ip_list );		} else {			DEBUG(4, ("initialise_wins: not adding name (ttl problem) "				"%s#%02x ttl = %d first IP %s flags = %2x\n",				name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));		}		SAFE_FREE(ip_list);	}     	x_fclose(fp);	return True;}/****************************************************************************Send a WINS WACK (Wait ACKnowledgement) response.**************************************************************************/static void send_wins_wack_response(int ttl, struct packet_struct *p){	struct nmb_packet *nmb = &p->packet.nmb;	unsigned char rdata[2];	rdata[0] = rdata[1] = 0;	/* Taken from nmblib.c - we need to send back almost		identical bytes from the requesting packet header. */

⌨️ 快捷键说明

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