Half-way though the big conversion of all nmbd access to wire elements being
authorJeremy Allison <jra@samba.org>
Sat, 23 Aug 2003 01:59:14 +0000 (01:59 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 23 Aug 2003 01:59:14 +0000 (01:59 +0000)
converted to pull/push_ascii. This will not work right at the moment for non
English codepages, but compiles - I will finish the work over the weekend.
Then nmbd should be completely codepage correct.
Jeremy.
(This used to be commit 236d6adadf32397b28028ea82ae2ec027366f7c8)

12 files changed:
source3/include/nameserv.h
source3/include/safe_string.h
source3/include/smb.h
source3/lib/charcnv.c
source3/nmbd/nmbd.c
source3/nmbd/nmbd_become_dmb.c
source3/nmbd/nmbd_become_lmb.c
source3/nmbd/nmbd_browserdb.c
source3/nmbd/nmbd_browsesync.c
source3/nmbd/nmbd_elections.c
source3/nmbd/nmbd_incomingdgrams.c
source3/nmbd/nmbd_namequery.c

index 14561cf44d1e0ae3f6f2ea5c9e06b633c689807a..10e1295fb6e951647e9c66da8671e357de99c7b0 100644 (file)
@@ -176,124 +176,116 @@ enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
 enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
 enum packet_type {NMB_PACKET, DGRAM_PACKET};
 
-enum master_state
-{
-  MST_NONE,
-  MST_POTENTIAL,
-  MST_BACKUP,
-  MST_MSB,
-  MST_BROWSER,
-  MST_UNBECOMING_MASTER
+enum master_state {
+       MST_NONE,
+       MST_POTENTIAL,
+       MST_BACKUP,
+       MST_MSB,
+       MST_BROWSER,
+       MST_UNBECOMING_MASTER
 };
 
-enum domain_state
-{
-  DOMAIN_NONE,
-  DOMAIN_WAIT,
-  DOMAIN_MST
+enum domain_state {
+       DOMAIN_NONE,
+       DOMAIN_WAIT,
+       DOMAIN_MST
 };
 
-enum logon_state
-{
-  LOGON_NONE,
-  LOGON_WAIT,
-  LOGON_SRV
+enum logon_state {
+       LOGON_NONE,
+       LOGON_WAIT,
+       LOGON_SRV
 };
 
 struct subnet_record;
 
-struct nmb_data
-{
-  uint16 nb_flags;         /* Netbios flags. */
-  int num_ips;             /* Number of ip entries. */
-  struct in_addr *ip;      /* The ip list for this name. */
+struct nmb_data {
+       uint16 nb_flags;         /* Netbios flags. */
+       int num_ips;             /* Number of ip entries. */
+       struct in_addr *ip;      /* The ip list for this name. */
 
-  enum name_source source; /* Where the name came from. */
+       enum name_source source; /* Where the name came from. */
 
-  time_t death_time; /* The time the record must be removed (do not remove if 0). */
-  time_t refresh_time; /* The time the record should be refreshed. */
+       time_t death_time; /* The time the record must be removed (do not remove if 0). */
+       time_t refresh_time; /* The time the record should be refreshed. */
   
-  SMB_BIG_UINT id;             /* unique id */
-  struct in_addr wins_ip;      /* the adress of the wins server this record comes from */
+       SMB_BIG_UINT id;                /* unique id */
+       struct in_addr wins_ip; /* the adress of the wins server this record comes from */
 
-  int wins_flags;              /* similar to the netbios flags but different ! */
+       int wins_flags;         /* similar to the netbios flags but different ! */
 };
 
 /* This structure represents an entry in a local netbios name list. */
-struct name_record
-  {
-  ubi_trNode            node[1];
-  struct subnet_record *subnet;
-  struct nmb_name       name;    /* The netbios name. */
-  struct nmb_data       data;    /* The netbios data. */
-  };
+struct name_record {
+       ubi_trNode            node[1];
+       struct subnet_record *subnet;
+       struct nmb_name       name;    /* The netbios name. */
+       struct nmb_data       data;    /* The netbios data. */
+};
 
 /* Browser cache for synchronising browse lists. */
-struct browse_cache_record
-  {
-  ubi_dlNode     node[1];
-  pstring        lmb_name;
-  pstring        work_group;
-  struct in_addr ip;
-  time_t         sync_time;
-  time_t         death_time; /* The time the record must be removed. */
-  };
+struct browse_cache_record {
+       ubi_dlNode     node[1];
+       pstring        lmb_name;
+       pstring        work_group;
+       struct in_addr ip;
+       time_t         sync_time;
+       time_t         death_time; /* The time the record must be removed. */
+};
 
 /* This is used to hold the list of servers in my domain, and is
    contained within lists of domains. */
 
-struct server_record
-{
-  struct server_record *next;
-  struct server_record *prev;
+struct server_record {
+       struct server_record *next;
+       struct server_record *prev;
 
-  struct subnet_record *subnet;
+       struct subnet_record *subnet;
 
-  struct server_info_struct serv;
-  time_t death_time;  
+       struct server_info_struct serv;
+       time_t death_time;  
 };
 
 /* A workgroup structure. It contains a list of servers. */
-struct work_record
-{
-  struct work_record *next;
-  struct work_record *prev;
+struct work_record {
+       struct work_record *next;
+       struct work_record *prev;
 
-  struct subnet_record *subnet;
+       struct subnet_record *subnet;
 
-  struct server_record *serverlist;
+       struct server_record *serverlist;
 
-  /* Stage of development from non-local-master up to local-master browser. */
-  enum master_state mst_state;
+       /* Stage of development from non-local-master up to local-master browser. */
+       enum master_state mst_state;
 
-  /* Stage of development from non-domain-master to domain-master browser. */
-  enum domain_state dom_state;
+       /* Stage of development from non-domain-master to domain-master browser. */
+       enum domain_state dom_state;
 
-  /* Stage of development from non-logon-server to logon server. */
-  enum logon_state log_state;
+       /* Stage of development from non-logon-server to logon server. */
+       enum logon_state log_state;
 
-  /* Work group info. */
-  fstring work_group;
-  int     token;        /* Used when communicating with backup browsers. */
-  fstring local_master_browser_name;      /* Current local master browser. */
+       /* Work group info. */
+       fstring work_group;
+       int     token;        /* Used when communicating with backup browsers. */
+       fstring local_master_browser_name;      /* Current local master browser. */
 
-  /* Announce info. */
-  time_t lastannounce_time;
-  int announce_interval;
-  BOOL    needannounce;
+       /* Announce info. */
+       time_t lastannounce_time;
+       int announce_interval;
+       BOOL    needannounce;
 
-  /* Timeout time for this workgroup. 0 means permanent. */
-  time_t death_time;  
+       /* Timeout time for this workgroup. 0 means permanent. */
+       time_t death_time;  
 
-  /* Election info */
-  BOOL    RunningElection;
-  BOOL    needelection;
-  int     ElectionCount;
-  uint32  ElectionCriterion;
+       /* Election info */
+       BOOL    RunningElection;
+       BOOL    needelection;
+       int     ElectionCount;
+       uint32  ElectionCriterion;
 
-  /* Domain master browser info. Used for efficient syncs. */
-  struct nmb_name dmb_name;
-  struct in_addr dmb_addr;
+       /* Domain master browser info. Used for efficient syncs. */
+       struct nmb_name dmb_name;
+       struct in_addr dmb_addr;
 };
 
 /* typedefs needed to define copy & free functions for userdata. */
@@ -305,10 +297,10 @@ typedef void (*userdata_free_fn)(struct userdata_struct *);
 /* Structure to define any userdata passed around. */
 
 struct userdata_struct {
-  userdata_copy_fn copy_fn;
-  userdata_free_fn free_fn;
-  unsigned int userdata_len;
-  char data[16]; /* 16 is to ensure alignment/padding on all systems */
+       userdata_copy_fn copy_fn;
+       userdata_free_fn free_fn;
+       unsigned int userdata_len;
+       char data[16]; /* 16 is to ensure alignment/padding on all systems */
 };
 
 struct response_record;
@@ -382,33 +374,32 @@ typedef void (*node_status_fail_function)( struct subnet_record *,
 
 /* Initiated name queries are recorded in this list to track any responses. */
 
-struct response_record
-{
-  struct response_record *next;
-  struct response_record *prev;
+struct response_record {
+       struct response_record *next;
+       struct response_record *prev;
 
-  uint16 response_id;
+       uint16 response_id;
 
-  /* Callbacks for packets received or not. */ 
-  response_function resp_fn;
-  timeout_response_function timeout_fn;
+       /* Callbacks for packets received or not. */ 
+       response_function resp_fn;
+       timeout_response_function timeout_fn;
 
-  /* Callbacks for the request succeeding or not. */
-  success_function success_fn;
-  fail_function fail_fn;
+       /* Callbacks for the request succeeding or not. */
+       success_function success_fn;
+       fail_function fail_fn;
  
-  struct packet_struct *packet;
+       struct packet_struct *packet;
 
-  struct userdata_struct *userdata;
+       struct userdata_struct *userdata;
 
-  int num_msgs;
+       int num_msgs;
 
-  time_t repeat_time;
-  time_t repeat_interval;
-  int    repeat_count;
+       time_t repeat_time;
+       time_t repeat_interval;
+       int    repeat_count;
 
-  /* Recursion protection. */
-  BOOL in_expiration_processing;
+       /* Recursion protection. */
+       BOOL in_expiration_processing;
 };
 
 /* A subnet structure. It contains a list of workgroups and netbios names. */
@@ -420,42 +411,41 @@ struct response_record
 */
 
 enum subnet_type {
-  NORMAL_SUBNET              = 0,  /* Subnet listed in interfaces list. */
-  UNICAST_SUBNET             = 1,  /* Subnet for unicast packets. */
-  REMOTE_BROADCAST_SUBNET    = 2,  /* Subnet for remote broadcasts. */
-  WINS_SERVER_SUBNET         = 3   /* Only created if we are a WINS server. */
+       NORMAL_SUBNET              = 0,  /* Subnet listed in interfaces list. */
+       UNICAST_SUBNET             = 1,  /* Subnet for unicast packets. */
+       REMOTE_BROADCAST_SUBNET    = 2,  /* Subnet for remote broadcasts. */
+       WINS_SERVER_SUBNET         = 3   /* Only created if we are a WINS server. */
 };
 
-struct subnet_record
-{
-  struct subnet_record *next;
-  struct subnet_record *prev;
+struct subnet_record {
+       struct subnet_record *next;
+       struct subnet_record *prev;
 
-  char  *subnet_name;      /* For Debug identification. */
-  enum subnet_type type;   /* To catagorize the subnet. */
+       char  *subnet_name;      /* For Debug identification. */
+       enum subnet_type type;   /* To catagorize the subnet. */
 
-  struct work_record     *workgrouplist; /* List of workgroups. */
-  ubi_trRoot              namelist[1];   /* List of netbios names. */
-  struct response_record *responselist;  /* List of responses expected. */
+       struct work_record     *workgrouplist; /* List of workgroups. */
+       ubi_trRoot              namelist[1];   /* List of netbios names. */
+       struct response_record *responselist;  /* List of responses expected. */
 
-  BOOL namelist_changed;
-  BOOL work_changed;
+       BOOL namelist_changed;
+       BOOL work_changed;
 
-  struct in_addr bcast_ip;
-  struct in_addr mask_ip;
-  struct in_addr myip;
-  int nmb_sock;               /* socket to listen for unicast 137. */
-  int dgram_sock;             /* socket to listen for unicast 138. */
+       struct in_addr bcast_ip;
+       struct in_addr mask_ip;
+       struct in_addr myip;
+       int nmb_sock;               /* socket to listen for unicast 137. */
+       int dgram_sock;             /* socket to listen for unicast 138. */
 };
 
 /* A resource record. */
 struct res_rec {
-  struct nmb_name rr_name;
-  int rr_type;
-  int rr_class;
-  int ttl;
-  int rdlength;
-  char rdata[MAX_DGRAM_SIZE];
+       struct nmb_name rr_name;
+       int rr_type;
+       int rr_class;
+       int ttl;
+       int rdlength;
+       char rdata[MAX_DGRAM_SIZE];
 };
 
 /* Define these so we can pass info back to caller of name_query */
@@ -467,35 +457,34 @@ struct res_rec {
 #define NM_FLAGS_B  0x01 /* Broadcast           */
 
 /* An nmb packet. */
-struct nmb_packet
-{
-  struct {
-    int name_trn_id;
-    int opcode;
-    BOOL response;
-    struct {
-      BOOL bcast;
-      BOOL recursion_available;
-      BOOL recursion_desired;
-      BOOL trunc;
-      BOOL authoritative;
-    } nm_flags;
-    int rcode;
-    int qdcount;
-    int ancount;
-    int nscount;
-    int arcount;
-  } header;
-
-  struct {
-    struct nmb_name question_name;
-    int question_type;
-    int question_class;
-  } question;
-
-  struct res_rec *answers;
-  struct res_rec *nsrecs;
-  struct res_rec *additional;
+struct nmb_packet {
+       struct {
+               int name_trn_id;
+               int opcode;
+               BOOL response;
+               struct {
+                       BOOL bcast;
+                       BOOL recursion_available;
+                       BOOL recursion_desired;
+                       BOOL trunc;
+                       BOOL authoritative;
+               } nm_flags;
+               int rcode;
+               int qdcount;
+               int ancount;
+               int nscount;
+               int arcount;
+       } header;
+
+       struct {
+               struct nmb_name question_name;
+               int question_type;
+               int question_class;
+       } question;
+
+       struct res_rec *answers;
+       struct res_rec *nsrecs;
+       struct res_rec *additional;
 };
 
 /* msg_type field options - from rfc1002. */
@@ -511,23 +500,23 @@ struct nmb_packet
 /* A datagram - this normally contains SMB data in the data[] array. */
 
 struct dgram_packet {
-  struct {
-    int msg_type;
-    struct {
-      enum node_type node_type;
-      BOOL first;
-      BOOL more;
-    } flags;
-    int dgm_id;
-    struct in_addr source_ip;
-    int source_port;
-    int dgm_length;
-    int packet_offset;
-  } header;
-  struct nmb_name source_name;
-  struct nmb_name dest_name;
-  int datasize;
-  char data[MAX_DGRAM_SIZE];
+       struct {
+               int msg_type;
+               struct {
+                       enum node_type node_type;
+                       BOOL first;
+                       BOOL more;
+               } flags;
+               int dgm_id;
+               struct in_addr source_ip;
+               int source_port;
+               int dgm_length;
+               int packet_offset;
+       } header;
+       struct nmb_name source_name;
+       struct nmb_name dest_name;
+       int datasize;
+       char data[MAX_DGRAM_SIZE];
 };
 
 /* Define a structure used to queue packets. This will be a linked
@@ -535,18 +524,18 @@ struct dgram_packet {
 
 struct packet_struct
 {
-  struct packet_struct *next;
-  struct packet_struct *prev;
-  BOOL locked;
-  struct in_addr ip;
-  int port;
-  int fd;
-  time_t timestamp;
-  enum packet_type packet_type;
-  union {
-    struct nmb_packet nmb;
-    struct dgram_packet dgram;
-  } packet;
+       struct packet_struct *next;
+       struct packet_struct *prev;
+       BOOL locked;
+       struct in_addr ip;
+       int port;
+       int fd;
+       time_t timestamp;
+       enum packet_type packet_type;
+       union {
+               struct nmb_packet nmb;
+               struct dgram_packet dgram;
+       } packet;
 };
 
 /* NETLOGON opcodes */
index 6656f4f6bbb804fbc61d7713895c9dd7d393c535..07578b2424c3d00ffcaa2394c201b90e9726fc40 100644 (file)
@@ -124,6 +124,7 @@ size_t __unsafe_string_function_usage_here_char__(void);
 #define pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1)
 #define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
 #define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1)
+#define nstrcpy(d,s) safe_strcpy((d), (s),sizeof(nstring)-1)
 
 /* the addition of the DEVELOPER checks in safe_strcpy means we must
  * update a lot of code. To make this a little easier here are some
index 36c53065bce8cee09b390e17d267ee5b5fc7f3aa..8c6f47f23fbbb087d8d5a7a1f2c163e9bb05a15a 100644 (file)
@@ -1484,9 +1484,11 @@ struct cnotify_fns {
 
 #include "smb_macros.h"
 
+typedef char nstring[16];
+
 /* A netbios name structure. */
 struct nmb_name {
-       char         name[16];
+       nstring      name;
        char         scope[64];
        unsigned int name_type;
 };
@@ -1494,7 +1496,7 @@ struct nmb_name {
 
 /* A netbios node status array element. */
 struct node_status {
-       char name[16];
+       nstring name;
        unsigned char type;
        unsigned char flags;
 };
index 02d94582fbf59dd30d8d2b6d4a284f701a5193fc..7f372b358fcfa0d5816fecb3cc6bdd443d3ea143 100644 (file)
@@ -529,6 +529,11 @@ size_t push_ascii_pstring(void *dest, const char *src)
        return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
 }
 
+size_t push_ascii_nstring(void *dest, const char *src)
+{
+       return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
+}
+
 /**
  * Copy a string from a dos codepage source to a unix char* destination.
  *
@@ -582,6 +587,11 @@ size_t pull_ascii_fstring(char *dest, const void *src)
        return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
 }
 
+size_t pull_ascii_nstring(char *dest, const void *src)
+{
+       return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
+}
+
 /**
  * Copy a string from a char* src to a unicode destination.
  *
index fd648a4a2704da44da9cb70bdd1db0b59aa49ecc..c33011a4177d45634e1483bbbb04c098d16f71d8 100644 (file)
@@ -303,6 +303,7 @@ static BOOL reload_nmbd_services(BOOL test)
  * We use buf here to return BOOL result to process() when reload_interfaces()
  * detects that there are no subnets.
  **************************************************************************** */
+
 static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len)
 {
        write_browse_list( 0, True );
@@ -650,126 +651,120 @@ static BOOL open_sockets(BOOL isdaemon, int port)
                log_stdout = True;
        }
 
-  if ( log_stdout && Fork ) {
-    DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
-    exit(1);
-  }
+       if ( log_stdout && Fork ) {
+               DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
+               exit(1);
+       }
 
-  setup_logging( argv[0], log_stdout );
+       setup_logging( argv[0], log_stdout );
 
-  reopen_logs();
+       reopen_logs();
 
-  DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
-  DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
+       DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
+       DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) );
 
-  if ( !reload_nmbd_services(False) )
-    return(-1);
+       if ( !reload_nmbd_services(False) )
+               return(-1);
 
-  if(!init_names())
-    return -1;
+       if(!init_names())
+               return -1;
 
-  reload_nmbd_services( True );
+       reload_nmbd_services( True );
 
-  if (strequal(lp_workgroup(),"*"))
-  {
-    DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
-    exit(1);
-  }
+       if (strequal(lp_workgroup(),"*")) {
+               DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
+               exit(1);
+       }
 
-  set_samba_nb_type();
+       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 (!is_daemon && !is_a_socket(0)) {
+               DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+               is_daemon = True;
+       }
   
-  if (is_daemon && !opt_interactive)
-  {
-    DEBUG( 2, ( "Becoming a daemon.\n" ) );
-    become_daemon(Fork);
-  }
+       if (is_daemon && !opt_interactive) {
+               DEBUG( 2, ( "Becoming a daemon.\n" ) );
+               become_daemon(Fork);
+       }
 
 #if HAVE_SETPGID
-  /*
-   * If we're interactive we want to set our own process group for 
-   * signal management.
-   */
-  if (opt_interactive)
-    setpgid( (pid_t)0, (pid_t)0 );
+       /*
+        * If we're interactive we want to set our own process group for 
+        * signal management.
+        */
+       if (opt_interactive)
+               setpgid( (pid_t)0, (pid_t)0 );
 #endif
 
 #ifndef SYNC_DNS
-  /* Setup the async dns. We do it here so it doesn't have all the other
-     stuff initialised and thus chewing memory and sockets */
-  if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
-         start_async_dns();
-  }
+       /* Setup the async dns. We do it here so it doesn't have all the other
+               stuff initialised and thus chewing memory and sockets */
+       if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
+               start_async_dns();
+       }
 #endif
 
-  if (!directory_exist(lp_lockdir(), NULL)) {
-         mkdir(lp_lockdir(), 0755);
-  }
-
-  pidfile_create("nmbd");
-  message_init();
-  message_register(MSG_FORCE_ELECTION, nmbd_message_election);
-  message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
-  message_register(MSG_SHUTDOWN, nmbd_terminate);
-  message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
-
-  DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
-
-  if ( !open_sockets( is_daemon, global_nmb_port ) ) {
-    kill_async_dns_child();
-    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"));
-    kill_async_dns_child();
-    exit(1);
-  }
-
-  /* Load in any static local names. */ 
-  load_lmhosts_file(dyn_LMHOSTSFILE);
-  DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
-
-  /* If we are acting as a WINS server, initialise data structures. */
-  if( !initialise_wins() )
-  {
-    DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
-    kill_async_dns_child();
-    exit(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"));
-    kill_async_dns_child();
-    exit(1);
-  }
-
-  /* We can only take signals in the select. */
-  BlockSignals( True, SIGTERM );
-
-  process();
-
-  if (dbf)
-    x_fclose(dbf);
-  kill_async_dns_child();
-  return(0);
+       if (!directory_exist(lp_lockdir(), NULL)) {
+               mkdir(lp_lockdir(), 0755);
+       }
+
+       pidfile_create("nmbd");
+       message_init();
+       message_register(MSG_FORCE_ELECTION, nmbd_message_election);
+       message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
+       message_register(MSG_SHUTDOWN, nmbd_terminate);
+       message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
+
+       DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
+
+       if ( !open_sockets( is_daemon, global_nmb_port ) ) {
+               kill_async_dns_child();
+               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"));
+               kill_async_dns_child();
+               exit(1);
+       }
+
+       /* Load in any static local names. */ 
+       load_lmhosts_file(dyn_LMHOSTSFILE);
+       DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
+
+       /* If we are acting as a WINS server, initialise data structures. */
+       if( !initialise_wins() ) {
+               DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
+               kill_async_dns_child();
+               exit(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"));
+               kill_async_dns_child();
+               exit(1);
+       }
+
+       /* We can only take signals in the select. */
+       BlockSignals( True, SIGTERM );
+
+       process();
+
+       if (dbf)
+               x_fclose(dbf);
+       kill_async_dns_child();
+       return(0);
 }
index 2e76e51f453676cd3354afdf91f2b06e498ba3d9..46d37fbb817801bc59887c4ca8ebf94f6020fd96 100644 (file)
@@ -3,7 +3,7 @@
    NBT netbios routines and daemon - version 2
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
-   Copyright (C) Jeremy Allison 1994-1998
+   Copyright (C) Jeremy Allison 1994-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -37,36 +37,37 @@ static void become_domain_master_fail(struct subnet_record *subrec,
                                       struct response_record *rrec,
                                       struct nmb_name *fail_name)
 {
-  struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
-  struct server_record *servrec;
-
-  if(!work)
-  {
-    DEBUG(0,("become_domain_master_fail: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
-    return;
-  }
-
-  /* Set the state back to DOMAIN_NONE. */
-  work->dom_state = DOMAIN_NONE;
-
-  if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
-  {
-    DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
+       nstring failname;
+       struct work_record *work;
+       struct server_record *servrec;
+
+       pull_ascii_nstring(failname, fail_name->name);
+       work = find_workgroup_on_subnet(subrec, failname);
+       if(!work) {
+               DEBUG(0,("become_domain_master_fail: Error - cannot find \
+workgroup %s on subnet %s\n", failname, subrec->subnet_name));
+               return;
+       }
+
+       /* Set the state back to DOMAIN_NONE. */
+       work->dom_state = DOMAIN_NONE;
+
+       if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
+               DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), work->work_group, subrec->subnet_name));
-    return;
-  }
+                       global_myname(), work->work_group, subrec->subnet_name));
+               return;
+       }
 
-  /* Update our server status. */
-  servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
+       /* Update our server status. */
+       servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
 
-  /* Tell the namelist writer to write out a change. */
-  subrec->work_changed = True;
+       /* Tell the namelist writer to write out a change. */
+       subrec->work_changed = True;
 
-  DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
+       DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
 workgroup %s on subnet %s. Couldn't register name %s.\n",
-       work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
+               work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
 }
 
 /****************************************************************************
@@ -79,115 +80,112 @@ static void become_domain_master_stage2(struct subnet_record *subrec,
                                         uint16 nb_flags,
                                         int ttl, struct in_addr registered_ip)
 {
-  struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
-  struct server_record *servrec;
-
-  if(!work)
-  {
-    DEBUG(0,("become_domain_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
-    return;
-  }
-
-  if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
-  {
-    DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
+       nstring regname;
+       struct work_record *work;
+       struct server_record *servrec;
+
+       pull_ascii_nstring(regname, registered_name->name);
+       work = find_workgroup_on_subnet( subrec, regname);
+
+       if(!work) {
+               DEBUG(0,("become_domain_master_stage2: Error - cannot find \
+workgroup %s on subnet %s\n", regname, subrec->subnet_name));
+               return;
+       }
+
+       if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
+               DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
 in workgroup %s on subnet %s\n", 
-       global_myname(), registered_name->name, subrec->subnet_name));
-    work->dom_state = DOMAIN_NONE;
-    return;
-  }
-
-  /* Set the state in the workgroup structure. */
-  work->dom_state = DOMAIN_MST; /* Become domain master. */
-
-  /* Update our server status. */
-  servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
-
-  /* Tell the namelist writer to write out a change. */
-  subrec->work_changed = True;
-
-  if( DEBUGLVL( 0 ) )
-    {
-    dbgtext( "*****\n\nSamba server %s ", global_myname() );
-    dbgtext( "is now a domain master browser for " );
-    dbgtext( "workgroup %s ", work->work_group );
-    dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
-    }
-
-  if( subrec == unicast_subnet )
-  {
-    struct nmb_name nmbname;
-    struct in_addr my_first_ip;
-
-    /* Put our name and first IP address into the 
-       workgroup struct as domain master browser. This
-       will stop us syncing with ourself if we are also
-       a local master browser. */
-
-    make_nmb_name(&nmbname, global_myname(), 0x20);
-
-    work->dmb_name = nmbname;
-    /* Pick the first interface ip address as the domain master browser ip. */
-    my_first_ip = *iface_n_ip(0);
-
-    putip((char *)&work->dmb_addr, &my_first_ip);
-
-    /* We successfully registered by unicast with the
-       WINS server.  We now expect to become the domain
-       master on the local subnets. If this fails, it's
-       probably a 1.9.16p2 to 1.9.16p11 server's fault.
-
-       This is a configuration issue that should be addressed
-       by the network administrator - you shouldn't have
-       several machines configured as a domain master browser
-       for the same WINS scope (except if they are 1.9.17 or
-       greater, and you know what you're doing.
-
-       see docs/DOMAIN.txt.
-
-     */
-    become_domain_master_browser_bcast(work->work_group);
-  }
-  else
-  {
-    /*
-     * Now we are a domain master on a broadcast subnet, we need to add
-     * the WORKGROUP<1b> name to the unicast subnet so that we can answer
-     * unicast requests sent to this name. This bug wasn't found for a while
-     * as it is strange to have a DMB without using WINS. JRA.
-     */
-    insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
-  }
+               global_myname(), regname, subrec->subnet_name));
+               work->dom_state = DOMAIN_NONE;
+               return;
+       }
+
+       /* Set the state in the workgroup structure. */
+       work->dom_state = DOMAIN_MST; /* Become domain master. */
+
+       /* Update our server status. */
+       servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
+
+       /* Tell the namelist writer to write out a change. */
+       subrec->work_changed = True;
+
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "*****\n\nSamba server %s ", global_myname() );
+               dbgtext( "is now a domain master browser for " );
+               dbgtext( "workgroup %s ", work->work_group );
+               dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+       }
+
+       if( subrec == unicast_subnet ) {
+               struct nmb_name nmbname;
+               struct in_addr my_first_ip;
+
+               /* Put our name and first IP address into the 
+                  workgroup struct as domain master browser. This
+                  will stop us syncing with ourself if we are also
+                  a local master browser. */
+
+               make_nmb_name(&nmbname, global_myname(), 0x20);
+
+               work->dmb_name = nmbname;
+               /* Pick the first interface ip address as the domain master browser ip. */
+               my_first_ip = *iface_n_ip(0);
+
+               putip((char *)&work->dmb_addr, &my_first_ip);
+
+               /* We successfully registered by unicast with the
+                  WINS server.  We now expect to become the domain
+                  master on the local subnets. If this fails, it's
+                  probably a 1.9.16p2 to 1.9.16p11 server's fault.
+
+                  This is a configuration issue that should be addressed
+                  by the network administrator - you shouldn't have
+                  several machines configured as a domain master browser
+                  for the same WINS scope (except if they are 1.9.17 or
+                  greater, and you know what you're doing.
+
+                  see docs/DOMAIN.txt.
+
+               */
+               become_domain_master_browser_bcast(work->work_group);
+       } else {
+               /*
+                * Now we are a domain master on a broadcast subnet, we need to add
+                * the WORKGROUP<1b> name to the unicast subnet so that we can answer
+                * unicast requests sent to this name. This bug wasn't found for a while
+                * as it is strange to have a DMB without using WINS. JRA.
+                */
+               insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
+       }
 }
 
 /****************************************************************************
   Start the name registration process when becoming a Domain Master Browser
   on a subnet.
-  ****************************************************************************/
+****************************************************************************/
 
