/*
   Unix SMB/Netbios implementation.
   Version 1.9.
   NBT netbios routines and daemon - version 2
   Copyright (C) Andrew Tridgell 1994-1998
   
   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.
   
   Revision History:

   14 jan 96: lkcl@pires.co.uk
   added multiple workgroup domain master support

*/

/******************************************************************************
 *
 * RCS ID
 * $Id: nmbd_interface,v 1.4 2002/11/17 16:43:22 david Exp $
 *
 * HISTORY
 * $Log: nmbd_interface,v $
 * Revision 1.4  2002/11/17 16:43:22  david
 * Updates to compiler with new 32-bit compiler
 *
 * Revision 1.3  2000/04/22 14:50:55  david
 * Updates for nmbd module debugging.
 * Updates for integrating nmbd with main smbserver application
 *
 * Revision 1.2  2000/04/17 16:46:29  david
 * updates to run in RISCOS MODULE
 *
 * Revision 1.1  2000/04/02 16:57:31  david
 * Updates to use the Internet event, use wimp poll event,
 * use non blocking sockets correctly,
 * compile libs in format suitable for RISCOS module
 * new nmbd module
 *
 *
 *
 *****************************************************************************/

#include "kernel.h"
#include "includes.h"
#include "protonmbd.h"
#include <signal.h>
#include "smbswi.h"

#define SIG_ATOMIC_T
#define SIGHUP 1
#define SIGPIPE 13

#ifndef SIGNAL_CAST
#define SIGNAL_CAST
#endif

#ifndef VOLATILE
#define VOLATILE
#endif
                  
#define NMBLOGFILE "<samba$dir>.Resources.nmbdlog"  


extern int DEBUGLEVEL;

extern pstring debugf;
pstring servicesf = CONFIGFILE;

extern pstring scope;

int ClientNMB       = -1;
int ClientDGRAM     = -1;
int global_nmb_port = -1;

BOOL run_election=False;

extern pstring myhostname;
static pstring host_file;
extern pstring global_myname;
extern fstring global_myworkgroup;
extern char **my_netbios_names;

extern BOOL global_in_nmbd;

/* are we running as a daemon ? */
static BOOL is_daemon = False;

/* have we found LanMan clients yet? */
BOOL found_lm_clients = False;

/* what server type are we currently */

time_t StartupTime = 0;

extern struct in_addr ipzero;
              
static int doneSigTerm=0;
                       
static void close_nmbd_sockets(void);

int doneNmbdStop = 0;

/**************************************************************************** **
  finalise code
 **************************************************************************** */
void nmbd_stop(BOOL force)
{             
  if (doneNmbdStop==0 && (lp_nameserver_enabled() || force))
  {
    doneNmbdStop=1;
  
    doneSigTerm=1;

    deregisterSocket(NMBD_SOCK_SET, ClientNMB);
    deregisterSocket(NMBD_SOCK_SET, ClientDGRAM);
    close(ClientNMB);
    close(ClientDGRAM);

    BlockSignals(True,SIGTERM);
  
    DEBUG(0,("Got SIGTERM: going down...\n"));
  
    /* Write out wins.dat file if samba is a WINS server */
    wins_write_database(False);
  
    /* Remove all SELF registered names. */
    release_my_names();
  
    /* Announce all server entries as 0 time-to-live, 0 type. */
    announce_my_servers_removed();

    /* If there was an async dns child - kill it. */
    kill_async_dns_child();          
                 
    close_nmbd_sockets();     

    del_subnets();
  } 
} 

/**************************************************************************** **
  finalise code
 **************************************************************************** */
void nmbd_exit(void)
{             
  nmbd_stop(False);  
  close_malloc(); 
} 

/**************************************************************************** **
 catch a sighup
 **************************************************************************** */
static VOLATILE SIG_ATOMIC_T BOOL reload_after_sighup = False;

static void nmnd_sig_hup(int sig)
{
  BlockSignals( True, SIGHUP );

  DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );

  write_browse_list( 0, True );

  dump_all_namelists();

  reload_after_sighup = True;

  BlockSignals(False,SIGHUP);

} /* sig_hup */


/**************************************************************************** **
 expire old names from the namelist and server list
 **************************************************************************** */
static void expire_names_and_servers(time_t t)
{
  static time_t lastrun = 0;
  
  if ( !lastrun )
    lastrun = t;
  if ( t < (lastrun + 5) )
    return;
  lastrun = t;

  /*
   * Expire any timed out names on all the broadcast
   * subnets and those registered with the WINS server.
   * (nmbd_namelistdb.c)
   */
  expire_names(t);

  /*
   * Go through all the broadcast subnets and for each
   * workgroup known on that subnet remove any expired
   * server names. If a workgroup has an empty serverlist
   * and has itself timed out then remove the workgroup.
   * (nmbd_workgroupdb.c)
   */
  expire_workgroups_and_servers(t);
} /* expire_names_and_servers */

