nisppass.c: Fixed incorrect parameter usage.
authorJeremy Allison <jra@samba.org>
Sat, 27 Jun 1998 00:27:44 +0000 (00:27 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 27 Jun 1998 00:27:44 +0000 (00:27 +0000)
nmbd_become_lmb.c: Add 'force_new_election' parameter to some functions.
                   This allows the start of the election to be done *after*
                   the demotion from local master browser is done.
                   Also changed code so release of 1d name is done
                   immediately to allow other local master to gain it.
nmbd_elections.c: Ensured no elections are run until we have registered
                  the WORKGROUP<1e> name that we must listen on to participate
                  in elections.
nmbd_incomingdgrams.c: Use force_new_election code.
nmbd_namelistdb.c: Make update_name_in_namelist static.
nmbd_subnetdb.c: Fix bug in comparison function. We cannot use memcmp
                   as structure packing may make this fail.
nmbd_packets.c: Ensure that we only send one release packet when
                sending a broadcast packet.
nmbd_workgroupdb.c: Ensure we put the correct value in the ElectionCriterion field.
nmblib.c: Ensure make_nmb_name zero's the struct nmb_name.
Jeremy.
(This used to be commit 1fcb094ba04f01be1261ac92198c25b21b0d5ad5)

source3/include/proto.h
source3/libsmb/nmblib.c
source3/nmbd/nmbd_become_lmb.c
source3/nmbd/nmbd_elections.c
source3/nmbd/nmbd_incomingdgrams.c
source3/nmbd/nmbd_namelistdb.c
source3/nmbd/nmbd_packets.c
source3/nmbd/nmbd_subnetdb.c
source3/nmbd/nmbd_workgroupdb.c
source3/passdb/nispass.c

index 1758301ef49f5fa9a1f3f6a82d5056dba5a47114..edf6e60915a4f19a41e1c1bdcaa34a8f01db36e7 100644 (file)
@@ -1260,8 +1260,8 @@ void unbecome_local_master_success(struct subnet_record *subrec,
                              struct in_addr released_ip);
 void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
                        struct nmb_name *fail_name);
-void release_1d_name( struct subnet_record *subrec, char *workgroup_name);
-void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work);
+void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
+                                   BOOL force_new_election);
 void become_local_master_browser(struct subnet_record *subrec, struct work_record *work);
 void set_workgroup_local_master_browser_name( struct work_record *work, char *newname);
 
@@ -1335,8 +1335,6 @@ void refresh_my_names(time_t t);
 
 void set_samba_nb_type(void);
 BOOL ms_browser_name( char *name, int type );
