home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / samba-1.9.18p7.tar.gz / samba-1.9.18p7.tar / samba-1.9.18p7 / source / nmbd_become_dmb.c < prev    next >
C/C++ Source or Header  |  1998-01-26  |  17KB  |  473 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-1998
  6.    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
  7.    Copyright (C) Jeremy Allison 1994-1998
  8.    
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2 of the License, or
  12.    (at your option) any later version.
  13.    
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.    
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.    
  23. */
  24.  
  25. #include "includes.h"
  26.  
  27. extern int DEBUGLEVEL;
  28.  
  29. extern pstring scope;
  30. extern pstring myname;
  31. extern fstring myworkgroup;
  32. extern char **my_netbios_names;
  33. extern struct in_addr ipzero;
  34. extern struct in_addr allones_ip;
  35.  
  36. extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
  37.  
  38. static void become_domain_master_browser_bcast(char *);
  39.  
  40. /*******************************************************************
  41.   Unbecome a domain master browser - name release success function.
  42.   ******************************************************************/
  43.  
  44. static void unbecome_dmb_success(struct subnet_record *subrec,
  45.                                  struct userdata_struct *userdata,
  46.                                  struct nmb_name *released_name,
  47.                                  struct in_addr released_ip)
  48. {
  49.   struct work_record *work = find_workgroup_on_subnet(subrec, released_name->name);
  50.   struct server_record *servrec;
  51.  
  52.   if(!work)
  53.   {
  54.     DEBUG(0,("unbecome_dmb_success: Cannot find workgroup %s on subnet %s\n",
  55.              released_name->name, subrec->subnet_name));
  56.     return;
  57.   }
  58.  
  59.   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
  60.   {
  61.     DEBUG(0,("unbecome_dmb_success: Error - cannot find server %s \
  62. in workgroup %s on subnet %s\n",
  63.        myname, released_name->name, subrec->subnet_name));
  64.     return;
  65.   }
  66.  
  67.   /* Set the state in the workgroup structure. */
  68.   work->dom_state = DOMAIN_NONE;
  69.  
  70.   /* Update our server status. */
  71.   servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
  72.  
  73.   /* Tell the namelist writer to write out a change. */
  74.   subrec->work_changed = True;
  75.  
  76.   /* Remove any list of local master browsers we are syncing with. */
  77.   remove_workgroup_lmb_browsers(released_name->name);
  78.  
  79.   /* Delete the known domain master browser name from the workgroup
  80.      struct. */
  81.   bzero((char *)&work->dmb_name, sizeof(work->dmb_name));
  82.   putip((char *)&work->dmb_addr, &ipzero);
  83.  
  84.   DEBUG(0,("\n%s ***** Samba server %s has stopped being a domain master browser \
  85. for workgroup %s on subnet %s *****\n\n", timestring(), myname, work->work_group, subrec->subnet_name));
  86.  
  87. }
  88.  
  89. /*******************************************************************
  90.   Unbecome a domain master browser - name release fail function.
  91.   ******************************************************************/
  92.  
  93. static void unbecome_dmb_fail(struct subnet_record *subrec,
  94.                                  struct response_record *rrec,
  95.                                  struct nmb_name *released_name)
  96. {
  97.   DEBUG(0,("unbecome_dmb_fail: Failed to unbecome domain master browser for \
  98. workgroup %s on subnet %s.\n", released_name->name, subrec->subnet_name));
  99. }
  100.  
  101. /*******************************************************************
  102.   Unbecome a domain master browser.
  103.   ******************************************************************/
  104.  
  105. void unbecome_domain_master(char *workgroup_name)
  106. {   
  107.   struct subnet_record *subrec;
  108.  
  109.   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
  110.   {
  111.     struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
  112.  
  113.     if(work && (work->dom_state == DOMAIN_MST))
  114.     {
  115.       struct name_record *namerec;
  116.       struct nmb_name nmbname;
  117.       make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
  118.  
  119.       /* We can only do this if we are a domain master already. */
  120.       DEBUG(2,("unbecome_domain_master: attempting to stop being a domain \
  121. master browser for workgroup %s on subnet %s\n",
  122.               work->work_group, subrec->subnet_name));
  123.    
  124.       /* Find the WORKGROUP<1b> name on the subnet namelist. */
  125.       if((namerec = find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME))==NULL)
  126.       {
  127.         DEBUG(0,("unbecome_domain_master: Cannot find name %s on subnet %s.\n",
  128.                 namestr(&nmbname), subrec->subnet_name));
  129.         continue;
  130.       }
  131.       release_name(subrec, namerec, 
  132.                    unbecome_dmb_success,
  133.                    unbecome_dmb_fail,
  134.                    NULL);
  135.     }
  136.   }
  137.  
  138. /****************************************************************************
  139.   Fail to become a Domain Master Browser on a subnet.
  140.   ****************************************************************************/
  141.  
  142. static void become_domain_master_fail(struct subnet_record *subrec,
  143.                                       struct response_record *rrec,
  144.                                       struct nmb_name *fail_name)
  145. {
  146.   struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
  147.   struct server_record *servrec;
  148.  
  149.   if(!work)
  150.   {
  151.     DEBUG(0,("become_domain_master_fail: Error - cannot find \
  152. workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
  153.     return;
  154.   }
  155.  
  156.   /* Set the state back to DOMAIN_NONE. */
  157.   work->dom_state = DOMAIN_NONE;
  158.  
  159.   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
  160.   {
  161.     DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
  162. in workgroup %s on subnet %s\n",
  163.        myname, work->work_group, subrec->subnet_name));
  164.     return;
  165.   }
  166.  
  167.   /* Update our server status. */
  168.   servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
  169.  
  170.   /* Tell the namelist writer to write out a change. */
  171.   subrec->work_changed = True;
  172.  
  173.   DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
  174. workgroup %s on subnet %s. Couldn't register name %s.\n",
  175.        work->work_group, subrec->subnet_name, namestr(fail_name)));
  176. }
  177.  
  178. /****************************************************************************
  179.   Become a Domain Master Browser on a subnet.
  180.   ****************************************************************************/
  181.  
  182. static void become_domain_master_stage2(struct subnet_record *subrec, 
  183.                                         struct userdata_struct *userdata,
  184.                                         struct nmb_name *registered_name,
  185.                                         uint16 nb_flags,
  186.                                         int ttl, struct in_addr registered_ip)
  187. {
  188.   struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
  189.   struct server_record *servrec;
  190.  
  191.   if(!work)
  192.   {
  193.     DEBUG(0,("become_domain_master_stage2: Error - cannot find \
  194. workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
  195.     return;
  196.   }
  197.  
  198.   if((servrec = find_server_in_workgroup( work, myname)) == NULL)
  199.   {
  200.     DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
  201. in workgroup %s on subnet %s\n", 
  202.        myname, registered_name->name, subrec->subnet_name));
  203.     work->dom_state = DOMAIN_NONE;
  204.     return;
  205.   }
  206.  
  207.   /* Set the state in the workgroup structure. */
  208.   work->dom_state = DOMAIN_MST; /* Become domain master. */
  209.  
  210.   /* Update our server status. */
  211.   servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
  212.  
  213.   /* Tell the namelist writer to write out a change. */
  214.   subrec->work_changed = True;
  215.  
  216.   DEBUG(0,("\n%s ***** Samba server %s is now a domain master browser for \
  217. workgroup %s on subnet %s *****\n\n", timestring(),myname, work->work_group, 
  218. subrec->subnet_name));
  219.  
  220.   if(subrec == unicast_subnet)
  221.   {
  222.     struct nmb_name nmbname;
  223.     struct in_addr my_first_ip;
  224.  
  225.     /* Put our name and first IP address into the 
  226.        workgroup struct as domain master browser. This
  227.        will stop us syncing with ourself if we are also
  228.        a local master browser. */
  229.  
  230.     make_nmb_name(&nmbname, myname, 0x20, scope);
  231.  
  232.     work->dmb_name = nmbname;
  233.     /* Pick the first interface ip address as the domain master browser ip. */
  234.     my_first_ip = *iface_n_ip(0);
  235.  
  236.     putip((char *)&work->dmb_addr, &my_first_ip);
  237.  
  238.     /* We successfully registered by unicast with the
  239.        WINS server.  We now expect to become the domain
  240.        master on the local subnets. If this fails, it's
  241.        probably a 1.9.16p2 to 1.9.16p11 server's fault.
  242.  
  243.        This is a configuration issue that should be addressed
  244.        by the network administrator - you shouldn't have
  245.        several machines configured as a domain master browser
  246.        for the same WINS scope (except if they are 1.9.17 or
  247.        greater, and you know what you're doing.
  248.  
  249.        see docs/DOMAIN.txt.
  250.  
  251.      */
  252.     become_domain_master_browser_bcast(work->work_group);
  253.   }
  254. }
  255.  
  256. /****************************************************************************
  257.   Start the name registration process when becoming a Domain Master Browser
  258.   on a subnet.
  259.   ****************************************************************************/
  260.  
  261. static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
  262.   struct work_record *work;
  263.  
  264.   DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
  265. workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
  266.  
  267.   /* First, find the workgroup on the subnet. */
  268.   if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
  269.   {
  270.     DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
  271.           wg_name, subrec->subnet_name));
  272.     return;
  273.   }
  274.  
  275.   DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
  276.   work->dom_state = DOMAIN_WAIT;
  277.  
  278.   /* WORKGROUP<1b> is the domain master browser name. */
  279.   register_name(subrec, work->work_group,0x1b,samba_nb_type,
  280.                 become_domain_master_stage2,
  281.                 become_domain_master_fail, NULL);
  282. }
  283.  
  284. /****************************************************************************
  285.   Function called when a query for a WORKGROUP<1b> name succeeds.
  286.   This is normally a fail condition as it means there is already
  287.   a domain master browser for a workgroup and we were trying to
  288.   become one.
  289. ****************************************************************************/
  290.  
  291. static void become_domain_master_query_success(struct subnet_record *subrec,
  292.                         struct userdata_struct *userdata,
  293.                         struct nmb_name *nmbname, struct in_addr ip, 
  294.                         struct res_rec *rrec)
  295. {
  296.   /* If the given ip is not ours, then we can't become a domain
  297.      controler as the name is already registered.
  298.    */
  299.  
  300.  /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
  301.     address or zero ip for this query. Pretend this is ok. */
  302.  
  303.   if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
  304.   {
  305.     DEBUG(3,("become_domain_master_query_success: Our address (%s) returned \
  306. in query for name %s (domain master browser name) on subnet %s. \
  307. Continuing with domain master code.\n", 
  308.            inet_ntoa(ip), namestr(nmbname), subrec->subnet_name));
  309.  
  310.     become_domain_master_stage1(subrec, nmbname->name);
  311.   }
  312.   else
  313.   {
  314.     DEBUG(0,("%s become_domain_master_query_success: There is already a domain \
  315. master browser at IP %s for workgroup %s registered on subnet %s.\n",
  316.           timestring(), inet_ntoa(ip), nmbname->name, subrec->subnet_name));
  317.   }
  318. }
  319.  
  320. /****************************************************************************
  321.   Function called when a query for a WORKGROUP<1b> name fails.
  322.   This is normally a success condition as it then allows us to register
  323.   our own Domain Master Browser name.
  324.   ****************************************************************************/
  325.  
  326. static void become_domain_master_query_fail(struct subnet_record *subrec,
  327.                                     struct response_record *rrec,
  328.                                     struct nmb_name *question_name, int fail_code)
  329. {
  330.   /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
  331.      then this is a failure. Otherwise, not finding the name is what we want. */
  332.   if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
  333.   {
  334.     DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
  335. querying WINS server for name %s.\n", 
  336.                   fail_code, namestr(question_name)));
  337.     return;
  338.   }
  339.  
  340.   /* Otherwise - not having the name allows us to register it. */
  341.   become_domain_master_stage1(subrec, question_name->name);
  342. }
  343.  
  344. /****************************************************************************
  345.   Attempt to become a domain master browser on all broadcast subnets.
  346.   ****************************************************************************/
  347.  
  348. static void become_domain_master_browser_bcast(char *workgroup_name)
  349. {
  350.   struct subnet_record *subrec;
  351.  
  352.   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
  353.   { 
  354.     struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
  355.  
  356.     if (work && (work->dom_state == DOMAIN_NONE))
  357.     {
  358.       struct nmb_name nmbname;
  359.       make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
  360.  
  361.       /*
  362.        * Check for our name on the given broadcast subnet first, only initiate
  363.        * further processing if we cannot find it.
  364.        */
  365.  
  366.       if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
  367.       {
  368.         DEBUG(0,("become_domain_master_browser_bcast: At time %s attempting to become domain \
  369. master browser on workgroup %s on subnet %s\n", timestring(), 
  370.                  workgroup_name, subrec->subnet_name));
  371.  
  372.         /* Send out a query to establish whether there's a 
  373.            domain controller on the local subnet. If not,
  374.            we can become a domain controller. 
  375.          */
  376.  
  377.         DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
  378. for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
  379.  
  380.         query_name(subrec, nmbname.name, nmbname.name_type,
  381.                    become_domain_master_query_success, 
  382.                    become_domain_master_query_fail,
  383.                    NULL);
  384.       }
  385.     }
  386.   }
  387. }
  388.  
  389. /****************************************************************************
  390.   Attempt to become a domain master browser by registering with WINS.
  391.   ****************************************************************************/
  392.  
  393. static void become_domain_master_browser_wins(char *workgroup_name)
  394. {
  395.   struct work_record *work;
  396.  
  397.   work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
  398.  
  399.   if (work && (work->dom_state == DOMAIN_NONE))
  400.   {
  401.     struct nmb_name nmbname;
  402.  
  403.     make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
  404.  
  405.     /*
  406.      * Check for our name on the unicast subnet first, only initiate
  407.      * further processing if we cannot find it.
  408.      */
  409.  
  410.     if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
  411.     {
  412.       DEBUG(0,("%s become_domain_master_browser_wins: attempting to become domain \
  413. master browser on workgroup %s, subnet %s.\n",
  414.       timestring(), workgroup_name, unicast_subnet->subnet_name));
  415.  
  416.       /* Send out a query to establish whether there's a 
  417.          domain master broswer registered with WINS. If not,
  418.          we can become a domain master browser. 
  419.        */
  420.  
  421.       DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
  422. for domain master browser name %s on workgroup %s\n",
  423.          inet_ntoa(unicast_subnet->myip), namestr(&nmbname), workgroup_name));
  424.  
  425.       query_name(unicast_subnet, nmbname.name, nmbname.name_type,
  426.                    become_domain_master_query_success,
  427.                    become_domain_master_query_fail,
  428.                    NULL);
  429.     }
  430.   }
  431. }
  432.  
  433. /****************************************************************************
  434.   Add the domain logon server and domain master browser names
  435.   if we are set up to do so.
  436.   **************************************************************************/
  437.  
  438. void add_domain_names(time_t t)
  439. {
  440.   static time_t lastrun = 0;
  441.  
  442.   if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
  443.     return;
  444.  
  445.   lastrun = t;
  446.  
  447.   /* Do the "internet group" - <1c> names. */
  448.   if (lp_domain_logons())
  449.     add_logon_names();
  450.  
  451.   /* Do the domain master names. */
  452.   if(lp_domain_master())
  453.   {
  454.     if(we_are_a_wins_client())
  455.     {
  456.       /* We register the WORKGROUP<1b> name with the WINS
  457.          server first, and call add_domain_master_bcast()
  458.          only if this is successful.
  459.  
  460.          This results in domain logon services being gracefully provided,
  461.          as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
  462.          1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
  463.          cannot provide domain master / domain logon services.
  464.        */
  465.       become_domain_master_browser_wins(myworkgroup);
  466.     }
  467.     else
  468.       become_domain_master_browser_bcast(myworkgroup);
  469.   }
  470. }
  471.