diff options
Diffstat (limited to 'source3/nmbd/nmbd_namelistdb.c')
-rw-r--r-- | source3/nmbd/nmbd_namelistdb.c | 327 |
1 files changed, 190 insertions, 137 deletions
diff --git a/source3/nmbd/nmbd_namelistdb.c b/source3/nmbd/nmbd_namelistdb.c index 88d5ea52f5..894b877613 100644 --- a/source3/nmbd/nmbd_namelistdb.c +++ b/source3/nmbd/nmbd_namelistdb.c @@ -32,24 +32,26 @@ uint16 samba_nb_type = 0; /* samba's NetBIOS name type */ void set_samba_nb_type(void) { - if( lp_wins_support() || wins_srv_count() ) + if( lp_wins_support() || wins_srv_count() ) { samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ - else + } 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, struct nmb_name *source ) +static void upcase_name( struct nmb_name *target, const struct nmb_name *source ) { int i; unstring targ; fstring scope; - if( NULL != source ) + if( NULL != source ) { memcpy( target, source, sizeof( struct nmb_name ) ); + } pull_ascii_nstring(targ, sizeof(targ), target->name); strupper_m( targ ); @@ -63,25 +65,11 @@ static void upcase_name( struct nmb_name *target, struct nmb_name *source ) * unused space doesn't have garbage in it. */ - for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) + for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) { target->name[i] = '\0'; - for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) + } + for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) { target->scope[i] = '\0'; -} - -/************************************************************************** - Add a new or overwrite an existing namelist entry. -***************************************************************************/ - -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 ); } } @@ -89,64 +77,81 @@ static void update_name_in_namelist( struct subnet_record *subrec, Remove a name from the namelist. ***************************************************************************/ -void remove_name_from_namelist( struct subnet_record *subrec, - struct name_record *namerec ) +void remove_name_from_namelist(struct subnet_record *subrec, + struct name_record *namerec ) { - ubi_trRemove( subrec->namelist, namerec ); + if (subrec == wins_server_subnet) { + remove_name_from_wins_namelist(namerec); + } else { + subrec->namelist_changed = True; + } + DLIST_REMOVE(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, - struct nmb_name *nmbname, - BOOL self_only ) +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 nmb_name uc_name; struct name_record *name_ret; - upcase_name( uc_name, nmbname ); - name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); + upcase_name( &uc_name, nmbname ); + + if (subrec == wins_server_subnet) { + return find_name_on_wins_subnet(&uc_name, self_only); + } + + for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) { + if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) { + break; + } + } + 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 ); + return False; } 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 ); + + 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 ); + + 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 name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname, + BOOL self_only) { struct subnet_record *subrec; - struct name_record *namerec = NULL; + struct name_record *namerec; for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) { - if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) - break; + namerec = find_name_on_subnet(subrec, nmbname, self_only); + if (namerec) { + return namerec; + } } - return( namerec ); + return NULL; } /************************************************************************** @@ -157,34 +162,40 @@ void update_name_ttl( struct name_record *namerec, int ttl ) { time_t time_now = time(NULL); - if( namerec->data.death_time != PERMANENT_TTL ) + 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; + if (namerec->subnet == wins_server_subnet) { + wins_store_changed_namerec(namerec); + } else { + 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) +BOOL 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) { + BOOL ret = False; 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 ); + return False; } memset( (char *)namerec, '\0', sizeof(*namerec) ); @@ -193,7 +204,7 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); ZERO_STRUCTP(namerec); SAFE_FREE(namerec); - return NULL; + return False; } namerec->subnet = subrec; @@ -206,8 +217,9 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, namerec->data.wins_flags = WINS_ACTIVE; /* If it's our primary name, flag it as so. */ - if( strequal( my_netbios_names(0), name ) ) + if (strequal( my_netbios_names(0), name )) { namerec->data.nb_flags |= NB_PERM; + } /* Copy the IPs. */ namerec->data.num_ips = num_ips; @@ -217,16 +229,14 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, namerec->data.source = source; /* Setup the death_time and refresh_time. */ - if( ttl == PERMANENT_TTL ) + if (ttl == PERMANENT_TTL) { namerec->data.death_time = PERMANENT_TTL; - else + } 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 ), @@ -235,9 +245,20 @@ ttl=%d nb_flags=%2x to subnet %s\n", (unsigned int)nb_flags, subrec->subnet_name ) ); - subrec->namelist_changed = True; + /* Now add the record to the name list. */ + + if (subrec == wins_server_subnet) { + ret = add_name_to_wins_subnet(namerec); + /* Free namerec - it's stored in the tdb. */ + SAFE_FREE(namerec->data.ip); + SAFE_FREE(namerec); + } else { + DLIST_ADD(subrec->namelist, namerec); + subrec->namelist_changed = True; + ret = True; + } - return(namerec); + return ret; } /******************************************************************* @@ -253,8 +274,8 @@ void standard_success_register(struct subnet_record *subrec, { struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - if( NULL == 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, @@ -277,14 +298,15 @@ void standard_fail_register( struct subnet_record *subrec, { struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + 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 ) + if( namerec ) { remove_name_from_namelist(subrec, namerec); + } } /******************************************************************* @@ -293,13 +315,18 @@ on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); static void remove_nth_ip_in_record( struct name_record *namerec, int ind) { - if( ind != namerec->data.num_ips ) + if( ind != namerec->data.num_ips ) { memmove( (char *)(&namerec->data.ip[ind]), (char *)(&namerec->data.ip[ind+1]), ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); + } namerec->data.num_ips--; - namerec->subnet->namelist_changed = True; + if (namerec->subnet == wins_server_subnet) { + wins_store_changed_namerec(namerec); + } else { + namerec->subnet->namelist_changed = True; + } } /******************************************************************* @@ -310,9 +337,11 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) { int i; - for(i = 0; i < namerec->data.num_ips; i++) - if(ip_equal( namerec->data.ip[i], ip)) + for(i = 0; i < namerec->data.num_ips; i++) { + if(ip_equal( namerec->data.ip[i], ip)) { return True; + } + } return False; } @@ -326,8 +355,9 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) struct in_addr *new_list; /* Don't add one we already have. */ - if( find_ip_in_name_record( namerec, new_ip ) ) + if( find_ip_in_name_record( namerec, new_ip )) { return; + } new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1); if( NULL == new_list ) { @@ -342,7 +372,11 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) namerec->data.ip = new_list; namerec->data.num_ips += 1; - namerec->subnet->namelist_changed = True; + if (namerec->subnet == wins_server_subnet) { + wins_store_changed_namerec(namerec); + } else { + namerec->subnet->namelist_changed = True; + } } /******************************************************************* @@ -388,26 +422,29 @@ on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa( remove_ip_from_name_record( namerec, released_ip ); - if( namerec->data.num_ips == orig_num ) + if( namerec->data.num_ips == orig_num ) { DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) ); + } } - if( namerec->data.num_ips == 0 ) + if( namerec->data.num_ips == 0 ) { remove_name_from_namelist( subrec, namerec ); + } } /******************************************************************* - Expires old names in a subnet namelist. + Expires old names in a subnet namelist. + NB. Does not touch the wins_subnet - no wins specific processing here. ******************************************************************/ -void expire_names_on_subnet(struct subnet_record *subrec, time_t t) +static void expire_names_on_subnet(struct subnet_record *subrec, time_t t) { struct name_record *namerec; struct name_record *next_namerec; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) { - next_namerec = (struct name_record *)ubi_trNext( namerec ); + for( namerec = subrec->namelist; namerec; namerec = next_namerec ) { + next_namerec = namerec->next; if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { if( namerec->data.source == SELF_NAME ) { DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ @@ -420,13 +457,14 @@ name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) ); DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name))); - remove_name_from_namelist( subrec, namerec ); + remove_name_from_namelist(subrec, namerec ); } } } /******************************************************************* - Expires old names in all subnet namelists. + Expires old names in all subnet namelists. + NB. Does not touch the wins_subnet. ******************************************************************/ void expire_names(time_t t) @@ -479,75 +517,85 @@ void add_samba_names_to_subnet( struct subnet_record *subrec ) add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, PERMANENT_NAME, num_ips, iplist); - if(iplist != &subrec->myip) + if(iplist != &subrec->myip) { SAFE_FREE(iplist); + } } /**************************************************************************** - Dump the contents of the namelists on all the subnets (including unicast) - into a file. Initiated by SIGHUP - used to debug the state of the namelists. + Dump a name_record struct. **************************************************************************/ -static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) +void dump_name_record( struct name_record *namerec, XFILE *fp) { - struct name_record *namerec; const char *src_type; struct tm *tm; int i; - x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) { - - x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); - switch(namerec->data.source) { - case LMHOSTS_NAME: - src_type = "LMHOSTS_NAME"; - break; - case WINS_PROXY_NAME: - src_type = "WINS_PROXY_NAME"; - break; - case REGISTER_NAME: - src_type = "REGISTER_NAME"; - break; - case SELF_NAME: - src_type = "SELF_NAME"; - break; - case DNS_NAME: - src_type = "DNS_NAME"; - break; - case DNSFAIL_NAME: - src_type = "DNSFAIL_NAME"; - break; - case PERMANENT_NAME: - src_type = "PERMANENT_NAME"; - break; - default: - src_type = "unknown!"; - break; - } + x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); + switch(namerec->data.source) { + case LMHOSTS_NAME: + src_type = "LMHOSTS_NAME"; + break; + case WINS_PROXY_NAME: + src_type = "WINS_PROXY_NAME"; + break; + case REGISTER_NAME: + src_type = "REGISTER_NAME"; + break; + case SELF_NAME: + src_type = "SELF_NAME"; + break; + case DNS_NAME: + src_type = "DNS_NAME"; + break; + case DNSFAIL_NAME: + src_type = "DNSFAIL_NAME"; + break; + case PERMANENT_NAME: + src_type = "PERMANENT_NAME"; + break; + default: + src_type = "unknown!"; + break; + } - x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); + x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - if(namerec->data.death_time != PERMANENT_TTL) { - tm = localtime(&namerec->data.death_time); - x_fprintf(fp, "death_time = %s\t", asctime(tm)); - } else { - x_fprintf(fp, "death_time = PERMANENT\t"); - } + if(namerec->data.death_time != PERMANENT_TTL) { + tm = localtime(&namerec->data.death_time); + x_fprintf(fp, "death_time = %s\t", asctime(tm)); + } else { + x_fprintf(fp, "death_time = PERMANENT\t"); + } - if(namerec->data.refresh_time != PERMANENT_TTL) { - tm = localtime(&namerec->data.refresh_time); - x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); - } else { - x_fprintf(fp, "refresh_time = PERMANENT\n"); - } + if(namerec->data.refresh_time != PERMANENT_TTL) { + tm = localtime(&namerec->data.refresh_time); + x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); + } else { + x_fprintf(fp, "refresh_time = PERMANENT\n"); + } - x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); - for(i = 0; i < namerec->data.num_ips; i++) - x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); + x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); + for(i = 0; i < namerec->data.num_ips; i++) { + x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); + } + + x_fprintf(fp, "\n\n"); + +} + +/**************************************************************************** + Dump the contents of the namelists on all the subnets (including unicast) + into a file. Initiated by SIGHUP - used to debug the state of the namelists. +**************************************************************************/ - x_fprintf(fp, "\n\n"); +static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) +{ + struct name_record *namerec; + x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); + for( namerec = subrec->namelist; namerec; namerec = namerec->next) { + dump_name_record(namerec, fp); } } @@ -569,16 +617,21 @@ void dump_all_namelists(void) return; } - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { dump_subnet_namelist( subrec, fp ); + } - if( !we_are_a_wins_client() ) + if (!we_are_a_wins_client()) { dump_subnet_namelist( unicast_subnet, fp ); + } - if( remote_broadcast_subnet->namelist != NULL ) + if (remote_broadcast_subnet->namelist != NULL) { dump_subnet_namelist( remote_broadcast_subnet, fp ); + } + + if (wins_server_subnet != NULL) { + dump_wins_subnet_namelist(fp ); + } - if( wins_server_subnet != NULL ) - dump_subnet_namelist( wins_server_subnet, fp ); x_fclose( fp ); } |