nmbd_incomingdgrams.c

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

C
845
字号
	uint32 servertype = IVAL(buf,1);	int osmajor=CVAL(buf,5);           /* major version of node software */	int osminor=CVAL(buf,6);           /* minor version of node software */	int ttl = SVAL(buf,7);	unstring announce_name;	struct work_record *work;	struct server_record *servrec;	unstring work_name;	unstring source_name;	fstring comment;	char *s = buf+9;	START_PROFILE(lm_host_announce);	s = skip_string(s,1);	pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE);	pull_ascii_nstring(announce_name,sizeof(announce_name),buf+9);	pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name);	/* For a LanMan host announce the workgroup name is the destination name. */	pull_ascii_nstring(work_name,sizeof(work_name),dgram->dest_name.name);	DEBUG(3,("process_lm_host_announce: LM Announcement from %s IP %s to \%s for server %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),		nmb_namestr(&dgram->dest_name),announce_name));	DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",		osmajor, osminor, ttl, servertype,comment));	if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) {		DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \originate from OS/2 Warp client. Ignoring packet.\n"));		/* Could have been from a Windows machine (with its LM Announce enabled),			or a Samba server. Then don't disrupt the current browse list. */		goto done;	}	/* Filter servertype to remove impossible bits. */	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);	/* A LanMan host announcement must be sent to the name WORKGROUP<00>. */	if(dgram->dest_name.name_type != 0x00) {		DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \(was %02x) should be 0x00. Allowing packet anyway.\n",			inet_ntoa(p->ip), dgram->dest_name.name_type));		/* Change it so it was. */		dgram->dest_name.name_type = 0x00;	}	/*	 * 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. This code is probably	 * not needed in the LanMan announce code, but it won't hurt.	 */	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;	found_lm_clients = True;done:	END_PROFILE(lm_host_announce);}/****************************************************************************  Send a backup list response.*****************************************************************************/static void send_backup_list_response(struct subnet_record *subrec, 				      struct work_record *work,				      struct nmb_name *send_to_name,				      unsigned char max_number_requested,				      uint32 token, struct in_addr sendto_ip,				      int port){                     	char outbuf[1024];	char *p, *countptr;	unsigned int count = 0;	unstring send_to_namestr;#if 0  struct server_record *servrec;#endif	unstring myname;	memset(outbuf,'\0',sizeof(outbuf));	DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",		work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));  	p = outbuf;  	SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */	p++;	countptr = p;	p++;	SIVAL(p,0,token); /* The sender's unique info. */	p += 4;  	/* We always return at least one name - our own. */	count = 1;	unstrcpy(myname, global_myname());	strupper_m(myname);	myname[15]='\0';	push_pstring_base(p, myname, outbuf);	p = skip_string(p,1);	/* Look for backup browsers in this workgroup. */#if 0  /* we don't currently send become_backup requests so we should never     send any other servers names out as backups for our     workgroup. That's why this is commented out (tridge) */  /*   * NB. Note that the struct work_record here is not neccessarily   * attached to the subnet *subrec.   */  for (servrec = work->serverlist; servrec; servrec = servrec->next)  {     int len = PTR_DIFF(p, outbuf);    if((sizeof(outbuf) - len) < 16)      break;    if(count >= (unsigned int)max_number_requested)      break;    if(strnequal(servrec->serv.name, global_myname(),15))      continue;    if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))      continue;    StrnCpy(p, servrec->serv.name, 15);    strupper_m(p);    count++;    DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",              p, count));    p = skip_string(p,1);  }#endif	SCVAL(countptr, 0, count);	pull_ascii_nstring(send_to_namestr, sizeof(send_to_namestr), send_to_name->name);	DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",		send_to_namestr, inet_ntoa(sendto_ip), count));	send_mailslot(True, BROWSE_MAILSLOT,		outbuf,PTR_DIFF(p,outbuf),		global_myname(), 0, 		send_to_namestr,0,		sendto_ip, subrec->myip, port);}/*******************************************************************  Process a send backup list request packet.  A client sends a backup list request to ask for a list of servers on  the net that maintain server lists for a domain. A server is then  chosen from this list to send NetServerEnum commands to to list  available servers.********************************************************************/void process_get_backup_list_request(struct subnet_record *subrec,                                     struct packet_struct *p,char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	struct work_record *work;	unsigned char max_number_requested = CVAL(buf,0);	uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */	int name_type = dgram->dest_name.name_type;	unstring workgroup_name;	struct subnet_record *search_subrec = subrec;	START_PROFILE(get_backup_list);	pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);	DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",		nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),		nmb_namestr(&dgram->dest_name)));  	/* We have to be a master browser, or a domain master browser		for the requested workgroup. That means it must be our		workgroup. */	if(strequal(workgroup_name, lp_workgroup()) == False) {		DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",			workgroup_name));		goto done;	}	if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) {		DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \subnet %s.\n", workgroup_name, search_subrec->subnet_name));		goto done;	}	/* 	 * If the packet was sent to WORKGROUP<1b> instead	 * of WORKGROUP<1d> then it was unicast to us a domain master	 * browser. Change search subrec to unicast.	 */	if(name_type == 0x1b) {		/* We must be a domain master browser in order to			process this packet. */		if(!AM_DOMAIN_MASTER_BROWSER(work)) {			DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \and I am not a domain master browser.\n", workgroup_name));			goto done;		}		search_subrec = unicast_subnet;	} else if (name_type == 0x1d) {		/* We must be a local master browser in order to process this packet. */		if(!AM_LOCAL_MASTER_BROWSER(work)) {			DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \and I am not a local master browser.\n", workgroup_name));			goto done;		}	} else {		DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",			name_type));		goto done;	}	send_backup_list_response(subrec, work, &dgram->source_name,			max_number_requested, token, p->ip, p->port);done:	END_PROFILE(get_backup_list);}/*******************************************************************  Process a reset browser state packet.  Diagnostic packet:  0x1 - Stop being a master browser and become a backup browser.  0x2 - Discard browse lists, stop being a master browser, try again.  0x4 - Stop being a master browser forever.         ******************************************************************/void process_reset_browser(struct subnet_record *subrec,                                  struct packet_struct *p,char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	int state = CVAL(buf,0);	struct subnet_record *sr;	START_PROFILE(reset_browser);	DEBUG(1,("process_reset_browser: received diagnostic browser reset \request from %s IP %s state=0x%X\n",		nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));	/* Stop being a local master browser on all our broadcast subnets. */	if (state & 0x1) {		for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) {			struct work_record *work;			for (work = sr->workgrouplist; work; work = work->next) {				if (AM_LOCAL_MASTER_BROWSER(work))					unbecome_local_master_browser(sr, work, True);			}		}	}  	/* Discard our browse lists. */	if (state & 0x2) {		/*		 * Calling expire_workgroups_and_servers with a -1		 * time causes all servers not marked with a PERMANENT_TTL		 * on the workgroup lists to be discarded, and all 		 * workgroups with empty server lists to be discarded.		 * This means we keep our own server names and workgroup		 * as these have a PERMANENT_TTL.		 */		expire_workgroups_and_servers(-1);	}  	/* Request to stop browsing altogether. */	if (state & 0x4)		DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));	END_PROFILE(reset_browser);}/*******************************************************************  Process an announcement request packet.  We don't respond immediately, we just check it's a request for  our workgroup and then set the flag telling the announce code  in nmbd_sendannounce.c:announce_my_server_names that an   announcement is needed soon.******************************************************************/void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	struct work_record *work;	unstring workgroup_name; 	START_PROFILE(announce_request);	pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);	DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",		nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),		nmb_namestr(&dgram->dest_name)));  	/* We only send announcement requests on our workgroup. */	if(strequal(workgroup_name, lp_workgroup()) == False) {		DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",			workgroup_name));		goto done;	}	if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {		DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",			workgroup_name));		goto done;	}	work->needannounce = True;done:	END_PROFILE(lm_host_announce);}/*******************************************************************  Process a LanMan announcement request packet.  We don't respond immediately, we just check it's a request for  our workgroup and then set the flag telling that we have found  a LanMan client (DOS or OS/2) and that we will have to start  sending LanMan announcements (unless specifically disabled  through the "lm announce" parameter in smb.conf)******************************************************************/void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf){	struct dgram_packet *dgram = &p->packet.dgram;	unstring workgroup_name;	START_PROFILE(lm_announce_request);	pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);	DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",		nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),		nmb_namestr(&dgram->dest_name)));	/* We only send announcement requests on our workgroup. */	if(strequal(workgroup_name, lp_workgroup()) == False) {		DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",			workgroup_name));		goto done;	}	if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) {		DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",			workgroup_name));		goto done;	}	found_lm_clients = True;done:	END_PROFILE(lm_host_announce);}

⌨️ 快捷键说明

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