-static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
+static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name)
 { 
-  struct work_record *work;
+       struct work_record *work;
 
-  DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
+       DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
 
-  /* First, find the workgroup on the subnet. */
-  if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
-  {
-    DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
-          wg_name, subrec->subnet_name));
-    return;
-  }
-
-  DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
-  work->dom_state = DOMAIN_WAIT;
-
-  /* WORKGROUP<1b> is the domain master browser name. */
-  register_name(subrec, work->work_group,0x1b,samba_nb_type,
-                become_domain_master_stage2,
-                become_domain_master_fail, NULL);
+       /* First, find the workgroup on the subnet. */
+       if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) {
+               DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
+                       wg_name, subrec->subnet_name));
+               return;
+       }
+
+       DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
+       work->dom_state = DOMAIN_WAIT;
+
+       /* WORKGROUP<1b> is the domain master browser name. */
+       register_name(subrec, work->work_group,0x1b,samba_nb_type,
+                       become_domain_master_stage2,
+                       become_domain_master_fail, NULL);
 }
 
 /****************************************************************************
@@ -202,37 +200,35 @@ static void become_domain_master_query_success(struct subnet_record *subrec,
                         struct nmb_name *nmbname, struct in_addr ip, 
                         struct res_rec *rrec)
 {
-  /* If the given ip is not ours, then we can't become a domain
-     controler as the name is already registered.
-   */
-
- /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
-    address or zero ip for this query. Pretend this is ok. */
-
-  if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
-  {
-    if( DEBUGLVL( 3 ) )
-    {
-      dbgtext( "become_domain_master_query_success():\n" );
-      dbgtext( "Our address (%s) ", inet_ntoa(ip) );
-      dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
-      dbgtext( "(domain master browser name) " );
-      dbgtext( "on subnet %s.\n", subrec->subnet_name );
-      dbgtext( "Continuing with domain master code.\n" );
-    }
-
-    become_domain_master_stage1(subrec, nmbname->name);
-  }
-  else
-  {
-    if( DEBUGLVL( 0 ) )
-      {
-      dbgtext( "become_domain_master_query_success:\n" );
-      dbgtext( "There is already a domain master browser at " );
-      dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
-      dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
-      }
-  }
+       nstring name;
+       pull_ascii_nstring(name, nmbname->name);
+
+       /* If the given ip is not ours, then we can't become a domain
+               controler as the name is already registered.
+       */
+
+       /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
+               address or zero ip for this query. Pretend this is ok. */
+
+       if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) {
+               if( DEBUGLVL( 3 ) ) {
+                       dbgtext( "become_domain_master_query_success():\n" );
+                       dbgtext( "Our address (%s) ", inet_ntoa(ip) );
+                       dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
+                       dbgtext( "(domain master browser name) " );
+                       dbgtext( "on subnet %s.\n", subrec->subnet_name );
+                       dbgtext( "Continuing with domain master code.\n" );
+               }
+
+               become_domain_master_stage1(subrec, name);
+       } else {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "become_domain_master_query_success:\n" );
+                       dbgtext( "There is already a domain master browser at " );
+                       dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), name );
+                       dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
+               }
+       }
 }
 
 /****************************************************************************
@@ -245,18 +241,21 @@ static void become_domain_master_query_fail(struct subnet_record *subrec,
                                     struct response_record *rrec,
                                     struct nmb_name *question_name, int fail_code)
 {
-  /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
-     then this is a failure. Otherwise, not finding the name is what we want. */
-  if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
-  {
-    DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
+       nstring name;
+
+       /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
+               then this is a failure. Otherwise, not finding the name is what we want. */
+
+       if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) {
+               DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
 querying WINS server for name %s.\n", 
-                  fail_code, nmb_namestr(question_name)));
-    return;
-  }
+                       fail_code, nmb_namestr(question_name)));
+               return;
+       }
 
-  /* Otherwise - not having the name allows us to register it. */
-  become_domain_master_stage1(subrec, question_name->name);
+       /* Otherwise - not having the name allows us to register it. */
+       pull_ascii_nstring(name, question_name->name);
+       become_domain_master_stage1(subrec, name);
 }
 
 /****************************************************************************
@@ -265,47 +264,43 @@ querying WINS server for name %s.\n",
 
 static void become_domain_master_browser_bcast(const char *workgroup_name)
 {
-  struct subnet_record *subrec;
-
-  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
-  { 
-    struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
-    if (work && (work->dom_state == DOMAIN_NONE))
-    {
-      struct nmb_name nmbname;
-      make_nmb_name(&nmbname,workgroup_name,0x1b);
-
-      /*
-       * Check for our name on the given broadcast subnet first, only initiate
-       * further processing if we cannot find it.
-       */
-
-      if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
-      {
-        if( DEBUGLVL( 0 ) )
-          {
-          dbgtext( "become_domain_master_browser_bcast:\n" );
-          dbgtext( "Attempting to become domain master browser on " );
-          dbgtext( "workgroup %s on subnet %s\n",
-                    workgroup_name, subrec->subnet_name );
-          }
-
-        /* Send out a query to establish whether there's a 
-           domain controller on the local subnet. If not,
-           we can become a domain controller. 
-         */
-
-        DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
+       struct subnet_record *subrec;
+
+       for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { 
+               struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
+
+               if (work && (work->dom_state == DOMAIN_NONE)) {
+                       struct nmb_name nmbname;
+                       make_nmb_name(&nmbname,workgroup_name,0x1b);
+
+                       /*
+                        * Check for our name on the given broadcast subnet first, only initiate
+                        * further processing if we cannot find it.
+                        */
+
+                       if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
+                               if( DEBUGLVL( 0 ) ) {
+                                       dbgtext( "become_domain_master_browser_bcast:\n" );
+                                       dbgtext( "Attempting to become domain master browser on " );
+                                       dbgtext( "workgroup %s on subnet %s\n",
+                                               workgroup_name, subrec->subnet_name );
+                               }
+
+                               /* Send out a query to establish whether there's a 
+                                  domain controller on the local subnet. If not,
+                                  we can become a domain controller. 
+                               */
+
+                               DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
 
-        query_name(subrec, nmbname.name, nmbname.name_type,
-                   become_domain_master_query_success, 
-                   become_domain_master_query_fail,
-                   NULL);
-      }
-    }
-  }
+                               query_name(subrec, workgroup_name, nmbname.name_type,
+                                       become_domain_master_query_success, 
+                                       become_domain_master_query_fail,
+                                       NULL);
+                       }
+               }
+       }
 }
 
 /****************************************************************************
@@ -314,46 +309,43 @@ for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_nam
 
 static void become_domain_master_browser_wins(const char *workgroup_name)
 {
-  struct work_record *work;
+       struct work_record *work;
 
-  work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
+       work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
 
-  if (work && (work->dom_state == DOMAIN_NONE))
-  {
-    struct nmb_name nmbname;
+       if (work && (work->dom_state == DOMAIN_NONE)) {
+               struct nmb_name nmbname;
 
-    make_nmb_name(&nmbname,workgroup_name,0x1b);
+               make_nmb_name(&nmbname,workgroup_name,0x1b);
 
-    /*
-     * Check for our name on the unicast subnet first, only initiate
-     * further processing if we cannot find it.
-     */
+               /*
+                * Check for our name on the unicast subnet first, only initiate
+                * further processing if we cannot find it.
+                */
 
