📄 nmbd_namelistdb.c
字号:
/* 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"uint16 samba_nb_type = 0; /* samba's NetBIOS name type *//************************************************************************** Set Samba's NetBIOS name type.***************************************************************************/void set_samba_nb_type(void){ if( lp_wins_support() || wins_srv_count() ) { samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ } else { samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ }}/*************************************************************************** Convert a NetBIOS name to upper case.***************************************************************************/static void upcase_name( struct nmb_name *target, const struct nmb_name *source ){ int i; unstring targ; fstring scope; if( NULL != source ) { memcpy( target, source, sizeof( struct nmb_name ) ); } pull_ascii_nstring(targ, sizeof(targ), target->name); strupper_m( targ ); push_ascii_nstring( target->name, targ); pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE); strupper_m( scope ); push_ascii(target->scope, scope, 64, STR_TERMINATE); /* fudge... We're using a byte-by-byte compare, so we must be sure that * unused space doesn't have garbage in it. */ for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) { target->name[i] = '\0'; } for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) { target->scope[i] = '\0'; }}/************************************************************************** Remove a name from the namelist.***************************************************************************/static void update_name_in_namelist( struct subnet_record *subrec, struct name_record *namerec ){ struct name_record *oldrec = NULL; ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); if( oldrec ) { SAFE_FREE( oldrec->data.ip ); SAFE_FREE( oldrec ); }}/************************************************************************** Remove a name from the namelist.***************************************************************************/void remove_name_from_namelist( struct subnet_record *subrec, struct name_record *namerec ){ ubi_trRemove( subrec->namelist, namerec ); SAFE_FREE(namerec->data.ip); ZERO_STRUCTP(namerec); SAFE_FREE(namerec); subrec->namelist_changed = True;}/************************************************************************** Find a name in a subnet.**************************************************************************/struct name_record *find_name_on_subnet(struct subnet_record *subrec, const struct nmb_name *nmbname, BOOL self_only){ struct nmb_name uc_name[1]; struct name_record *name_ret; upcase_name( uc_name, nmbname ); name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); if( name_ret ) { /* Self names only - these include permanent names. */ if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) { DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", subrec->subnet_name, nmb_namestr(nmbname) ) ); return( NULL ); } DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); return name_ret; } DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", subrec->subnet_name, nmb_namestr(nmbname) ) ); return NULL;}/************************************************************************** Find a name over all known broadcast subnets.************************************************************************/struct name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname, BOOL self_only){ struct subnet_record *subrec; struct name_record *namerec; for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) { namerec = find_name_on_subnet(subrec, nmbname, self_only); if (namerec) { return namerec; } } return NULL;} /************************************************************************** Update the ttl of an entry in a subnet name list.***************************************************************************/void update_name_ttl( struct name_record *namerec, int ttl ){ time_t time_now = time(NULL); if( namerec->data.death_time != PERMANENT_TTL) { namerec->data.death_time = time_now + ttl; } namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); namerec->subnet->namelist_changed = True;}/************************************************************************** Add an entry to a subnet name list.***********************************************************************/struct name_record *add_name_to_subnet( struct subnet_record *subrec, const char *name, int type, uint16 nb_flags, int ttl, enum name_source source, int num_ips, struct in_addr *iplist){ struct name_record *namerec; time_t time_now = time(NULL); namerec = SMB_MALLOC_P(struct name_record); if( NULL == namerec ) { DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); return( NULL ); } memset( (char *)namerec, '\0', sizeof(*namerec) ); namerec->data.ip = SMB_MALLOC_ARRAY( struct in_addr, num_ips ); if( NULL == namerec->data.ip ) { DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); ZERO_STRUCTP(namerec); SAFE_FREE(namerec); return NULL; } namerec->subnet = subrec; make_nmb_name(&namerec->name, name, type); upcase_name(&namerec->name, NULL ); /* Enter the name as active. */ namerec->data.nb_flags = nb_flags | NB_ACTIVE; namerec->data.wins_flags = WINS_ACTIVE; /* If it's our primary name, flag it as so. */ if (strequal( my_netbios_names(0), name )) { namerec->data.nb_flags |= NB_PERM; } /* Copy the IPs. */ namerec->data.num_ips = num_ips; memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); /* Data source. */ namerec->data.source = source; /* Setup the death_time and refresh_time. */ if (ttl == PERMANENT_TTL) { namerec->data.death_time = PERMANENT_TTL; } else { namerec->data.death_time = time_now + ttl; } namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); /* Now add the record to the name list. */ update_name_in_namelist( subrec, namerec ); DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ttl=%d nb_flags=%2x to subnet %s\n", nmb_namestr( &namerec->name ), inet_ntoa( *iplist ), ttl, (unsigned int)nb_flags, subrec->subnet_name ) ); subrec->namelist_changed = True; return(namerec);}/******************************************************************* Utility function automatically called when a name refresh or register succeeds. By definition this is a SELF_NAME (or we wouldn't be registering it). ******************************************************************/void standard_success_register(struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *nmbname, uint16 nb_flags, int ttl, struct in_addr registered_ip){ struct name_record *namerec; namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME); if (namerec == NULL) { unstring name; pull_ascii_nstring(name, sizeof(name), nmbname->name); add_name_to_subnet( subrec, name, nmbname->name_type, nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); } else { update_name_ttl( namerec, ttl ); }}/******************************************************************* Utility function automatically called when a name refresh or register fails. Note that this is only ever called on a broadcast subnet with one IP address per name. This is why it can just delete the name without enumerating the IP adresses. JRA. ******************************************************************/void standard_fail_register( struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname ){ struct name_record *namerec; namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME); DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); /* Remove the name from the subnet. */ if( namerec ) { remove_name_from_namelist(subrec, namerec); }}/******************************************************************* Utility function to remove an IP address from a name record.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -