nmbd_incomingdgrams.c

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

C
845
字号
/*    Unix SMB/CIFS implementation.   NBT netbios routines and daemon - version 2   Copyright (C) Andrew Tridgell 1994-1998   Copyright (C) Luke Kenneth Casson Leighton 1994-1998   Copyright (C) Jeremy Allison 1994-1998      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"extern BOOL found_lm_clients;#if 0/* XXXX note: This function is currently unsuitable for use, as it   does not properly check that a server is in a fit state to become   a backup browser before asking it to be one.   The code is left here to be worked on at a later date.*//****************************************************************************Tell a server to become a backup browser**************************************************************************/void tell_become_backup(void){  struct subnet_record *subrec;  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))  {    struct work_record *work;    for (work = subrec->workgrouplist; work; work = work->next)    {      struct server_record *servrec;      int num_servers = 0;      int num_backups = 0;	        for (servrec = work->serverlist; servrec; servrec = servrec->next)      {        num_servers++;	              if (is_myname(servrec->serv.name))          continue;	              if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER)         {          num_backups++;          continue;        }	              if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)          continue;	              if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))          continue;	              DEBUG(3,("num servers: %d num backups: %d\n",               num_servers, num_backups));	              /* make first server a backup server. thereafter make every           tenth server a backup server */        if (num_backups != 0 && (num_servers+9) / num_backups > 10)          continue;	              DEBUG(2,("sending become backup to %s %s for %s\n",             servrec->serv.name, inet_ntoa(subrec->bcast_ip),             work->work_group));	              /* type 11 request from MYNAME(20) to WG(1e) for SERVER */        do_announce_request(servrec->serv.name, work->work_group,              ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);      }    }  }}#endif/*******************************************************************  Process an incoming host announcement packet.*******************************************************************/void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	int ttl = IVAL(buf,1)/1000;	unstring announce_name;	uint32 servertype = IVAL(buf,23);	fstring comment;	struct work_record *work;	struct server_record *servrec;	unstring work_name;	unstring source_name;	START_PROFILE(host_announce);	pull_ascii_fstring(comment, buf+31);	comment[42] = 0;  	pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5);	pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);	DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),			nmb_namestr(&dgram->dest_name),announce_name));	DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",		ttl, servertype,comment));	/* Filter servertype to remove impossible bits. */	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);	/* A host announcement must be sent to the name WORKGROUP<1d>. */	if(dgram->dest_name.name_type != 0x1d) {		DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \(was %02x) should be 0x1d. Allowing packet anyway.\n",			inet_ntoa(p->ip), dgram->dest_name.name_type));		/* Change it so it was. */		dgram->dest_name.name_type = 0x1d;	}	/* For a host announce the workgroup name is the destination name. */	pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);	/*	 * Syntax servers version 5.1 send HostAnnounce packets to	 * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>	 * instead of WORKGROUP<1d> name. So to fix this we check if	 * the workgroup name is our own name, and if so change it	 * to be our primary workgroup name.	 */	if(strequal(work_name, global_myname()))		unstrcpy(work_name,lp_workgroup());	/*	 * We are being very agressive here in adding a workgroup	 * name on the basis of a host announcing itself as being	 * in that workgroup. Maybe we should wait for the workgroup	 * announce instead ? JRA.	 */	work = find_workgroup_on_subnet(subrec, work_name);	if(servertype != 0) {		if (work ==NULL ) {			/* We have no record of this workgroup. Add it. */			if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)				goto done;		}  		if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {			/* If this server is not already in the workgroup, add it. */			create_server_on_workgroup(work, announce_name, 				servertype|SV_TYPE_LOCAL_LIST_ONLY, 				ttl, comment);		} else {			/* Update the record. */			servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;			update_server_ttl( servrec, ttl);			fstrcpy(servrec->serv.comment,comment);		}	} else {		/*		 * This server is announcing it is going down. Remove it from the 		 * workgroup.		 */		if(!is_myname(announce_name) && (work != NULL) &&				((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {			remove_server_from_workgroup( work, servrec);		}	}	subrec->work_changed = True;done:	END_PROFILE(host_announce);}/*******************************************************************  Process an incoming WORKGROUP announcement packet.*******************************************************************/void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	int ttl = IVAL(buf,1)/1000;	unstring workgroup_announce_name;	unstring master_name;	uint32 servertype = IVAL(buf,23);	struct work_record *work;	unstring source_name;	unstring dest_name;	START_PROFILE(workgroup_announce);	pull_ascii_nstring(workgroup_announce_name,sizeof(workgroup_announce_name),buf+5);	pull_ascii_nstring(master_name,sizeof(master_name),buf+31);	pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name);	pull_ascii_nstring(dest_name,sizeof(dest_name),dgram->dest_name.name);	DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),			nmb_namestr(&dgram->dest_name),workgroup_announce_name));	DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",		ttl, servertype, master_name));	/* Workgroup announcements must only go to the MSBROWSE name. */	if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) {		DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",			inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));		goto done;	}	if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) {		/* We have no record of this workgroup. Add it. */		if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)			goto done;	} else {		/* Update the workgroup death_time. */		update_workgroup_ttl(work, ttl);	}	if(*work->local_master_browser_name == '\0') {		/* Set the master browser name. */		set_workgroup_local_master_browser_name( work, master_name );	}	subrec->work_changed = True;done:	END_PROFILE(workgroup_announce);}/*******************************************************************  Process an incoming local master browser announcement packet.*******************************************************************/void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	int ttl = IVAL(buf,1)/1000;	unstring server_name;	uint32 servertype = IVAL(buf,23);	fstring comment;	unstring work_name;	struct work_record *work;	struct server_record *servrec;	unstring source_name;	START_PROFILE(local_master_announce);	pull_ascii_nstring(server_name,sizeof(server_name),buf+5);	pull_ascii_fstring(comment, buf+31);	comment[42] = 0;	pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);	pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);	DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),		nmb_namestr(&dgram->dest_name),server_name));	DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",		ttl, servertype, comment));	/* A local master announcement must be sent to the name WORKGROUP<1e>. */	if(dgram->dest_name.name_type != 0x1e) {		DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \(was %02x) should be 0x1e. Ignoring packet.\n",			inet_ntoa(p->ip), dgram->dest_name.name_type));		goto done;	}	/* Filter servertype to remove impossible bits. */	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);	/* For a local master announce the workgroup name is the destination name. */	if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) {		/* Don't bother adding if it's a local master release announce. */		if(servertype == 0)			goto done;		/* We have no record of this workgroup. Add it. */		if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)			goto done;	}	/* If we think we're the local master browser for this workgroup,		we should never have got this packet. We don't see our own		packets.	*/	if(AM_LOCAL_MASTER_BROWSER(work)) {		DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \a local master browser for workgroup %s and we think we are master. Forcing election.\n",			server_name, inet_ntoa(p->ip), work_name));		/* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when		 they have become a local master browser once, they will never		 stop sending local master announcements. To fix this we send		 them a reset browser packet, with level 0x2 on the __SAMBA__		 name that only they should be listening to. */   		send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);		/* We should demote ourself and force an election. */		unbecome_local_master_browser( subrec, work, True);		/* The actual election requests are handled in nmbd_election.c */		goto done;	}  	/* Find the server record on this workgroup. If it doesn't exist, add it. */	if(servertype != 0) {		if((servrec = find_server_in_workgroup( work, server_name))==NULL) {			/* If this server is not already in the workgroup, add it. */			create_server_on_workgroup(work, server_name, 				servertype|SV_TYPE_LOCAL_LIST_ONLY, 				ttl, comment);		} else {			/* Update the record. */			servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;			update_server_ttl(servrec, ttl);			fstrcpy(servrec->serv.comment,comment);		}			set_workgroup_local_master_browser_name( work, server_name );	} else {		/*		 * This server is announcing it is going down. Remove it from the		 * workgroup.		 */		if(!is_myname(server_name) && (work != NULL) &&				((servrec = find_server_in_workgroup( work, server_name))!=NULL)) {			remove_server_from_workgroup( work, servrec);		}	}	subrec->work_changed = True;done:	END_PROFILE(local_master_announce);}/*******************************************************************  Process a domain master announcement frame.  Domain master browsers receive these from local masters. The Domain  master should then issue a sync with the local master, asking for  that machines local server list.******************************************************************/void process_master_browser_announce(struct subnet_record *subrec,                                      struct packet_struct *p,char *buf){	unstring local_master_name;	struct work_record *work;	struct browse_cache_record *browrec;	START_PROFILE(master_browser_announce);	pull_ascii_nstring(local_master_name,sizeof(local_master_name),buf);  	DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",		local_master_name, inet_ntoa(p->ip)));  	if (!lp_domain_master()) {		DEBUG(0,("process_master_browser_announce: Not configured as domain \master - ignoring master announce.\n"));		goto done;	}  	if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) {		DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",			lp_workgroup(), subrec->subnet_name));		goto done;	}	if(!AM_DOMAIN_MASTER_BROWSER(work)) {		DEBUG(0,("process_master_browser_announce: Local master announce made to us from \%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));		goto done;	}	/* Add this host as a local master browser entry on the browse lists.		This causes a sync request to be made to it at a later date.	*/	if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) {		/* Add it. */		create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);	} else {		update_browser_death_time(browrec);	}done:	END_PROFILE(master_browser_announce);}/*******************************************************************  Process an incoming LanMan host announcement packet.*******************************************************************/void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;

⌨️ 快捷键说明

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