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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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 );
* 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 );
}
}
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 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 );
+
+ 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;
}
/**************************************************************************
{
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 = (struct name_record *)malloc( sizeof(*namerec) );
+ 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) );
- namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) * num_ips );
+ 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;
+ return False;
}
namerec->subnet = 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;
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 ),
(unsigned int)nb_flags,
subrec->subnet_name ) );
- subrec->namelist_changed = True;
+ /* Now add the record to the name list. */
- return(namerec);
+ 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 ret;
}
/*******************************************************************
{
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,
{
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);
+ }
}
/*******************************************************************
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;
+ }
}
/*******************************************************************
{
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;
}
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 = (struct in_addr *)malloc( (namerec->data.num_ips + 1) * sizeof(struct in_addr) );
+ new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1);
if( NULL == new_list ) {
DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
return;
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;
+ }
}
/*******************************************************************
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 \
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)
/* Create an IP list containing all our known subnets. */
num_ips = iface_count();
- iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) );
+ iplist = SMB_MALLOC_ARRAY( struct in_addr, num_ips);
if( NULL == iplist ) {
DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
return;
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) {
+ const char *asct;
+ tm = localtime(&namerec->data.death_time);
+ if (!tm) {
+ return;
}
+ asct = asctime(tm);
+ if (!asct) {
+ return;
+ }
+ x_fprintf(fp, "death_time = %s\t", asct);
+ } 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) {
+ const char *asct;
+ tm = localtime(&namerec->data.refresh_time);
+ if (!tm) {
+ return;
+ }
+ asct = asctime(tm);
+ if (!asct) {
+ return;
}
+ x_fprintf(fp, "refresh_time = %s\n", asct);
+ } 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");
+
+}
- 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.
+**************************************************************************/
+
+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);
}
}
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 );
}