/**************************************************************************** **
  reload the services file
 **************************************************************************** */
BOOL nmbd_reload_services(BOOL test)
{
  BOOL ret=False;
  extern fstring remote_machine;

  fstrcpy( remote_machine, "nmb" );

  if ( lp_loaded() )
  {
#ifdef RISCOS_MODULE
    static pstring fname;  
#else 
    pstring fname;
#endif
    pstrcpy( fname,lp_configfile());
    if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
    {
      pstrcpy(servicesf,fname);
      test = False;
    }
  }

  if ( test && !lp_file_list_changed() )
    return(True);

  ret = lp_load( servicesf, True , False, False);

  /* perhaps the config filename is now set */
  if ( !test )
  {
    DEBUG( 3, ( "services not loaded\n" ) );
    nmbd_reload_services( True );
  }

  /* Do a sanity check for a misconfigured nmbd */
  if( lp_wins_support() && *lp_wins_server() )
  {
    DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
cannot be set in the smb.conf file. nmbd aborting.\n"));
    return -1;
  }

  return(ret);
} /* reload_services */

/**************************************************************************** **
 The main select loop.
 **************************************************************************** */


int nmbd_main(int whoCalledMe)
{
    BOOL run_election=False;

    time_t t = time(NULL);
      

    DEBUG(10,("nmbd_main: t %d, whoCalledMe %d, \n", t, whoCalledMe));
    /*
     * Check all broadcast subnets to see if
     * we need to run an election on any of them.
     * (nmbd_elections.c)
     */
    run_election = check_elections();

    /*
     * Read incoming UDP packets.
     * (nmbd_packets.c)
     */
    if(listen_for_packets(run_election))
      return False;

    /*
     * Process all incoming packets
     * read above. This calls the success and
     * failure functions registered when response
     * packets arrrive, and also deals with request
     * packets from other sources.
     * (nmbd_packets.c)
     */
    DEBUG(10,("run_packet_queue\n"));
    run_packet_queue();

    /*
     * Run any elections - initiate becoming
     * a local master browser if we have won.
     * (nmbd_elections.c)
     */
    DEBUG(10,("run_elections\n"));
    run_elections(t);

    /*
     * Send out any broadcast announcements
     * of our server names. This also announces
     * the workgroup name if we are a local
     * master browser.
     * (nmbd_sendannounce.c)
     */                     
    DEBUG(10,("announce_my_server_names\n"));
    announce_my_server_names(t);

    /*
     * Send out any LanMan broadcast announcements
     * of our server names.
     * (nmbd_sendannounce.c)
     */                                
    DEBUG(10,("announce_my_lm_server_names\n"));
    announce_my_lm_server_names(t);

    /*
     * If we are a local master browser, periodically
     * announce ourselves to the domain master browser.
     * This also deals with syncronising the domain master
     * browser server lists with ourselves as a local
     * master browser.
     * (nmbd_sendannounce.c)
     */
    DEBUG(10,("announce_myselt_to_domain_master_browser\n"));
    announce_myself_to_domain_master_browser(t);

    /*
     * Fullfill any remote announce requests.
     * (nmbd_sendannounce.c)
     */                                                
    DEBUG(10,("announce_remote\n"));
    announce_remote(t);

    /*
     * Fullfill any remote browse sync announce requests.
     * (nmbd_sendannounce.c)
     */                       
    DEBUG(10,("browse_sync_remote\n"));
    browse_sync_remote(t);

    /*
     * Scan the broadcast subnets, and WINS client
     * namelists and refresh any that need refreshing.
     * (nmbd_mynames.c)
     */                          
    DEBUG(10,("refresh_my_names\n"));
    refresh_my_names(t);

    /*
     * Scan the subnet namelists and server lists and
     * expire thos that have timed out.
     * (nmbd.c)
     */                        
    DEBUG(10,("expire_names_and_servers\n"));
    expire_names_and_servers(t);

    /*
     * Write out a snapshot of our current browse list into
     * the browse.dat file. This is used by smbd to service
     * incoming NetServerEnum calls - used to synchronise
     * browse lists over subnets.
     * (nmbd_serverlistdb.c)
     */                                
    DEBUG(10,("write_browse_list\n"));
    write_browse_list(t, False);

    /*
     * If we are a domain master browser, we have a list of
     * local master browsers we should synchronise browse
     * lists with (these are added by an incoming local
     * master browser announcement packet). Expire any of
     * these that are no longer current, and pull the server
     * lists from each of these known local master browsers.
     * (nmbd_browsesync.c)
     */                         
    DEBUG(10,("dmb_expire_and_sync_browser_lists\n"));
    dmb_expire_and_sync_browser_lists(t);

    /*
     * Check that there is a local master browser for our
     * workgroup for all our broadcast subnets. If one
     * is not found, start an election (which we ourselves
     * may or may not participate in, depending on the
     * setting of the 'local master' parameter.
     * (nmbd_elections.c)
     */
    DEBUG(10,("check_master_browser_exists\n"));
    check_master_browser_exists(t);

    /*
     * If we are configured as a logon server, attempt to
     * register the special NetBIOS names to become such
     * (WORKGROUP<1c> name) on all broadcast subnets and
     * with the WINS server (if used). If we are configured
     * to become a domain master browser, attempt to register
     * the special NetBIOS name (WORKGROUP<1b> name) to
     * become such.
     * (nmbd_become_dmb.c)
     */
    DEBUG(10,("add_domain_names\n"));
    add_domain_names(t);

    /*
     * If we are a WINS server, do any timer dependent
     * processing required.
     * (nmbd_winsserver.c)
     */          
    DEBUG(10,("initiate_wins_processing\n"));
    initiate_wins_processing(t);

    /*
     * If we are a domain master browser, attempt to contact the
     * WINS server to get a list of all known WORKGROUPS/DOMAINS.
     * This will only work to a Samba WINS server.
     * (nmbd_browsesync.c)
     */          
    DEBUG(10,("collect_all_workgroup_names_from_wins_server\n"));
    collect_all_workgroup_names_from_wins_server(t);

    /*
     * Go through the response record queue and time out or re-transmit
     * and expired entries.
     * (nmbd_packets.c)
     */          
    DEBUG(10,("retransmit_or_expire_response_records\n"));
    retransmit_or_expire_response_records(t);

    /*
     * check to see if any remote browse sync child processes have completed
     */          
    DEBUG(10,("sync_check_completion\n"));
    sync_check_completion();

    /*
     * regularly sync with any other DMBs we know about 
     */          
    DEBUG(10,("sync_all_dmbs\n"));
    sync_all_dmbs(t);

    /*
     * Reload the services file if we got a sighup.
     */

    if(reload_after_sighup) {
      nmbd_reload_services( True );
      reload_after_sighup = False;
    }


    return (int) run_election; 
} /* process */

static void close_nmbd_sockets(void)
{
  struct subnet_record *subrec;
 
  for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
  {                         
    if (subrec->nmb_sock!=-1 && subrec->nmb_sock!=0)
    {
      deregisterSocket(NMBD_SOCK_SET, subrec->nmb_sock);
      close(subrec->nmb_sock);
      subrec->nmb_sock=-1;
    }
 
    if (subrec->dgram_sock!=-1 && subrec->dgram_sock!=0)
    {
      deregisterSocket(NMBD_SOCK_SET, subrec->dgram_sock);
      close(subrec->dgram_sock);
      subrec->dgram_sock=-1;
    }
  }

}


/**************************************************************************** **
 open the socket communication
 **************************************************************************** */
static BOOL open_sockets(BOOL isdaemon, int port)
{
  /* The sockets opened here will be used to receive broadcast
     packets *only*. Interface specific sockets are opened in
     make_subnet() in namedbsubnet.c. Thus we bind to the
     address "0.0.0.0". The parameter 'socket address' is
     now deprecated.
   */

  if ( isdaemon )
  {
    ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
    if (ClientNMB == -2)
    {
      if (killSocket(port,0)==True)
      {
        ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
      }
    }
  }
  else
    ClientNMB = 0;
  
  ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0);

  if ( ClientNMB == -1 )
    return( False );
 
  if (mySockOpts(ClientNMB)==-1)
    return False;

  if (mySockOpts(ClientDGRAM)==-1)
    return False;

  /* we are never interested in SIGPIPE */
  BlockSignals(True,SIGPIPE);

  set_socket_options( ClientNMB,   "SO_BROADCAST" );
  set_socket_options( ClientDGRAM, "SO_BROADCAST" );

  registerSocket(NMBD_SOCK_SET, ClientNMB);
  registerSocket(NMBD_SOCK_SET, ClientDGRAM);

  DEBUG(10,("ClientNMB %d, ClientDGRAM %d\n", ClientNMB, ClientDGRAM)); 

  DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
  return( True );
} /* open_sockets */


