home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / nameelect.c < prev    next >
C/C++ Source or Header  |  1997-08-12  |  26KB  |  859 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios routines and daemon - version 2
  5.    Copyright (C) Andrew Tridgell 1994-1997
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.    
  21.    Module name: nameelect.c
  22.  
  23.    Revision History:
  24.  
  25.    14 jan 96: lkcl@pires.co.uk
  26.    added multiple workgroup domain master support
  27.  
  28.    04 jul 96: lkcl@pires.co.uk
  29.    added system to become a master browser by stages.
  30.  
  31.  
  32. */
  33.  
  34. #include "includes.h"
  35.  
  36. extern int ClientNMB;
  37. extern int ClientDGRAM;
  38.  
  39. extern int DEBUGLEVEL;
  40. extern pstring scope;
  41.  
  42. extern pstring myname;
  43. extern fstring myworkgroup;
  44. extern struct in_addr ipzero;
  45. extern struct in_addr wins_ip;
  46.  
  47. /* here are my election parameters */
  48.  
  49. extern time_t StartupTime;
  50.  
  51. extern struct subnet_record *subnetlist;
  52.  
  53. extern uint16 nb_type; /* samba's NetBIOS name type */
  54.  
  55.  
  56. /*******************************************************************
  57.   occasionally check to see if the master browser is around
  58.   ******************************************************************/
  59. void check_master_browser(time_t t)
  60. {
  61.   static time_t lastrun=0;
  62.   struct subnet_record *d;
  63.  
  64.   if (!lastrun) lastrun = t;
  65.   if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
  66.  
  67.   lastrun = t;
  68.  
  69.   dump_workgroups();
  70.  
  71.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
  72.   {
  73.     struct work_record *work;
  74.  
  75.     for (work = d->workgrouplist; work; work = work->next)
  76.     {
  77.       if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work))
  78.       {
  79.         if (lp_local_master())
  80.         {
  81.           /* potential master browser - not a master browser.  force
  82.              becoming a master browser, hence the log message.
  83.            */
  84.  
  85.           DEBUG(2,("%s potential master for %s %s - force election\n",
  86.                    timestring(), work->work_group,
  87.                    inet_ntoa(d->bcast_ip)));
  88.  
  89.           browser_gone(work->work_group, d->bcast_ip);
  90.         }
  91.         else
  92.         {
  93.           /* if we are not the browse master of a workgroup,
  94.              and we can't find a browser on the subnet, do
  95.              something about it.
  96.            */
  97.  
  98.           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
  99.                     work->work_group,0x1d,0,0,0,NULL,NULL,
  100.                     True,False,d->bcast_ip,d->bcast_ip);
  101.         }
  102.       }
  103.     }
  104.   }
  105. }
  106.  
  107.  
  108. /*******************************************************************
  109.   what to do if a master browser DOESN't exist.
  110.  
  111.   option 1: force an election, and participate in it
  112.   option 2: force an election, and let everyone else participate.
  113.  
  114.   ******************************************************************/
  115. void browser_gone(char *work_name, struct in_addr ip)
  116. {
  117.   struct subnet_record *d = find_subnet(ip);
  118.   struct work_record *work = find_workgroupstruct(d, work_name, False);
  119.  
  120.   /* i don't know about this workgroup, therefore i don't care */
  121.   if (!work || !d) return;
  122.  
  123.   /* don't do election stuff on the WINS subnet */
  124.   if (ip_equal(d->bcast_ip,wins_ip)) 
  125.     return;
  126.  
  127.   if (strequal(work->work_group, myworkgroup))
  128.   {
  129.  
  130.     if (lp_local_master())
  131.     {
  132.       /* we have discovered that there is no local master
  133.          browser, and we are configured to initiate
  134.          an election under exactly such circumstances.
  135.        */
  136.       DEBUG(2,("Forcing election on %s %s\n",
  137.            work->work_group,inet_ntoa(d->bcast_ip)));
  138.  
  139.       /* we can attempt to become master browser */
  140.       work->needelection = True;
  141.     }
  142.     else
  143.     {
  144.       /* we need to force an election, because we are configured
  145.          not to _become_ the local master, but we still _need_ one,
  146.          having detected that one doesn't exist.
  147.        */
  148.  
  149.       /* local interfaces: force an election */
  150.       send_election(d, work->work_group, 0, 0, myname);
  151.  
  152.       /* only removes workgroup completely on a local interface 
  153.          persistent lmhosts entries on a local interface _will_ be removed).
  154.        */
  155.       remove_workgroup(d, work,True);
  156.       add_workgroup_to_subnet(d, work->work_group);
  157.     }
  158.   }
  159. }
  160.  
  161.  
  162. /****************************************************************************
  163.   send an election packet
  164.   **************************************************************************/
  165. void send_election(struct subnet_record *d, char *group,uint32 criterion,
  166.            int timeup,char *name)
  167. {
  168.   pstring outbuf;
  169.   char *p;
  170.  
  171.   if (!d) return;
  172.   
  173.   DEBUG(2,("Sending election to %s for workgroup %s\n",
  174.        inet_ntoa(d->bcast_ip),group));       
  175.  
  176.   bzero(outbuf,sizeof(outbuf));
  177.   p = outbuf;
  178.   CVAL(p,0) = ANN_Election; /* election */
  179.   p++;
  180.  
  181.   CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
  182.   SIVAL(p,1,criterion);
  183.   SIVAL(p,5,timeup*1000); /* ms - despite the spec */
  184.   p += 13;
  185.   strcpy(p,name);
  186.   strupper(p);
  187.   p = skip_string(p,1);
  188.   
  189.   send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
  190.               outbuf,PTR_DIFF(p,outbuf),
  191.               name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
  192. }
  193.  
  194.  
  195. /****************************************************************************
  196.   un-register a SELF name that got rejected.
  197.  
  198.   if this name happens to be rejected when samba is in the process
  199.   of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
  200.   or WORKGROUP(1b)) then we must stop being a master browser. sad.
  201.  
  202.   **************************************************************************/
  203. void name_unregister_work(struct subnet_record *d, char *name, int name_type)
  204. {
  205.     struct work_record *work;
  206.     int remove_type_local  = 0;
  207.     int remove_type_domain = 0;
  208.     int remove_type_logon  = 0;
  209.  
  210.     remove_netbios_name(d,name,name_type,SELF,ipzero);
  211.  
  212.     if (!(work = find_workgroupstruct(d, name, False))) return;
  213.  
  214.     /* work out what to unbecome, from the name type being removed */
  215.  
  216.     if (ms_browser_name(name, name_type))
  217.     {
  218.       remove_type_local |= SV_TYPE_MASTER_BROWSER;
  219.     }
  220.     if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d)
  221.     {
  222.       remove_type_local |= SV_TYPE_MASTER_BROWSER;
  223.     }
  224.     if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b)
  225.     {
  226.       remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
  227.     }
  228.     if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c)
  229.     {
  230.       remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
  231.     }
  232.  
  233.     if (remove_type_local ) unbecome_local_master (d, work, remove_type_local );
  234.     if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain);
  235.     if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon );
  236. }
  237.  
  238.  
  239. /****************************************************************************
  240.   registers a name.
  241.  
  242.   if the name being added is a SELF name, we must additionally check
  243.   whether to proceed to the next stage in samba becoming a master browser.
  244.  
  245.   **************************************************************************/
  246. void name_register_work(struct subnet_record *d, char *name, int name_type,
  247.                 int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
  248. {
  249.   enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
  250.                               SELF : REGISTER;
  251.  
  252.   if (source == SELF)
  253.     {
  254.       struct work_record *work = find_workgroupstruct(d, 
  255.                                   myworkgroup, False);
  256.  
  257.       add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
  258.  
  259.       if (work)
  260.       {
  261.         int add_type_local  = False;
  262.         int add_type_domain = False;
  263.         int add_type_logon  = False;
  264.  
  265.         DEBUG(4,("checking next stage: name_register_work %s\n", name));
  266.  
  267.         /* work out what to become, from the name type being added */
  268.  
  269.         if (ms_browser_name(name, name_type))
  270.         {
  271.           add_type_local = True;
  272.         }
  273.         if (strequal(name, myworkgroup) && name_type == 0x1d)
  274.         {
  275.           add_type_local = True;
  276.         }
  277.         if (strequal(name, myworkgroup) && name_type == 0x1b)
  278.         {
  279.           add_type_domain = True;
  280.         }
  281.         if (strequal(name, myworkgroup) && name_type == 0x1c)
  282.         {
  283.           add_type_logon = True;
  284.         }
  285.  
  286.         if (add_type_local ) become_local_master (d, work);
  287.         if (add_type_domain) become_domain_master(d, work);
  288.         if (add_type_logon ) become_logon_server (d, work);
  289.       }
  290.     }
  291. }
  292.  
  293.  
  294. /*******************************************************************
  295.   become the local master browser.
  296.  
  297.   this is done in stages. note that this could take a while, 
  298.   particularly on a broadcast subnet, as we have to wait for
  299.   the implicit registration of each name to be accepted.
  300.  
  301.   as each name is successfully registered, become_local_master() is
  302.   called again, in order to initiate the next stage. see
  303.   dead_netbios_entry() - deals with implicit name registration
  304.   and response_name_reg() - deals with explicit registration
  305.   with a WINS server.
  306.  
  307.   stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
  308.   stage 2: was MST_BACK  - go to MST_MSB  and register WORKGROUP(0x1d)
  309.   stage 3: was MST_MSB  - go to MST_BROWSER and stay there 
  310.  
  311.   XXXX note: this code still does not cope with the distinction
  312.   between different types of nodes, particularly between M and P
  313.   nodes. that comes later.
  314.  
  315.   ******************************************************************/
  316. void become_local_master(struct subnet_record *d, struct work_record *work)
  317. {
  318.   /* domain type must be limited to domain enum + server type. it must
  319.      not have SV_TYPE_SERVER or anything else with SERVER in it, else
  320.      clients get confused and start thinking this entry is a server
  321.      not a workgroup
  322.    */
  323.   uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
  324.  
  325.   if (!work || !d) 
  326.     return;
  327.   
  328.   if (!lp_local_master())
  329.   { 
  330.     DEBUG(0,("Samba not configured as a local master browser.\n"));
  331.     return;
  332.   }
  333.  
  334.   DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
  335.            work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
  336.   
  337.   switch (work->mst_state)
  338.   {
  339.     case MST_POTENTIAL: /* while we were nothing but a server... */
  340.     {
  341.       DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
  342.       work->mst_state = MST_BACK; /* an election win was successful */
  343.  
  344.       work->ElectionCriterion |= 0x5;
  345.  
  346.       /* update our server status */
  347.       work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
  348.       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
  349.                 0,lp_serverstring(),True);
  350.  
  351.       /* add special browser name */
  352.       add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
  353.  
  354.       /* DON'T do anything else after calling add_my_name_entry() */
  355.       break;
  356.     }
  357.  
  358.     case MST_BACK: /* while nothing had happened except we won an election... */
  359.     {
  360.       DEBUG(3,("go to second stage: register as master browser\n"));
  361.       work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
  362.  
  363.       /* add server entry on successful registration of MSBROWSE */
  364.       add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY,
  365.                 0,myname,True);
  366.  
  367.       /* add master name */
  368.       add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
  369.   
  370.       /* DON'T do anything else after calling add_my_name_entry() */
  371.       break;
  372.     }
  373.  
  374.     case MST_MSB: /* while we were still only registered MSBROWSE state... */
  375.     {
  376.       int i = 0;
  377.       struct server_record *sl;
  378.  
  379.       DEBUG(3,("2nd stage complete: registered as master browser for workgroup %s \
  380. on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip)));
  381.       work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
  382.  
  383.       /* update our server status */
  384.       work->ServerType |= SV_TYPE_MASTER_BROWSER;
  385.  
  386.       DEBUG(3,("become_local_master: updating our server %s to type %x\n", 
  387.                 myname, work->ServerType));
  388.  
  389.       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
  390.                 0,lp_serverstring(),True);
  391.  
  392.       /* Count the number of servers we have on our list. If it's
  393.          less than 10 (just a heuristic) request the servers
  394.          to announce themselves.
  395.        */
  396.       for( sl = work->serverlist; sl != NULL; sl = sl->next)
  397.         i++;
  398.  
  399.       if (i < 10)
  400.       {
  401.         /* ask all servers on our local net to announce to us */
  402.         announce_request(work, d->bcast_ip);
  403.       }
  404.  
  405.       /* Reset the announce master timer so that we do an announce as soon as possible
  406.          now we are a master. */
  407.       reset_announce_timer();
  408.  
  409.       DEBUG(0,("Samba is now a local master browser for workgroup %s on subnet %s\n", 
  410.                 work->work_group, inet_ntoa(d->bcast_ip)));
  411.  
  412.       break;
  413.     }
  414.  
  415.     case MST_BROWSER:
  416.     {
  417.       /* don't have to do anything: just report success */
  418.       DEBUG(3,("3rd stage: become master browser!\n"));
  419.       break;
  420.     }
  421.   }
  422. }
  423.  
  424.  
  425. /*******************************************************************
  426.   become the domain master browser.
  427.  
  428.   this is done in stages. note that this could take a while, 
  429.   particularly on a broadcast subnet, as we have to wait for
  430.   the implicit registration of each name to be accepted.
  431.  
  432.   as each name is successfully registered, become_domain_master() is
  433.   called again, in order to initiate the next stage. see
  434.   dead_netbios_entry() - deals with implicit name registration
  435.   and response_name_reg() - deals with explicit registration
  436.   with a WINS server.
  437.  
  438.   stage 1: was DOMAIN_NONE - go to DOMAIN_MST 
  439.  
  440.   XXXX note: this code still does not cope with the distinction
  441.   between different types of nodes, particularly between M and P
  442.   nodes. that comes later.
  443.  
  444.   ******************************************************************/
  445. void become_domain_master(struct subnet_record *d, struct work_record *work)
  446. {
  447.     /* domain type must be limited to domain enum + server type. it must
  448.     not have SV_TYPE_SERVER or anything else with SERVER in it, else
  449.     clients get confused and start thinking this entry is a server
  450.     not a workgroup
  451.     */
  452.  
  453.     if (!work || !d) return;
  454.  
  455.     if (!lp_domain_master())
  456.     { 
  457.         DEBUG(0,("Samba not configured as a domain master browser.\n"));
  458.         return;
  459.     }
  460.  
  461.     DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
  462.     work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
  463.  
  464.     switch (work->dom_state)
  465.     {
  466.         case DOMAIN_NONE: /* while we were nothing but a server... */
  467.         {
  468.             DEBUG(3,("become_domain_master: go to first stage: register <1b> name\n"));
  469.             work->dom_state = DOMAIN_WAIT;
  470.  
  471.             /* XXXX the 0x1b is domain master browser name */
  472.             add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE);
  473.  
  474.             /* DON'T do anything else after calling add_my_name_entry() */
  475.             break;
  476.         }
  477.  
  478.         case DOMAIN_WAIT:
  479.         {
  480.             work->dom_state = DOMAIN_MST; /* ... become domain master */
  481.             DEBUG(3,("become_domain_master: first stage - register as domain member\n"));
  482.  
  483.             /* update our server status */
  484.             work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
  485.             add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
  486.                              0, lp_serverstring(),True);
  487.  
  488.             DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n", 
  489.             work->work_group, inet_ntoa(d->bcast_ip)));
  490.  
  491.             if (d == wins_subnet)
  492.             {
  493.                 /* ok! we successfully registered by unicast with the
  494.                    WINS server.  we now expect to become the domain
  495.                    master on the local subnets.  if this fails, it's
  496.                    probably a 1.9.16p2 to 1.9.16p11 server's fault.
  497.  
  498.                    this is a configuration issue that should be addressed
  499.                    by the network administrator - you shouldn't have
  500.                    several machines configured as a domain master browser
  501.                    for the same WINS scope (except if they are 1.9.17 or
  502.                    greater, and you know what you're doing.
  503.  
  504.                    see DOMAIN.txt.
  505.  
  506.                  */
  507.                 add_domain_master_bcast();
  508.             }
  509.             break;
  510.         }
  511.  
  512.         case DOMAIN_MST:
  513.         {
  514.             /* don't have to do anything: just report success */
  515.             DEBUG(3,("domain second stage: there isn't one!\n"));
  516.             break;
  517.         }
  518.     }
  519. }
  520.  
  521.  
  522. /*******************************************************************
  523.   become a logon server.
  524.   ******************************************************************/
  525. void become_logon_server(struct subnet_record *d, struct work_record *work)
  526. {
  527.   if (!work || !d) return;
  528.   
  529.   if (!lp_domain_logons())
  530.   {
  531.     DEBUG(0,("samba not configured as a logon master.\n"));
  532.     return;
  533.   }
  534.  
  535.   DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
  536.     work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
  537.   
  538.   switch (work->log_state)
  539.   {
  540.     case LOGON_NONE: /* while we were nothing but a server... */
  541.     {
  542.       DEBUG(3,("go to first stage: register <1c> name\n"));
  543.             work->log_state = LOGON_WAIT;
  544.  
  545.      /* XXXX the 0x1c is apparently something to do with domain logons */
  546.      add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
  547.  
  548.       /* DON'T do anything else after calling add_my_name_entry() */
  549.       break;
  550.     }
  551.  
  552.     case LOGON_WAIT:
  553.     {
  554.       work->log_state = LOGON_SRV; /* ... become logon server */
  555.       DEBUG(3,("logon second stage: register \n"));
  556.  
  557.       /* update our server status */
  558.       work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
  559.       add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY
  560.                     ,0, lp_serverstring(),True);
  561.  
  562.       /* DON'T do anything else after calling add_my_name_entry() */
  563.       break;
  564.     }
  565.  
  566.     case LOGON_SRV:
  567.     {
  568.       DEBUG(3,("logon third stage: there isn't one!\n"));
  569.       break;
  570.     }
  571.   }
  572. }
  573.  
  574.  
  575. /*******************************************************************
  576.   unbecome the local master browser. initates removal of necessary netbios 
  577.   names, and tells the world that we are no longer a master browser.
  578.  
  579.   XXXX this _should_ be used to demote to a backup master browser, without
  580.   going straight to non-master browser.  another time.
  581.  
  582.   ******************************************************************/
  583. void unbecome_local_master(struct subnet_record *d, struct work_record *work,
  584.                 int remove_type)
  585. {
  586.   int new_server_type = work->ServerType;
  587.  
  588.   /* can only remove master types with this function */
  589.   remove_type &= SV_TYPE_MASTER_BROWSER;
  590.  
  591.   new_server_type &= ~remove_type;
  592.  
  593.   if (remove_type)
  594.   {
  595.     DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
  596.   
  597.     /* no longer a master browser of any sort */
  598.  
  599.     work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
  600.     work->ElectionCriterion &= ~0x4;
  601.     work->mst_state = MST_POTENTIAL;
  602.  
  603.     /* announce ourselves as no longer active as a master browser. */
  604.     announce_server(d, work, work->work_group, myname, 0, 0);
  605.     remove_name_entry(d,MSBROWSE        ,0x01);
  606.     remove_name_entry(d,work->work_group,0x1d);
  607.   }
  608. }
  609.  
  610.  
  611. /*******************************************************************
  612.   unbecome the domain master browser. initates removal of necessary netbios 
  613.   names, and tells the world that we are no longer a domain browser.
  614.   ******************************************************************/
  615. void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
  616.                 int remove_type)
  617. {
  618.   int new_server_type = work->ServerType;
  619.  
  620.   DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
  621.   
  622.   /* can only remove master or domain types with this function */
  623.   remove_type &= SV_TYPE_DOMAIN_MASTER;
  624.  
  625.   new_server_type &= ~remove_type;
  626.  
  627.   if (remove_type)
  628.   {
  629.     /* no longer a domain master browser of any sort */
  630.  
  631.     work->dom_state = DOMAIN_NONE;
  632.  
  633.     /* announce ourselves as no longer active as a master browser on
  634.        all our local subnets. */
  635.     for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
  636.     {
  637.       work = find_workgroupstruct(d, myworkgroup, False);
  638.  
  639.       announce_server(d, work, work->work_group, myname, 0, 0);
  640.       /* Remove the name entry without any NetBIOS traffic as that's
  641.          how it was registered. */
  642.       remove_name_entry(d,work->work_group,0x1b);    
  643.     }
  644.  
  645.     /* Unregister the 1b name from the WINS server. */
  646.     if(wins_subnet != NULL)
  647.       remove_name_entry(wins_subnet, myworkgroup, 0x1b);
  648.   }
  649. }
  650.  
  651.  
  652. /*******************************************************************
  653.   unbecome the logon server. initates removal of necessary netbios 
  654.   names, and tells the world that we are no longer a logon server.
  655.   ******************************************************************/
  656. void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
  657.                 int remove_type)
  658. {
  659.   int new_server_type = work->ServerType;
  660.  
  661.   DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
  662.   
  663.   /* can only remove master or domain types with this function */
  664.   remove_type &= SV_TYPE_DOMAIN_MEMBER;
  665.  
  666.   new_server_type &= ~remove_type;
  667.  
  668.   if (remove_type)
  669.   {
  670.     /* no longer a master browser of any sort */
  671.  
  672.     work->log_state = LOGON_NONE;
  673.  
  674.     /* announce ourselves as no longer active as a master browser. */
  675.     announce_server(d, work, work->work_group, myname, 0, 0);
  676.     remove_name_entry(d,work->work_group,0x1c);    
  677.   }
  678. }
  679.  
  680.  
  681. /*******************************************************************
  682.   run the election
  683.   ******************************************************************/
  684. void run_elections(time_t t)
  685. {
  686.   static time_t lastime = 0;
  687.   
  688.   struct subnet_record *d;
  689.   
  690.   /* send election packets once a second */
  691.   if (lastime && t-lastime <= 0) return;
  692.   
  693.   lastime = t;
  694.   
  695.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
  696.   {
  697.     struct work_record *work;
  698.  
  699.     for (work = d->workgrouplist; work; work = work->next)
  700.     {
  701.       if (work->RunningElection)
  702.       {
  703.         send_election(d,work->work_group, work->ElectionCriterion,
  704.                 t-StartupTime,myname);
  705.           
  706.         if (work->ElectionCount++ >= 4)
  707.         {
  708.           /* I won! now what :-) */
  709.           DEBUG(2,(">>> Won election on %s %s <<<\n",
  710.                work->work_group,inet_ntoa(d->bcast_ip)));
  711.           
  712.           work->RunningElection = False;
  713.           work->mst_state = MST_POTENTIAL;
  714.  
  715.           become_local_master(d, work);
  716.         }
  717.       }
  718.     }
  719.   }
  720. }
  721.  
  722.  
  723. /*******************************************************************
  724.   work out if I win an election
  725.   ******************************************************************/
  726. static BOOL win_election(struct work_record *work,int version,uint32 criterion,
  727.              int timeup,char *name)
  728. {  
  729.   int mytimeup = time(NULL) - StartupTime;
  730.   uint32 mycriterion = work->ElectionCriterion;
  731.  
  732.   /* If local master is false then never win
  733.      in election broadcasts. */
  734.   if(!lp_local_master())
  735.   {
  736.     DEBUG(3,("win_election: Losing election as local master == False\n"));
  737.     return False;
  738.   }
  739.  
  740.   DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
  741.        version,ELECTION_VERSION,
  742.        criterion,mycriterion,
  743.        timeup,mytimeup,
  744.        name,myname));
  745.  
  746.   if (version > ELECTION_VERSION) return(False);
  747.   if (version < ELECTION_VERSION) return(True);
  748.   
  749.   if (criterion > mycriterion) return(False);
  750.   if (criterion < mycriterion) return(True);
  751.  
  752.   if (timeup > mytimeup) return(False);
  753.   if (timeup < mytimeup) return(True);
  754.  
  755.   if (strcasecmp(myname,name) > 0) return(False);
  756.   
  757.   return(True);
  758. }
  759.  
  760.  
  761. /*******************************************************************
  762.   process a election packet
  763.  
  764.   An election dynamically decides who will be the master. 
  765.   ******************************************************************/
  766. void process_election(struct packet_struct *p,char *buf)
  767. {
  768.     struct dgram_packet *dgram = &p->packet.dgram;
  769.     struct in_addr ip = dgram->header.source_ip;
  770.     struct subnet_record *d = find_subnet(ip);
  771.     int version = CVAL(buf,0);
  772.     uint32 criterion = IVAL(buf,1);
  773.     int timeup = IVAL(buf,5)/1000;
  774.     char *name = buf+13;
  775.     struct work_record *work;
  776.  
  777.     if (!d) return;
  778.  
  779.     if (ip_equal(d->bcast_ip,wins_ip))
  780.     {
  781.         DEBUG(0,("Unexpected election request from %s %s on WINS net\n",
  782.                   name, inet_ntoa(p->ip)));
  783.         return;
  784.     }
  785.  
  786.     name[15] = 0;  
  787.  
  788.     DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
  789.               name,inet_ntoa(p->ip),version,criterion,timeup));
  790.  
  791.     if (same_context(dgram)) return;
  792.  
  793.     for (work = d->workgrouplist; work; work = work->next)
  794.     {
  795.         if (!strequal(work->work_group, myworkgroup))
  796.         continue;
  797.  
  798.         if (win_election(work, version,criterion,timeup,name))
  799.         {
  800.             if (!work->RunningElection)
  801.             {
  802.                 work->needelection = True;
  803.                 work->ElectionCount=0;
  804.                 work->mst_state = MST_POTENTIAL;
  805.             }
  806.         }
  807.         else
  808.         {
  809.             work->needelection = False;
  810.  
  811.             if (work->RunningElection || AM_MASTER(work))
  812.             {
  813.                 work->RunningElection = False;
  814.                 DEBUG(3,(">>> Lost election on %s %s <<<\n",
  815.                           work->work_group,inet_ntoa(d->bcast_ip)));
  816.                 if (AM_MASTER(work))
  817.                 {
  818.                     unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
  819.                 }
  820.             }
  821.         }
  822.     }
  823. }
  824.  
  825.  
  826. /****************************************************************************
  827.   checks whether a browser election is to be run on any workgroup
  828.  
  829.   this function really ought to return the time between election
  830.   packets (which depends on whether samba intends to be a domain
  831.   master or a master browser) in milliseconds.
  832.  
  833.   ***************************************************************************/
  834. BOOL check_elections(void)
  835. {
  836.   struct subnet_record *d;
  837.   BOOL run_any_election = False;
  838.  
  839.   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
  840.     {
  841.       struct work_record *work;
  842.       for (work = d->workgrouplist; work; work = work->next)
  843.     {
  844.       run_any_election |= work->RunningElection;
  845.       
  846.       if (work->needelection && !work->RunningElection)
  847.         {
  848.           DEBUG(3,(">>> Starting election on %s %s <<<\n",
  849.                work->work_group,inet_ntoa(d->bcast_ip)));
  850.           work->ElectionCount = 0;
  851.           work->RunningElection = True;
  852.           work->needelection = False;
  853.         }
  854.     }
  855.     }
  856.   return run_any_election;
  857. }
  858.  
  859.