nmbd_winsserver.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,043 行 · 第 1/5 页
C
2,043 行
return; } DEBUG(3,("wins_process_name_release_request: %s name release for name %s \IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); /* * Deal with policy regarding 0x1d names. */ if(!releasing_group_name && (question->name_type == 0x1d)) { DEBUG(3,("wins_process_name_release_request: Ignoring request \to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); send_wins_name_release_response(0, p); return; } /* * See if the name already exists. */ namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) { send_wins_name_release_response(NAM_ERR, p); return; } /* * Check that the sending machine has permission to release this name. * If it's a group name not ending in 0x1c then just say yes and let * the group time out. */ if(releasing_group_name && (question->name_type != 0x1c)) { send_wins_name_release_response(0, p); return; } /* * Check that the releasing node is on the list of IP addresses * for this name. Disallow the release if not. */ if(!find_ip_in_name_record(namerec, from_ip)) { DEBUG(3,("wins_process_name_release_request: Refusing request to \release name %s as IP %s is not one of the known IP's for this name.\n", nmb_namestr(question), inet_ntoa(from_ip) )); send_wins_name_release_response(NAM_ERR, p); return; } /* * Check if the record is active. IF it's already released * or tombstoned, refuse the release. */ if (!WINS_STATE_ACTIVE(namerec)) { DEBUG(3,("wins_process_name_release_request: Refusing request to \release name %s as this record is not active anymore.\n", nmb_namestr(question) )); send_wins_name_release_response(NAM_ERR, p); return; } /* * Check if the record is a 0x1c group * and has more then one ip * remove only this address. */ if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) { remove_ip_from_name_record(namerec, from_ip); DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", inet_ntoa(from_ip),nmb_namestr(question))); wins_hook("delete", namerec, 0); send_wins_name_release_response(0, p); return; } /* * Send a release response. * Flag the name as released and update the ttl */ namerec->data.wins_flags |= WINS_RELEASED; update_name_ttl(namerec, EXTINCTION_INTERVAL); wins_hook("delete", namerec, 0); send_wins_name_release_response(0, p);}/******************************************************************* WINS time dependent processing.******************************************************************/void initiate_wins_processing(time_t t){ static time_t lasttime = 0; struct name_record *namerec; struct name_record *next_namerec; struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); if (!lasttime) lasttime = t; if (t - lasttime < 20) return; lasttime = t; if(!lp_we_are_a_wins_server()) return; for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = next_namerec ) { next_namerec = (struct name_record *)ubi_trNext( namerec ); if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { if( namerec->data.source == SELF_NAME ) { DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n", wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); namerec->data.death_time += 300; namerec->subnet->namelist_changed = True; continue; } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) { DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n", nmb_namestr(&namerec->name))); remove_name_from_namelist( wins_server_subnet, namerec ); continue; } /* handle records, samba is the wins owner */ if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { switch (namerec->data.wins_flags | WINS_STATE_MASK) { case WINS_ACTIVE: namerec->data.wins_flags&=~WINS_STATE_MASK; namerec->data.wins_flags|=WINS_RELEASED; namerec->data.death_time = t + EXTINCTION_INTERVAL; DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name))); break; case WINS_RELEASED: namerec->data.wins_flags&=~WINS_STATE_MASK; namerec->data.wins_flags|=WINS_TOMBSTONED; namerec->data.death_time = t + EXTINCTION_TIMEOUT; get_global_id_and_update(&namerec->data.id, True); DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); break; case WINS_TOMBSTONED: DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); remove_name_from_namelist( wins_server_subnet, namerec ); break; } } else { switch (namerec->data.wins_flags | WINS_STATE_MASK) { case WINS_ACTIVE: /* that's not as MS says it should be */ namerec->data.wins_flags&=~WINS_STATE_MASK; namerec->data.wins_flags|=WINS_TOMBSTONED; namerec->data.death_time = t + EXTINCTION_TIMEOUT; DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); case WINS_TOMBSTONED: DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); remove_name_from_namelist( wins_server_subnet, namerec ); break; case WINS_RELEASED: DEBUG(0,("initiate_wins_processing: %s is in released state and\we are not the wins owner !\n", nmb_namestr(&namerec->name))); break; } } } } if(wins_server_subnet->namelist_changed) wins_write_database(True); wins_server_subnet->namelist_changed = False;}/******************************************************************* Write out the current WINS database.******************************************************************/void wins_write_database(BOOL background){ struct name_record *namerec; pstring fname, fnamenew; XFILE *fp; if(!lp_we_are_a_wins_server()) return; /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ if (background) { CatchChild(); if (sys_fork()) { return; } } slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); all_string_sub(fname,"//", "/", 0); slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) { DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); if (background) { _exit(0); } return; } DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { int i; struct tm *tm; DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); if( namerec->data.death_time != PERMANENT_TTL ) { char *ts, *nl; tm = localtime(&namerec->data.death_time); ts = asctime(tm); nl = strrchr( ts, '\n' ); if( NULL != nl ) { *nl = '\0'; } DEBUGADD(4,("TTL = %s ", ts )); } else { DEBUGADD(4,("TTL = PERMANENT ")); } for (i = 0; i < namerec->data.num_ips; i++) { DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); } DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); if( namerec->data.source == REGISTER_NAME ) { unstring name; pull_ascii_nstring(name, sizeof(name), namerec->name.name); x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ (int)namerec->data.death_time); for (i = 0; i < namerec->data.num_ips; i++) x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); } } x_fclose(fp); chmod(fnamenew,0644); unlink(fname); rename(fnamenew,fname); if (background) { _exit(0); }}#if 0 Until winsrepl is done./**************************************************************************** Process a internal Samba message receiving a wins record.***************************************************************************/void nmbd_wins_new_entry(int msg_type, struct process_id src, void *buf, size_t len){ WINS_RECORD *record; struct name_record *namerec = NULL; struct name_record *new_namerec = NULL; struct nmb_name question; BOOL overwrite=False; struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); int i; if (buf==NULL) { return; } /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ record=(WINS_RECORD *)buf; make_nmb_name(&question, record->name, record->type); namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); /* record doesn't exist, add it */ if (namerec == NULL) { DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", record->name, record->type, inet_ntoa(record->wins_ip))); new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); if (new_namerec!=NULL) { update_wins_owner(new_namerec, record->wins_ip); update_wins_flag(new_namerec, record->wins_flags); new_namerec->data.id=record->id; wins_server_subnet->namelist_changed = True; } } /* check if we have a conflict */ if (namerec != NULL) { /* both records are UNIQUE */ if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) { /* the database record is a replica */ if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) { if (ip_equal(namerec->data.wins_ip, record->wins_ip)) overwrite=True; } else overwrite=True; } else { /* we are the wins owner of the database record */ /* the 2 records have the same IP address */ if (ip_equal(namerec->data.ip[0], record->ip[0])) { if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) get_global_id_and_update(&namerec->data.id, True); else overwrite=True; } else { /* the 2 records have different IP address */ if (namerec->data.wins_flags&WINS_ACTIVE) { if (record->wins_flags&WINS_TOMBSTONED) get_global_id_and_update(&namerec->data.id, True); if (record->wins_flags&WINS_ACTIVE) /* send conflict challenge to the replica node */ ; } else overwrite=True; } } } /* the replica is a standard group */ if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) { /* if the database record is unique and active force a name release */ if (namerec->data.wins_flags&WINS_UNIQUE) /* send a release name to the unique node */ ; overwrite=True; } /* the replica is a special group */ if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) { if (namerec->data.wins_flags&WINS_ACTIVE) { for (i=0; i<record->num_ips; i++) if(!find_ip_in_name_record(namerec, record->ip[i])) add_ip_to_name_record(namerec, record->ip[i]); } else { overwrite=True; } } /* the replica is a multihomed host */ /* I'm giving up on multi homed. Too much complex to understand */ if (record->wins_flags&WINS_MHOMED) { if (! (namerec->data.wins_flags&WINS_ACTIVE)) { if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP)) overwrite=True; } else { if (ip_equal(record->wins_ip, namerec->data.wins_ip)) overwrite=True; if (ip_equal(namerec->data.wins_ip, our_fake_ip)) if (namerec->data.wins_flags&WINS_UNIQUE) get_global_id_and_update(&namerec->data.id, True); } if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE) if (namerec->data.wins_flags&WINS_UNIQUE || namerec->data.wins_flags&WINS_MHOMED) if (ip_equal(record->wins_ip, namerec->data.wins_ip)) overwrite=True; } if (overwrite == False) DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", record->name, record->type, inet_ntoa(record->wins_ip))); else { DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", record->name, record->type, inet_ntoa(record->wins_i
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?