/**************************************************************************** **
 initialise connect, service and file structs
 **************************************************************************** */
static BOOL nmbd_init_structs(void)
{
  extern fstring local_machine;
  char *p, *ptr;
  int namecount;
  int n;
  int nodup;
#ifdef RISCOS_MODULE
  static pstring nbname;   
#else 
  pstring nbname;
#endif

  if (! *global_myname)
  {
    fstrcpy( global_myname, myhostname );
    p = strchr( global_myname, '.' );
    if (p)
      *p = 0;
  }
  strupper( global_myname );

  /* Add any NETBIOS name aliases. Ensure that the first entry
     is equal to global_myname.
   */
  /* Work out the max number of netbios aliases that we have */
  ptr = lp_netbios_aliases();
  for( namecount=0; next_token(&ptr,nbname,NULL, sizeof(nbname)); namecount++ )
    ;
  if ( *global_myname )
    namecount++;

  /* Allocate space for the netbios aliases */
  my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
  if( NULL == my_netbios_names )
  {
     DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
     return( False );
  }
 
  /* Use the global_myname string first */
  namecount=0;
  if ( *global_myname )
    my_netbios_names[namecount++] = global_myname;
  
  ptr = lp_netbios_aliases();
  while ( next_token( &ptr, nbname, NULL, sizeof(nbname) ) )
  {
    strupper( nbname );
    /* Look for duplicates */
    nodup=1;
    for( n=0; n<namecount; n++ )
    {
      if( 0 == strcmp( nbname, my_netbios_names[n] ) )
        nodup=0;
    }
    if (nodup)
      my_netbios_names[namecount++] = strdup( nbname );
  }
  
  /* Check the strdups succeeded. */
  for( n = 0; n < namecount; n++ )
    if( NULL == my_netbios_names[n] )
    {
      DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
      return False;
    }
  
  /* Terminate name list */
  my_netbios_names[namecount++] = NULL;
  
  fstrcpy( local_machine, global_myname );
  trim_string( local_machine, " ", " " );
  p = strchr( local_machine, ' ' );
  if (p)
    *p = 0;
  strlower( local_machine );

  DEBUG( 5, ("Netbios name list:-\n") );
  for( n=0; my_netbios_names[n]; n++ )
    DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );

  return( True );
} /* init_structs */


/**************************************************************************** **
 main program
 **************************************************************************** */
/* 
 * nmbd_entry called from module code or standalone command line nmbd executable
 */
int nmbd_entry(void)
{
  int opt;
  extern FILE *dbf;
  extern char *optarg;
  extern BOOL  append_log;

  DEBUGLEVEL=10;

  init_malloc();
  is_daemon = True;
  doneNmbdStop = 0;

  global_nmb_port = NMB_PORT;
  *host_file = 0;
  global_in_nmbd = True;

  StartupTime = time(NULL);

  sys_srandom(time(NULL) ^ getpid());

  TimeInit();

  pstrcpy( debugf, NMBLOGFILE );

  setup_logging( "nmbd", False );
  dbf=stdout;
  charset_initialise();

#ifdef LMHOSTSFILE
  pstrcpy( host_file, LMHOSTSFILE );
#endif


  DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
  DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );

  if( !get_myname( myhostname, NULL) )
  {
    DEBUG( 0, ( "Unable to get my hostname - exiting.\n" ) );
    return -1;
  }

  if ( !nmbd_reload_services(False) )
    return(-1);

  codepage_initialise(lp_client_code_page());

  if(!nmbd_init_structs())
    return -1;

  nmbd_reload_services( True );

  fstrcpy( global_myworkgroup, lp_workgroup() );

  if (strequal(global_myworkgroup,"*"))
  {
    DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
    return -1;
  }

  set_samba_nb_type();

  if (!is_daemon && !is_a_socket(0))
  {
    DEBUG(0,("standard input is not a socket, assuming -D option\n"));
    is_daemon = True;
  }
  
#if 0
  if (is_daemon)
  {
    DEBUG( 2, ( "Becoming a daemon.\n" ) );
    become_daemon();
  }
#endif

#if 0
  if (!directory_exist(lp_lockdir(), NULL)) {
	  mkdir(lp_lockdir(), 0755);
  }