-    if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
-    {
-      if( DEBUGLVL( 0 ) )
-        {
-        dbgtext( "become_domain_master_browser_wins:\n" );
-        dbgtext( "Attempting to become domain master browser " );
-        dbgtext( "on workgroup %s, subnet %s.\n",
-                  workgroup_name, unicast_subnet->subnet_name );
-        }
+               if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) {
+                       if( DEBUGLVL( 0 ) ) {
+                               dbgtext( "become_domain_master_browser_wins:\n" );
+                               dbgtext( "Attempting to become domain master browser " );
+                               dbgtext( "on workgroup %s, subnet %s.\n",
+                                       workgroup_name, unicast_subnet->subnet_name );
+                       }
 
-      /* Send out a query to establish whether there's a 
-         domain master broswer registered with WINS. If not,
-         we can become a domain master browser. 
-       */
+                       /* Send out a query to establish whether there's a 
+                          domain master broswer registered with WINS. If not,
+                          we can become a domain master browser. 
+                       */
 
-      DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
+                       DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
 for domain master browser name %s on workgroup %s\n",
-         inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
-
-      query_name(unicast_subnet, nmbname.name, nmbname.name_type,
-                   become_domain_master_query_success,
-                   become_domain_master_query_fail,
-                   NULL);
-    }
-  }
+                               inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
+
+                       query_name(unicast_subnet, workgroup_name, nmbname.name_type,
+                               become_domain_master_query_success,
+                               become_domain_master_query_fail,
+                               NULL);
+               }
+       }
 }
 
 /****************************************************************************
@@ -363,34 +355,32 @@ for domain master browser name %s on workgroup %s\n",
 
 void add_domain_names(time_t t)
 {
-  static time_t lastrun = 0;
-
-  if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
-    return;
-
-  lastrun = t;
-
-  /* Do the "internet group" - <1c> names. */
-  if (lp_domain_logons())
-    add_logon_names();
-
-  /* Do the domain master names. */
-  if(lp_domain_master())
-  {
-    if(we_are_a_wins_client())
-    {
-      /* We register the WORKGROUP<1b> name with the WINS
-         server first, and call add_domain_master_bcast()
-         only if this is successful.
-
-         This results in domain logon services being gracefully provided,
-         as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
-         1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
-         cannot provide domain master / domain logon services.
-       */
-      become_domain_master_browser_wins(lp_workgroup());
-    }
-    else
-      become_domain_master_browser_bcast(lp_workgroup());
-  }
+       static time_t lastrun = 0;
+
+       if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
+               return;
+
+       lastrun = t;
+
+       /* Do the "internet group" - <1c> names. */
+       if (lp_domain_logons())
+               add_logon_names();
+
+       /* Do the domain master names. */
+       if(lp_domain_master()) {
+               if(we_are_a_wins_client()) {
+                       /* We register the WORKGROUP<1b> name with the WINS
+                               server first, and call add_domain_master_bcast()
+                               only if this is successful.
+
+                               This results in domain logon services being gracefully provided,
+                               as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
+                               1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
+                               cannot provide domain master / domain logon services.
+                       */
+                       become_domain_master_browser_wins(lp_workgroup());
+               } else {
+                       become_domain_master_browser_bcast(lp_workgroup());
+               }
+       }
 }
index d390bf72e9547cc8cc62f4e2a2705187fe7b2ad4..a6ae1ce42e74cff1c4ab9be7ef9d052115e28798 100644 (file)
@@ -3,7 +3,7 @@
    NBT netbios routines and daemon - version 2
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
-   Copyright (C) Jeremy Allison 1994-1998
+   Copyright (C) Jeremy Allison 1994-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -33,21 +33,20 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
 void insert_permanent_name_into_unicast( struct subnet_record *subrec, 
                                                 struct nmb_name *nmbname, uint16 nb_type )
 {
-  struct name_record *namerec;
-
-  if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
-  {
-    /* The name needs to be created on the unicast subnet. */
-    (void)add_name_to_subnet( unicast_subnet, nmbname->name,
-                              nmbname->name_type, nb_type,
-                              PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
-  }
-  else
-  {
-    /* The name already exists on the unicast subnet. Add our local
-       IP for the given broadcast subnet to the name. */
-    add_ip_to_name_record( namerec, subrec->myip);
-  }
+       nstring name;
+       struct name_record *namerec;
+
+       if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) {
+               pull_ascii_nstring(name, nmbname->name);
+               /* The name needs to be created on the unicast subnet. */
+               (void)add_name_to_subnet( unicast_subnet, name,
+                               nmbname->name_type, nb_type,
+                               PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
+       } else {
+               /* The name already exists on the unicast subnet. Add our local
+               IP for the given broadcast subnet to the name. */
+               add_ip_to_name_record( namerec, subrec->myip);
+       }
 }
 
 /*******************************************************************
@@ -57,15 +56,14 @@ void insert_permanent_name_into_unicast( struct subnet_record *subrec,
 static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
                                                 struct nmb_name *nmbname )
 {
-  struct name_record *namerec;
-
-  if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
-  {
-    /* Remove this broadcast subnet IP address from the name. */
-    remove_ip_from_name_record( namerec, subrec->myip);
-    if(namerec->data.num_ips == 0)
-      remove_name_from_namelist( unicast_subnet, namerec);
-  }
+       struct name_record *namerec;
+
+       if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) {
+               /* Remove this broadcast subnet IP address from the name. */
+               remove_ip_from_name_record( namerec, subrec->myip);
+               if(namerec->data.num_ips == 0)
+                       remove_name_from_namelist( unicast_subnet, namerec);
+       }
 }
 
 /*******************************************************************
@@ -73,60 +71,58 @@ static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
  state back to potential browser, or none.
 ******************************************************************/
 
-static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name,
+static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name,
                                    BOOL force_new_election )
 {
-  struct work_record *work;
-  struct server_record *servrec;
-  struct nmb_name nmbname;
+       struct work_record *work;
+       struct server_record *servrec;
+       struct nmb_name nmbname;
 
-  if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
-  {
-    DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
+       if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) {
+               DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
 subnet %s.\n", workgroup_name, subrec->subnet_name ));
-    return;
-  }
+               return;
+       }
 
-  if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
-  {
-    DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
+       if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
+               DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), work->work_group, subrec->subnet_name));
-    work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
-    return;
-  }
+                       global_myname(), work->work_group, subrec->subnet_name));
+               work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
+               return;
+       }
 
-  /* Update our server status - remove any master flag and replace
-   it with the potential browser flag. */
-  servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
-  servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
+       /* Update our server status - remove any master flag and replace
+               it with the potential browser flag. */
+       servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
+       servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
 
-  /* Tell the namelist writer to write out a change. */
-  subrec->work_changed = True;
+       /* Tell the namelist writer to write out a change. */
+       subrec->work_changed = True;
 
-  /* Reset our election flags. */
-  work->ElectionCriterion &= ~0x4;
+       /* Reset our election flags. */
+       work->ElectionCriterion &= ~0x4;
 
-  work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
+       work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
 
-  /* Forget who the local master browser was for
-     this workgroup. */
+       /* Forget who the local master browser was for
+               this workgroup. */
 
-  set_workgroup_local_master_browser_name( work, "");
+       set_workgroup_local_master_browser_name( work, "");
 
-  /*
-   * Ensure the IP address of this subnet is not registered as one
-   * of the IP addresses of the WORKGROUP<1d> name on the unicast
-   * subnet. This undoes what we did below when we became a local
-   * master browser.
-   */
+       /*
+        * Ensure the IP address of this subnet is not registered as one
+        * of the IP addresses of the WORKGROUP<1d> name on the unicast
+        * subnet. This undoes what we did below when we became a local
+        * master browser.
+        */
 
-  make_nmb_name(&nmbname, work->work_group, 0x1d);
+       make_nmb_name(&nmbname, work->work_group, 0x1d);
 
-  remove_permanent_name_from_unicast( subrec, &nmbname);
+       remove_permanent_name_from_unicast( subrec, &nmbname);
 
-  if(force_new_election)
-    work->needelection = True;
+       if(force_new_election)
+               work->needelection = True;
 }
 
 /*******************************************************************
@@ -138,24 +134,25 @@ static void unbecome_local_master_success(struct subnet_record *subrec,
                              struct nmb_name *released_name,
                              struct in_addr released_ip)
 { 
-  BOOL force_new_election = False;
+       BOOL force_new_election = False;
+       nstring relname;
 
-  memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
+       memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
 
-  DEBUG(3,("unbecome_local_master_success: released name %s.\n",
-             nmb_namestr(released_name)));
+       DEBUG(3,("unbecome_local_master_success: released name %s.\n",
+               nmb_namestr(released_name)));
 
-  /* Now reset the workgroup and server state. */
-  reset_workgroup_state( subrec, released_name->name, force_new_election );
+       /* Now reset the workgroup and server state. */
+       pull_ascii_nstring(relname, released_name->name);
+       reset_workgroup_state( subrec, relname, force_new_election );
 
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "*****\n\n" );
-    dbgtext( "Samba name server %s ", global_myname() );
-    dbgtext( "has stopped being a local master browser " );
-    dbgtext( "for workgroup %s ", released_name->name );
-    dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
-  }
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "*****\n\n" );
+               dbgtext( "Samba name server %s ", global_myname() );
+               dbgtext( "has stopped being a local master browser " );
+               dbgtext( "for workgroup %s ", relname );
+               dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+       }
 
 }
 
@@ -166,67 +163,66 @@ static void unbecome_local_master_success(struct subnet_record *subrec,
 static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
                        struct nmb_name *fail_name)
 {
-  struct name_record *namerec;
-  struct userdata_struct *userdata = rrec->userdata;
-  BOOL force_new_election = False;
+       struct name_record *namerec;
+       struct userdata_struct *userdata = rrec->userdata;
+       BOOL force_new_election = False;
+       nstring failname;
 
-  memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
+       memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
 
-  DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
+       DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
 Removing from namelist anyway.\n", nmb_namestr(fail_name)));
 
-  /* Do it anyway. */
-  namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
-  if(namerec)
-    remove_name_from_namelist(subrec, namerec);
-
-  /* Now reset the workgroup and server state. */
-  reset_workgroup_state( subrec, fail_name->name, force_new_election );
-
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "*****\n\n" );
-    dbgtext( "Samba name server %s ", global_myname() );
-    dbgtext( "has stopped being a local master browser " );
-    dbgtext( "for workgroup %s ", fail_name->name );
-    dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
-  }
+       /* Do it anyway. */
+       namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
+       if(namerec)
+               remove_name_from_namelist(subrec, namerec);
+
+       /* Now reset the workgroup and server state. */
+       pull_ascii_nstring(failname, fail_name->name);
+       reset_workgroup_state( subrec, failname, force_new_election );
+
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "*****\n\n" );
+               dbgtext( "Samba name server %s ", global_myname() );
+               dbgtext( "has stopped being a local master browser " );
+               dbgtext( "for workgroup %s ", failname );
+               dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+       }
 }
 
 /*******************************************************************
  Utility function to remove the WORKGROUP<1d> name.
 ******************************************************************/
 
-static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
+static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name,
                              BOOL force_new_election)
 {
-  struct nmb_name nmbname;
-  struct name_record *namerec;
-
-  make_nmb_name(&nmbname, workgroup_name, 0x1d);
-  if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
-  {
-    struct userdata_struct *userdata;
-    size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
-
-    if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
-    {
-      DEBUG(0,("release_1d_name: malloc fail.\n"));
-      return;
-    }
-
-    userdata->copy_fn = NULL;
-    userdata->free_fn = NULL;
-    userdata->userdata_len = sizeof(BOOL);
-    memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
-
-    release_name(subrec, namerec,
-                 unbecome_local_master_success,
-                 unbecome_local_master_fail,
-                 userdata);
-
-    zero_free(userdata, size);
-  }
+       struct nmb_name nmbname;
+       struct name_record *namerec;
+
+       make_nmb_name(&nmbname, workgroup_name, 0x1d);
+       if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
+               struct userdata_struct *userdata;
+               size_t size = sizeof(struct userdata_struct) + sizeof(BOOL);
+
+               if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
+                       DEBUG(0,("release_1d_name: malloc fail.\n"));
+                       return;
+               }
+
+               userdata->copy_fn = NULL;
+               userdata->free_fn = NULL;
+               userdata->userdata_len = sizeof(BOOL);
+               memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
+
+               release_name(subrec, namerec,
+                       unbecome_local_master_success,
+                       unbecome_local_master_fail,
+                       userdata);
+
+               zero_free(userdata, size);
+       }
 }
 
 /*******************************************************************
@@ -238,11 +234,11 @@ static void release_msbrowse_name_success(struct subnet_record *subrec,
                       struct nmb_name *released_name,
                       struct in_addr released_ip)
 {
-  DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
-           nmb_namestr(released_name), subrec->subnet_name ));
+       DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
+               nmb_namestr(released_name), subrec->subnet_name ));
 
-  /* Remove the permanent MSBROWSE name added into the unicast subnet. */
-  remove_permanent_name_from_unicast( subrec, released_name);
+       /* Remove the permanent MSBROWSE name added into the unicast subnet. */
+       remove_permanent_name_from_unicast( subrec, released_name);
 }
 
 /*******************************************************************
@@ -253,18 +249,18 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
                        struct response_record *rrec,
                        struct nmb_name *fail_name)
 {
-  struct name_record *namerec;
+       struct name_record *namerec;
 
-  DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
-           nmb_namestr(fail_name), subrec->subnet_name ));
+       DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
+               nmb_namestr(fail_name), subrec->subnet_name ));
 
-  /* Release the name anyway. */
-  namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
-  if(namerec)
-    remove_name_from_namelist(subrec, namerec);
+       /* Release the name anyway. */
+       namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
+       if(namerec)
+               remove_name_from_namelist(subrec, namerec);
 
-  /* Remove the permanent MSBROWSE name added into the unicast subnet. */
-  remove_permanent_name_from_unicast( subrec, fail_name);
+       /* Remove the permanent MSBROWSE name added into the unicast subnet. */
+       remove_permanent_name_from_unicast( subrec, fail_name);
 }
 
 /*******************************************************************
@@ -275,50 +271,48 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
 void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
                                    BOOL force_new_election)
 {
-  struct name_record *namerec;
-  struct nmb_name nmbname;
+       struct name_record *namerec;
+       struct nmb_name nmbname;
 
   /* Sanity check. */
 
-  DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
+       DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
 on subnet %s\n",work->work_group, subrec->subnet_name));
   
-  if(find_server_in_workgroup( work, global_myname()) == NULL)
-  {
-    DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
+       if(find_server_in_workgroup( work, global_myname()) == NULL) {
+               DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), work->work_group, subrec->subnet_name));
-    work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
-    return;
-  }
+                       global_myname(), work->work_group, subrec->subnet_name));
+                       work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
+               return;
+       }
   
-  /* Set the state to unbecoming. */
-  work->mst_state = MST_UNBECOMING_MASTER;
-
-  /*
-   * Release the WORKGROUP<1d> name asap to allow another machine to
-   * claim it.
-   */
-
-  release_1d_name( subrec, work->work_group, force_new_election);
-
-  /* Deregister any browser names we may have. */
-  make_nmb_name(&nmbname, MSBROWSE, 0x1);
-  if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
-  {
-    release_name(subrec, namerec,
-                 release_msbrowse_name_success,
-                 release_msbrowse_name_fail,
-                 NULL);
-  }
-
-  /*
-   * Ensure we have sent and processed these release packets
-   * before returning - we don't want to process any election
-   * packets before dealing with the 1d release.
-   */
-
-  retransmit_or_expire_response_records(time(NULL));
+       /* Set the state to unbecoming. */
+       work->mst_state = MST_UNBECOMING_MASTER;
+
+       /*
+        * Release the WORKGROUP<1d> name asap to allow another machine to
+        * claim it.
+        */
+
+       release_1d_name( subrec, work->work_group, force_new_election);
+
+       /* Deregister any browser names we may have. */
+       make_nmb_name(&nmbname, MSBROWSE, 0x1);
+       if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) {
+               release_name(subrec, namerec,
+                       release_msbrowse_name_success,
+                       release_msbrowse_name_fail,
+                       NULL);
+       }
+
+       /*
+        * Ensure we have sent and processed these release packets
+        * before returning - we don't want to process any election
+        * packets before dealing with the 1d release.
+        */
+
+       retransmit_or_expire_response_records(time(NULL));
 }
 
 /****************************************************************************
@@ -332,104 +326,107 @@ static void become_local_master_stage2(struct subnet_record *subrec,
                                         uint16 nb_flags,
                                         int ttl, struct in_addr registered_ip)
 {
-  int i = 0;
-  struct server_record *sl;
-  struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
-  struct server_record *servrec;
-
-  if(!work)
-  {
-    DEBUG(0,("become_local_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
-    return;
-  }
-
-  if((servrec = find_server_in_workgroup( work, global_myname())) == NULL)
-  {
-    DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
+       int i = 0;
+       struct server_record *sl;
+       struct work_record *work;
+       struct server_record *servrec;
+       nstring regname;
+
+       pull_ascii_nstring(regname, registered_name->name);
+       work = find_workgroup_on_subnet( subrec, regname);
+
+       if(!work) {
+               DEBUG(0,("become_local_master_stage2: Error - cannot find \
+workgroup %s on subnet %s\n", regname, subrec->subnet_name));
+               return;
+       }
+
+       if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
+               DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), registered_name->name, subrec->subnet_name));
-    work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
-    return;
-  }
+                       global_myname(), regname, subrec->subnet_name));
+                       work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
+               return;
+       }
   
-  DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
+       DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
 on subnet %s\n", work->work_group, subrec->subnet_name));
 
-  work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
-
-  /* update our server status */
-  servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
-  servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
-
-  /* Tell the namelist writer to write out a change. */
-  subrec->work_changed = True;
-
-  /* Add this name to the workgroup as local master browser. */
-  set_workgroup_local_master_browser_name( work, global_myname());
-
-  /* Count the number of servers we have on our list. If it's
-     less than 10 (just a heuristic) request the servers
-     to announce themselves.
-   */
-  for( sl = work->serverlist; sl != NULL; sl = sl->next)
-    i++;
-
-  if (i < 10)
-  {
-    /* Ask all servers on our local net to announce to us. */
-    broadcast_announce_request(subrec, work);
-  }
-
-  /*
-   * Now we are a local master on a broadcast subnet, we need to add
-   * the WORKGROUP<1d> name to the unicast subnet so that we can answer
-   * unicast requests sent to this name. We can create this name directly on
-   * the unicast subnet as a WINS server always returns true when registering
-   * this name, and discards the registration. We use the number of IP
-   * addresses registered to this name as a reference count, as we
-   * remove this broadcast subnet IP address from it when we stop becoming a local
-   * master browser for this broadcast subnet.
-   */
-
-  insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
-  /* Reset the announce master browser timer so that we try and tell a domain
-     master browser as soon as possible that we are a local master browser. */
-  reset_announce_timer();
-
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "*****\n\n" );
-    dbgtext( "Samba name server %s ", global_myname() );
-    dbgtext( "is now a local master browser " );
-    dbgtext( "for workgroup %s ", work->work_group );
-    dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
-  }
-
+       work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
+
+       /* update our server status */
+       servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
+       servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
+
+       /* Tell the namelist writer to write out a change. */
+       subrec->work_changed = True;
+
+       /* Add this name to the workgroup as local master browser. */
+       set_workgroup_local_master_browser_name( work, global_myname());
+
+       /* Count the number of servers we have on our list. If it's
+               less than 10 (just a heuristic) request the servers
+               to announce themselves.
+       */
+       for( sl = work->serverlist; sl != NULL; sl = sl->next)
+               i++;
+
+       if (i < 10) {
+               /* Ask all servers on our local net to announce to us. */
+               broadcast_announce_request(subrec, work);
+       }
+
+       /*
+        * Now we are a local master on a broadcast subnet, we need to add
+        * the WORKGROUP<1d> name to the unicast subnet so that we can answer
+        * unicast requests sent to this name. We can create this name directly on
+        * the unicast subnet as a WINS server always returns true when registering
+        * this name, and discards the registration. We use the number of IP
+        * addresses registered to this name as a reference count, as we
+        * remove this broadcast subnet IP address from it when we stop becoming a local
+        * master browser for this broadcast subnet.
+        */
+
+       insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
+
+       /* Reset the announce master browser timer so that we try and tell a domain
+               master browser as soon as possible that we are a local master browser. */
+       reset_announce_timer();
+
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "*****\n\n" );
+               dbgtext( "Samba name server %s ", global_myname() );
+               dbgtext( "is now a local master browser " );
+               dbgtext( "for workgroup %s ", work->work_group );
+               dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
+       }
 }
 
 /****************************************************************************
   Failed to register the WORKGROUP<1d> name.
   ****************************************************************************/
