LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd_namelistdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 167 280 59.6 %
Date: 2024-04-21 15:09:00 Functions: 15 20 75.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios routines and daemon - version 2
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
       6             :    Copyright (C) Jeremy Allison 1994-2003
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             :    
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/filesys.h"
      25             : #include "nmbd/nmbd.h"
      26             : 
      27             : uint16_t samba_nb_type = 0; /* samba's NetBIOS name type */
      28             : 
      29             : 
      30             : /**************************************************************************
      31             :  Set Samba's NetBIOS name type.
      32             : ***************************************************************************/
      33             : 
      34          43 : void set_samba_nb_type(void)
      35             : {
      36          43 :         if( lp_we_are_a_wins_server() || wins_srv_count() ) {
      37           0 :                 samba_nb_type = NB_HFLAG;               /* samba is a 'hybrid' node type. */
      38             :         } else {
      39          43 :                 samba_nb_type = NB_BFLAG;           /* samba is broadcast-only node type. */
      40             :         }
      41          43 : }
      42             : 
      43             : /***************************************************************************
      44             :  Convert a NetBIOS name to upper case.
      45             : ***************************************************************************/
      46             : 
      47       12385 : static bool upcase_name( struct nmb_name *target, const struct nmb_name *source )
      48             : {
      49             :         int i;
      50             :         unstring targ;
      51             :         fstring scope;
      52             : 
      53       12385 :         if( NULL != source ) {
      54       11245 :                 memcpy( target, source, sizeof( struct nmb_name ) );
      55             :         }
      56             : 
      57       12385 :         pull_ascii_nstring(targ, sizeof(targ), target->name);
      58       12385 :         if (!strupper_m( targ )) {
      59           0 :                 return false;
      60             :         }
      61       12385 :         push_ascii_nstring( target->name, targ);
      62             : 
      63       12385 :         pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE);
      64       12385 :         if (!strupper_m( scope )) {
      65           0 :                 return false;
      66             :         }
      67       12385 :         push_ascii(target->scope, scope, 64, STR_TERMINATE);
      68             : 
      69             :         /* fudge... We're using a byte-by-byte compare, so we must be sure that
      70             :          * unused space doesn't have garbage in it.
      71             :          */
      72             : 
      73       87557 :         for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) {
      74       75172 :                 target->name[i] = '\0';
      75             :         }
      76      805025 :         for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) {
      77      792640 :                 target->scope[i] = '\0';
      78             :         }
      79       12385 :         return true;
      80             : }
      81             : 
      82             : /**************************************************************************
      83             :  Remove a name from the namelist.
      84             : ***************************************************************************/
      85             : 
      86           8 : void remove_name_from_namelist(struct subnet_record *subrec, 
      87             :                                 struct name_record *namerec )
      88             : {
      89           8 :         if (subrec == wins_server_subnet) 
      90           0 :                 remove_name_from_wins_namelist(namerec);
      91             :         else {
      92           8 :                 subrec->namelist_changed = True;
      93           8 :                 DLIST_REMOVE(subrec->namelist, namerec);
      94             :         }
      95             : 
      96           8 :         SAFE_FREE(namerec->data.ip);
      97           8 :         ZERO_STRUCTP(namerec);
      98           8 :         SAFE_FREE(namerec);
      99           8 : }
     100             : 
     101             : /**************************************************************************
     102             :  Find a name in a subnet.
     103             : **************************************************************************/
     104             : 
     105       11245 : struct name_record *find_name_on_subnet(struct subnet_record *subrec,
     106             :                                 const struct nmb_name *nmbname,
     107             :                                 bool self_only)
     108             : {
     109             :         struct nmb_name uc_name;
     110             :         struct name_record *name_ret;
     111             : 
     112       11245 :         if (!upcase_name( &uc_name, nmbname )) {
     113           0 :                 return NULL;
     114             :         }
     115             :         
     116       11245 :         if (subrec == wins_server_subnet) {
     117           0 :                 return find_name_on_wins_subnet(&uc_name, self_only);
     118             :         }
     119             : 
     120      108921 :         for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) {
     121       99689 :                 if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) {
     122        2013 :                         break;
     123             :                 }
     124             :         }
     125             : 
     126       11245 :         if( name_ret ) {
     127             :                 /* Self names only - these include permanent names. */
     128        2013 :                 if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) {
     129           0 :                         DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
     130             :                                                 subrec->subnet_name, nmb_namestr(nmbname) ) );
     131           0 :                         return NULL;
     132             :                 }
     133             : 
     134        2013 :                 DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
     135             :                         subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
     136             : 
     137        2013 :                 return name_ret;
     138             :         }
     139             : 
     140        9232 :         DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
     141             :                 subrec->subnet_name, nmb_namestr(nmbname) ) );
     142             : 
     143        9232 :         return NULL;
     144             : }
     145             : 
     146             : /**************************************************************************
     147             :  Find a name over all known broadcast subnets.
     148             : ************************************************************************/
     149             : 
     150           0 : struct name_record *find_name_for_remote_broadcast_subnet(struct nmb_name *nmbname,
     151             :                                                 bool self_only)
     152             : {
     153             :         struct subnet_record *subrec;
     154             :         struct name_record *namerec;
     155             : 
     156           0 :         for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) {
     157           0 :                 namerec = find_name_on_subnet(subrec, nmbname, self_only);
     158           0 :                 if (namerec) {
     159           0 :                         return namerec;
     160             :                 }
     161             :         }
     162             : 
     163           0 :         return NULL;
     164             : }
     165             :   
     166             : /**************************************************************************
     167             :  Update the ttl of an entry in a subnet name list.
     168             : ***************************************************************************/
     169             : 
     170           0 : void update_name_ttl( struct name_record *namerec, int ttl )
     171             : {
     172           0 :         time_t time_now = time(NULL);
     173             : 
     174           0 :         if( namerec->data.death_time != PERMANENT_TTL) {
     175           0 :                 namerec->data.death_time = time_now + ttl;
     176             :         }
     177             : 
     178           0 :         namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
     179             : 
     180           0 :         if (namerec->subnet == wins_server_subnet) {
     181           0 :                 wins_store_changed_namerec(namerec);
     182             :         } else {
     183           0 :                 namerec->subnet->namelist_changed = True;
     184             :         }
     185           0 : }
     186             : 
     187             : /**************************************************************************
     188             :  Add an entry to a subnet name list.
     189             : ***********************************************************************/
     190             : 
     191        1140 : bool add_name_to_subnet( struct subnet_record *subrec,
     192             :                         const char *name,
     193             :                         int type,
     194             :                         uint16_t nb_flags,
     195             :                         int ttl,
     196             :                         enum name_source source,
     197             :                         int num_ips,
     198             :                         struct in_addr *iplist)
     199             : {
     200        1140 :         bool ret = False;
     201             :         struct name_record *namerec;
     202        1140 :         time_t time_now = time(NULL);
     203             : 
     204        1140 :         if (num_ips == 0) {
     205           0 :                 return false;
     206             :         }
     207             : 
     208        1140 :         namerec = SMB_MALLOC_P(struct name_record);
     209        1140 :         if( NULL == namerec ) {
     210           0 :                 DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
     211           0 :                 return False;
     212             :         }
     213             : 
     214        1140 :         memset( (char *)namerec, '\0', sizeof(*namerec) );
     215        1140 :         namerec->data.ip = SMB_MALLOC_ARRAY( struct in_addr, num_ips );
     216        1140 :         if( NULL == namerec->data.ip ) {
     217           0 :                 DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
     218           0 :                 ZERO_STRUCTP(namerec);
     219           0 :                 SAFE_FREE(namerec);
     220           0 :                 return False;
     221             :         }
     222             : 
     223        1140 :         namerec->subnet = subrec;
     224             : 
     225        1140 :         make_nmb_name(&namerec->name, name, type);
     226        1140 :         if (!upcase_name(&namerec->name, NULL )) {
     227           0 :                 SAFE_FREE(namerec->data.ip);
     228           0 :                 SAFE_FREE(namerec);
     229           0 :                 return False;
     230             :         }
     231             : 
     232             :         /* Enter the name as active. */
     233        1140 :         namerec->data.nb_flags = nb_flags | NB_ACTIVE;
     234        1140 :         namerec->data.wins_flags = WINS_ACTIVE;
     235             : 
     236             :         /* If it's our primary name, flag it as so. */
     237        1140 :         if (strequal( my_netbios_names(0), name )) {
     238         258 :                 namerec->data.nb_flags |= NB_PERM;
     239             :         }
     240             : 
     241             :         /* Copy the IPs. */
     242        1140 :         namerec->data.num_ips = num_ips;
     243        1140 :         memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
     244             : 
     245             :         /* Data source. */
     246        1140 :         namerec->data.source = source;
     247             : 
     248             :         /* Setup the death_time and refresh_time. */
     249        1140 :         if (ttl == PERMANENT_TTL) {
     250        1140 :                 namerec->data.death_time = PERMANENT_TTL;
     251             :         } else {
     252           0 :                 namerec->data.death_time = time_now + ttl;
     253             :         }
     254             : 
     255        1140 :         namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
     256             : 
     257        1140 :         DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
     258             : ttl=%d nb_flags=%2x to subnet %s\n",
     259             :                 nmb_namestr( &namerec->name ),
     260             :                 inet_ntoa( *iplist ),
     261             :                 ttl,
     262             :                 (unsigned int)nb_flags,
     263             :                 subrec->subnet_name ) );
     264             : 
     265             :         /* Now add the record to the name list. */    
     266             : 
     267        1140 :         if (subrec == wins_server_subnet) {
     268           0 :                 ret = add_name_to_wins_subnet(namerec);
     269             :                 /* Free namerec - it's stored in the tdb. */
     270           0 :                 SAFE_FREE(namerec->data.ip);
     271           0 :                 SAFE_FREE(namerec);
     272             :         } else {
     273        1140 :                 DLIST_ADD(subrec->namelist, namerec);
     274        1140 :                 subrec->namelist_changed = True;
     275        1140 :                 ret = True;
     276             :         }
     277             : 
     278        1140 :         return ret;
     279             : }
     280             : 
     281             : /*******************************************************************
     282             :  Utility function automatically called when a name refresh or register 
     283             :  succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
     284             :  it).
     285             :  ******************************************************************/
     286             : 
     287         312 : void standard_success_register(struct subnet_record *subrec, 
     288             :                              struct userdata_struct *userdata,
     289             :                              struct nmb_name *nmbname, uint16_t nb_flags, int ttl,
     290             :                              struct in_addr registered_ip)
     291             : {
     292             :         struct name_record *namerec;
     293             : 
     294         312 :         namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
     295         312 :         if (namerec == NULL) {
     296             :                 unstring name;
     297         312 :                 pull_ascii_nstring(name, sizeof(name), nmbname->name);
     298         312 :                 add_name_to_subnet( subrec, name, nmbname->name_type,
     299             :                         nb_flags, ttl, SELF_NAME, 1, &registered_ip );
     300             :         } else {
     301           0 :                 update_name_ttl( namerec, ttl );
     302             :         }
     303         312 : }
     304             : 
     305             : /*******************************************************************
     306             :  Utility function automatically called when a name refresh or register 
     307             :  fails. Note that this is only ever called on a broadcast subnet with
     308             :  one IP address per name. This is why it can just delete the name 
     309             :  without enumerating the IP addresses. JRA.
     310             :  ******************************************************************/
     311             : 
     312           0 : void standard_fail_register( struct subnet_record   *subrec,
     313             :                              struct nmb_name        *nmbname )
     314             : {
     315             :         struct name_record *namerec;
     316             : 
     317           0 :         namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME);
     318             : 
     319           0 :         DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
     320             : on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) );
     321             : 
     322             :         /* Remove the name from the subnet. */
     323           0 :         if( namerec ) {
     324           0 :                 remove_name_from_namelist(subrec, namerec);
     325             :         }
     326           0 : }
     327             : 
     328             : /*******************************************************************
     329             :  Utility function to remove an IP address from a name record.
     330             :  ******************************************************************/
     331             : 
     332           8 : static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
     333             : {
     334           8 :         if( ind != namerec->data.num_ips ) {
     335           8 :                 memmove( (char *)(&namerec->data.ip[ind]),
     336           8 :                                 (char *)(&namerec->data.ip[ind+1]), 
     337           8 :                                 ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
     338             :         }
     339             : 
     340           8 :         namerec->data.num_ips--;
     341           8 :         if (namerec->subnet == wins_server_subnet) {
     342           0 :                 wins_store_changed_namerec(namerec);
     343             :         } else {
     344           8 :                 namerec->subnet->namelist_changed = True;
     345             :         }
     346           8 : }
     347             : 
     348             : /*******************************************************************
     349             :  Utility function to check if an IP address exists in a name record.
     350             :  ******************************************************************/
     351             : 
     352           0 : bool find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
     353             : {
     354             :         int i;
     355             : 
     356           0 :         for(i = 0; i < namerec->data.num_ips; i++) {
     357           0 :                 if(ip_equal_v4( namerec->data.ip[i], ip)) {
     358           0 :                         return True;
     359             :                 }
     360             :         }
     361             : 
     362           0 :         return False;
     363             : }
     364             : 
     365             : /*******************************************************************
     366             :  Utility function to add an IP address to a name record.
     367             :  ******************************************************************/
     368             : 
     369           0 : void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
     370             : {
     371             :         struct in_addr *new_list;
     372             : 
     373             :         /* Don't add one we already have. */
     374           0 :         if( find_ip_in_name_record( namerec, new_ip )) {
     375           0 :                 return;
     376             :         }
     377             :   
     378           0 :         new_list = SMB_MALLOC_ARRAY( struct in_addr, namerec->data.num_ips + 1);
     379           0 :         if( NULL == new_list ) {
     380           0 :                 DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
     381           0 :                 return;
     382             :         }
     383             : 
     384           0 :         memcpy( (char *)new_list, (char *)namerec->data.ip, namerec->data.num_ips * sizeof(struct in_addr) );
     385           0 :         new_list[namerec->data.num_ips] = new_ip;
     386             : 
     387           0 :         SAFE_FREE(namerec->data.ip);
     388           0 :         namerec->data.ip = new_list;
     389           0 :         namerec->data.num_ips += 1;
     390             : 
     391           0 :         if (namerec->subnet == wins_server_subnet) {
     392           0 :                 wins_store_changed_namerec(namerec);
     393             :         } else {
     394           0 :                 namerec->subnet->namelist_changed = True;
     395             :         }
     396             : }
     397             : 
     398             : /*******************************************************************
     399             :  Utility function to remove an IP address from a name record.
     400             :  ******************************************************************/
     401             : 
     402           8 : void remove_ip_from_name_record( struct name_record *namerec,
     403             :                                  struct in_addr      remove_ip )
     404             : {
     405             :         /* Try and find the requested ip address - remove it. */
     406             :         int i;
     407           8 :         int orig_num = namerec->data.num_ips;
     408             : 
     409           8 :         for(i = 0; i < orig_num; i++) {
     410           8 :                 if( ip_equal_v4( remove_ip, namerec->data.ip[i]) ) {
     411           8 :                         remove_nth_ip_in_record( namerec, i);
     412           8 :                         break;
     413             :                 }
     414             :         }
     415           8 : }
     416             : 
     417             : /*******************************************************************
     418             :  Utility function that release_name callers can plug into as the
     419             :  success function when a name release is successful. Used to save
     420             :  duplication of success_function code.
     421             :  ******************************************************************/
     422             : 
     423           4 : void standard_success_release( struct subnet_record   *subrec,
     424             :                                struct userdata_struct *userdata,
     425             :                                struct nmb_name        *nmbname,
     426             :                                struct in_addr          released_ip )
     427             : {
     428             :         struct name_record *namerec;
     429             : 
     430           4 :         namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME );
     431           4 :         if( namerec == NULL ) {
     432           0 :                 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
     433             : on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(released_ip),
     434             :                                 subrec->subnet_name) );
     435           0 :                 return;
     436             :         } else {
     437           4 :                 int orig_num = namerec->data.num_ips;
     438             : 
     439           4 :                 remove_ip_from_name_record( namerec, released_ip );
     440             : 
     441           4 :                 if( namerec->data.num_ips == orig_num ) {
     442           0 :                         DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
     443             : on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) );
     444             :                 }
     445             :         }
     446             : 
     447           4 :         if( namerec->data.num_ips == 0 ) {
     448           4 :                 remove_name_from_namelist( subrec, namerec );
     449             :         }
     450             : }
     451             : 
     452             : /*******************************************************************
     453             :  Expires old names in a subnet namelist.
     454             :  NB. Does not touch the wins_subnet - no wins specific processing here.
     455             : ******************************************************************/
     456             : 
     457        3499 : static void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
     458             : {
     459             :         struct name_record *namerec;
     460             :         struct name_record *next_namerec;
     461             : 
     462       44007 :         for( namerec = subrec->namelist; namerec; namerec = next_namerec ) {
     463       40508 :                 next_namerec = namerec->next;
     464       40508 :                 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
     465           0 :                         if( namerec->data.source == SELF_NAME ) {
     466           0 :                                 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
     467             : name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) );
     468           0 :                                 namerec->data.death_time += 300;
     469           0 :                                 namerec->subnet->namelist_changed = True;
     470           0 :                                 continue;
     471             :                         }
     472             : 
     473           0 :                         DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
     474             :                                 subrec->subnet_name, nmb_namestr(&namerec->name)));
     475             :   
     476           0 :                         remove_name_from_namelist(subrec, namerec );
     477             :                 }
     478             :         }
     479        3499 : }
     480             : 
     481             : /*******************************************************************
     482             :  Expires old names in all subnet namelists.
     483             :  NB. Does not touch the wins_subnet.
     484             : ******************************************************************/
     485             : 
     486        3499 : void expire_names(time_t t)
     487             : {
     488             :         struct subnet_record *subrec;
     489             : 
     490        6998 :         for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) {
     491        3499 :                 expire_names_on_subnet( subrec, t );
     492             :         }
     493        3499 : }
     494             : 
     495             : /****************************************************************************
     496             :   Add the magic samba names, useful for finding samba servers.
     497             :   These go directly into the name list for a particular subnet,
     498             :   without going through the normal registration process.
     499             :   When adding them to the unicast subnet, add them as a list of
     500             :   all broadcast subnet IP addresses.
     501             : **************************************************************************/
     502             : 
     503         129 : void add_samba_names_to_subnet( struct subnet_record *subrec )
     504             : {
     505         129 :         struct in_addr *iplist = &subrec->myip;
     506         129 :         int num_ips = 1;
     507             : 
     508             :         /* These names are added permanently (ttl of zero) and will NOT be refreshed.  */
     509             : 
     510         129 :         if( (subrec == unicast_subnet) || (subrec == wins_server_subnet) || (subrec == remote_broadcast_subnet) ) {
     511             :                 struct subnet_record *bcast_subrecs;
     512             :                 int i;
     513             : 
     514             :                 /* Create an IP list containing all our known subnets. */
     515             : 
     516          86 :                 num_ips = iface_count();
     517          86 :                 iplist = SMB_MALLOC_ARRAY( struct in_addr, num_ips);
     518          86 :                 if( NULL == iplist ) {
     519           0 :                         DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
     520           0 :                         return;
     521             :                 }
     522             : 
     523         172 :                 for( bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs &&
     524             :                                 i < num_ips;
     525          86 :                                 bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) {
     526          86 :                         iplist[i] = bcast_subrecs->myip;
     527             :                 }
     528          86 :                 num_ips = i;
     529             :         }
     530             : 
     531         129 :         add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
     532             :                                 PERMANENT_NAME, num_ips, iplist);
     533         129 :         add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
     534             :                                 PERMANENT_NAME, num_ips, iplist);
     535         129 :         add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
     536             :                                 PERMANENT_NAME, num_ips, iplist);
     537         129 :         add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
     538             :                                 PERMANENT_NAME, num_ips, iplist);
     539             : 
     540         129 :         if(iplist != &subrec->myip) {
     541          86 :                 SAFE_FREE(iplist);
     542             :         }
     543             : }
     544             : 
     545             : /****************************************************************************
     546             :  Dump a name_record struct.
     547             : **************************************************************************/
     548             : 
     549        2418 : void dump_name_record( struct name_record *namerec, FILE *fp)
     550             : {
     551             :         const char *src_type;
     552             :         struct tm *tm;
     553             :         int i;
     554             : 
     555        2418 :         fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
     556        2418 :         switch(namerec->data.source) {
     557           0 :                 case LMHOSTS_NAME:
     558           0 :                         src_type = "LMHOSTS_NAME";
     559           0 :                         break;
     560           0 :                 case WINS_PROXY_NAME:
     561           0 :                         src_type = "WINS_PROXY_NAME";
     562           0 :                         break;
     563           0 :                 case REGISTER_NAME:
     564           0 :                         src_type = "REGISTER_NAME";
     565           0 :                         break;
     566         711 :                 case SELF_NAME:
     567         711 :                         src_type = "SELF_NAME";
     568         711 :                         break;
     569           0 :                 case DNS_NAME:
     570           0 :                         src_type = "DNS_NAME";
     571           0 :                         break;
     572           0 :                 case DNSFAIL_NAME:
     573           0 :                         src_type = "DNSFAIL_NAME";
     574           0 :                         break;
     575        1707 :                 case PERMANENT_NAME:
     576        1707 :                         src_type = "PERMANENT_NAME";
     577        1707 :                         break;
     578           0 :                 default:
     579           0 :                         src_type = "unknown!";
     580           0 :                         break;
     581             :         }
     582             : 
     583        2418 :         fprintf(fp, "Source = %s\nb_flags = %x\t", src_type,
     584        2418 :                 namerec->data.nb_flags);
     585             : 
     586        2418 :         if(namerec->data.death_time != PERMANENT_TTL) {
     587             :                 const char *asct;
     588           0 :                 tm = localtime(&namerec->data.death_time);
     589           0 :                 if (!tm) {
     590           0 :                         return;
     591             :                 }
     592           0 :                 asct = asctime(tm);
     593           0 :                 if (!asct) {
     594           0 :                         return;
     595             :                 }
     596           0 :                 fprintf(fp, "death_time = %s\t", asct);
     597             :         } else {
     598        2418 :                 fprintf(fp, "death_time = PERMANENT\t");
     599             :         }
     600             : 
     601        2418 :         if(namerec->data.refresh_time != PERMANENT_TTL) {
     602             :                 const char *asct;
     603        2418 :                 tm = localtime(&namerec->data.refresh_time);
     604        2418 :                 if (!tm) {
     605           0 :                         return;
     606             :                 }
     607        2418 :                 asct = asctime(tm);
     608        2418 :                 if (!asct) {
     609           0 :                         return;
     610             :                 }
     611        2418 :                 fprintf(fp, "refresh_time = %s\n", asct);
     612             :         } else {
     613           0 :                 fprintf(fp, "refresh_time = PERMANENT\n");
     614             :         }
     615             : 
     616        2418 :         fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
     617        4836 :         for(i = 0; i < namerec->data.num_ips; i++) {
     618        2418 :                 fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
     619             :         }
     620             : 
     621        2418 :         fprintf(fp, "\n\n");
     622             : }
     623             : 
     624             : /****************************************************************************
     625             :  Dump the contents of the namelists on all the subnets (including unicast)
     626             :  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
     627             : **************************************************************************/
     628             : 
     629         249 : static void dump_subnet_namelist(struct subnet_record *subrec, FILE *fp)
     630             : {
     631             :         struct name_record *namerec;
     632         249 :         fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
     633        2667 :         for( namerec = subrec->namelist; namerec; namerec = namerec->next) {
     634        2418 :                 dump_name_record(namerec, fp);
     635             :         }
     636         249 : }
     637             : 
     638             : /****************************************************************************
     639             :  Dump the contents of the namelists on all the subnets (including unicast)
     640             :  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
     641             : **************************************************************************/
     642             : 
     643          83 : void dump_all_namelists(void)
     644             : {
     645             :         int fd;
     646             :         FILE *fp;
     647             :         struct subnet_record *subrec;
     648             :         char *dump_path;
     649             : 
     650          83 :         dump_path = lock_path(talloc_tos(), "namelist.debug");
     651          83 :         if (dump_path == NULL) {
     652           0 :                 DEBUG(0, ("out of memory!\n"));
     653           0 :                 return;
     654             :         }
     655             : 
     656          83 :         fd = open(dump_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
     657          83 :         if (fd == -1) {
     658           0 :                 DBG_ERR("Can't open file %s: %s\n", dump_path,
     659             :                         strerror(errno));
     660           0 :                 return;
     661             :         }
     662          83 :         TALLOC_FREE(dump_path);
     663             : 
     664          83 :         fp = fdopen(fd, "w");
     665          83 :         if (!fp) {
     666           0 :                 DBG_ERR("fdopen failed: %s\n", strerror(errno));
     667           0 :                 close(fd);
     668           0 :                 return;
     669             :         }
     670          83 :         fd = -1;
     671             : 
     672         166 :         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
     673          83 :                 dump_subnet_namelist( subrec, fp );
     674             :         }
     675             : 
     676          83 :         if (!we_are_a_wins_client()) {
     677          83 :                 dump_subnet_namelist( unicast_subnet, fp );
     678             :         }
     679             : 
     680          83 :         if (remote_broadcast_subnet->namelist != NULL) {
     681          83 :                 dump_subnet_namelist( remote_broadcast_subnet, fp );
     682             :         }
     683             : 
     684          83 :         if (wins_server_subnet != NULL) {
     685           0 :                 dump_wins_subnet_namelist(fp );
     686             :         }
     687             : 
     688          83 :         fclose( fp );
     689             : }

Generated by: LCOV version 1.14