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 + -
显示快捷键?