+
 static void become_local_master_fail2(struct subnet_record *subrec,
                                       struct response_record *rrec,
                                       struct nmb_name *fail_name)
 {
-  struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
+       nstring failname;
+       struct work_record *work;
 
-  DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
+       DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
 Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
 
-  if(!work)
-  {
-    DEBUG(0,("become_local_master_fail2: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
-    return;
-  }
+       pull_ascii_nstring(failname, fail_name->name);
+       work = find_workgroup_on_subnet( subrec, failname);
 
-  /* Roll back all the way by calling unbecome_local_master_browser(). */
-  unbecome_local_master_browser(subrec, work, False);
+       if(!work) {
+               DEBUG(0,("become_local_master_fail2: Error - cannot find \
+workgroup %s on subnet %s\n", failname, subrec->subnet_name));
+               return;
+       }
+
+       /* Roll back all the way by calling unbecome_local_master_browser(). */
+       unbecome_local_master_browser(subrec, work, False);
 }
 
 /****************************************************************************
@@ -442,35 +439,34 @@ static void become_local_master_stage1(struct subnet_record *subrec,
                                         uint16 nb_flags,
                                         int ttl, struct in_addr registered_ip)
 {
-  char *work_name = userdata->data;
-  struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
-
-  if(!work)
-  {
-    DEBUG(0,("become_local_master_stage1: Error - cannot find \
-workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
-    return;
-  }
-
-  DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
-            work->work_group));
-
-  work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
-
-  /*
-   * We registered the MSBROWSE name on a broadcast subnet, now need to add
-   * the MSBROWSE name to the unicast subnet so that we can answer
-   * unicast requests sent to this name. We create this name directly on
-   * the unicast subnet.
-   */
-
-  insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
-  /* Attempt to register the WORKGROUP<1d> name. */
-  register_name(subrec, work->work_group,0x1d,samba_nb_type,
-                become_local_master_stage2,
-                become_local_master_fail2,
-                NULL);
+       char *work_name = userdata->data;
+       struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
+
+       if(!work) {
+               DEBUG(0,("become_local_master_stage1: Error - cannot find \
+                       %s on subnet %s\n", work_name, subrec->subnet_name));
+               return;
+       }
+
+       DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
+               work->work_group));
+
+       work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
+
+       /*
+        * We registered the MSBROWSE name on a broadcast subnet, now need to add
+        * the MSBROWSE name to the unicast subnet so that we can answer
+        * unicast requests sent to this name. We create this name directly on
+        * the unicast subnet.
+        */
+
+       insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
+
+       /* Attempt to register the WORKGROUP<1d> name. */
+       register_name(subrec, work->work_group,0x1d,samba_nb_type,
+               become_local_master_stage2,
+               become_local_master_fail2,
+               NULL);
 }
 
 /****************************************************************************
@@ -481,29 +477,27 @@ static void become_local_master_fail1(struct subnet_record *subrec,
                                       struct response_record *rrec,
                                       struct nmb_name *fail_name)
 {
-  char *work_name = rrec->userdata->data;
-  struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
+       char *work_name = rrec->userdata->data;
+       struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
 
-  if(!work)
-  {
-    DEBUG(0,("become_local_master_fail1: Error - cannot find \
+       if(!work) {
+               DEBUG(0,("become_local_master_fail1: Error - cannot find \
 workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
-    return;
-  }
+               return;
+       }
 
-  if(find_server_in_workgroup(work, global_myname()) == NULL)
-  {
-    DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
+       if(find_server_in_workgroup(work, global_myname()) == NULL) {
+               DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), work->work_group, subrec->subnet_name));
-    return;
-  }
+                       global_myname(), work->work_group, subrec->subnet_name));
+               return;
+       }
 
-  reset_workgroup_state( subrec, work->work_group, False );
+       reset_workgroup_state( subrec, work->work_group, False );
 
-  DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
+       DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
 workgroup %s on subnet %s. Couldn't register name %s.\n",
-       work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
+               work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
 }
 
 /******************************************************************
@@ -517,61 +511,57 @@ workgroup %s on subnet %s. Couldn't register name %s.\n",
 
 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
 {
-  struct userdata_struct *userdata;
-  size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
-
-  /* Sanity check. */
-  if (!lp_local_master())
-  { 
-    DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
-    return;
-  }
-
-  if(!AM_POTENTIAL_MASTER_BROWSER(work))
-  {
-    DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
-              work->mst_state ));
-    return;
-  }
-
-  if(find_server_in_workgroup( work, global_myname()) == NULL)
-  {
-    DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
+       struct userdata_struct *userdata;
+       size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
+
+       /* Sanity check. */
+       if (!lp_local_master()) { 
+               DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
+               return;
+       }
+
+       if(!AM_POTENTIAL_MASTER_BROWSER(work)) {
+               DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
+                       work->mst_state ));
+               return;
+       }
+
+       if(find_server_in_workgroup( work, global_myname()) == NULL) {
+               DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
 in workgroup %s on subnet %s\n",
-       global_myname(), work->work_group, subrec->subnet_name));
-    return;
-  }
+                       global_myname(), work->work_group, subrec->subnet_name));
+               return;
+       }
 
-  DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
+       DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
 %s on subnet %s\n", work->work_group, subrec->subnet_name));
   
-  DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
-  work->mst_state = MST_BACKUP; /* an election win was successful */
+       DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
+       work->mst_state = MST_BACKUP; /* an election win was successful */
 
-  work->ElectionCriterion |= 0x5;
+       work->ElectionCriterion |= 0x5;
 
-  /* Tell the namelist writer to write out a change. */
-  subrec->work_changed = True;
+       /* Tell the namelist writer to write out a change. */
+       subrec->work_changed = True;
 
-  /* Setup the userdata_struct. */
-  if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
-  {
-    DEBUG(0,("become_local_master_browser: malloc fail.\n"));
-    return;
-  }
+       /* Setup the userdata_struct. */
+       if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
+               DEBUG(0,("become_local_master_browser: malloc fail.\n"));
+               return;
+       }
 
-  userdata->copy_fn = NULL;
-  userdata->free_fn = NULL;
-  userdata->userdata_len = strlen(work->work_group)+1;
-  overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
+       userdata->copy_fn = NULL;
+       userdata->free_fn = NULL;
+       userdata->userdata_len = strlen(work->work_group)+1;
+       overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
 
-  /* Register the special browser group name. */
-  register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
-                become_local_master_stage1,
-                become_local_master_fail1,
-                userdata);
+       /* Register the special browser group name. */
+       register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
+               become_local_master_stage1,
+               become_local_master_fail1,
+               userdata);
 
-  zero_free(userdata, size);
+       zero_free(userdata, size);
 }
 
 /***************************************************************
@@ -583,7 +573,7 @@ in workgroup %s on subnet %s\n",
 
 void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
 {
-  DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
+       DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
 for workgroup %s.\n", newname, work->work_group ));
 
 #if 0
@@ -600,5 +590,5 @@ local_master_browser_name for workgroup %s to workgroup name.\n",
   }
 #endif
 
-  fstrcpy(work->local_master_browser_name, newname);
+       fstrcpy(work->local_master_browser_name, newname);
 }
index 4a302ddfd411e2e8760a071f08d337aed89c4b64..83dfba66e98033c31ccd1d8a14676bcbad085b02 100644 (file)
@@ -80,8 +80,8 @@ void update_browser_death_time( struct browse_cache_record *browc )
  *
  * ************************************************************************** **
  */
-struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, 
-                                                         char *browser_name, 
+struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name, 
+                                                         const char *browser_name, 
                                                          struct in_addr ip )
 {
        struct browse_cache_record *browc;
@@ -134,7 +134,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name,
  *
  * ************************************************************************** **
  */
-struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name )
+struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name )
 {
        struct browse_cache_record *browc;
 
index 26d4735744fa791847c09dac874d50713bf73a36..95e542354ff917845d01b182c21a7d25ff1c8c5e 100644 (file)
@@ -3,7 +3,7 @@
    NBT netbios routines and daemon - version 2
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
-   Copyright (C) Jeremy Allison 1994-1998
+   Copyright (C) Jeremy Allison 1994-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -29,74 +29,70 @@ extern ubi_dlList lmb_browserlist[];
 /****************************************************************************
 As a domain master browser, do a sync with a local master browser.
 **************************************************************************/
+
 static void sync_with_lmb(struct browse_cache_record *browc)
 {                     
-  struct work_record *work;
-
-  if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
-  {
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "sync_with_lmb:\n" );
-      dbgtext( "Failed to get a workgroup for a local master browser " );
-      dbgtext( "cache entry workgroup " );
-      dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
-    }
-    return;
-  }
+       struct work_record *work;
 
-  /* We should only be doing this if we are a domain master browser for
-     the given workgroup. Ensure this is so. */
-
-  if(!AM_DOMAIN_MASTER_BROWSER(work))
-  {
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "sync_with_lmb:\n" );
-      dbgtext( "We are trying to sync with a local master browser " );
-      dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
-      dbgtext( "and we are not a domain master browser on this workgroup.\n" );
-      dbgtext( "Error!\n" );
-    }
-    return;
-  }
+       if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "sync_with_lmb:\n" );
+                       dbgtext( "Failed to get a workgroup for a local master browser " );
+                       dbgtext( "cache entry workgroup " );
+                       dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
+               }
+               return;
+       }
 
-  if( DEBUGLVL( 2 ) )
-  {
-    dbgtext( "sync_with_lmb:\n" );
-    dbgtext( "Initiating sync with local master browser " );
-    dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
-    dbgtext( "for workgroup %s\n", browc->work_group );
-  }
+       /* We should only be doing this if we are a domain master browser for
+               the given workgroup. Ensure this is so. */
 
-  sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
+       if(!AM_DOMAIN_MASTER_BROWSER(work)) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "sync_with_lmb:\n" );
+                       dbgtext( "We are trying to sync with a local master browser " );
+                       dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
+                       dbgtext( "and we are not a domain master browser on this workgroup.\n" );
+                       dbgtext( "Error!\n" );
+               }
+               return;
+       }
+
+       if( DEBUGLVL( 2 ) ) {
+               dbgtext( "sync_with_lmb:\n" );
+               dbgtext( "Initiating sync with local master browser " );
+               dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
+               dbgtext( "for workgroup %s\n", browc->work_group );
+       }
+
+       sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
 
-  browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
+       browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
 }
 
 /****************************************************************************
 Sync or expire any local master browsers.
 **************************************************************************/
+
 void dmb_expire_and_sync_browser_lists(time_t t)
 {
-  static time_t last_run = 0;
-  struct browse_cache_record *browc;
+       static time_t last_run = 0;
+       struct browse_cache_record *browc;
 
-  /* Only do this every 20 seconds. */  
-  if (t - last_run < 20) 
-   return;
+       /* Only do this every 20 seconds. */  
+       if (t - last_run < 20) 
+               return;
 
-  last_run = t;
+       last_run = t;
 
-  expire_lmb_browsers(t);
+       expire_lmb_browsers(t);
 
-  for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
-       browc;
-       browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
-  {
-    if (browc->sync_time < t)
-      sync_with_lmb(browc);
-  }
+       for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
+                       browc;
+                       browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
+               if (browc->sync_time < t)
+                       sync_with_lmb(browc);
+       }
 }
 
 /****************************************************************************
@@ -105,46 +101,43 @@ As a local master browser, send an announce packet to the domain master browser.
 
 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
 {
-  pstring outbuf;
-  fstring myname;
-  char *p;
-
-  if(ismyip(work->dmb_addr))
-  {
-    if( DEBUGLVL( 2 ) )
-    {
-      dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
-      dbgtext( "We are both a domain and a local master browser for " );
-      dbgtext( "workgroup %s.  ", work->work_group );
-      dbgtext( "Do not announce to ourselves.\n" );
-    }
-    return;
-  }
+       pstring outbuf;
+       fstring myname;
+       char *p;
+
+       if(ismyip(work->dmb_addr)) {
+               if( DEBUGLVL( 2 ) ) {
+                       dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
+                       dbgtext( "We are both a domain and a local master browser for " );
+                       dbgtext( "workgroup %s.  ", work->work_group );
+                       dbgtext( "Do not announce to ourselves.\n" );
+               }
+               return;
+       }
 
-  memset(outbuf,'\0',sizeof(outbuf));
-  p = outbuf;
-  SCVAL(p,0,ANN_MasterAnnouncement);
-  p++;
+       memset(outbuf,'\0',sizeof(outbuf));
+       p = outbuf;
+       SCVAL(p,0,ANN_MasterAnnouncement);
+       p++;
 
-  fstrcpy(myname, global_myname());
-  strupper_m(myname);
-  myname[15]='\0';
-  push_pstring_base(p, myname, outbuf);
+       fstrcpy(myname, global_myname());
+       strupper_m(myname);
+       myname[15]='\0';
+       /* The call below does CH_UNIX -> CH_DOS conversion. JRA */
+       push_pstring_base(p, myname, outbuf);
 
-  p = skip_string(p,1);
+       p = skip_string(p,1);
 
-  if( DEBUGLVL( 4 ) )
-  {
-    dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
-    dbgtext( "Sending local master announce to " );
-    dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
-                                       work->work_group );
-  }
+       if( DEBUGLVL( 4 ) ) {
+               dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
+               dbgtext( "Sending local master announce to " );
+               dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
+                                       work->work_group );
+       }
 
-  send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
+       send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
                global_myname(), 0x0, work->dmb_name.name, 0x0, 
                work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
-
 }
 
 /****************************************************************************
@@ -153,17 +146,19 @@ As a local master browser, do a sync with a domain master browser.
 
 static void sync_with_dmb(struct work_record *work)
 {
-  if( DEBUGLVL( 2 ) )
-  {
-    dbgtext( "sync_with_dmb:\n" );
-    dbgtext( "Initiating sync with domain master browser " );
-    dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
-    dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
-    dbgtext( "for workgroup %s\n", work->work_group );
-  }
+       nstring dmb_name;
+
+       if( DEBUGLVL( 2 ) ) {
+               dbgtext( "sync_with_dmb:\n" );
+               dbgtext( "Initiating sync with domain master browser " );
+               dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
+               dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
+               dbgtext( "for workgroup %s\n", work->work_group );
+       }
 
-  sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type, 
-                    work->dmb_addr, False, True);
+       pull_ascii_nstring(dmb_name, work->dmb_name.name);
+       sync_browse_lists(work, dmb_name, work->dmb_name.name_type, 
+               work->dmb_addr, False, True);
 }
 
 /****************************************************************************
@@ -175,78 +170,69 @@ static void domain_master_node_status_success(struct subnet_record *subrec,
                                               struct res_rec *answers,
                                               struct in_addr from_ip)
 {
-  struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
-
-  if( work == NULL )
-  {
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "domain_master_node_status_success:\n" );
-      dbgtext( "Unable to find workgroup " );
-      dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
-    }
-    return;
-  }
+       struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
 
-  if( DEBUGLVL( 3 ) )
-  {
-    dbgtext( "domain_master_node_status_success:\n" );
-    dbgtext( "Success in node status for workgroup " );
-    dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
-  }
+       if( work == NULL ) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "domain_master_node_status_success:\n" );
+                       dbgtext( "Unable to find workgroup " );
+                       dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
+               }
+               return;
+       }
+
+       if( DEBUGLVL( 3 ) ) {
+               dbgtext( "domain_master_node_status_success:\n" );
+               dbgtext( "Success in node status for workgroup " );
+               dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
+       }
 
   /* Go through the list of names found at answers->rdata and look for
      the first SERVER<0x20> name. */
 
-  if(answers->rdata != NULL)
-  {
-    char *p = answers->rdata;
-    int numnames = CVAL(p, 0);
+       if(answers->rdata != NULL) {
+               char *p = answers->rdata;
+               int numnames = CVAL(p, 0);
 
-    p += 1;
+               p += 1;
 
-    while (numnames--)
-    {
-      char qname[17];
-      uint16 nb_flags;
-      int name_type;
+               while (numnames--) {
+                       nstring qname;
+                       uint16 nb_flags;
+                       int name_type;
 
-      StrnCpy(qname,p,15);
-      name_type = CVAL(p,15);
-      nb_flags = get_nb_flags(&p[16]);
-      trim_string(qname,NULL," ");
+                       pull_ascii_nstring(qname, p);
+                       name_type = CVAL(p,15);
+                       nb_flags = get_nb_flags(&p[16]);
+                       trim_string(qname,NULL," ");
 
-      p += 18;
+                       p += 18;
 
-      if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
-      {
-        struct nmb_name nmbname;
+                       if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
+                               struct nmb_name nmbname;
 
-        make_nmb_name(&nmbname, qname, name_type);
+                               make_nmb_name(&nmbname, qname, name_type);
 
-        /* Copy the dmb name and IP address
-           into the workgroup struct. */
+                               /* Copy the dmb name and IP address
+                                       into the workgroup struct. */
 
-        work->dmb_name = nmbname;
-        putip((char *)&work->dmb_addr, &from_ip);
+                               work->dmb_name = nmbname;
+                               putip((char *)&work->dmb_addr, &from_ip);
 
-        /* Do the local master browser announcement to the domain
-           master browser name and IP. */
-        announce_local_master_browser_to_domain_master_browser( work );
+                               /* Do the local master browser announcement to the domain
+                                       master browser name and IP. */
+                               announce_local_master_browser_to_domain_master_browser( work );
 
-        /* Now synchronise lists with the domain master browser. */
-        sync_with_dmb(work);
-        break;
-      }
-    }
-  }
-  else
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "domain_master_node_status_success:\n" );
-      dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
-      dbgtext( "%s.\n", inet_ntoa(from_ip) );
-    }
+                               /* Now synchronise lists with the domain master browser. */
+                               sync_with_dmb(work);
+                               break;
+                       }
+               }
+       } else if( DEBUGLVL( 0 ) ) {
+               dbgtext( "domain_master_node_status_success:\n" );
+               dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
+               dbgtext( "%s.\n", inet_ntoa(from_ip) );
+       }
 }
 
 /****************************************************************************
@@ -256,16 +242,15 @@ static void domain_master_node_status_success(struct subnet_record *subrec,
 static void domain_master_node_status_fail(struct subnet_record *subrec,
                        struct response_record *rrec)
 {
-  struct userdata_struct *userdata = rrec->userdata;
-
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "domain_master_node_status_fail:\n" );
-    dbgtext( "Doing a node status request to the domain master browser\n" );
-    dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
-    dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
-    dbgtext( "Cannot sync browser lists.\n" );
-  }
+       struct userdata_struct *userdata = rrec->userdata;
+
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "domain_master_node_status_fail:\n" );
+               dbgtext( "Doing a node status request to the domain master browser\n" );
+               dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
+               dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
+               dbgtext( "Cannot sync browser lists.\n" );
+       }
 }
 
 /****************************************************************************
@@ -276,100 +261,99 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec,
                         struct userdata_struct *userdata_in,
                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
 {
-  /* 
-   * Unfortunately, finding the IP address of the Domain Master Browser,
-   * as we have here, is not enough. We need to now do a sync to the
-   * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
-   * respond to the SMBSERVER name. To get this name from IP
-   * address we do a Node status request, and look for the first
-   * NAME<0x20> in the response, and take that as the server name.
-   * We also keep a cache of the Domain Master Browser name for this
-   * workgroup in the Workgroup struct, so that if the same IP addess
-   * is returned every time, we don't need to do the node status
-   * request.
-   */
-
-  struct work_record *work;
-  struct nmb_name nmbname;
-  struct userdata_struct *userdata;
-  size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
-
-  if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
-  {
-    if( DEBUGLVL( 0 ) )
-      {
-      dbgtext( "find_domain_master_name_query_success:\n" );
-      dbgtext( "Failed to find workgroup %s\n", q_name->name );
-      }
-    return;
+       /* 
+        * Unfortunately, finding the IP address of the Domain Master Browser,
+        * as we have here, is not enough. We need to now do a sync to the
+        * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
+        * respond to the SMBSERVER name. To get this name from IP
+        * address we do a Node status request, and look for the first
+        * NAME<0x20> in the response, and take that as the server name.
+        * We also keep a cache of the Domain Master Browser name for this
+        * workgroup in the Workgroup struct, so that if the same IP addess
+        * is returned every time, we don't need to do the node status
+        * request.
+        */
+
+       struct work_record *work;
+       struct nmb_name nmbname;
+       struct userdata_struct *userdata;
+       size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
+       nstring qname;
+
+       pull_ascii_nstring(qname, q_name->name);
+       if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "find_domain_master_name_query_success:\n" );
+                       dbgtext( "Failed to find workgroup %s\n", qname);
+               }
+       return;
   }
 
   /* First check if we already have a dmb for this workgroup. */
 
-  if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip))
-  {
-    /* Do the local master browser announcement to the domain
-       master browser name and IP. */
-    announce_local_master_browser_to_domain_master_browser( work );
+       if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) {
+               /* Do the local master browser announcement to the domain
+                       master browser name and IP. */
+               announce_local_master_browser_to_domain_master_browser( work );
 
-    /* Now synchronise lists with the domain master browser. */
-    sync_with_dmb(work);
-    return;
-  }
-  else
-    zero_ip(&work->dmb_addr);
-
-  /* Now initiate the node status request. */
-
-  /* We used to use the name "*",0x0 here, but some Windows
-   * servers don't answer that name. However we *know* they
-   * have the name workgroup#1b (as we just looked it up).
-   * So do the node status request on this name instead.
-   * Found at LBL labs. JRA.
-   */
-
-  make_nmb_name(&nmbname,work->work_group,0x1b);
-
-  /* Put the workgroup name into the userdata so we know
-     what workgroup we're talking to when the reply comes
-     back. */
-
-  /* Setup the userdata_struct - this is copied so we can use
-     a stack variable for this. */
-  if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
-  {
-    DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
-    return;
-  }
+               /* Now synchronise lists with the domain master browser. */
+               sync_with_dmb(work);
+               return;
+       } else {
+               zero_ip(&work->dmb_addr);
+       }
 
-  userdata->copy_fn = NULL;
-  userdata->free_fn = NULL;
-  userdata->userdata_len = strlen(work->work_group)+1;
-  overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
+       /* Now initiate the node status request. */
 
-  node_status( subrec, &nmbname, answer_ip, 
-               domain_master_node_status_success,
-               domain_master_node_status_fail,
-               userdata);
+       /* We used to use the name "*",0x0 here, but some Windows
+        * servers don't answer that name. However we *know* they
+        * have the name workgroup#1b (as we just looked it up).
+        * So do the node status request on this name instead.
+        * Found at LBL labs. JRA.
+        */
 
-  zero_free(userdata, size);
+       make_nmb_name(&nmbname,work->work_group,0x1b);
+
+       /* Put the workgroup name into the userdata so we know
+        what workgroup we're talking to when the reply comes
+        back. */
+
+       /* Setup the userdata_struct - this is copied so we can use
+       a stack variable for this. */
+
+       if((userdata = (struct userdata_struct *)malloc(size)) == NULL) {
+               DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
+               return;
+       }
+
+       userdata->copy_fn = NULL;
+       userdata->free_fn = NULL;
+       userdata->userdata_len = strlen(work->work_group)+1;
+       overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
+
+       node_status( subrec, &nmbname, answer_ip, 
+               domain_master_node_status_success,
+               domain_master_node_status_fail,
+               userdata);
+
+       zero_free(userdata, size);
 }
 
 /****************************************************************************
   Function called when a query for a WORKGROUP<1b> name fails.
   ****************************************************************************/
+
 static void find_domain_master_name_query_fail(struct subnet_record *subrec,
                                     struct response_record *rrec,
                                     struct nmb_name *question_name, int fail_code)
 {
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "find_domain_master_name_query_fail:\n" );
-    dbgtext( "Unable to find the Domain Master Browser name " );
-    dbgtext( "%s for the workgroup %s.\n",
-             nmb_namestr(question_name), question_name->name );
-    dbgtext( "Unable to sync browse lists in this workgroup.\n" );
-  }
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "find_domain_master_name_query_fail:\n" );
+               dbgtext( "Unable to find the Domain Master Browser name " );
+               dbgtext( "%s for the workgroup %s.\n",
+                       nmb_namestr(question_name), question_name->name );
+               dbgtext( "Unable to sync browse lists in this workgroup.\n" );
+       }
 }
 
 /****************************************************************************
@@ -381,27 +365,20 @@ full domain browse lists from it onto the given subnet.
 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
                                                    struct work_record *work)
 {
-  struct nmb_name nmbname;
-
-  /* Only do this if we are using a WINS server. */
-  if(we_are_a_wins_client() == False)
-  {
-    if( DEBUGLVL( 10 ) )
-    {
-      dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
-      dbgtext( "Ignoring, as we are not a WINS client.\n" );
-    }
-    return;
-  }
-
-  make_nmb_name(&nmbname,work->work_group,0x1b);
+       /* Only do this if we are using a WINS server. */
+       if(we_are_a_wins_client() == False) {
+               if( DEBUGLVL( 10 ) ) {
+                       dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
+                       dbgtext( "Ignoring, as we are not a WINS client.\n" );
+               }
+               return;
+       }
 
-  /* First, query for the WORKGROUP<1b> name from the WINS server. */
-  query_name(unicast_subnet, nmbname.name, nmbname.name_type,
+       /* First, query for the WORKGROUP<1b> name from the WINS server. */
+       query_name(unicast_subnet, work->work_group, 0x1b,
              find_domain_master_name_query_success,
              find_domain_master_name_query_fail,
              NULL);
-
 }
 
 /****************************************************************************
@@ -421,89 +398,81 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub
                                               struct res_rec *answers,
                                               struct in_addr from_ip)
 {
-  struct work_record *work;
-  fstring server_name;
+       struct work_record *work;
+       fstring server_name;
 
-  server_name[0] = 0;
+       server_name[0] = 0;
 
-  if( DEBUGLVL( 3 ) )
-  {
-    dbgtext( "get_domain_master_name_node_status_success:\n" );
-    dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
-  }
+       if( DEBUGLVL( 3 ) ) {
+               dbgtext( "get_domain_master_name_node_status_success:\n" );
+               dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
+       }
 
-  /* 
-   * Go through the list of names found at answers->rdata and look for
-   * the first WORKGROUP<0x1b> name.
-   */
-
-  if(answers->rdata != NULL)
-  {
-    char *p = answers->rdata;
-    int numnames = CVAL(p, 0);
-
-    p += 1;
-
-    while (numnames--)
-    {
-      char qname[17];
-      uint16 nb_flags;
-      int name_type;
-
-      StrnCpy(qname,p,15);
-      name_type = CVAL(p,15);
-      nb_flags = get_nb_flags(&p[16]);
-      trim_string(qname,NULL," ");
-
-      p += 18;
-
-      if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
-        server_name[0] == 0) {
-             /* this is almost certainly the server netbios name */
-             fstrcpy(server_name, qname);
-             continue;
-      }
-
-      if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
-      {
-        if( DEBUGLVL( 5 ) )
-        {
-          dbgtext( "get_domain_master_name_node_status_success:\n" );
-          dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
-          dbgtext( "is a domain master browser for workgroup " );
-          dbgtext( "%s. Adding this name.\n", qname );
-        }
-
-        /* 
-         * If we don't already know about this workgroup, add it
-         * to the workgroup list on the unicast_subnet.
-         */
-        if((work = find_workgroup_on_subnet( subrec, qname)) == NULL)
-       {
-               struct nmb_name nmbname;
-               /* 
-                * Add it - with an hour in the cache.
-                */
-               if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
-                       return;
-
-               /* remember who the master is */
-               fstrcpy(work->local_master_browser_name, server_name);
-               make_nmb_name(&nmbname, server_name, 0x20);
-               work->dmb_name = nmbname;
-               work->dmb_addr = from_ip;
-        }
-        break;
-      }
-    }
-  }
-  else
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "get_domain_master_name_node_status_success:\n" );
-      dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
-      dbgtext( "%s.\n", inet_ntoa(from_ip) );
-    }
+       /* 
+        * Go through the list of names found at answers->rdata and look for
+        * the first WORKGROUP<0x1b> name.
+        */
+
+       if(answers->rdata != NULL) {
+               char *p = answers->rdata;
+               int numnames = CVAL(p, 0);
+
+               p += 1;
+
+               while (numnames--) {
+                       nstring qname;
+                       uint16 nb_flags;
+                       int name_type;
+
+                       pull_ascii_nstring(qname, p);
+                       name_type = CVAL(p,15);
+                       nb_flags = get_nb_flags(&p[16]);
+                       trim_string(qname,NULL," ");
+
+                       p += 18;
+
+                       if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
+                                       server_name[0] == 0) {
+                               /* this is almost certainly the server netbios name */
+                               fstrcpy(server_name, qname);
+                               continue;
+                       }
+
+                       if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
+                               if( DEBUGLVL( 5 ) ) {
+                                       dbgtext( "get_domain_master_name_node_status_success:\n" );
+                                       dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
+                                       dbgtext( "is a domain master browser for workgroup " );
+                                       dbgtext( "%s. Adding this name.\n", qname );
+                               }
+
+                               /* 
+                                * If we don't already know about this workgroup, add it
+                                * to the workgroup list on the unicast_subnet.
+                                */
+
+                               if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
+                                       struct nmb_name nmbname;
+                                       /* 
+                                        * Add it - with an hour in the cache.
+                                        */
+                                       if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
+                                               return;
+
+                                       /* remember who the master is */
+                                       fstrcpy(work->local_master_browser_name, server_name);
+                                       make_nmb_name(&nmbname, server_name, 0x20);
+                                       work->dmb_name = nmbname;
+                                       work->dmb_addr = from_ip;
+                               }
+                               break;
+                       }
+               }
+       } else if( DEBUGLVL( 0 ) ) {
+               dbgtext( "get_domain_master_name_node_status_success:\n" );
+               dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
+               dbgtext( "%s.\n", inet_ntoa(from_ip) );
+       }
 }
 
 /****************************************************************************
@@ -513,13 +482,12 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub
 static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
                        struct response_record *rrec)
 {
-  if( DEBUGLVL( 0 ) )
-  {
-    dbgtext( "get_domain_master_name_node_status_fail:\n" );
-    dbgtext( "Doing a node status request to the domain master browser " );
-    dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
-    dbgtext( "Cannot get workgroup name.\n" );
-  }
+       if( DEBUGLVL( 0 ) ) {
+               dbgtext( "get_domain_master_name_node_status_fail:\n" );
+               dbgtext( "Doing a node status request to the domain master browser " );
+               dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
+               dbgtext( "Cannot get workgroup name.\n" );
+       }
 }
 
 /****************************************************************************
@@ -530,58 +498,53 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub
                         struct userdata_struct *userdata_in,
                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
 {
-  /* 
-   * We now have a list of all the domain master browsers for all workgroups
-   * that have registered with the WINS server. Now do a node status request
-   * to each one and look for the first 1b name in the reply. This will be
-   * the workgroup name that we will add to the unicast subnet as a 'non-local'
-   * workgroup.
-   */
-
-  struct nmb_name nmbname;
-  struct in_addr send_ip;
-  int i;
-
-  if( DEBUGLVL( 5 ) )
-  {
-    dbgtext( "find_all_domain_master_names_query_succes:\n" );
-    dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
-    dbgtext( "IP addresses for Domain Master Browsers.\n" );
-  }
+       /* 
+        * We now have a list of all the domain master browsers for all workgroups
+        * that have registered with the WINS server. Now do a node status request
+        * to each one and look for the first 1b name in the reply. This will be
+        * the workgroup name that we will add to the unicast subnet as a 'non-local'
+        * workgroup.
+        */
+
+       struct nmb_name nmbname;
+       struct in_addr send_ip;
+       int i;
+
+       if( DEBUGLVL( 5 ) ) {
+               dbgtext( "find_all_domain_master_names_query_succes:\n" );
+               dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
+               dbgtext( "IP addresses for Domain Master Browsers.\n" );
+       }
 
-  for(i = 0; i < rrec->rdlength / 6; i++)
-  {
-    /* Initiate the node status requests. */
-    make_nmb_name(&nmbname, "*", 0);
-
-    putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
-
-    /* 
-     * Don't send node status requests to ourself.
-     */
-
-    if(ismyip( send_ip ))
-    {
-      if( DEBUGLVL( 5 ) )
-      {
-        dbgtext( "find_all_domain_master_names_query_succes:\n" );
-        dbgtext( "Not sending node status to our own IP " );
-        dbgtext( "%s.\n", inet_ntoa(send_ip) );
-      }
-      continue;
-    }
-
-    if( DEBUGLVL( 5 ) )
-    {
-      dbgtext( "find_all_domain_master_names_query_success:\n" );
-      dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
-    }
-
-    node_status( subrec, &nmbname, send_ip, 
-                 get_domain_master_name_node_status_success,
-                 get_domain_master_name_node_status_fail,
-                 NULL);
-  }
+       for(i = 0; i < rrec->rdlength / 6; i++) {
+               /* Initiate the node status requests. */
+               make_nmb_name(&nmbname, "*", 0);
+
+               putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
+
+               /* 
+                * Don't send node status requests to ourself.
+                */
+
+               if(ismyip( send_ip )) {
+                       if( DEBUGLVL( 5 ) ) {
+                               dbgtext( "find_all_domain_master_names_query_succes:\n" );
+                               dbgtext( "Not sending node status to our own IP " );
+                               dbgtext( "%s.\n", inet_ntoa(send_ip) );
+                       }
+                       continue;
+               }
+
+               if( DEBUGLVL( 5 ) ) {
+                       dbgtext( "find_all_domain_master_names_query_success:\n" );
+                       dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
+               }
+
+               node_status( subrec, &nmbname, send_ip, 
+                               get_domain_master_name_node_status_success,
+                               get_domain_master_name_node_status_fail,
+                               NULL);
+       }
 }
 
 /****************************************************************************
@@ -591,13 +554,12 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec
                                     struct response_record *rrec,
                                     struct nmb_name *question_name, int fail_code)
 {
-  if( DEBUGLVL( 10 ) )
-  {
-    dbgtext( "find_domain_master_name_query_fail:\n" );
-    dbgtext( "WINS server did not reply to a query for name " );
-    dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
-    dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
-  }
+       if( DEBUGLVL( 10 ) ) {
+               dbgtext( "find_domain_master_name_query_fail:\n" );
+               dbgtext( "WINS server did not reply to a query for name " );
+               dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
+               dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
+       }
 }
 
 /****************************************************************************
@@ -608,43 +570,39 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec
  <1b> name in the reply - this is the workgroup name. Add this to the unicast
  subnet. This is expensive, so we only do this every 15 minutes.
 **************************************************************************/
+
 void collect_all_workgroup_names_from_wins_server(time_t t)
 {
-  static time_t lastrun = 0;
-  struct work_record *work;
-  struct nmb_name nmbname;
-
-  /* Only do this if we are using a WINS server. */
-  if(we_are_a_wins_client() == False)
-    return;
-
-  /* Check to see if we are a domain master browser on the unicast subnet. */
-  if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL)
-  {
-    if( DEBUGLVL( 0 ) )
-    {
-      dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
-      dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
-      dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
-    }
-    return;
-  }
+       static time_t lastrun = 0;
+       struct work_record *work;
 
