LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 226 374 60.4 %
Date: 2024-06-13 04:01:37 Functions: 14 17 82.4 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios routines and daemon - version 2
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Jeremy Allison 1997-2002
       6             :    Copyright (C) Jelmer Vernooij 2002,2003 (Conversion to popt)
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/filesys.h"
      24             : #include "lib/cmdline/cmdline.h"
      25             : #include "nmbd/nmbd.h"
      26             : #include "serverid.h"
      27             : #include "messages.h"
      28             : #include "../lib/util/pidfile.h"
      29             : #include "util_cluster.h"
      30             : #include "lib/gencache.h"
      31             : #include "lib/global_contexts.h"
      32             : #include "source3/lib/substitute.h"
      33             : 
      34             : int ClientNMB       = -1;
      35             : int ClientDGRAM     = -1;
      36             : int global_nmb_port = -1;
      37             : 
      38             : extern bool rescan_listen_set;
      39             : extern bool global_in_nmbd;
      40             : 
      41             : /* have we found LanMan clients yet? */
      42             : bool found_lm_clients = False;
      43             : 
      44             : /* what server type are we currently */
      45             : 
      46             : time_t StartupTime = 0;
      47             : 
      48       47440 : struct tevent_context *nmbd_event_context(void)
      49             : {
      50       47440 :         return global_event_context();
      51             : }
      52             : 
      53             : /**************************************************************************** **
      54             :  Handle a SIGTERM in band.
      55             :  **************************************************************************** */
      56             : 
      57          23 : static void terminate(struct messaging_context *msg)
      58             : {
      59          23 :         DEBUG(0,("Got SIGTERM: going down...\n"));
      60             : 
      61             :         /* Write out wins.dat file if samba is a WINS server */
      62          23 :         wins_write_database(0,False);
      63             : 
      64             :         /* Remove all SELF registered names from WINS */
      65          23 :         release_wins_names();
      66             : 
      67             :         /* Announce all server entries as 0 time-to-live, 0 type. */
      68          23 :         announce_my_servers_removed();
      69             : 
      70             :         /* If there was an async dns child - kill it. */
      71          23 :         kill_async_dns_child();
      72             : 
      73          23 :         pidfile_unlink(lp_pid_directory(), "nmbd");
      74             : 
      75          23 :         exit(0);
      76             : }
      77             : 
      78           0 : static void nmbd_sig_term_handler(struct tevent_context *ev,
      79             :                                   struct tevent_signal *se,
      80             :                                   int signum,
      81             :                                   int count,
      82             :                                   void *siginfo,
      83             :                                   void *private_data)
      84             : {
      85           0 :         struct messaging_context *msg = talloc_get_type_abort(
      86             :                 private_data, struct messaging_context);
      87             : 
      88           0 :         terminate(msg);
      89           0 : }
      90             : 
      91             : /*
      92             :   handle stdin becoming readable when we are in --foreground mode
      93             :  */
      94          23 : static void nmbd_stdin_handler(struct tevent_context *ev,
      95             :                                struct tevent_fd *fde,
      96             :                                uint16_t flags,
      97             :                                void *private_data)
      98             : {
      99             :         char c;
     100          23 :         if (read(0, &c, 1) != 1) {
     101          23 :                 struct messaging_context *msg = talloc_get_type_abort(
     102             :                         private_data, struct messaging_context);
     103             :                 
     104          23 :                 DEBUG(0,("EOF on stdin\n"));
     105          23 :                 terminate(msg);
     106             :         }
     107           0 : }
     108             : 
     109          23 : static bool nmbd_setup_sig_term_handler(struct messaging_context *msg)
     110             : {
     111             :         struct tevent_signal *se;
     112             : 
     113          23 :         se = tevent_add_signal(nmbd_event_context(),
     114             :                                nmbd_event_context(),
     115             :                                SIGTERM, 0,
     116             :                                nmbd_sig_term_handler,
     117             :                                msg);
     118          23 :         if (!se) {
     119           0 :                 DEBUG(0,("failed to setup SIGTERM handler"));
     120           0 :                 return false;
     121             :         }
     122             : 
     123          23 :         return true;
     124             : }
     125             : 
     126          23 : static bool nmbd_setup_stdin_handler(struct messaging_context *msg, bool foreground)
     127             : {
     128          23 :         if (foreground) {
     129             :                 /* if we are running in the foreground then look for
     130             :                    EOF on stdin, and exit if it happens. This allows
     131             :                    us to die if the parent process dies
     132             :                    Only do this on a pipe or socket, no other device.
     133             :                 */
     134             :                 struct stat st;
     135          23 :                 if (fstat(0, &st) != 0) {
     136           0 :                         return false;
     137             :                 }
     138          23 :                 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
     139          23 :                         tevent_add_fd(nmbd_event_context(),
     140             :                                 nmbd_event_context(),
     141             :                                 0,
     142             :                                 TEVENT_FD_READ,
     143             :                                 nmbd_stdin_handler,
     144             :                                 msg);
     145             :                 }
     146             :         }
     147             : 
     148          23 :         return true;
     149             : }
     150             : 
     151             : static void msg_reload_nmbd_services(struct messaging_context *msg,
     152             :                                      void *private_data,
     153             :                                      uint32_t msg_type,
     154             :                                      struct server_id server_id,
     155             :                                      DATA_BLOB *data);
     156             : 
     157           0 : static void nmbd_sig_hup_handler(struct tevent_context *ev,
     158             :                                  struct tevent_signal *se,
     159             :                                  int signum,
     160             :                                  int count,
     161             :                                  void *siginfo,
     162             :                                  void *private_data)
     163             : {
     164           0 :         struct messaging_context *msg = talloc_get_type_abort(
     165             :                 private_data, struct messaging_context);
     166             : 
     167           0 :         DEBUG(0,("Got SIGHUP dumping debug info.\n"));
     168           0 :         msg_reload_nmbd_services(msg, NULL, MSG_SMB_CONF_UPDATED,
     169             :                                  messaging_server_id(msg), NULL);
     170           0 : }
     171             : 
     172          23 : static bool nmbd_setup_sig_hup_handler(struct messaging_context *msg)
     173             : {
     174             :         struct tevent_signal *se;
     175             : 
     176          23 :         se = tevent_add_signal(nmbd_event_context(),
     177             :                                nmbd_event_context(),
     178             :                                SIGHUP, 0,
     179             :                                nmbd_sig_hup_handler,
     180             :                                msg);
     181          23 :         if (!se) {
     182           0 :                 DEBUG(0,("failed to setup SIGHUP handler"));
     183           0 :                 return false;
     184             :         }
     185             : 
     186          23 :         return true;
     187             : }
     188             : 
     189             : /**************************************************************************** **
     190             :  Handle a SHUTDOWN message from smbcontrol.
     191             :  **************************************************************************** */
     192             : 
     193           0 : static void nmbd_terminate(struct messaging_context *msg,
     194             :                            void *private_data,
     195             :                            uint32_t msg_type,
     196             :                            struct server_id server_id,
     197             :                            DATA_BLOB *data)
     198             : {
     199           0 :         terminate(msg);
     200           0 : }
     201             : 
     202             : /**************************************************************************** **
     203             :  Expire old names from the namelist and server list.
     204             :  **************************************************************************** */
     205             : 
     206        5884 : static void expire_names_and_servers(time_t t)
     207             : {
     208             :         static time_t lastrun = 0;
     209             : 
     210        5884 :         if ( !lastrun )
     211          23 :                 lastrun = t;
     212        5884 :         if ( t < (lastrun + 5) )
     213        5442 :                 return;
     214         442 :         lastrun = t;
     215             : 
     216             :         /*
     217             :          * Expire any timed out names on all the broadcast
     218             :          * subnets and those registered with the WINS server.
     219             :          * (nmbd_namelistdb.c)
     220             :          */
     221             : 
     222         442 :         expire_names(t);
     223             : 
     224             :         /*
     225             :          * Go through all the broadcast subnets and for each
     226             :          * workgroup known on that subnet remove any expired
     227             :          * server names. If a workgroup has an empty serverlist
     228             :          * and has itself timed out then remove the workgroup.
     229             :          * (nmbd_workgroupdb.c)
     230             :          */
     231             : 
     232         442 :         expire_workgroups_and_servers(t);
     233             : }
     234             : 
     235             : /************************************************************************** **
     236             :  Reload the list of network interfaces.
     237             :  Doesn't return until a network interface is up.
     238             :  ************************************************************************** */
     239             : 
     240        5887 : static void reload_interfaces(time_t t)
     241             : {
     242             :         static time_t lastt;
     243             :         int n;
     244        5887 :         bool print_waiting_msg = true;
     245             :         struct subnet_record *subrec;
     246             : 
     247        5887 :         if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
     248        5837 :                 return;
     249             :         }
     250             : 
     251          50 :         lastt = t;
     252             : 
     253          50 :         if (!interfaces_changed()) {
     254          50 :                 return;
     255             :         }
     256             : 
     257           0 :   try_again:
     258             : 
     259             :         /* the list of probed interfaces has changed, we may need to add/remove
     260             :            some subnets */
     261           0 :         load_interfaces();
     262             : 
     263             :         /* find any interfaces that need adding */
     264           0 :         for (n=iface_count() - 1; n >= 0; n--) {
     265             :                 char str[INET6_ADDRSTRLEN];
     266           0 :                 const struct interface *iface = get_interface(n);
     267             :                 struct in_addr ip, nmask;
     268             : 
     269           0 :                 if (!iface) {
     270           0 :                         DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
     271           0 :                         continue;
     272             :                 }
     273             : 
     274             :                 /* Ensure we're only dealing with IPv4 here. */
     275           0 :                 if (iface->ip.ss_family != AF_INET) {
     276           0 :                         DEBUG(2,("reload_interfaces: "
     277             :                                 "ignoring non IPv4 interface.\n"));
     278           0 :                         continue;
     279             :                 }
     280             : 
     281           0 :                 ip = ((const struct sockaddr_in *)(const void *)&iface->ip)->sin_addr;
     282           0 :                 nmask = ((const struct sockaddr_in *)(const void *)
     283           0 :                          &iface->netmask)->sin_addr;
     284             : 
     285             :                 /*
     286             :                  * We don't want to add a loopback interface, in case
     287             :                  * someone has added 127.0.0.1 for smbd, nmbd needs to
     288             :                  * ignore it here. JRA.
     289             :                  */
     290             : 
     291           0 :                 if (is_loopback_addr((const struct sockaddr *)(const void *)&iface->ip)) {
     292           0 :                         DEBUG(2,("reload_interfaces: Ignoring loopback "
     293             :                                 "interface %s\n",
     294             :                                 print_sockaddr(str, sizeof(str), &iface->ip) ));
     295           0 :                         continue;
     296             :                 }
     297             : 
     298           0 :                 for (subrec=subnetlist; subrec; subrec=subrec->next) {
     299           0 :                         if (ip_equal_v4(ip, subrec->myip) &&
     300           0 :                             ip_equal_v4(nmask, subrec->mask_ip)) {
     301           0 :                                 break;
     302             :                         }
     303             :                 }
     304             : 
     305           0 :                 if (!subrec) {
     306             :                         /* it wasn't found! add it */
     307           0 :                         DEBUG(2,("Found new interface %s\n",
     308             :                                  print_sockaddr(str,
     309             :                                          sizeof(str), &iface->ip) ));
     310           0 :                         subrec = make_normal_subnet(iface);
     311           0 :                         if (subrec)
     312           0 :                                 register_my_workgroup_one_subnet(subrec);
     313             :                 }
     314             :         }
     315             : 
     316             :         /* find any interfaces that need deleting */
     317           0 :         for (subrec=subnetlist; subrec; subrec=subrec->next) {
     318           0 :                 for (n=iface_count() - 1; n >= 0; n--) {
     319           0 :                         struct interface *iface = get_interface(n);
     320             :                         struct in_addr ip, nmask;
     321           0 :                         if (!iface) {
     322           0 :                                 continue;
     323             :                         }
     324             :                         /* Ensure we're only dealing with IPv4 here. */
     325           0 :                         if (iface->ip.ss_family != AF_INET) {
     326           0 :                                 DEBUG(2,("reload_interfaces: "
     327             :                                         "ignoring non IPv4 interface.\n"));
     328           0 :                                 continue;
     329             :                         }
     330           0 :                         ip = ((struct sockaddr_in *)(void *)
     331           0 :                               &iface->ip)->sin_addr;
     332           0 :                         nmask = ((struct sockaddr_in *)(void *)
     333           0 :                                  &iface->netmask)->sin_addr;
     334           0 :                         if (ip_equal_v4(ip, subrec->myip) &&
     335           0 :                             ip_equal_v4(nmask, subrec->mask_ip)) {
     336           0 :                                 break;
     337             :                         }
     338             :                 }
     339           0 :                 if (n == -1) {
     340             :                         /* oops, an interface has disappeared. This is
     341             :                          tricky, we don't dare actually free the
     342             :                          interface as it could be being used, so
     343             :                          instead we just wear the memory leak and
     344             :                          remove it from the list of interfaces without
     345             :                          freeing it */
     346           0 :                         DEBUG(2,("Deleting dead interface %s\n",
     347             :                                  inet_ntoa(subrec->myip)));
     348           0 :                         close_subnet(subrec);
     349             :                 }
     350             :         }
     351             : 
     352           0 :         rescan_listen_set = True;
     353             : 
     354             :         /* We need to wait if there are no subnets... */
     355           0 :         if (FIRST_SUBNET == NULL) {
     356             :                 void (*saved_handler)(int);
     357             : 
     358           0 :                 if (print_waiting_msg) {
     359           0 :                         DEBUG(0,("reload_interfaces: "
     360             :                                 "No subnets to listen to. Waiting..\n"));
     361           0 :                         print_waiting_msg = false;
     362             :                 }
     363             : 
     364             :                 /*
     365             :                  * Whilst we're waiting for an interface, allow SIGTERM to
     366             :                  * cause us to exit.
     367             :                  */
     368           0 :                 saved_handler = CatchSignal(SIGTERM, SIG_DFL);
     369             : 
     370             :                 /* We only count IPv4, non-loopback interfaces here. */
     371           0 :                 while (iface_count_v4_nl() == 0) {
     372           0 :                         usleep(NMBD_WAIT_INTERFACES_TIME_USEC);
     373           0 :                         load_interfaces();
     374             :                 }
     375             : 
     376           0 :                 CatchSignal(SIGTERM, saved_handler);
     377             : 
     378             :                 /*
     379             :                  * We got an interface, go back to blocking term.
     380             :                  */
     381             : 
     382           0 :                 goto try_again;
     383             :         }
     384             : }
     385             : 
     386             : /**************************************************************************** **
     387             :  Reload the services file.
     388             :  **************************************************************************** */
     389             : 
     390          72 : static bool reload_nmbd_services(bool test)
     391             : {
     392          48 :         const struct loadparm_substitution *lp_sub =
     393          24 :                 loadparm_s3_global_substitution();
     394             :         bool ret;
     395             : 
     396          72 :         set_remote_machine_name("nmbd", False);
     397             : 
     398          72 :         if ( lp_loaded() ) {
     399          72 :                 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
     400          72 :                 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
     401           0 :                         set_dyn_CONFIGFILE(fname);
     402           0 :                         test = False;
     403             :                 }
     404          72 :                 TALLOC_FREE(fname);
     405             :         }
     406             : 
     407          72 :         if ( test && !lp_file_list_changed() )
     408          49 :                 return(True);
     409             : 
     410          23 :         ret = lp_load_global(get_dyn_CONFIGFILE());
     411             : 
     412             :         /* perhaps the config filename is now set */
     413          23 :         if ( !test ) {
     414          23 :                 DEBUG( 3, ( "services not loaded\n" ) );
     415          23 :                 reload_nmbd_services( True );
     416             :         }
     417             : 
     418          23 :         reopen_logs();
     419             : 
     420          23 :         return(ret);
     421             : }
     422             : 
     423             : /**************************************************************************** **
     424             :  * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
     425             :  **************************************************************************** */
     426             : 
     427           3 : static void msg_reload_nmbd_services(struct messaging_context *msg,
     428             :                                      void *private_data,
     429             :                                      uint32_t msg_type,
     430             :                                      struct server_id server_id,
     431             :                                      DATA_BLOB *data)
     432             : {
     433           3 :         write_browse_list( 0, True );
     434           3 :         dump_all_namelists();
     435           3 :         reload_nmbd_services( True );
     436           3 :         reopen_logs();
     437           3 :         reload_interfaces(0);
     438           3 :         nmbd_init_my_netbios_names();
     439           3 : }
     440             : 
     441           2 : static void msg_nmbd_send_packet(struct messaging_context *msg,
     442             :                                  void *private_data,
     443             :                                  uint32_t msg_type,
     444             :                                  struct server_id src,
     445             :                                  DATA_BLOB *data)
     446             : {
     447           2 :         struct packet_struct *p = (struct packet_struct *)data->data;
     448             :         struct subnet_record *subrec;
     449             :         struct sockaddr_storage ss;
     450             :         const struct sockaddr_storage *pss;
     451             :         const struct in_addr *local_ip;
     452             : 
     453           2 :         DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
     454             : 
     455           2 :         if (data->length != sizeof(struct packet_struct)) {
     456           0 :                 DEBUG(2, ("Discarding invalid packet length from %u\n",
     457             :                           (unsigned int)procid_to_pid(&src)));
     458           0 :                 return;
     459             :         }
     460             : 
     461           4 :         if ((p->packet_type != NMB_PACKET) &&
     462           2 :             (p->packet_type != DGRAM_PACKET)) {
     463           0 :                 DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
     464             :                           (unsigned int)procid_to_pid(&src), p->packet_type));
     465           0 :                 return;
     466             :         }
     467             : 
     468           2 :         in_addr_to_sockaddr_storage(&ss, p->ip);
     469           2 :         pss = iface_ip((struct sockaddr *)(void *)&ss);
     470             : 
     471           2 :         if (pss == NULL) {
     472           0 :                 DEBUG(2, ("Could not find ip for packet from %u\n",
     473             :                           (unsigned int)procid_to_pid(&src)));
     474           0 :                 return;
     475             :         }
     476             : 
     477           2 :         local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
     478           2 :         subrec = FIRST_SUBNET;
     479             : 
     480           2 :         p->recv_fd = -1;
     481           4 :         p->send_fd = (p->packet_type == NMB_PACKET) ?
     482           2 :                 subrec->nmb_sock : subrec->dgram_sock;
     483             : 
     484           4 :         for (subrec = FIRST_SUBNET; subrec != NULL;
     485           0 :              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     486           2 :                 if (ip_equal_v4(*local_ip, subrec->myip)) {
     487           4 :                         p->send_fd = (p->packet_type == NMB_PACKET) ?
     488           2 :                                 subrec->nmb_sock : subrec->dgram_sock;
     489           2 :                         break;
     490             :                 }
     491             :         }
     492             : 
     493           2 :         if (p->packet_type == DGRAM_PACKET) {
     494           2 :                 p->port = 138;
     495           2 :                 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
     496           2 :                 p->packet.dgram.header.source_port = 138;
     497             :         }
     498             : 
     499           2 :         send_packet(p);
     500             : }
     501             : 
     502             : /**************************************************************************** **
     503             :  The main select loop.
     504             :  **************************************************************************** */
     505             : 
     506        3652 : static void process(struct messaging_context *msg)
     507             : {
     508             :         bool run_election;
     509             : 
     510        5884 :         while( True ) {
     511        5907 :                 time_t t = time(NULL);
     512        5907 :                 TALLOC_CTX *frame = talloc_stackframe();
     513             : 
     514             :                 /*
     515             :                  * Check all broadcast subnets to see if
     516             :                  * we need to run an election on any of them.
     517             :                  * (nmbd_elections.c)
     518             :                  */
     519             : 
     520        5907 :                 run_election = check_elections();
     521             : 
     522             :                 /*
     523             :                  * Read incoming UDP packets.
     524             :                  * (nmbd_packets.c)
     525             :                  */
     526             : 
     527        5907 :                 if (listen_for_packets(msg, run_election)) {
     528           0 :                         TALLOC_FREE(frame);
     529           0 :                         return;
     530             :                 }
     531             : 
     532             :                 /*
     533             :                  * Process all incoming packets
     534             :                  * read above. This calls the success and
     535             :                  * failure functions registered when response
     536             :                  * packets arrive, and also deals with request
     537             :                  * packets from other sources.
     538             :                  * (nmbd_packets.c)
     539             :                  */
     540             : 
     541        5884 :                 run_packet_queue();
     542             : 
     543             :                 /*
     544             :                  * Run any elections - initiate becoming
     545             :                  * a local master browser if we have won.
     546             :                  * (nmbd_elections.c)
     547             :                  */
     548             : 
     549        5884 :                 run_elections(t);
     550             : 
     551             :                 /*
     552             :                  * Send out any broadcast announcements
     553             :                  * of our server names. This also announces
     554             :                  * the workgroup name if we are a local
     555             :                  * master browser.
     556             :                  * (nmbd_sendannounce.c)
     557             :                  */
     558             : 
     559        5884 :                 announce_my_server_names(t);
     560             : 
     561             :                 /*
     562             :                  * Send out any LanMan broadcast announcements
     563             :                  * of our server names.
     564             :                  * (nmbd_sendannounce.c)
     565             :                  */
     566             : 
     567        5884 :                 announce_my_lm_server_names(t);
     568             : 
     569             :                 /*
     570             :                  * If we are a local master browser, periodically
     571             :                  * announce ourselves to the domain master browser.
     572             :                  * This also deals with syncronising the domain master
     573             :                  * browser server lists with ourselves as a local
     574             :                  * master browser.
     575             :                  * (nmbd_sendannounce.c)
     576             :                  */
     577             : 
     578        5884 :                 announce_myself_to_domain_master_browser(t);
     579             : 
     580             :                 /*
     581             :                  * Fullfill any remote announce requests.
     582             :                  * (nmbd_sendannounce.c)
     583             :                  */
     584             : 
     585        5884 :                 announce_remote(t);
     586             : 
     587             :                 /*
     588             :                  * Fullfill any remote browse sync announce requests.
     589             :                  * (nmbd_sendannounce.c)
     590             :                  */
     591             : 
     592        5884 :                 browse_sync_remote(t);
     593             : 
     594             :                 /*
     595             :                  * Scan the broadcast subnets, and WINS client
     596             :                  * namelists and refresh any that need refreshing.
     597             :                  * (nmbd_mynames.c)
     598             :                  */
     599             : 
     600        5884 :                 refresh_my_names(t);
     601             : 
     602             :                 /*
     603             :                  * Scan the subnet namelists and server lists and
     604             :                  * expire thos that have timed out.
     605             :                  * (nmbd.c)
     606             :                  */
     607             : 
     608        5884 :                 expire_names_and_servers(t);
     609             : 
     610             :                 /*
     611             :                  * Write out a snapshot of our current browse list into
     612             :                  * the browse.dat file. This is used by smbd to service
     613             :                  * incoming NetServerEnum calls - used to synchronise
     614             :                  * browse lists over subnets.
     615             :                  * (nmbd_serverlistdb.c)
     616             :                  */
     617             : 
     618        5884 :                 write_browse_list(t, False);
     619             : 
     620             :                 /*
     621             :                  * If we are a domain master browser, we have a list of
     622             :                  * local master browsers we should synchronise browse
     623             :                  * lists with (these are added by an incoming local
     624             :                  * master browser announcement packet). Expire any of
     625             :                  * these that are no longer current, and pull the server
     626             :                  * lists from each of these known local master browsers.
     627             :                  * (nmbd_browsesync.c)
     628             :                  */
     629             : 
     630        5884 :                 dmb_expire_and_sync_browser_lists(t);
     631             : 
     632             :                 /*
     633             :                  * Check that there is a local master browser for our
     634             :                  * workgroup for all our broadcast subnets. If one
     635             :                  * is not found, start an election (which we ourselves
     636             :                  * may or may not participate in, depending on the
     637             :                  * setting of the 'local master' parameter.
     638             :                  * (nmbd_elections.c)
     639             :                  */
     640             : 
     641        5884 :                 check_master_browser_exists(t);
     642             : 
     643             :                 /*
     644             :                  * If we are configured as a logon server, attempt to
     645             :                  * register the special NetBIOS names to become such
     646             :                  * (WORKGROUP<1c> name) on all broadcast subnets and
     647             :                  * with the WINS server (if used). If we are configured
     648             :                  * to become a domain master browser, attempt to register
     649             :                  * the special NetBIOS name (WORKGROUP<1b> name) to
     650             :                  * become such.
     651             :                  * (nmbd_become_dmb.c)
     652             :                  */
     653             : 
     654        5884 :                 add_domain_names(t);
     655             : 
     656             :                 /*
     657             :                  * If we are a WINS server, do any timer dependent
     658             :                  * processing required.
     659             :                  * (nmbd_winsserver.c)
     660             :                  */
     661             : 
     662        5884 :                 initiate_wins_processing(t);
     663             : 
     664             :                 /*
     665             :                  * If we are a domain master browser, attempt to contact the
     666             :                  * WINS server to get a list of all known WORKGROUPS/DOMAINS.
     667             :                  * This will only work to a Samba WINS server.
     668             :                  * (nmbd_browsesync.c)
     669             :                  */
     670             : 
     671        5884 :                 if (lp_enhanced_browsing())
     672        5884 :                         collect_all_workgroup_names_from_wins_server(t);
     673             : 
     674             :                 /*
     675             :                  * Go through the response record queue and time out or re-transmit
     676             :                  * and expired entries.
     677             :                  * (nmbd_packets.c)
     678             :                  */
     679             : 
     680        5884 :                 retransmit_or_expire_response_records(t);
     681             : 
     682             :                 /*
     683             :                  * check to see if any remote browse sync child processes have completed
     684             :                  */
     685             : 
     686        5884 :                 sync_check_completion();
     687             : 
     688             :                 /*
     689             :                  * regularly sync with any other DMBs we know about 
     690             :                  */
     691             : 
     692        5884 :                 if (lp_enhanced_browsing())
     693        5884 :                         sync_all_dmbs(t);
     694             : 
     695             :                 /* check for new network interfaces */
     696             : 
     697        5884 :                 reload_interfaces(t);
     698             : 
     699             :                 /* free up temp memory */
     700        5884 :                 TALLOC_FREE(frame);
     701             :         }
     702             : }
     703             : 
     704             : /**************************************************************************** **
     705             :  Open the socket communication.
     706             :  **************************************************************************** */
     707             : 
     708          23 : static bool open_sockets(bool isdaemon, int port)
     709             : {
     710             :         struct sockaddr_storage ss;
     711          23 :         const char *sock_addr = lp_nbt_client_socket_address();
     712             : 
     713             :         /*
     714             :          * The sockets opened here will be used to receive broadcast
     715             :          * packets *only*. Interface specific sockets are opened in
     716             :          * make_subnet() in namedbsubnet.c. Thus we bind to the
     717             :          * address "0.0.0.0". The parameter 'socket address' is
     718             :          * now deprecated.
     719             :          */
     720             : 
     721          23 :         if (!interpret_string_addr(&ss, sock_addr,
     722             :                                 AI_NUMERICHOST|AI_PASSIVE)) {
     723           0 :                 DEBUG(0,("open_sockets: unable to get socket address "
     724             :                         "from string %s", sock_addr));
     725           0 :                 return false;
     726             :         }
     727          23 :         if (ss.ss_family != AF_INET) {
     728           0 :                 DEBUG(0,("open_sockets: unable to use IPv6 socket"
     729             :                         "%s in nmbd\n",
     730             :                         sock_addr));
     731           0 :                 return false;
     732             :         }
     733             : 
     734          23 :         if (isdaemon) {
     735          23 :                 ClientNMB = open_socket_in(SOCK_DGRAM, &ss, port, true);
     736             :         } else {
     737           0 :                 ClientNMB = 0;
     738             :         }
     739             : 
     740          23 :         if (ClientNMB < 0) {
     741           0 :                 return false;
     742             :         }
     743             : 
     744          23 :         ClientDGRAM = open_socket_in(SOCK_DGRAM, &ss, DGRAM_PORT, true);
     745             : 
     746          23 :         if (ClientDGRAM < 0) {
     747           0 :                 if (ClientNMB != 0) {
     748           0 :                         close(ClientNMB);
     749             :                 }
     750           0 :                 return false;
     751             :         }
     752             : 
     753             :         /* we are never interested in SIGPIPE */
     754          23 :         BlockSignals(True,SIGPIPE);
     755             : 
     756          23 :         set_socket_options( ClientNMB,   "SO_BROADCAST" );
     757          23 :         set_socket_options( ClientDGRAM, "SO_BROADCAST" );
     758             : 
     759             :         /* Ensure we're non-blocking. */
     760          23 :         set_blocking( ClientNMB, False);
     761          23 :         set_blocking( ClientDGRAM, False);
     762             : 
     763          23 :         DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
     764          23 :         return( True );
     765             : }
     766             : 
     767             : /**************************************************************************** **
     768             :  main program
     769             :  **************************************************************************** */
     770             : 
     771          23 :  int main(int argc, const char *argv[])
     772             : {
     773          23 :         struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
     774          23 :         bool log_stdout = false;
     775             :         poptContext pc;
     776          23 :         char *p_lmhosts = NULL;
     777             :         int opt;
     778             :         struct messaging_context *msg;
     779          92 :         struct poptOption long_options[] = {
     780             :                 POPT_AUTOHELP
     781             :                 {
     782             :                         .longName   = "hosts",
     783             :                         .shortName  = 'H',
     784             :                         .argInfo    = POPT_ARG_STRING,
     785             :                         .arg        = &p_lmhosts,
     786             :                         .val        = 0,
     787             :                         .descrip    = "Load a netbios hosts file",
     788             :                 },
     789             :                 {
     790             :                         .longName   = "port",
     791             :                         .shortName  = 'p',
     792             :                         .argInfo    = POPT_ARG_INT,
     793             :                         .arg        = &global_nmb_port,
     794             :                         .val        = 0,
     795             :                         .descrip    = "Listen on the specified port",
     796             :                 },
     797          23 :                 POPT_COMMON_SAMBA
     798          23 :                 POPT_COMMON_DAEMON
     799          23 :                 POPT_COMMON_VERSION
     800             :                 POPT_TABLEEND
     801             :         };
     802          15 :         const struct loadparm_substitution *lp_sub =
     803           8 :                 loadparm_s3_global_substitution();
     804             :         TALLOC_CTX *frame;
     805             :         NTSTATUS status;
     806             :         bool ok;
     807             : 
     808             :         /*
     809             :          * Do this before any other talloc operation
     810             :          */
     811          23 :         talloc_enable_null_tracking();
     812          23 :         frame = talloc_stackframe();
     813             : 
     814             :         /*
     815             :          * We want total control over the permissions on created files,
     816             :          * so set our umask to 0.
     817             :          */
     818          23 :         umask(0);
     819             : 
     820          23 :         smb_init_locale();
     821             : 
     822          23 :         ok = samba_cmdline_init(frame,
     823             :                                 SAMBA_CMDLINE_CONFIG_SERVER,
     824             :                                 true /* require_smbconf */);
     825          23 :         if (!ok) {
     826           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
     827           0 :                 TALLOC_FREE(frame);
     828           0 :                 exit(ENOMEM);
     829             :         }
     830             : 
     831          23 :         cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
     832             : 
     833          23 :         global_nmb_port = NMB_PORT;
     834             : 
     835          23 :         pc = samba_popt_get_context(getprogname(),
     836             :                                     argc,
     837             :                                     argv,
     838             :                                     long_options,
     839             :                                     0);
     840          23 :         if (pc == NULL) {
     841           0 :                 DBG_ERR("Failed to setup popt context!\n");
     842           0 :                 TALLOC_FREE(frame);
     843           0 :                 exit(1);
     844             :         }
     845             : 
     846          23 :         while ((opt = poptGetNextOpt(pc)) != -1) {
     847           0 :                 d_fprintf(stderr, "\nInvalid options\n\n");
     848           0 :                 poptPrintUsage(pc, stderr, 0);
     849           0 :                 exit(1);
     850             :         };
     851          23 :         poptFreeContext(pc);
     852             : 
     853          23 :         global_in_nmbd = true;
     854             : 
     855          23 :         StartupTime = time(NULL);
     856             : 
     857          23 :         sys_srandom(time(NULL) ^ getpid());
     858             : 
     859          23 :         if (is_default_dyn_LOGFILEBASE()) {
     860           0 :                 char *lfile = NULL;
     861           0 :                 if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
     862           0 :                         exit(1);
     863             :                 }
     864           0 :                 lp_set_logfile(lfile);
     865           0 :                 SAFE_FREE(lfile);
     866             :         }
     867             : 
     868          23 :         dump_core_setup("nmbd", lp_logfile(talloc_tos(), lp_sub));
     869             : 
     870             :         /* POSIX demands that signals are inherited. If the invoking process has
     871             :          * these signals masked, we will have problems, as we won't receive them. */
     872          23 :         BlockSignals(False, SIGHUP);
     873          23 :         BlockSignals(False, SIGUSR1);
     874          23 :         BlockSignals(False, SIGTERM);
     875             : 
     876             : #if defined(SIGFPE)
     877             :         /* we are never interested in SIGFPE */
     878          23 :         BlockSignals(True,SIGFPE);
     879             : #endif
     880             : 
     881             :         /* We no longer use USR2... */
     882             : #if defined(SIGUSR2)
     883          23 :         BlockSignals(True, SIGUSR2);
     884             : #endif
     885             : 
     886             :         /* Ignore children - no zombies. */
     887          23 :         CatchChild();
     888             : 
     889          23 :         log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
     890          23 :         if ( cmdline_daemon_cfg->interactive ) {
     891           0 :                 log_stdout = True;
     892             :         }
     893             : 
     894          23 :         if ( log_stdout && cmdline_daemon_cfg->fork ) {
     895           0 :                 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
     896           0 :                 exit(1);
     897             :         }
     898             : 
     899          23 :         reopen_logs();
     900             : 
     901          23 :         DEBUG(0,("nmbd version %s started.\n", samba_version_string()));
     902          23 :         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
     903             : 
     904          23 :         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
     905           0 :             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
     906             :                 /* TODO: when we have a merged set of defaults for
     907             :                  * loadparm, we could possibly check if the internal
     908             :                  * nbt server is in the list, and allow a startup if disabled */
     909           0 :                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running nmbd standalone. \n"));
     910           0 :                 DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal nbt server\n"));
     911           0 :                 exit(1);
     912             :         }
     913             : 
     914          23 :         if (!cluster_probe_ok()) {
     915           0 :                 exit(1);
     916             :         }
     917             : 
     918          23 :         msg = messaging_init(NULL, global_event_context());
     919          23 :         if (msg == NULL) {
     920           0 :                 DBG_ERR("Failed to init messaging context!\n");
     921           0 :                 return 1;
     922             :         }
     923             : 
     924          23 :         if ( !reload_nmbd_services(False) )
     925           0 :                 return(-1);
     926             : 
     927          23 :         if (!nmbd_init_my_netbios_names()) {
     928           0 :                 return -1;
     929             :         }
     930             : 
     931          23 :         reload_nmbd_services( True );
     932             : 
     933          23 :         if (strequal(lp_workgroup(),"*")) {
     934           0 :                 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
     935           0 :                 exit(1);
     936             :         }
     937             : 
     938          23 :         set_samba_nb_type();
     939             : 
     940          23 :         if (!cmdline_daemon_cfg->daemon && !is_a_socket(0)) {
     941          23 :                 DEBUG(3, ("standard input is not a socket, assuming -D option\n"));
     942          23 :                 cmdline_daemon_cfg->daemon = true;
     943             :         }
     944             : 
     945          23 :         if (cmdline_daemon_cfg->daemon && !cmdline_daemon_cfg->interactive) {
     946          23 :                 DEBUG(3, ("Becoming a daemon.\n"));
     947          38 :                 become_daemon(cmdline_daemon_cfg->fork,
     948          23 :                               cmdline_daemon_cfg->no_process_group,
     949             :                               log_stdout);
     950           0 :         } else if (!cmdline_daemon_cfg->interactive) {
     951           0 :                 daemon_status("nmbd", "Starting process...");
     952             :         }
     953             : 
     954             : #ifdef HAVE_SETPGID
     955             :         /*
     956             :          * If we're interactive we want to set our own process group for 
     957             :          * signal management.
     958             :          */
     959          23 :         if (cmdline_daemon_cfg->interactive &&
     960           0 :             !cmdline_daemon_cfg->no_process_group)
     961             :         {
     962           0 :                 setpgid( (pid_t)0, (pid_t)0 );
     963             :         }
     964             : #endif
     965             : 
     966             : #ifndef SYNC_DNS
     967             :         /* Setup the async dns. We do it here so it doesn't have all the other
     968             :                 stuff initialised and thus chewing memory and sockets */
     969          23 :         if(lp_we_are_a_wins_server() && lp_wins_dns_proxy()) {
     970           0 :                 start_async_dns(msg);
     971             :         }
     972             : #endif
     973             : 
     974          23 :         ok = directory_create_or_exist(lp_lock_directory(), 0755);
     975          23 :         if (!ok) {
     976           0 :                 exit_daemon("Failed to create directory for lock files, check 'lock directory'", errno);
     977             :         }
     978             : 
     979          23 :         ok = directory_create_or_exist(lp_pid_directory(), 0755);
     980          23 :         if (!ok) {
     981           0 :                 exit_daemon("Failed to create directory for pid files, check 'pid directory'", errno);
     982             :         }
     983             : 
     984          23 :         pidfile_create(lp_pid_directory(), "nmbd");
     985             : 
     986          23 :         status = reinit_after_fork(msg, nmbd_event_context(), false, NULL);
     987             : 
     988          23 :         if (!NT_STATUS_IS_OK(status)) {
     989           0 :                 exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status));
     990             :         }
     991             : 
     992             :         /*
     993             :          * Do not initialize the parent-child-pipe before becoming
     994             :          * a daemon: this is used to detect a died parent in the child
     995             :          * process.
     996             :          */
     997          23 :         status = init_before_fork();
     998          23 :         if (!NT_STATUS_IS_OK(status)) {
     999           0 :                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
    1000             :         }
    1001             : 
    1002          23 :         if (!nmbd_setup_sig_term_handler(msg))
    1003           0 :                 exit_daemon("NMBD failed to setup signal handler", EINVAL);
    1004          23 :         if (!nmbd_setup_stdin_handler(msg, !cmdline_daemon_cfg->fork))
    1005           0 :                 exit_daemon("NMBD failed to setup stdin handler", EINVAL);
    1006          23 :         if (!nmbd_setup_sig_hup_handler(msg))
    1007           0 :                 exit_daemon("NMBD failed to setup SIGHUP handler", EINVAL);
    1008             : 
    1009          23 :         if (!messaging_parent_dgm_cleanup_init(msg)) {
    1010           0 :                 exit(1);
    1011             :         }
    1012             : 
    1013          23 :         messaging_register(msg, NULL, MSG_FORCE_ELECTION,
    1014             :                            nmbd_message_election);
    1015             : #if 0
    1016             :         /* Until winsrepl is done. */
    1017             :         messaging_register(msg, NULL, MSG_WINS_NEW_ENTRY,
    1018             :                            nmbd_wins_new_entry);
    1019             : #endif
    1020          23 :         messaging_register(msg, NULL, MSG_SHUTDOWN,
    1021             :                            nmbd_terminate);
    1022          23 :         messaging_register(msg, NULL, MSG_SMB_CONF_UPDATED,
    1023             :                            msg_reload_nmbd_services);
    1024          23 :         messaging_register(msg, NULL, MSG_SEND_PACKET,
    1025             :                            msg_nmbd_send_packet);
    1026             : 
    1027          23 :         TimeInit();
    1028             : 
    1029          23 :         DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
    1030             : 
    1031          23 :         if ( !open_sockets( cmdline_daemon_cfg->daemon, global_nmb_port ) ) {
    1032           0 :                 kill_async_dns_child();
    1033           0 :                 return 1;
    1034             :         }
    1035             : 
    1036             :         /* Determine all the IP addresses we have. */
    1037          23 :         load_interfaces();
    1038             : 
    1039             :         /* Create an nmbd subnet record for each of the above. */
    1040          23 :         if( False == create_subnets() ) {
    1041           0 :                 kill_async_dns_child();
    1042           0 :                 exit_daemon("NMBD failed when creating subnet lists", EACCES);
    1043             :         }
    1044             : 
    1045             :         /* Load in any static local names. */ 
    1046          23 :         if (p_lmhosts) {
    1047           0 :                 set_dyn_LMHOSTSFILE(p_lmhosts);
    1048             :         }
    1049          23 :         load_lmhosts_file(get_dyn_LMHOSTSFILE());
    1050          23 :         DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));
    1051             : 
    1052             :         /* If we are acting as a WINS server, initialise data structures. */
    1053          23 :         if( !initialise_wins() ) {
    1054           0 :                 kill_async_dns_child();
    1055           0 :                 exit_daemon( "NMBD failed when initialising WINS server.", EACCES);
    1056             :         }
    1057             : 
    1058             :         /* 
    1059             :          * Register nmbd primary workgroup and nmbd names on all
    1060             :          * the broadcast subnets, and on the WINS server (if specified).
    1061             :          * Also initiate the startup of our primary workgroup (start
    1062             :          * elections if we are setup as being able to be a local
    1063             :          * master browser.
    1064             :          */
    1065             : 
    1066          23 :         if( False == register_my_workgroup_and_names() ) {
    1067           0 :                 kill_async_dns_child();
    1068           0 :                 exit_daemon( "NMBD failed when creating my workgroup.", EACCES);
    1069             :         }
    1070             : 
    1071          23 :         if (!initialize_nmbd_proxy_logon()) {
    1072           0 :                 kill_async_dns_child();
    1073           0 :                 exit_daemon( "NMBD failed to setup nmbd_proxy_logon.", EACCES);
    1074             :         }
    1075             : 
    1076          23 :         if (!nmbd_init_packet_server()) {
    1077           0 :                 kill_async_dns_child();
    1078           0 :                 exit_daemon( "NMBD failed to setup packet server.", EACCES);
    1079             :         }
    1080             : 
    1081          23 :         if (!cmdline_daemon_cfg->interactive) {
    1082          23 :                 daemon_ready("nmbd");
    1083             :         }
    1084             : 
    1085          23 :         TALLOC_FREE(frame);
    1086          23 :         process(msg);
    1087             : 
    1088           0 :         kill_async_dns_child();
    1089           0 :         return(0);
    1090             : }

Generated by: LCOV version 1.13