nmbd_browsesync.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 680 行 · 第 1/2 页
C
680 行
/* 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-2003 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"/* This is our local master browser list database. */extern ubi_dlList lmb_browserlist[];/****************************************************************************As a domain master browser, do a sync with a local master browser.**************************************************************************/static void sync_with_lmb(struct browse_cache_record *browc){ struct work_record *work; if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) { if( DEBUGLVL( 0 ) ) { dbgtext( "sync_with_lmb:\n" ); dbgtext( "Failed to get a workgroup for a local master browser " ); dbgtext( "cache entry workgroup " ); dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name ); } return; } /* We should only be doing this if we are a domain master browser for the given workgroup. Ensure this is so. */ if(!AM_DOMAIN_MASTER_BROWSER(work)) { if( DEBUGLVL( 0 ) ) { dbgtext( "sync_with_lmb:\n" ); dbgtext( "We are trying to sync with a local master browser " ); dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group ); dbgtext( "and we are not a domain master browser on this workgroup.\n" ); dbgtext( "Error!\n" ); } return; } if( DEBUGLVL( 2 ) ) { dbgtext( "sync_with_lmb:\n" ); dbgtext( "Initiating sync with local master browser " ); dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) ); dbgtext( "for workgroup %s\n", browc->work_group ); } sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True); browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);}/****************************************************************************Sync or expire any local master browsers.**************************************************************************/void dmb_expire_and_sync_browser_lists(time_t t){ static time_t last_run = 0; struct browse_cache_record *browc; /* Only do this every 20 seconds. */ if (t - last_run < 20) return; last_run = t; expire_lmb_browsers(t); for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); browc; browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) { if (browc->sync_time < t) sync_with_lmb(browc); }}/****************************************************************************As a local master browser, send an announce packet to the domain master browser.**************************************************************************/static void announce_local_master_browser_to_domain_master_browser( struct work_record *work){ pstring outbuf; unstring myname; unstring dmb_name; char *p; if(ismyip(work->dmb_addr)) { if( DEBUGLVL( 2 ) ) { dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); dbgtext( "We are both a domain and a local master browser for " ); dbgtext( "workgroup %s. ", work->work_group ); dbgtext( "Do not announce to ourselves.\n" ); } return; } memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; SCVAL(p,0,ANN_MasterAnnouncement); p++; unstrcpy(myname, global_myname()); strupper_m(myname); myname[15]='\0'; /* The call below does CH_UNIX -> CH_DOS conversion. JRA */ push_pstring_base(p, myname, outbuf); p = skip_string(p,1); if( DEBUGLVL( 4 ) ) { dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); dbgtext( "Sending local master announce to " ); dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name), work->work_group ); } /* Target name for send_mailslot must be in UNIX charset. */ pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name); send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), global_myname(), 0x0, dmb_name, 0x0, work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);}/****************************************************************************As a local master browser, do a sync with a domain master browser.**************************************************************************/static void sync_with_dmb(struct work_record *work){ unstring dmb_name; if( DEBUGLVL( 2 ) ) { dbgtext( "sync_with_dmb:\n" ); dbgtext( "Initiating sync with domain master browser " ); dbgtext( "%s ", nmb_namestr(&work->dmb_name) ); dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) ); dbgtext( "for workgroup %s\n", work->work_group ); } pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name); sync_browse_lists(work, dmb_name, work->dmb_name.name_type, work->dmb_addr, False, True);}/**************************************************************************** Function called when a node status query to a domain master browser IP succeeds.****************************************************************************/static void domain_master_node_status_success(struct subnet_record *subrec, struct userdata_struct *userdata, struct res_rec *answers, struct in_addr from_ip){ struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data); if( work == NULL ) { if( DEBUGLVL( 0 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Unable to find workgroup " ); dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name ); } return; } if( DEBUGLVL( 3 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Success in node status for workgroup " ); dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) ); } /* Go through the list of names found at answers->rdata and look for the first SERVER<0x20> name. */ if(answers->rdata != NULL) { char *p = answers->rdata; int numnames = CVAL(p, 0); p += 1; while (numnames--) { unstring qname; uint16 nb_flags; int name_type; pull_ascii_nstring(qname, sizeof(qname), p); name_type = CVAL(p,15); nb_flags = get_nb_flags(&p[16]); trim_char(qname,'\0',' '); p += 18; if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) { struct nmb_name nmbname; make_nmb_name(&nmbname, qname, name_type); /* Copy the dmb name and IP address into the workgroup struct. */ work->dmb_name = nmbname; putip((char *)&work->dmb_addr, &from_ip); /* Do the local master browser announcement to the domain master browser name and IP. */ announce_local_master_browser_to_domain_master_browser( work ); /* Now synchronise lists with the domain master browser. */ sync_with_dmb(work); break; } } } else if( DEBUGLVL( 0 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " ); dbgtext( "%s.\n", inet_ntoa(from_ip) ); }}/**************************************************************************** Function called when a node status query to a domain master browser IP fails.****************************************************************************/static void domain_master_node_status_fail(struct subnet_record *subrec, struct response_record *rrec){ struct userdata_struct *userdata = rrec->userdata; if( DEBUGLVL( 0 ) ) { dbgtext( "domain_master_node_status_fail:\n" ); dbgtext( "Doing a node status request to the domain master browser\n" ); dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" ); dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); dbgtext( "Cannot sync browser lists.\n" ); }}/**************************************************************************** Function called when a query for a WORKGROUP<1b> name succeeds.****************************************************************************/static void find_domain_master_name_query_success(struct subnet_record *subrec, struct userdata_struct *userdata_in, struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec){ /* * Unfortunately, finding the IP address of the Domain Master Browser, * as we have here, is not enough. We need to now do a sync to the * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will * respond to the SMBSERVER name. To get this name from IP * address we do a Node status request, and look for the first * NAME<0x20> in the response, and take that as the server name. * We also keep a cache of the Domain Master Browser name for this * workgroup in the Workgroup struct, so that if the same IP addess * is returned every time, we don't need to do the node status * request. */ struct work_record *work; struct nmb_name nmbname; struct userdata_struct *userdata; size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1; unstring qname; pull_ascii_nstring(qname, sizeof(qname), q_name->name); if( !(work = find_workgroup_on_subnet(subrec, qname)) ) { if( DEBUGLVL( 0 ) ) { dbgtext( "find_domain_master_name_query_success:\n" ); dbgtext( "Failed to find workgroup %s\n", qname); } return; } /* First check if we already have a dmb for this workgroup. */ if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) { /* Do the local master browser announcement to the domain master browser name and IP. */ announce_local_master_browser_to_domain_master_browser( work ); /* Now synchronise lists with the domain master browser. */ sync_with_dmb(work); return; } else { zero_ip(&work->dmb_addr); } /* Now initiate the node status request. */ /* We used to use the name "*",0x0 here, but some Windows * servers don't answer that name. However we *know* they * have the name workgroup#1b (as we just looked it up). * So do the node status request on this name instead. * Found at LBL labs. JRA. */ make_nmb_name(&nmbname,work->work_group,0x1b); /* Put the workgroup name into the userdata so we know what workgroup we're talking to when the reply comes back. */ /* Setup the userdata_struct - this is copied so we can use a stack variable for this. */ if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) { DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n")); return; } userdata->copy_fn = NULL; userdata->free_fn = NULL; userdata->userdata_len = strlen(work->work_group)+1; overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); node_status( subrec, &nmbname, answer_ip, domain_master_node_status_success, domain_master_node_status_fail, userdata);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?