-  if(!AM_DOMAIN_MASTER_BROWSER(work))
-    return;
+       /* Only do this if we are using a WINS server. */
+       if(we_are_a_wins_client() == False)
+               return;
 
-  if ((lastrun != 0) && (t < lastrun + (15 * 60)))
-    return;
-     
-  lastrun = t;
+       /* Check to see if we are a domain master browser on the unicast subnet. */
+       if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
+               if( DEBUGLVL( 0 ) ) {
+                       dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
+                       dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
+                       dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
+               }
+               return;
+       }
+
+       if(!AM_DOMAIN_MASTER_BROWSER(work))
+               return;
 
-  make_nmb_name(&nmbname,"*",0x1b);
+       if ((lastrun != 0) && (t < lastrun + (15 * 60)))
+               return;
+     
+       lastrun = t;
 
-  /* First, query for the *<1b> name from the WINS server. */
-  query_name(unicast_subnet, nmbname.name, nmbname.name_type,
-             find_all_domain_master_names_query_success,
-             find_all_domain_master_names_query_fail,
-             NULL);
+       /* First, query for the *<1b> name from the WINS server. */
+       query_name(unicast_subnet, "*", 0x1b,
+               find_all_domain_master_names_query_success,
+               find_all_domain_master_names_query_fail,
+               NULL);
 } 
 
 
@@ -656,6 +614,7 @@ To prevent exponential network traffic with large numbers of workgroups
 we use a randomised system where sync probability is inversely proportional
 to the number of known workgroups
 **************************************************************************/
+
 void sync_all_dmbs(time_t t)
 {
        static time_t lastrun = 0;
@@ -669,7 +628,8 @@ void sync_all_dmbs(time_t t)
        /* Check to see if we are a domain master browser on the
            unicast subnet. */
        work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
-       if (!work) return;
+       if (!work)
+               return;
 
        if (!AM_DOMAIN_MASTER_BROWSER(work))
                return;
@@ -687,7 +647,10 @@ void sync_all_dmbs(time_t t)
        /* sync with a probability of 1/count */
        for (work=unicast_subnet->workgrouplist; work; work = work->next) {
                if (strcmp(lp_workgroup(), work->work_group)) {
-                       if (((unsigned)sys_random()) % count != 0) continue;
+                       nstring dmb_name;
+
+                       if (((unsigned)sys_random()) % count != 0)
+                               continue;
 
                        lastrun = t;
 
@@ -699,13 +662,15 @@ void sync_all_dmbs(time_t t)
                                              0x20);
                        }
 
+                       pull_ascii_nstring(dmb_name, work->dmb_name.name);
+
                        DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
-                                work->dmb_name.name, 
-                                inet_ntoa(work->dmb_addr)));
+                                dmb_name, inet_ntoa(work->dmb_addr)));
+
                        sync_browse_lists(work, 
-                                         work->dmb_name.name,
+                                         dmb_name,
                                          work->dmb_name.name_type, 
                                          work->dmb_addr, False, False);
                }
        }
-} 
+}
index b948eb9d04ea5bef6a19adb9fd636a440dd08244..09ab9ee783537d44d073f55a53767db552c975b0 100644 (file)
@@ -3,7 +3,7 @@
    NBT netbios routines and daemon - version 2
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
-   Copyright (C) Jeremy Allison 1994-1998
+   Copyright (C) Jeremy Allison 1994-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -29,32 +29,35 @@ extern time_t StartupTime;
 /****************************************************************************
   Send an election datagram packet.
 **************************************************************************/
+
 static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
                                 uint32 criterion, int timeup,const char *server_name)
 {
-  pstring outbuf;
-  char *p;
-
-  DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
-       workgroup_name, subrec->subnet_name ));
-
-  memset(outbuf,'\0',sizeof(outbuf));
-  p = outbuf;
-  SCVAL(p,0,ANN_Election); /* Election opcode. */
-  p++;
-
-  SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
-  SIVAL(p,1,criterion);
-  SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
-  p += 13;
-  pstrcpy_base(p, server_name, outbuf);
-  strupper_m(p);
-  p = skip_string(p,1);
+       pstring outbuf;
+       fstring srv_name;
+       char *p;
+
+       DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
+               workgroup_name, subrec->subnet_name ));
+
+       memset(outbuf,'\0',sizeof(outbuf));
+       p = outbuf;
+       SCVAL(p,0,ANN_Election); /* Election opcode. */
+       p++;
+
+       SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
+       SIVAL(p,1,criterion);
+       SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
+       p += 13;
+       fstrcpy(srv_name, server_name);
+       strupper_m(srv_name);
+       pstrcpy_base(p, srv_name, outbuf);
+       p = skip_string(p,1);
   
-  send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
-                global_myname(), 0,
-                workgroup_name, 0x1e,
-                subrec->bcast_ip, subrec->myip, DGRAM_PORT);
+       send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
+               global_myname(), 0,
+               workgroup_name, 0x1e,
+               subrec->bcast_ip, subrec->myip, DGRAM_PORT);
 }
 
 /*******************************************************************
@@ -66,8 +69,10 @@ static void check_for_master_browser_success(struct subnet_record *subrec,
                                  struct nmb_name *answer_name,
                                  struct in_addr answer_ip, struct res_rec *rrec)
 {
-  DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
-IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) ));
+       nstring aname;
+       pull_ascii_nstring(aname, answer_name->name);
+       DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
+IP %s (just checking).\n", aname, inet_ntoa(answer_ip) ));
 }
 
 /*******************************************************************
@@ -79,41 +84,39 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
                                            struct nmb_name *question_name,
                                            int fail_code)
 {
-  char *workgroup_name = question_name->name;
-  struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
-  if(work == NULL)
-  {
-    DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
-          workgroup_name, subrec->subnet_name ));
-    return;
-  }
-
-  if (strequal(work->work_group, lp_workgroup()))
-  {
-
-    if (lp_local_master())
-    {
-      /* We have discovered that there is no local master
-         browser, and we are configured to initiate
-         an election that we will participate in.
-       */
-      DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
-               work->work_group, subrec->subnet_name ));
-
-      /* Setting this means we will participate when the
-         election is run in run_elections(). */
-      work->needelection = True;
-    }
-    else
-    {
-      /* We need to force an election, because we are configured
-         not to become the local master, but we still need one,
-         having detected that one doesn't exist.
-       */
-      send_election_dgram(subrec, work->work_group, 0, 0, "");
-    }
-  }
+       nstring workgroup_name;
+       struct work_record *work;
+
+       pull_ascii_nstring(workgroup_name,question_name->name);
+
+       work = find_workgroup_on_subnet(subrec, workgroup_name);
+       if(work == NULL) {
+               DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
+                       workgroup_name, subrec->subnet_name ));
+               return;
+       }
+
+       if (strequal(work->work_group, lp_workgroup())) {
+
+               if (lp_local_master()) {
+                       /* We have discovered that there is no local master
+                               browser, and we are configured to initiate
+                               an election that we will participate in.
+                       */
+                       DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
+                               work->work_group, subrec->subnet_name ));
+
+                       /* Setting this means we will participate when the
+                               election is run in run_elections(). */
+                       work->needelection = True;
+               } else {
+                       /* We need to force an election, because we are configured
+                               not to become the local master, but we still need one,
+                               having detected that one doesn't exist.
+                       */
+                       send_election_dgram(subrec, work->work_group, 0, 0, "");
+               }
+       }
 }
 
 /*******************************************************************
@@ -123,36 +126,33 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
 
 void check_master_browser_exists(time_t t)
 {
-  static time_t lastrun=0;
-  struct subnet_record *subrec;
-  const char *workgroup_name = lp_workgroup();
-
-  if (!lastrun)
-    lastrun = t;
-
-  if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
-    return;
-
-  lastrun = t;
-
-  dump_workgroups(False);
-
-  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
-  {
-    struct work_record *work;
-
-    for (work = subrec->workgrouplist; work; work = work->next)
-    {
-      if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work))
-      {
-        /* Do a name query for the local master browser on this net. */
-        query_name( subrec, work->work_group, 0x1d,
-                    check_for_master_browser_success,
-                    check_for_master_browser_fail,
-                    NULL);
-      }
-    }
-  }
+       static time_t lastrun=0;
+       struct subnet_record *subrec;
+       const char *workgroup_name = lp_workgroup();
+
+       if (!lastrun)
+               lastrun = t;
+
+       if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
+               return;
+
+       lastrun = t;
+
+       dump_workgroups(False);
+
+       for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
+               struct work_record *work;
+
+               for (work = subrec->workgrouplist; work; work = work->next) {
+                       if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
+                               /* Do a name query for the local master browser on this net. */
+                               query_name( subrec, work->work_group, 0x1d,
+                                       check_for_master_browser_success,
+                                       check_for_master_browser_fail,
+                                       NULL);
+                       }
+               }
+       }
 }
 
 /*******************************************************************
@@ -161,56 +161,52 @@ void check_master_browser_exists(time_t t)
 
 void run_elections(time_t t)
 {
-  static time_t lastime = 0;
+       static time_t lastime = 0;
   
-  struct subnet_record *subrec;
+       struct subnet_record *subrec;
   
-  /* Send election packets once every 2 seconds - note */
-  if (lastime && (t - lastime < 2))
-    return;
+       /* Send election packets once every 2 seconds - note */
+       if (lastime && (t - lastime < 2))
+               return;
   
-  lastime = t;
+       lastime = t;
   
-  START_PROFILE(run_elections);
-  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
-  {
-    struct work_record *work;
-
-    for (work = subrec->workgrouplist; work; work = work->next)
-    {
-      if (work->RunningElection)
-      {
-        /*
-         * We can only run an election for a workgroup if we have
-         * registered the WORKGROUP<1e> name, as that's the name
-         * we must listen to.
-         */
-        struct nmb_name nmbname;
-
-        make_nmb_name(&nmbname, work->work_group, 0x1e);
-        if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
-          DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
+       START_PROFILE(run_elections);
+       for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
+               struct work_record *work;
+
+               for (work = subrec->workgrouplist; work; work = work->next) {
+                       if (work->RunningElection) {
+                               /*
+                                * We can only run an election for a workgroup if we have
+                                * registered the WORKGROUP<1e> name, as that's the name
+                                * we must listen to.
+                                */
+                               struct nmb_name nmbname;
+
+                               make_nmb_name(&nmbname, work->work_group, 0x1e);
+                               if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
+                                       DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
 yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
-          continue;
-        }
+                                       continue;
+                               }
 
-        send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
-                      t - StartupTime, global_myname());
+                               send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
+                                               t - StartupTime, global_myname());
              
-        if (work->ElectionCount++ >= 4)
-        {
-          /* Won election (4 packets were sent out uncontested. */
-          DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
-                    work->work_group, subrec->subnet_name ));
-
-          work->RunningElection = False;
-
-          become_local_master_browser(subrec, work);
-        }
-      }
-    }
-  }
-  END_PROFILE(run_elections);
+                               if (work->ElectionCount++ >= 4) {
+                                       /* Won election (4 packets were sent out uncontested. */
+                                       DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
+                                               work->work_group, subrec->subnet_name ));
+
+                                       work->RunningElection = False;
+
+                                       become_local_master_browser(subrec, work);
+                               }
+                       }
+               }
+       }
+       END_PROFILE(run_elections);
 }
 
 /*******************************************************************
@@ -218,44 +214,42 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
 ******************************************************************/
 
 static BOOL win_election(struct work_record *work, int version,
-                         uint32 criterion, int timeup, char *server_name)
+                         uint32 criterion, int timeup, const char *server_name)
 {  
-  int mytimeup = time(NULL) - StartupTime;
-  uint32 mycriterion = work->ElectionCriterion;
-
-  /* If local master is false then never win
-     in election broadcasts. */
-  if(!lp_local_master())
-  {
-    DEBUG(3,("win_election: Losing election as local master == False\n"));
-    return False;
-  }
+       int mytimeup = time(NULL) - StartupTime;
+       uint32 mycriterion = work->ElectionCriterion;
+
+       /* If local master is false then never win in election broadcasts. */
+       if(!lp_local_master()) {
+               DEBUG(3,("win_election: Losing election as local master == False\n"));
+               return False;
+       }
  
-  DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
-        version, ELECTION_VERSION,
-        criterion, mycriterion,
-        timeup, mytimeup,
-        server_name, global_myname()));
-
-  if (version > ELECTION_VERSION)
-    return(False);
-  if (version < ELECTION_VERSION)
-    return(True);
+       DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
+                       version, ELECTION_VERSION,
+                       criterion, mycriterion,
+                       timeup, mytimeup,
+                       server_name, global_myname()));
+
+       if (version > ELECTION_VERSION)
+               return(False);
+       if (version < ELECTION_VERSION)
+               return(True);
   
-  if (criterion > mycriterion)
-    return(False);
-  if (criterion < mycriterion)
-    return(True);
-
-  if (timeup > mytimeup)
-    return(False);
-  if (timeup < mytimeup)
-    return(True);
-
-  if (strcasecmp(global_myname(), server_name) > 0)
-    return(False);
+       if (criterion > mycriterion)
+               return(False);
+       if (criterion < mycriterion)
+               return(True);
+
+       if (timeup > mytimeup)
+               return(False);
+       if (timeup < mytimeup)
+               return(True);
+
+       if (strcasecmp(global_myname(), server_name) > 0)
+               return(False);
   
-  return(True);
+       return(True);
 }
 
 /*******************************************************************
@@ -264,66 +258,63 @@ static BOOL win_election(struct work_record *work, int version,
 
 void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  int version = CVAL(buf,0);
-  uint32 criterion = IVAL(buf,1);
-  int timeup = IVAL(buf,5)/1000;
-  char *server_name = buf+13;
-  struct work_record *work;
-  char *workgroup_name = dgram->dest_name.name;
-
-  START_PROFILE(election);
-  server_name[15] = 0;  
-
-  DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
-      server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
-
-  DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
-
-  if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
-  {
-    DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
-          workgroup_name, subrec->subnet_name ));
-    goto done;
-  }
-
-  if (!strequal(work->work_group, lp_workgroup()))
-  {
-    DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
+       struct dgram_packet *dgram = &p->packet.dgram;
+       int version = CVAL(buf,0);
+       uint32 criterion = IVAL(buf,1);
+       int timeup = IVAL(buf,5)/1000;
+       nstring server_name;
+       struct work_record *work;
+       nstring workgroup_name;
+
+       pull_ascii_nstring(server_name, buf+13);
+       pull_ascii_nstring(workgroup_name, dgram->dest_name.name);
+
+       START_PROFILE(election);
+       server_name[15] = 0;  
+
+       DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
+               server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
+
+       DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
+
+       if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
+               DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
+                       workgroup_name, subrec->subnet_name ));
+               goto done;
+       }
+
+       if (!strequal(work->work_group, lp_workgroup())) {
+               DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
 is not my workgroup.\n", work->work_group, subrec->subnet_name ));
-    goto done;
-  }
-
-  if (win_election(work, version,criterion,timeup,server_name))
-  {
-    /* We take precedence over the requesting server. */
-    if (!work->RunningElection)
-    {
-      /* We weren't running an election - start running one. */
-
-      work->needelection = True;
-      work->ElectionCount=0;
-    }
-
-    /* Note that if we were running an election for this workgroup on this
-       subnet already, we just ignore the server we take precedence over. */
-  }
-  else
-  {
-    /* We lost. Stop participating. */
-    work->needelection = False;
-
-    if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
-    {
-      work->RunningElection = False;
-      DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
-            work->work_group, subrec->subnet_name ));
-      if (AM_LOCAL_MASTER_BROWSER(work))
-        unbecome_local_master_browser(subrec, work, False);
-    }
-  }
+               goto done;
+       }
+
+       if (win_election(work, version,criterion,timeup,server_name)) {
+               /* We take precedence over the requesting server. */
+               if (!work->RunningElection) {
+                       /* We weren't running an election - start running one. */
+
+                       work->needelection = True;
+                       work->ElectionCount=0;
+               }
+
+               /* Note that if we were running an election for this workgroup on this
+                       subnet already, we just ignore the server we take precedence over. */
+       } else {
+               /* We lost. Stop participating. */
+               work->needelection = False;
+
+               if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) {
+                       work->RunningElection = False;
+                       DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
+                               work->work_group, subrec->subnet_name ));
+                       if (AM_LOCAL_MASTER_BROWSER(work))
+                               unbecome_local_master_browser(subrec, work, False);
+               }
+       }
 done:
-  END_PROFILE(election);
+
+       END_PROFILE(election);
 }
 
 /****************************************************************************
@@ -335,57 +326,53 @@ done:
 
 BOOL check_elections(void)
 {
-  struct subnet_record *subrec;
-  BOOL run_any_election = False;
-
-  for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
-  {
-    struct work_record *work;
-    for (work = subrec->workgrouplist; work; work = work->next)
-    {
-      run_any_election |= work->RunningElection;
-
-      /* 
-       * Start an election if we have any chance of winning.
-       * Note this is a change to the previous code, that would
-       * only run an election if nmbd was in the potential browser
-       * state. We need to run elections in any state if we're told
-       * to. JRA.
-       */
-
-      if (work->needelection && !work->RunningElection && lp_local_master())
-      {
-        /*
-         * We can only run an election for a workgroup if we have
-         * registered the WORKGROUP<1e> name, as that's the name
-         * we must listen to.
-         */
-        struct nmb_name nmbname;
-
-        make_nmb_name(&nmbname, work->work_group, 0x1e);
-        if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
-          DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
+       struct subnet_record *subrec;
+       BOOL run_any_election = False;
+
+       for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
+               struct work_record *work;
+               for (work = subrec->workgrouplist; work; work = work->next) {
+                       run_any_election |= work->RunningElection;
+
+                       /* 
+                        * Start an election if we have any chance of winning.
+                        * Note this is a change to the previous code, that would
+                        * only run an election if nmbd was in the potential browser
+                        * state. We need to run elections in any state if we're told
+                        * to. JRA.
+                        */
+
+                       if (work->needelection && !work->RunningElection && lp_local_master()) {
+                               /*
+                                * We can only run an election for a workgroup if we have
+                                * registered the WORKGROUP<1e> name, as that's the name
+                                * we must listen to.
+                                */
+                               struct nmb_name nmbname;
+
+                               make_nmb_name(&nmbname, work->work_group, 0x1e);
+                               if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
+                                       DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
 yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
-          continue;
-        }
-
-        DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
-              work->work_group, subrec->subnet_name ));
-
-        work->ElectionCount = 0;
-        work->RunningElection = True;
-        work->needelection = False;
-      }
-    }
-  }
-  return run_any_election;
-}
+                                       continue;
+                               }
 