-void update_name_in_namelist( struct subnet_record *subrec,
-                              struct name_record   *namerec );
 void remove_name_from_namelist( struct subnet_record *subrec, 
                                 struct name_record   *namerec );
 struct name_record *find_name_on_subnet( struct subnet_record *subrec,
index f59371d5593a7a6df87e3ee2fb8d80bf0d9e0ecf..89b0fa7a9276c289038007b65ecf354035aef68a 100644 (file)
@@ -762,6 +762,7 @@ static int build_dgram(char *buf,struct packet_struct *p)
   ******************************************************************/
 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
 {
+  memset((char *)n, '\0', sizeof(struct nmb_name));
   StrnCpy(n->name,name,15);
   strupper(n->name);
   n->name_type = (unsigned int)type & 0xFF;
index 7329de6f69d0eceac252efd14fc32620e15b6b1f..f66723eb17a9323973c4b201847aac7c0fc3a64b 100644 (file)
@@ -78,7 +78,8 @@ 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, char *workgroup_name,
+                                   BOOL force_new_election )
 {
   struct work_record *work;
   struct server_record *servrec;
@@ -129,6 +130,8 @@ in workgroup %s on subnet %s\n",
 
   remove_permanent_name_from_unicast( subrec, &nmbname);
 
+  if(force_new_election)
+    work->needelection = True;
 }
 
 /*******************************************************************
@@ -140,11 +143,15 @@ void unbecome_local_master_success(struct subnet_record *subrec,
                              struct nmb_name *released_name,
                              struct in_addr released_ip)
 { 
+  BOOL force_new_election = False;
+
+  memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
+
   DEBUG(3,("unbecome_local_master_success: released name %s.\n",
              namestr(released_name)));
 
   /* Now reset the workgroup and server state. */
-  reset_workgroup_state( subrec, released_name->name );
+  reset_workgroup_state( subrec, released_name->name, force_new_election );
 
   DEBUG(0,("\n%s *****   Samba name server %s has stopped being a local master browser for workgroup %s \
 on subnet %s *****\n\n", timestring(), global_myname, released_name->name, subrec->subnet_name));
@@ -159,6 +166,10 @@ void unbecome_local_master_fail(struct subnet_record *subrec, struct response_re
                        struct nmb_name *fail_name)
 {
   struct name_record *namerec;
+  struct userdata_struct *userdata = rrec->userdata;
+  BOOL force_new_election = False;
+
+  memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
 
   DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
 Removing from namelist anyway.\n", namestr(fail_name)));
@@ -169,19 +180,18 @@ Removing from namelist anyway.\n", namestr(fail_name)));
     remove_name_from_namelist(subrec, namerec);
 
   /* Now reset the workgroup and server state. */
-  reset_workgroup_state( subrec, fail_name->name );
+  reset_workgroup_state( subrec, fail_name->name, force_new_election );
 
   DEBUG(0,("\n%s *****   Samba name server %s has stopped being a local master browser for workgroup %s \
 on subnet %s *****\n\n", timestring(), global_myname, fail_name->name, subrec->subnet_name));
-
 }
 
 /*******************************************************************
- Utility function to remove the WORKGROUP<1d> name called by both
- success and fail of releasing the MSBROWSE name.
+ Utility function to remove the WORKGROUP<1d> name.
 ******************************************************************/
 
-void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
+static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
+                             BOOL force_new_election)
 {
   struct nmb_name nmbname;
   struct name_record *namerec;
@@ -189,10 +199,26 @@ void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
   make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
   if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
   {
+    struct userdata_struct *userdata;
+
+    if((userdata = (struct userdata_struct *)malloc( 
+                      sizeof(struct userdata_struct) + sizeof(BOOL))) == 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,
-                 NULL);
+                 userdata);
+
+    free((char *)userdata);
   }
 }
 
@@ -210,8 +236,6 @@ static void release_msbrowse_name_success(struct subnet_record *subrec,
 
   /* Remove the permanent MSBROWSE name added into the unicast subnet. */
   remove_permanent_name_from_unicast( subrec, released_name);
-
-  release_1d_name( subrec, userdata->data );
 }
 
 /*******************************************************************
@@ -222,7 +246,6 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
                        struct response_record *rrec,
                        struct nmb_name *fail_name)
 {
-  struct userdata_struct *userdata = rrec->userdata;
   struct name_record *namerec;
 
   DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
@@ -235,20 +258,19 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec,
 
   /* Remove the permanent MSBROWSE name added into the unicast subnet. */
   remove_permanent_name_from_unicast( subrec, fail_name);
-
-  release_1d_name( subrec, userdata->data );
 }
 
 /*******************************************************************
-  Unbecome the local master browser.
+  Unbecome the local master browser. If force_new_election is true, restart
+  the election process after we've unbecome the local master.
 ******************************************************************/
 
-void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work)
+void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
+                                   BOOL force_new_election)
 {
   struct server_record *servrec;
   struct name_record *namerec;
   struct nmb_name nmbname;
-  struct userdata_struct *userdata;
 
   /* Sanity check. */
 
@@ -267,17 +289,12 @@ in workgroup %s on subnet %s\n",
   /* Set the state to unbecoming. */
   work->mst_state = MST_UNBECOMING_MASTER;
 
-  /* Setup the userdata for the MSBROWSE name release. */
-  if((userdata = (struct userdata_struct *)malloc( sizeof(struct userdata_struct) + sizeof(fstring)+1)) == NULL)
-  {
-    DEBUG(0,("unbecome_local_master_browser: malloc fail.\n"));
-    return;
-  }
+  /*
+   * Release the WORKGROUP<1d> name asap to allow another machine to
+   * claim it.
+   */
 
-  userdata->copy_fn = NULL;
-  userdata->free_fn = NULL;
-  userdata->userdata_len = strlen(work->work_group)+1;
-  pstrcpy(userdata->data, work->work_group);
+  release_1d_name( subrec, work->work_group, force_new_election);
 
   /* Deregister any browser names we may have. */
   make_nmb_name(&nmbname, MSBROWSE, 0x1, scope);
@@ -286,10 +303,16 @@ in workgroup %s on subnet %s\n",
     release_name(subrec, namerec,
                  release_msbrowse_name_success,
                  release_msbrowse_name_fail,
-                 userdata);
+                 NULL);
   }
 
-  free((char *)userdata);
+  /*
+   * 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));
 }
 
 /****************************************************************************
@@ -394,7 +417,7 @@ workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
   }
 
   /* Roll back all the way by calling unbecome_local_master_browser(). */
-  unbecome_local_master_browser(subrec, work);
+  unbecome_local_master_browser(subrec, work, False);
 }
 
 /****************************************************************************
@@ -465,7 +488,7 @@ in workgroup %s on subnet %s\n",
     return;
   }
 
-  reset_workgroup_state( subrec, work->work_group );
+  reset_workgroup_state( subrec, work->work_group, False );
 
   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",
index 569b6531290004fc6d75d96d836a23e4c2217ca3..4be5b7350887617acdec24dd1bf7561929ceab77 100644 (file)
@@ -26,6 +26,8 @@
 
 extern int DEBUGLEVEL;
 
+extern pstring scope;
+
 extern pstring global_myname;
 extern fstring global_myworkgroup;
 
@@ -58,7 +60,7 @@ static void send_election_dgram(struct subnet_record *subrec, char *workgroup_na
   p = skip_string(p,1);
   
   send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
-                server_name, 0,
+                global_myname, 0,
                 workgroup_name, 0x1e,
                 subrec->bcast_ip, subrec->myip);
 }
@@ -117,7 +119,7 @@ static void check_for_master_browser_fail( struct subnet_record *subrec,
          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, global_myname);
+      send_election_dgram(subrec, work->work_group, 0, 0, "");
     }
   }
 }
@@ -171,8 +173,8 @@ void run_elections(time_t t)
   
   struct subnet_record *subrec;
   
-  /* Send election packets once a second - note */
-  if (lastime && (t - lastime <= 0))
+  /* Send election packets once every 2 seconds - note */
+  if (lastime && (t - lastime < 2))
     return;
   
   lastime = t;
@@ -185,6 +187,20 @@ void run_elections(time_t t)
     {
       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, scope);
+        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", namestr(&nmbname), subrec->subnet_name ));
+          continue;
+        }
+
         send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
                       t - StartupTime, global_myname);
              
@@ -308,7 +324,7 @@ is not my workgroup.\n", work->work_group, subrec->subnet_name ));
       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);
+        unbecome_local_master_browser(subrec, work, False);
     }
   }
 }
@@ -335,12 +351,29 @@ BOOL check_elections(void)
       /* Only start an election if we are in the potential browser state. */
       if (work->needelection && !work->RunningElection && AM_POTENTIAL_MASTER_BROWSER(work))
       {
+        /*
+         * 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, scope);
+        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", 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;
+
+        /* Send a force election packet to begin. */
+        send_election_dgram(subrec, work->work_group, 0, 0, "");
       }
     }
   }
index 62dc444e0c36f5a3c106ac7330591f5f07777aa3..daa321b3ae900e35a4523cc32ec3020859b68c08 100644 (file)
@@ -318,12 +318,10 @@ a local master browser for workgroup %s and we think we are master. Forcing elec
 
     /* We should demote ourself and force an election. */
 
-    unbecome_local_master_browser( subrec, work);
+    unbecome_local_master_browser( subrec, work, True);
 
     /* The actual election requests are handled in
        nmbd_election.c */
-
-    work->needelection = True;
     return;
   }  
 
@@ -722,10 +720,7 @@ request from %s IP %s state=0x%X\n",
       for (work = sr->workgrouplist; work; work = work->next)
       {
         if (AM_LOCAL_MASTER_BROWSER(work))
-        {
-          unbecome_local_master_browser(sr, work);
-          work->needelection = True;
-        }
+          unbecome_local_master_browser(sr, work, True);
       }
     }
   }
index d2c9ea2e71a440be5112ad1172d4be56f3e734aa..b7f185deeb4b79f653b3ea083388c0e04ba3d677 100644 (file)
@@ -86,7 +86,7 @@ static void upcase_name( struct nmb_name *target, struct nmb_name *source )
  * Add a new or overwrite an existing namelist entry.
  * ************************************************************************** **
  */
-void update_name_in_namelist( struct subnet_record *subrec,
+static void update_name_in_namelist( struct subnet_record *subrec,
                               struct name_record   *namerec )
   {
   struct name_record *oldrec = NULL;
index e07391fb485cb333ada9b372528136edc73b76d1..23db8453483daf6e2f7b62c7e22052278796cdd8 100644 (file)
@@ -602,6 +602,17 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
     return NULL;
   }
 
+  /*
+   * For a broadcast release packet, only send once.
+   * This will cause us to remove the name asap. JRA.
+   */
+
+  if(bcast)
+  {
+    rrec->repeat_count = 0;
+    rrec->repeat_time = 0;
+  }
+
   return rrec;
 }
 
index 2b29d1b45baefa19422bc4f98f47cfcfef19bc6f..40ae1db1b3580590cabc0a95ab8a2c573186f692 100644 (file)
@@ -75,12 +75,27 @@ static void add_subnet(struct subnet_record *subrec)
 
 /* CRH!!! */
 /* ************************************************************************** ** * This will go away when we move to a "real" database back-end.
+  Note that we cannot use memcmp here as we have no control
+  over how the struct nmb_name structures are packed in memory. JRA.
  * ************************************************************************** ** */
 int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
   {
   struct name_record *NR = (struct name_record *)Node;
+  struct nmb_name *nmbname = (struct nmb_name *)Item;
+  int ret;
 
-  return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
+  if(nmb_name_equal( &NR->name, nmbname))
+    return 0;
+
+  ret = strcmp( nmbname->name, NR->name.name);
+  if(ret)
+    return ret;
+
+  ret = strcmp( nmbname->scope, NR->name.scope);
+  if(ret)
+    return ret;
+
+  return nmbname->name_type - NR->name.name_type;
   } /* namelist_entry_compare */
 /* CRH!!! */   
 
index 0b392680df6c9a765828206b5c4e4748e6d17deb..818875c8209d658fd0ce543fd2a344aba08e26bc 100644 (file)
@@ -125,7 +125,7 @@ static struct work_record *create_workgroup(char *name, int ttl)
   /* WfWg  uses 01040b01 */
   /* Win95 uses 01041501 */
   /* NTAS  uses ???????? */
-  work->ElectionCriterion  = (MAINTAIN_LIST)|(ELECTION_VERSION<<8); 
+  work->ElectionCriterion  = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); 
   work->ElectionCriterion |= (lp_os_level() << 24);
   if (lp_domain_master())
     work->ElectionCriterion |= 0x80;
index bec303bd0f6a15e50164bcc57ca17e5bed1a9ebc..84eae0a40f0cb51cdf749f68d8096e2cc1a2d3ea 100644 (file)
@@ -195,7 +195,7 @@ struct nisp_enum_info
 static void *startnisppwent(BOOL update)
 {
        static struct nisp_enum_info res;
-       res.result = nisp_get_nis_list(lp_smb_pass_file());
+       res.result = nisp_get_nis_list(lp_smb_passwd_file());
        res.enum_entry = 0;
        return res.result != NULL ? &res : NULL;
 }