#endif

  pidfile_create("nmbd");

  DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );

  if ( !open_sockets( is_daemon, global_nmb_port ) )   
  {
    DEBUG(0,("open sockets failed\n"));
    return 1; 
  }

  /* Determine all the IP addresses we have. */
  load_interfaces();

  /* Create an nmbd subnet record for each of the above. */
  if( False == create_subnets() )
  {
    DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
    return -1;
  }

  /* Load in any static local names. */ 
  if ( *host_file )
  {
    load_lmhosts_file(host_file);
    DEBUG(3,("Loaded hosts file\n"));
  }

  /* If we are acting as a WINS server, initialise data structures. */
  if( !initialise_wins() )
  {
    DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
    return -1;
  }

  /* 
   * Register nmbd primary workgroup and nmbd names on all
   * the broadcast subnets, and on the WINS server (if specified).
   * Also initiate the startup of our primary workgroup (start
   * elections if we are setup as being able to be a local
   * master browser.
   */

  if( False == register_my_workgroup_and_names() )
  {
    DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
    return -1;
  }
  
  return(0);
} /* main */

/**************************************************************************** **
 main program
 **************************************************************************** */
/* 
 * nmbd_init called from when nmbd is integrated with !smbserver applications
 */
int nmbd_init(void)
{
  int opt;
  extern FILE *dbf;
  extern char *optarg;
  extern BOOL  append_log;
                               
  if (lp_nameserver_enabled()==False)
  {
    return 0;
  }

  is_daemon = True;  
  doneNmbdStop = 0;

  global_nmb_port = NMB_PORT;
  *host_file = 0;
  global_in_nmbd = True;

  StartupTime = time(NULL);

  sys_srandom(time(NULL) ^ getpid());

#ifdef LMHOSTSFILE
  pstrcpy( host_file, LMHOSTSFILE );
#endif


  DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
  DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );

  if( !get_myname( myhostname, NULL) )
  {
    DEBUG( 0, ( "Unable to get my hostname - exiting.\n" ) );
    return -1;
  }

  if(!nmbd_init_structs())
    return -1;

  fstrcpy( global_myworkgroup, lp_workgroup() );

  if (strequal(global_myworkgroup,"*"))
  {
    DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
    return -1;
  }

  set_samba_nb_type();

  if (!is_daemon && !is_a_socket(0))
  {
    DEBUG(0,("standard input is not a socket, assuming -D option\n"));
    is_daemon = True;
  }
  
#if 0
  if (is_daemon)
  {
    DEBUG( 2, ( "Becoming a daemon.\n" ) );
    become_daemon();
  }
#endif

#if 0
  if (!directory_exist(lp_lockdir(), NULL)) {
	  mkdir(lp_lockdir(), 0755);
  }
#endif

  pidfile_create("nmbd");

  DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );

  if ( !open_sockets( is_daemon, global_nmb_port ) )   
  {
    DEBUG(0,("open sockets failed\n"));
    return 1; 
  }

  /* Determine all the IP addresses we have. */
  load_interfaces();

  /* Create an nmbd subnet record for each of the above. */
  if( False == create_subnets() )
  {
    DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
    return -1;
  }

  /* Load in any static local names. */ 
  if ( *host_file )
  {
    load_lmhosts_file(host_file);
    DEBUG(3,("Loaded hosts file\n"));
  }

  /* If we are acting as a WINS server, initialise data structures. */
  if( !initialise_wins() )
  {
    DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
    return -1;
  }

  /* 
   * Register nmbd primary workgroup and nmbd names on all
   * the broadcast subnets, and on the WINS server (if specified).
   * Also initiate the startup of our primary workgroup (start
   * elections if we are setup as being able to be a local
   * master browser.
   */

  if( False == register_my_workgroup_and_names() )
  {
    DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
    return -1;
  }
  
  return(0);
} /* main */


int resetNmbdTimer(void)
{
  _kernel_swi_regs r; 
                           
  _kernel_swi(SmbServer_NmbdTimerStop, &r, &r);  

  return 0;
}

int startNmbdTimer(int delay)
{
  _kernel_swi_regs r; 
                       
  r.r[0] = delay;
    
  _kernel_swi(SmbServer_NmbdTimerStart, &r, &r);  

  return 0;
}

int nmbdPollWordNonZeroAction(int eventType)
{
  resetNmbdTimer();
  if (nmbd_main(eventType)==1)
  {
    startNmbdTimer(10);
  }
  else
  {
    startNmbdTimer(1000);
  } 

  return 1;
}          

void nmbdDumpInfo(void)
{
  FILE *fp;

  fp=fopen("<samba$dir>.Resources.nmbdinfo","w");

  if (fp!=NULL)
  {
    if (lp_nameserver_enabled())
    {
      print_interfaces(fp);
      fprintf(fp,"\nBrowse List\n");
      print_browse_list(fp); 
      fprintf(fp,"\nNamelists\n");
      print_all_namelists(fp); 
    }
    else
    {
      fprintf(fp,"Nameserver is not enabled\n");
    }
    fclose(fp);
  }

}