+                               DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
+                                       work->work_group, subrec->subnet_name ));
 
+                               work->ElectionCount = 0;
+                               work->RunningElection = True;
+                               work->needelection = False;
+                       }
+               }
+       }
+       return run_any_election;
+}
 
 /****************************************************************************
-process a internal Samba message forcing an election
+ Process a internal Samba message forcing an election.
 ***************************************************************************/
+
 void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len)
 {
        struct subnet_record *subrec;
index 80465ada0dc4d0e5ecaabeb4e4ef4cacd48e5e60..49fad8e86759b872987af3e4ee7beb0c3265fa46 100644 (file)
@@ -95,102 +95,99 @@ void tell_become_backup(void)
 
 void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  int ttl = IVAL(buf,1)/1000;
-  char *announce_name = buf+5;
-  uint32 servertype = IVAL(buf,23);
-  char *comment = buf+31;
-  struct work_record *work;
-  struct server_record *servrec;
-  const char *work_name;
-  char *source_name = dgram->source_name.name;
-
-  START_PROFILE(host_announce);
-  comment[43] = 0;
+       struct dgram_packet *dgram = &p->packet.dgram;
+       int ttl = IVAL(buf,1)/1000;
+       nstring announce_name;
+       uint32 servertype = IVAL(buf,23);
+       fstring comment;
+       struct work_record *work;
+       struct server_record *servrec;
+       nstring work_name;
+       nstring source_name;
+
+       START_PROFILE(host_announce);
+
+       pull_ascii_fstring(comment, buf+31);
+       comment[12] = 0;
   
-  DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
+       pull_ascii_nstring(announce_name, buf+5);
+       pull_ascii_nstring(source_name, dgram->source_name.name);
+
+       DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
 %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
-              nmb_namestr(&dgram->dest_name),announce_name));
+                       nmb_namestr(&dgram->dest_name),announce_name));
 
-  DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
-          ttl, servertype,comment));
+       DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
+               ttl, servertype,comment));
 
-  /* Filter servertype to remove impossible bits. */
-  servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
+       /* Filter servertype to remove impossible bits. */
+       servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
 
-  /* A host announcement must be sent to the name WORKGROUP<1d>. */
-  if(dgram->dest_name.name_type != 0x1d)
-  {
-    DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
+       /* A host announcement must be sent to the name WORKGROUP<1d>. */
+       if(dgram->dest_name.name_type != 0x1d) {
+               DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
 (was %02x) should be 0x1d. Allowing packet anyway.\n",
-              inet_ntoa(p->ip), dgram->dest_name.name_type));
-    /* Change it so it was. */
-    dgram->dest_name.name_type = 0x1d;
-  }
-
-  /* For a host announce the workgroup name is the destination name. */
-  work_name = dgram->dest_name.name;
-
-  /*
-   * Syntax servers version 5.1 send HostAnnounce packets to
-   * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
-   * instead of WORKGROUP<1d> name. So to fix this we check if
-   * the workgroup name is our own name, and if so change it
-   * to be our primary workgroup name.
-   */
-
-  if(strequal(work_name, global_myname()))
-    work_name = lp_workgroup();
-
-  /*
-   * We are being very agressive here in adding a workgroup
-   * name on the basis of a host announcing itself as being
-   * in that workgroup. Maybe we should wait for the workgroup
-   * announce instead ? JRA.
-   */
-
-  work = find_workgroup_on_subnet(subrec, work_name);
-
-  if(servertype != 0)
-  {
-    if (work ==NULL )
-    {
-      /* We have no record of this workgroup. Add it. */
-      if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
-        goto done;
-    }
+                       inet_ntoa(p->ip), dgram->dest_name.name_type));
+               /* Change it so it was. */
+               dgram->dest_name.name_type = 0x1d;
+       }
+
+       /* For a host announce the workgroup name is the destination name. */
+       pull_ascii_nstring(work_name, dgram->dest_name.name);
+
+       /*
+        * Syntax servers version 5.1 send HostAnnounce packets to
+        * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
+        * instead of WORKGROUP<1d> name. So to fix this we check if
+        * the workgroup name is our own name, and if so change it
+        * to be our primary workgroup name.
+        */
+
+       if(strequal(work_name, global_myname()))
+               nstrcpy(work_name,lp_workgroup());
+
+       /*
+        * We are being very agressive here in adding a workgroup
+        * name on the basis of a host announcing itself as being
+        * in that workgroup. Maybe we should wait for the workgroup
+        * announce instead ? JRA.
+        */
+
+       work = find_workgroup_on_subnet(subrec, work_name);
+
+       if(servertype != 0) {
+               if (work ==NULL ) {
+                       /* We have no record of this workgroup. Add it. */
+                       if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
+                               goto done;
+               }
   
-    if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
-    {
-      /* If this server is not already in the workgroup, add it. */
-      create_server_on_workgroup(work, announce_name, 
-                                 servertype|SV_TYPE_LOCAL_LIST_ONLY, 
-                                 ttl, comment);
-    }
-    else
-    {
-      /* Update the record. */
-      servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
-      update_server_ttl( servrec, ttl);
-      fstrcpy(servrec->serv.comment,comment);
-    }
-  }
-  else
-  {
-    /*
-     * This server is announcing it is going down. Remove it from the 
-     * workgroup.
-     */
-    if(!is_myname(announce_name) && (work != NULL) &&
-       ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
-      )
-    {
-      remove_server_from_workgroup( work, servrec);
-    }
-  }
-  subrec->work_changed = True;
+               if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
+                       /* If this server is not already in the workgroup, add it. */
+                       create_server_on_workgroup(work, announce_name, 
+                               servertype|SV_TYPE_LOCAL_LIST_ONLY, 
+                               ttl, comment);
+               } else {
+                       /* Update the record. */
+                       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
+                       update_server_ttl( servrec, ttl);
+                       fstrcpy(servrec->serv.comment,comment);
+               }
+       } else {
+               /*
+                * This server is announcing it is going down. Remove it from the 
+                * workgroup.
+                */
+               if(!is_myname(announce_name) && (work != NULL) &&
+                               ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
+                       remove_server_from_workgroup( work, servrec);
+               }
+       }
+
+       subrec->work_changed = True;
 done:
-  END_PROFILE(host_announce);
+
+       END_PROFILE(host_announce);
 }
 
 /*******************************************************************
@@ -199,53 +196,56 @@ done:
 
 void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  int ttl = IVAL(buf,1)/1000;
-  char *workgroup_announce_name = buf+5;
-  uint32 servertype = IVAL(buf,23);
-  char *master_name = buf+31;
-  struct work_record *work;
-  char *source_name = dgram->source_name.name;
-
-  START_PROFILE(workgroup_announce);
-  master_name[43] = 0;
-
-  DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
+       struct dgram_packet *dgram = &p->packet.dgram;
+       int ttl = IVAL(buf,1)/1000;
+       nstring workgroup_announce_name;
+       nstring master_name;
+       uint32 servertype = IVAL(buf,23);
+       struct work_record *work;
+       nstring source_name;
+       nstring dest_name;
+
+       START_PROFILE(workgroup_announce);
+
+       pull_ascii_nstring(workgroup_announce_name,buf+5);
+       pull_ascii_nstring(master_name,buf+31);
+       master_name[12] = 0;
+       pull_ascii_nstring(source_name,dgram->source_name.name);
+       pull_ascii_nstring(dest_name,dgram->dest_name.name);
+
+       DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
 %s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
-              nmb_namestr(&dgram->dest_name),workgroup_announce_name));
-
-  DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
-           ttl, servertype, master_name));
-
-  /* Workgroup announcements must only go to the MSBROWSE name. */
-  if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1))
-  {
-    DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
-              inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
-    goto done;
-  }
+                       nmb_namestr(&dgram->dest_name),workgroup_announce_name));
+
+       DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
+               ttl, servertype, master_name));
+
+       /* Workgroup announcements must only go to the MSBROWSE name. */
+       if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) {
+               DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
+                       inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
+               goto done;
+       }
+
+       if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) {
+               /* We have no record of this workgroup. Add it. */
+               if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
+                       goto done;
+       } else {
+               /* Update the workgroup death_time. */
+               update_workgroup_ttl(work, ttl);
+       }
+
+       if(*work->local_master_browser_name == '\0') {
+               /* Set the master browser name. */
+               set_workgroup_local_master_browser_name( work, master_name );
+       }
+
+       subrec->work_changed = True;
 
-  if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL)
-  {
-    /* We have no record of this workgroup. Add it. */
-    if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
-      goto done;
-  }
-  else
-  {
-    /* Update the workgroup death_time. */
-    update_workgroup_ttl(work, ttl);
-  }
-
-  if(*work->local_master_browser_name == '\0')
-  {
-    /* Set the master browser name. */
-    set_workgroup_local_master_browser_name( work, master_name );
-  }
-
-  subrec->work_changed = True;
 done:
-  END_PROFILE(workgroup_announce);
+
+       END_PROFILE(workgroup_announce);
 }
 
 /*******************************************************************
@@ -254,117 +254,110 @@ done:
 
 void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  int ttl = IVAL(buf,1)/1000;
-  char *server_name = buf+5;
-  uint32 servertype = IVAL(buf,23);
-  char *comment = buf+31;
-  char *work_name;
-  struct work_record *work;
-  struct server_record *servrec;
-  char *source_name = dgram->source_name.name;
-
-  START_PROFILE(local_master_announce);
-  comment[43] = 0;
-
-  DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
+       struct dgram_packet *dgram = &p->packet.dgram;
+       int ttl = IVAL(buf,1)/1000;
+       nstring server_name;
+       uint32 servertype = IVAL(buf,23);
+       fstring comment;
+       nstring work_name;
+       struct work_record *work;
+       struct server_record *servrec;
+       nstring source_name;
+
+       START_PROFILE(local_master_announce);
+
+       pull_ascii_nstring(server_name,buf+5);
+       pull_ascii_fstring(comment, buf+31);
+       comment[12] = 0;
+       pull_ascii_nstring(source_name, dgram->source_name.name);
+       pull_ascii_nstring(work_name, dgram->dest_name.name);
+
+       DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
 %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
-              nmb_namestr(&dgram->dest_name),server_name));
+               nmb_namestr(&dgram->dest_name),server_name));
 
-  DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
-           ttl, servertype, comment));
+       DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
+               ttl, servertype, comment));
 
-  /* A local master announcement must be sent to the name WORKGROUP<1e>. */
-  if(dgram->dest_name.name_type != 0x1e)
-  {
-    DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
+       /* A local master announcement must be sent to the name WORKGROUP<1e>. */
+       if(dgram->dest_name.name_type != 0x1e) {
+               DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
 (was %02x) should be 0x1e. Ignoring packet.\n",
-              inet_ntoa(p->ip), dgram->dest_name.name_type));
-    goto done;
-  }
-
-  /* Filter servertype to remove impossible bits. */
-  servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
-  /* For a local master announce the workgroup name is the destination name. */
-  work_name = dgram->dest_name.name;
-
-  if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
-  {
-    /* Don't bother adding if it's a local master release announce. */
-    if(servertype == 0)
-      goto done;
-
-    /* We have no record of this workgroup. Add it. */
-    if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
-      goto done;
-  }
-
-  /* If we think we're the local master browser for this workgroup,
-     we should never have got this packet. We don't see our own
-     packets.
-   */
-  if(AM_LOCAL_MASTER_BROWSER(work))
-  {
-    DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
+                       inet_ntoa(p->ip), dgram->dest_name.name_type));
+               goto done;
+       }
+
+       /* Filter servertype to remove impossible bits. */
+       servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
+
+       /* For a local master announce the workgroup name is the destination name. */
+
+       if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) {
+               /* Don't bother adding if it's a local master release announce. */
+               if(servertype == 0)
+                       goto done;
+
+               /* We have no record of this workgroup. Add it. */
+               if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
+                       goto done;
+       }
+
+       /* If we think we're the local master browser for this workgroup,
+               we should never have got this packet. We don't see our own
+               packets.
+       */
+       if(AM_LOCAL_MASTER_BROWSER(work)) {
+               DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
 a local master browser for workgroup %s and we think we are master. Forcing election.\n",
-      server_name, inet_ntoa(p->ip), work_name));
+                       server_name, inet_ntoa(p->ip), work_name));
 
-    /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
-       they have become a local master browser once, they will never
-       stop sending local master announcements. To fix this we send
-       them a reset browser packet, with level 0x2 on the __SAMBA__
-       name that only they should be listening to. */
+               /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
+                they have become a local master browser once, they will never
+                stop sending local master announcements. To fix this we send
+                them a reset browser packet, with level 0x2 on the __SAMBA__
+                name that only they should be listening to. */
    
-    send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
-
-    /* We should demote ourself and force an election. */
-
-    unbecome_local_master_browser( subrec, work, True);
-
-    /* The actual election requests are handled in
-       nmbd_election.c */
-    goto done;
-  }  
-
-  /* Find the server record on this workgroup. If it doesn't exist, add it. */
-
-  if(servertype != 0)
-  {
-    if((servrec = find_server_in_workgroup( work, server_name))==NULL)
-    {
-      /* If this server is not already in the workgroup, add it. */
-      create_server_on_workgroup(work, server_name, 
-                                 servertype|SV_TYPE_LOCAL_LIST_ONLY, 
-                                 ttl, comment);
-    }
-    else
-    {
-      /* Update the record. */
-      servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
-      update_server_ttl(servrec, ttl);
-      fstrcpy(servrec->serv.comment,comment);
-    }
-
-    set_workgroup_local_master_browser_name( work, server_name );
-  }
-  else
-  {
-    /*
-     * This server is announcing it is going down. Remove it from the
-     * workgroup.
-     */
-    if(!is_myname(server_name) && (work != NULL) &&
-       ((servrec = find_server_in_workgroup( work, server_name))!=NULL)
-      )
-    {
-      remove_server_from_workgroup( work, servrec);
-    }
-  }
-
-  subrec->work_changed = True;
+               send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
+
+               /* We should demote ourself and force an election. */
+
+               unbecome_local_master_browser( subrec, work, True);
+
+               /* The actual election requests are handled in nmbd_election.c */
+               goto done;
+       }  
+
+       /* Find the server record on this workgroup. If it doesn't exist, add it. */
+
+       if(servertype != 0) {
+               if((servrec = find_server_in_workgroup( work, server_name))==NULL) {
+                       /* If this server is not already in the workgroup, add it. */
+                       create_server_on_workgroup(work, server_name, 
+                               servertype|SV_TYPE_LOCAL_LIST_ONLY, 
+                               ttl, comment);
+               } else {
+                       /* Update the record. */
+                       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
+                       update_server_ttl(servrec, ttl);
+                       fstrcpy(servrec->serv.comment,comment);
+               }
+       
+               set_workgroup_local_master_browser_name( work, server_name );
+       } else {
+               /*
+                * This server is announcing it is going down. Remove it from the
+                * workgroup.
+                */
+               if(!is_myname(server_name) && (work != NULL) &&
+                               ((servrec = find_server_in_workgroup( work, server_name))!=NULL)) {
+                       remove_server_from_workgroup( work, servrec);
+               }
+       }
+
+       subrec->work_changed = True;
 done:
-  END_PROFILE(local_master_announce);
+
+       END_PROFILE(local_master_announce);
 }
 
 /*******************************************************************
@@ -377,50 +370,49 @@ done:
 void process_master_browser_announce(struct subnet_record *subrec, 
                                      struct packet_struct *p,char *buf)
 {
-  char *local_master_name = buf;
-  struct work_record *work;
-  struct browse_cache_record *browrec;
+       nstring local_master_name;
+       struct work_record *work;
+       struct browse_cache_record *browrec;
 
-  START_PROFILE(master_browser_announce);
-  local_master_name[15] = 0;
+       START_PROFILE(master_browser_announce);
+
+       pull_ascii_nstring(local_master_name,buf);
   
-  DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
-           local_master_name, inet_ntoa(p->ip)));
+       DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
+               local_master_name, inet_ntoa(p->ip)));
   
-  if (!lp_domain_master()) 
-  {
-    DEBUG(0,("process_master_browser_announce: Not configured as domain \
+       if (!lp_domain_master()) {
+               DEBUG(0,("process_master_browser_announce: Not configured as domain \
 master - ignoring master announce.\n"));
-    goto done;
-  }
+               goto done;
+       }
   
-  if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL)
-  {
-    DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
-           lp_workgroup(), subrec->subnet_name));
-    goto done;
-  }
-
-  if(!AM_DOMAIN_MASTER_BROWSER(work))
-  {
-    DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
+       if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) {
+               DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
+                       lp_workgroup(), subrec->subnet_name));
+               goto done;
+       }
+
+       if(!AM_DOMAIN_MASTER_BROWSER(work)) {
+               DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
 %s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));
-    goto done;
-  }
+               goto done;
+       }
 
-  /* Add this host as a local master browser entry on the browse lists.
-     This causes a sync request to be made to it at a later date.
-   */
+       /* Add this host as a local master browser entry on the browse lists.
+               This causes a sync request to be made to it at a later date.
+       */
+
+       if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) {
+               /* Add it. */
+               create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
+       } else {
+               update_browser_death_time(browrec);
+       }
 
-  if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL)
-  {
-    /* Add it. */
-    create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
-  }
-  else
-    update_browser_death_time(browrec);
 done:
-  END_PROFILE(master_browser_announce);
+
+       END_PROFILE(master_browser_announce);
 }
 
 /*******************************************************************
@@ -429,123 +421,117 @@ done:
 
 void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  uint32 servertype = IVAL(buf,1);
-  int osmajor=CVAL(buf,5);           /* major version of node software */
-  int osminor=CVAL(buf,6);           /* minor version of node software */
-  int ttl = SVAL(buf,7);
-  char *announce_name = buf+9;
-  struct work_record *work;
-  struct server_record *servrec;
-  const char *work_name;
-  char *source_name = dgram->source_name.name;
-  pstring comment;
-  char *s = buf+9;
-
-  START_PROFILE(lm_host_announce);
-  s = skip_string(s,1);
-  StrnCpy(comment, s, 43);
-
-  DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
-              nmb_namestr(&dgram->dest_name),announce_name));
-
-  DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
-          osmajor, osminor, ttl, servertype,comment));
-
-  if ((osmajor < 36) || (osmajor > 38) || (osminor !=0))
-  {
-    DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \
+       struct dgram_packet *dgram = &p->packet.dgram;
+       uint32 servertype = IVAL(buf,1);
+       int osmajor=CVAL(buf,5);           /* major version of node software */
+       int osminor=CVAL(buf,6);           /* minor version of node software */
+       int ttl = SVAL(buf,7);
+       nstring announce_name;
+       struct work_record *work;
+       struct server_record *servrec;
+       nstring work_name;
+       nstring source_name;
+       fstring comment;
+       char *s = buf+9;
+
+       START_PROFILE(lm_host_announce);
+       s = skip_string(s,1);
+       pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE);
+
+       pull_ascii_nstring(announce_name,buf+9);
+       pull_ascii_nstring(source_name,dgram->source_name.name);
+       /* For a LanMan host announce the workgroup name is the destination name. */
+       pull_ascii_nstring(work_name,dgram->dest_name.name);
+
+       DEBUG(3,("process_lm_host_announce: LM Announcement from %s IP %s to \
+%s for server %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
+               nmb_namestr(&dgram->dest_name),announce_name));
+
+       DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
+               osmajor, osminor, ttl, servertype,comment));
+
+       if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) {
+               DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \
 originate from OS/2 Warp client. Ignoring packet.\n"));
-    /* Could have been from a Windows machine (with its LM Announce enabled),
-       or a Samba server. Then don't disrupt the current browse list. */
-    goto done;
-  }
+               /* Could have been from a Windows machine (with its LM Announce enabled),
+                       or a Samba server. Then don't disrupt the current browse list. */
+               goto done;
+       }
 
-  /* Filter servertype to remove impossible bits. */
-  servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
+       /* Filter servertype to remove impossible bits. */
+       servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
 
-  /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
-  if(dgram->dest_name.name_type != 0x00)
-  {
-    DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
+       /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
+       if(dgram->dest_name.name_type != 0x00) {
+               DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
 (was %02x) should be 0x00. Allowing packet anyway.\n",
-              inet_ntoa(p->ip), dgram->dest_name.name_type));
-    /* Change it so it was. */
-    dgram->dest_name.name_type = 0x00;
-  }
-
-  /* For a LanMan host announce the workgroup name is the destination name. */
-  work_name = dgram->dest_name.name;
-
-  /*
-   * Syntax servers version 5.1 send HostAnnounce packets to
-   * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
-   * instead of WORKGROUP<1d> name. So to fix this we check if
-   * the workgroup name is our own name, and if so change it
-   * to be our primary workgroup name. This code is probably
-   * not needed in the LanMan announce code, but it won't hurt.
-   */
-
-  if(strequal(work_name, global_myname()))
-    work_name = lp_workgroup();
-
-  /*
-   * We are being very agressive here in adding a workgroup
-   * name on the basis of a host announcing itself as being
-   * in that workgroup. Maybe we should wait for the workgroup
-   * announce instead ? JRA.
-   */
+                       inet_ntoa(p->ip), dgram->dest_name.name_type));
+               /* Change it so it was. */
+               dgram->dest_name.name_type = 0x00;
+       }
+
+       /*
+        * Syntax servers version 5.1 send HostAnnounce packets to
+        * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
+        * instead of WORKGROUP<1d> name. So to fix this we check if
+        * the workgroup name is our own name, and if so change it
+        * to be our primary workgroup name. This code is probably
+        * not needed in the LanMan announce code, but it won't hurt.
+        */
+
+       if(strequal(work_name, global_myname()))
+               nstrcpy(work_name,lp_workgroup());
+
+       /*
+        * We are being very agressive here in adding a workgroup
+        * name on the basis of a host announcing itself as being
+        * in that workgroup. Maybe we should wait for the workgroup
+        * announce instead ? JRA.
+        */
+
+       work = find_workgroup_on_subnet(subrec, work_name);
+
+       if(servertype != 0) {
+               if (work == NULL) {
+                       /* We have no record of this workgroup. Add it. */
+                       if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
+                               goto done;
+               }
+
+               if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
+                       /* If this server is not already in the workgroup, add it. */
+                       create_server_on_workgroup(work, announce_name,
+                                       servertype|SV_TYPE_LOCAL_LIST_ONLY,
+                                       ttl, comment);
+               } else {
+                       /* Update the record. */
+                       servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
+                       update_server_ttl( servrec, ttl);
+                       fstrcpy(servrec->serv.comment,comment);
+               }
+       } else {
+               /*
+                * This server is announcing it is going down. Remove it from the
+                * workgroup.
+                */
+               if(!is_myname(announce_name) && (work != NULL) &&
+                               ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
+                       remove_server_from_workgroup( work, servrec);
+               }
+       }
+
+       subrec->work_changed = True;
+       found_lm_clients = True;
 
-  work = find_workgroup_on_subnet(subrec, work_name);
-
-  if(servertype != 0)
-  {
-    if (work == NULL)
-    {
-      /* We have no record of this workgroup. Add it. */
-      if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
-        goto done;
-    }
-
-    if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
-    {
-      /* If this server is not already in the workgroup, add it. */
-      create_server_on_workgroup(work, announce_name,
-                                 servertype|SV_TYPE_LOCAL_LIST_ONLY,
-                                 ttl, comment);
-    }
-    else
-    {
-      /* Update the record. */
-      servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
-      update_server_ttl( servrec, ttl);
-      fstrcpy(servrec->serv.comment,comment);
-    }
-  }
-  else
-  {
-    /*
-     * This server is announcing it is going down. Remove it from the
-     * workgroup.
-     */
-    if(!is_myname(announce_name) && (work != NULL) &&
-       ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
-      )
-    {
-      remove_server_from_workgroup( work, servrec);
-    }
-  }
-
-  subrec->work_changed = True;
-  found_lm_clients = True;
 done:
-  END_PROFILE(lm_host_announce);
+
+       END_PROFILE(lm_host_announce);
 }
 
 /****************************************************************************
   Send a backup list response.
 *****************************************************************************/
+
 static void send_backup_list_response(struct subnet_record *subrec, 
                                      struct work_record *work,
                                      struct nmb_name *send_to_name,
@@ -553,40 +539,41 @@ static void send_backup_list_response(struct subnet_record *subrec,
                                      uint32 token, struct in_addr sendto_ip,
                                      int port)
 {                     
-  char outbuf[1024];
-  char *p, *countptr;
-  unsigned int count = 0;
+       char outbuf[1024];
+       char *p, *countptr;
+       unsigned int count = 0;
+       nstring send_to_namestr;
 #if 0
   struct server_record *servrec;
 #endif
-  fstring myname;
+       fstring myname;
 
-  memset(outbuf,'\0',sizeof(outbuf));
+       memset(outbuf,'\0',sizeof(outbuf));
 
-  DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
-          work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
+       DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
+               work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
   
-  p = outbuf;
+       p = outbuf;
   
-  SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
-  p++;
+       SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
+       p++;
 
-  countptr = p;
-  p++;
+       countptr = p;
+       p++;
 
-  SIVAL(p,0,token); /* The sender's unique info. */
-  p += 4;
+       SIVAL(p,0,token); /* The sender's unique info. */
+       p += 4;
   
-  /* We always return at least one name - our own. */
-  count = 1;
-  fstrcpy(myname, global_myname());
-  strupper_m(myname);
-  myname[15]='\0';
-  push_pstring_base(p, myname, outbuf);
+       /* We always return at least one name - our own. */
+       count = 1;
+       fstrcpy(myname, global_myname());
+       strupper_m(myname);
+       myname[15]='\0';
+       push_pstring_base(p, myname, outbuf);
 
-  p = skip_string(p,1);
+       p = skip_string(p,1);
 
-  /* Look for backup browsers in this workgroup. */
+       /* Look for backup browsers in this workgroup. */
 
 #if 0
   /* we don't currently send become_backup requests so we should never
@@ -624,16 +611,18 @@ static void send_backup_list_response(struct subnet_record *subrec,
   }
 #endif
 
-  SCVAL(countptr, 0, count);
+       SCVAL(countptr, 0, count);
+
+       pull_ascii_nstring(send_to_namestr, send_to_name->name);
 
-  DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
-          send_to_name->name, inet_ntoa(sendto_ip), count));
+       DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
+               send_to_namestr, inet_ntoa(sendto_ip), count));
 
-  send_mailslot(True, BROWSE_MAILSLOT,
-                outbuf,PTR_DIFF(p,outbuf),
-                global_myname(), 0, 
-                send_to_name->name,0,
-                sendto_ip, subrec->myip, port);
+       send_mailslot(True, BROWSE_MAILSLOT,
+               outbuf,PTR_DIFF(p,outbuf),
+               global_myname(), 0, 
+               send_to_namestr,0,
+               sendto_ip, subrec->myip, port);
 }
 
 /*******************************************************************
@@ -649,80 +638,74 @@ static void send_backup_list_response(struct subnet_record *subrec,
 void process_get_backup_list_request(struct subnet_record *subrec,
                                      struct packet_struct *p,char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  struct work_record *work;
-  unsigned char max_number_requested = CVAL(buf,0);
-  uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
-  int name_type = dgram->dest_name.name_type;
-  char *workgroup_name = dgram->dest_name.name;
-  struct subnet_record *search_subrec = subrec;
-
-  START_PROFILE(get_backup_list);
-  DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
-           nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
-           nmb_namestr(&dgram->dest_name)));
+       struct dgram_packet *dgram = &p->packet.dgram;
+       struct work_record *work;
+       unsigned char max_number_requested = CVAL(buf,0);
+       uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
+       int name_type = dgram->dest_name.name_type;
+       nstring workgroup_name;
+       struct subnet_record *search_subrec = subrec;
+
+       START_PROFILE(get_backup_list);
+       pull_ascii_nstring(workgroup_name, dgram->dest_name.name);
+
+       DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
+               nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
+               nmb_namestr(&dgram->dest_name)));
   
-  /* We have to be a master browser, or a domain master browser
-     for the requested workgroup. That means it must be our
-     workgroup. */
-
-  if(strequal(workgroup_name, lp_workgroup()) == False)
-  {
-    DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
-           workgroup_name));
-    goto done;
-  }
-
-  if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL)
-  {
-    DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
+       /* We have to be a master browser, or a domain master browser
+               for the requested workgroup. That means it must be our
+               workgroup. */
+
+       if(strequal(workgroup_name, lp_workgroup()) == False) {
+               DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
+                       workgroup_name));
+               goto done;
+       }
+
+       if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) {
+               DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
 subnet %s.\n", workgroup_name, search_subrec->subnet_name));
-    goto done;
-  }
+               goto done;
+       }
 
-  /* 
-   * If the packet was sent to WORKGROUP<1b> instead
-   * of WORKGROUP<1d> then it was unicast to us a domain master
-   * browser. Change search subrec to unicast.
-   */
+       /* 
+        * If the packet was sent to WORKGROUP<1b> instead
+        * of WORKGROUP<1d> then it was unicast to us a domain master
+        * browser. Change search subrec to unicast.
+        */
 
-  if(name_type == 0x1b)
-  {
-    /* We must be a domain master browser in order to
-       process this packet. */
+       if(name_type == 0x1b) {
+               /* We must be a domain master browser in order to
+                       process this packet. */
 
-    if(!AM_DOMAIN_MASTER_BROWSER(work))
-    {
-      DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
+               if(!AM_DOMAIN_MASTER_BROWSER(work)) {
+                       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
 and I am not a domain master browser.\n", workgroup_name));
-      goto done;
-    }
+                       goto done;
+               }
 
-    search_subrec = unicast_subnet;
-  }
-  else if (name_type == 0x1d)
-  {
-    /* We must be a local master browser in order to
-       process this packet. */
+               search_subrec = unicast_subnet;
+       } else if (name_type == 0x1d) {
+               /* We must be a local master browser in order to process this packet. */
 
-    if(!AM_LOCAL_MASTER_BROWSER(work))
-    {
-      DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
+               if(!AM_LOCAL_MASTER_BROWSER(work)) {
+                       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
 and I am not a local master browser.\n", workgroup_name));
-      goto done;
-    }
-  }
-  else
-  {
-    DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
-            name_type));
-    goto done;
-  }
+                       goto done;
+               }
+       } else {
+               DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
+                       name_type));
+               goto done;
+       }
+
+       send_backup_list_response(subrec, work, &dgram->source_name,
+                       max_number_requested, token, p->ip, p->port);
 
-  send_backup_list_response(subrec, work, &dgram->source_name, 
-                            max_number_requested, token, p->ip, p->port);
 done:
-  END_PROFILE(get_backup_list);
+
+       END_PROFILE(get_backup_list);
 }
 
 /*******************************************************************
@@ -738,49 +721,46 @@ done:
 void process_reset_browser(struct subnet_record *subrec,
                                   struct packet_struct *p,char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  int state = CVAL(buf,0);
-  struct subnet_record *sr;
+       struct dgram_packet *dgram = &p->packet.dgram;
+       int state = CVAL(buf,0);
+       struct subnet_record *sr;
 
-  START_PROFILE(reset_browser);
-  DEBUG(1,("process_reset_browser: received diagnostic browser reset \
-request from %s IP %s state=0x%X\n",
-             nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));
+       START_PROFILE(reset_browser);
 
-  /* Stop being a local master browser on all our broadcast subnets. */
-  if (state & 0x1)
-  {
-    for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr))
-    {
-      struct work_record *work;
-      for (work = sr->workgrouplist; work; work = work->next)
-      {
-        if (AM_LOCAL_MASTER_BROWSER(work))
-          unbecome_local_master_browser(sr, work, True);
-      }
-    }
-  }
+       DEBUG(1,("process_reset_browser: received diagnostic browser reset \
+request from %s IP %s state=0x%X\n",
+               nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));
+
+       /* Stop being a local master browser on all our broadcast subnets. */
+       if (state & 0x1) {
+               for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) {
+                       struct work_record *work;
+                       for (work = sr->workgrouplist; work; work = work->next) {
+                               if (AM_LOCAL_MASTER_BROWSER(work))
+                                       unbecome_local_master_browser(sr, work, True);
+                       }
+               }
+       }
   
-  /* Discard our browse lists. */
-  if (state & 0x2)
-  {
-    /*
-     * Calling expire_workgroups_and_servers with a -1
-     * time causes all servers not marked with a PERMANENT_TTL
-     * on the workgroup lists to be discarded, and all 
-     * workgroups with empty server lists to be discarded.
-     * This means we keep our own server names and workgroup
-     * as these have a PERMANENT_TTL.
-     */
-
-    expire_workgroups_and_servers(-1);
-  }
+       /* Discard our browse lists. */
+       if (state & 0x2) {
+               /*
+                * Calling expire_workgroups_and_servers with a -1
+                * time causes all servers not marked with a PERMANENT_TTL
+                * on the workgroup lists to be discarded, and all 
+                * workgroups with empty server lists to be discarded.
+                * This means we keep our own server names and workgroup
+                * as these have a PERMANENT_TTL.
+                */
+
+               expire_workgroups_and_servers(-1);
+       }
   
-  /* Request to stop browsing altogether. */
-  if (state & 0x4)
-    DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
+       /* Request to stop browsing altogether. */
+       if (state & 0x4)
+               DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
 
-  END_PROFILE(reset_browser);
+       END_PROFILE(reset_browser);
 }
 
 /*******************************************************************
@@ -793,33 +773,34 @@ request from %s IP %s state=0x%X\n",
 
 void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  struct work_record *work;
-  char *workgroup_name = dgram->dest_name.name;
+       struct dgram_packet *dgram = &p->packet.dgram;
+       struct work_record *work;
+       nstring workgroup_name;
  
-  START_PROFILE(announce_request);
-  DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
-           nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
-           nmb_namestr(&dgram->dest_name)));
-  
-  /* We only send announcement requests on our workgroup. */
-  if(strequal(workgroup_name, lp_workgroup()) == False)
-  {
-    DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
-           workgroup_name));
-    goto done;
-  }
-
-  if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
-  {
-    DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
-            workgroup_name));
-    goto done;
-  }
+       START_PROFILE(announce_request);
 
-  work->needannounce = True;
+       pull_ascii_nstring(workgroup_name, dgram->dest_name.name);
+       DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
+               nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
+               nmb_namestr(&dgram->dest_name)));
+  
+       /* We only send announcement requests on our workgroup. */
+       if(strequal(workgroup_name, lp_workgroup()) == False) {
+               DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
+                       workgroup_name));
+               goto done;
+       }
+
+       if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
+               DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
+                       workgroup_name));
+               goto done;
+       }
+
+       work->needannounce = True;
 done:
-  END_PROFILE(lm_host_announce);
+
+       END_PROFILE(lm_host_announce);
 }
 
 /*******************************************************************
@@ -833,30 +814,32 @@ done:
 
 void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
-  struct dgram_packet *dgram = &p->packet.dgram;
-  char *workgroup_name = dgram->dest_name.name;
+       struct dgram_packet *dgram = &p->packet.dgram;
+       nstring workgroup_name;
 
-  START_PROFILE(lm_announce_request);
-  DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
-           nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
-           nmb_namestr(&dgram->dest_name)));
+       START_PROFILE(lm_announce_request);
 
-  /* We only send announcement requests on our workgroup. */
-  if(strequal(workgroup_name, lp_workgroup()) == False)
-  {
-    DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
-           workgroup_name));
-    goto done;
-  }
+       pull_ascii_nstring(workgroup_name, dgram->dest_name.name);
+       DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
+               nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
+               nmb_namestr(&dgram->dest_name)));
 
-  if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL)
-  {
-    DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
-            workgroup_name));
-    goto done;
-  }
+       /* We only send announcement requests on our workgroup. */
+       if(strequal(workgroup_name, lp_workgroup()) == False) {
+               DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
+                       workgroup_name));
+               goto done;
+       }
+
+       if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) {
+               DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
+                       workgroup_name));
+               goto done;
+       }
+
+       found_lm_clients = True;
 
-  found_lm_clients = True;
 done:
-  END_PROFILE(lm_host_announce);
+
+       END_PROFILE(lm_host_announce);
 }
index 8995e9ac522acc10249ebab9b61d5244b058183a..2a200713b9fd437054751f0389d802bfdab6df57 100644 (file)
@@ -201,7 +201,7 @@ static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name
  Try and query for a name.
 ****************************************************************************/
 
-BOOL query_name(struct subnet_record *subrec, char *name, int type,
+BOOL query_name(struct subnet_record *subrec, const char *name, int type,
                    query_name_success_function success_fn,
                    query_name_fail_function fail_fn, 
                    struct userdata_struct *userdata)
@@ -276,7 +276,7 @@ BOOL query_name(struct subnet_record *subrec, char *name, int type,
 ****************************************************************************/
 
 BOOL query_name_from_wins_server(struct in_addr ip_to, 
-                   char *name, int type,
+                   const char *name, int type,
                    query_name_success_function success_fn,
                    query_name_fail_function fail_fn, 
                    struct userdata_struct *userdata)