LCOV - code coverage report
Current view: top level - source3/nmbd - nmbd.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 223 370 60.3 %
Date: 2024-01-11 09:59:51 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      122816 : struct tevent_context *nmbd_event_context(void)
      49             : {
      50      122816 :         return global_event_context();
      51             : }
      52             : 
      53             : /**************************************************************************** **
      54             :  Handle a SIGTERM in band.
      55             :  **************************************************************************** */
      56             : 
      57          39 : static void terminate(struct messaging_context *msg)
      58             : {
      59          39 :         DBG_WARNING("Got SIGTERM: going down...\n");
      60             : 
      61             :         /* Write out wins.dat file if samba is a WINS server */
      62          39 :         wins_write_database(0,False);
      63             : 
      64             :         /* Remove all SELF registered names from WINS */
      65          39 :         release_wins_names();
      66             : 
      67             :         /* Announce all server entries as 0 time-to-live, 0 type. */
      68          39 :         announce_my_servers_removed();
      69             : 
      70             :         /* If there was an async dns child - kill it. */
      71          39 :         kill_async_dns_child();
      72             : 
      73          39 :         pidfile_unlink(lp_pid_directory(), "nmbd");
      74             : 
      75          39 :         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          39 : 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          39 :         if (read(0, &c, 1) != 1) {
     101          39 :                 struct messaging_context *msg = talloc_get_type_abort(
     102             :                         private_data, struct messaging_context);
     103             : 
     104          39 :                 DBG_WARNING("EOF on stdin\n");
     105          39 :                 terminate(msg);
     106             :         }
     107           0 : }
     108             : 
     109          39 : static bool nmbd_setup_sig_term_handler(struct messaging_context *msg)
     110             : {
     111             :         struct tevent_signal *se;
     112             : 
     113          39 :         se = tevent_add_signal(nmbd_event_context(),
     114             :                                nmbd_event_context(),
     115             :                                SIGTERM, 0,
     116             :                                nmbd_sig_term_handler,
     117             :                                msg);
     118          39 :         if (!se) {
     119           0 :                 DBG_ERR("failed to setup SIGTERM handler\n");
     120           0 :                 return false;
     121             :         }
     122             : 
     123          39 :         return true;
     124             : }
     125             : 
     126          39 : static bool nmbd_setup_stdin_handler(struct messaging_context *msg, bool foreground)
     127             : {
     128          39 :         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          39 :                 if (fstat(0, &st) != 0) {
     136           0 :                         return false;
     137             :                 }
     138          39 :                 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
     139          39 :                         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          39 :         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 :         DBG_WARNING("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          39 : static bool nmbd_setup_sig_hup_handler(struct messaging_context *msg)
     173             : {
     174             :         struct tevent_signal *se;
     175             : 
     176          39 :         se = tevent_add_signal(nmbd_event_context(),
     177             :                                nmbd_event_context(),
     178             :                                SIGHUP, 0,
     179             :                                nmbd_sig_hup_handler,
     180             :                                msg);
     181          39 :         if (!se) {
     182           0 :                 DBG_ERR("failed to setup SIGHUP handler\n");
     183           0 :                 return false;
     184             :         }
     185             : 
     186          39 :         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       15274 : static void expire_names_and_servers(time_t t)
     207             : {
     208             :         static time_t lastrun = 0;
     209             : 
     210       15274 :         if ( !lastrun )
     211          39 :                 lastrun = t;
     212       15274 :         if ( t < (lastrun + 5) )
     213       12154 :                 return;
     214        3120 :         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        3120 :         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        3120 :         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       15357 : static void reload_interfaces(time_t t)
     241             : {
     242             :         static time_t lastt;
     243             :         int n;
     244       15357 :         bool print_waiting_msg = true;
     245             :         struct subnet_record *subrec;
     246             : 
     247       15357 :         if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
     248       14933 :                 return;
     249             :         }
     250             : 
     251         424 :         lastt = t;
     252             : 
     253         424 :         if (!interfaces_changed()) {
     254         424 :                 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 :                         DBG_WARNING("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 :                         DBG_NOTICE("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 :                         DBG_NOTICE("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 :                         DBG_NOTICE("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 :                                 DBG_NOTICE("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 :                         DBG_NOTICE("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 :                         DBG_WARNING("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         200 : static bool reload_nmbd_services(bool test)
     391             : {
     392             :         const struct loadparm_substitution *lp_sub =
     393         200 :                 loadparm_s3_global_substitution();
     394             :         bool ret;
     395             : 
     396         200 :         set_remote_machine_name("nmbd", False);
     397             : 
     398         200 :         if ( lp_loaded() ) {
     399         200 :                 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
     400         200 :                 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
     401           0 :                         set_dyn_CONFIGFILE(fname);
     402           0 :                         test = False;
     403             :                 }
     404         200 :                 TALLOC_FREE(fname);
     405             :         }
     406             : 
     407         200 :         if ( test && !lp_file_list_changed() )
     408         139 :                 return(True);
     409             : 
     410          61 :         ret = lp_load_global(get_dyn_CONFIGFILE());
     411             : 
     412             :         /* perhaps the config filename is now set */
     413          61 :         if ( !test ) {
     414          39 :                 DBG_NOTICE( "services not loaded\n" );
     415          39 :                 reload_nmbd_services( True );
     416             :         }
     417             : 
     418          61 :         reopen_logs();
     419             : 
     420          61 :         return(ret);
     421             : }
     422             : 
     423             : /**************************************************************************** **
     424             :  * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
     425             :  **************************************************************************** */
     426             : 
     427          83 : 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          83 :         write_browse_list( 0, True );
     434          83 :         dump_all_namelists();
     435          83 :         reload_nmbd_services( True );
     436          83 :         reopen_logs();
     437          83 :         reload_interfaces(0);
     438          83 :         nmbd_init_my_netbios_names();
     439          83 : }
     440             : 
     441          12 : 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          12 :         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          12 :         DBG_DEBUG("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src));
     454             : 
     455          12 :         if (data->length != sizeof(struct packet_struct)) {
     456           0 :                 DBG_WARNING("Discarding invalid packet length from %u\n",
     457             :                           (unsigned int)procid_to_pid(&src));
     458           0 :                 return;
     459             :         }
     460             : 
     461          12 :         if ((p->packet_type != NMB_PACKET) &&
     462          12 :             (p->packet_type != DGRAM_PACKET)) {
     463           0 :                 DBG_WARNING("Discarding invalid packet type from %u: %d\n",
     464             :                           (unsigned int)procid_to_pid(&src), p->packet_type);
     465           0 :                 return;
     466             :         }
     467             : 
     468          12 :         in_addr_to_sockaddr_storage(&ss, p->ip);
     469          12 :         pss = iface_ip((struct sockaddr *)(void *)&ss);
     470             : 
     471          12 :         if (pss == NULL) {
     472           0 :                 DBG_WARNING("Could not find ip for packet from %u\n",
     473             :                           (unsigned int)procid_to_pid(&src));
     474           0 :                 return;
     475             :         }
     476             : 
     477          12 :         local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
     478          12 :         subrec = FIRST_SUBNET;
     479             : 
     480          12 :         p->recv_fd = -1;
     481          24 :         p->send_fd = (p->packet_type == NMB_PACKET) ?
     482          12 :                 subrec->nmb_sock : subrec->dgram_sock;
     483             : 
     484          12 :         for (subrec = FIRST_SUBNET; subrec != NULL;
     485           0 :              subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
     486          12 :                 if (ip_equal_v4(*local_ip, subrec->myip)) {
     487          24 :                         p->send_fd = (p->packet_type == NMB_PACKET) ?
     488          12 :                                 subrec->nmb_sock : subrec->dgram_sock;
     489          12 :                         break;
     490             :                 }
     491             :         }
     492             : 
     493          12 :         if (p->packet_type == DGRAM_PACKET) {
     494          12 :                 p->port = 138;
     495          12 :                 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
     496          12 :                 p->packet.dgram.header.source_port = 138;
     497             :         }
     498             : 
     499          12 :         send_packet(p);
     500             : }
     501             : 
     502             : /**************************************************************************** **
     503             :  The main select loop.
     504             :  **************************************************************************** */
     505             : 
     506       12845 : static void process(struct messaging_context *msg)
     507             : {
     508             :         bool run_election;
     509             : 
     510       15274 :         while( True ) {
     511       15313 :                 time_t t = time(NULL);
     512       15313 :                 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       15313 :                 run_election = check_elections();
     521             : 
     522             :                 /*
     523             :                  * Read incoming UDP packets.
     524             :                  * (nmbd_packets.c)
     525             :                  */
     526             : 
     527       15313 :                 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       15274 :                 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       15274 :                 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       15274 :                 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       15274 :                 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 synchronising the domain master
     573             :                  * browser server lists with ourselves as a local
     574             :                  * master browser.
     575             :                  * (nmbd_sendannounce.c)
     576             :                  */
     577             : 
     578       15274 :                 announce_myself_to_domain_master_browser(t);
     579             : 
     580             :                 /*
     581             :                  * Fulfill any remote announce requests.
     582             :                  * (nmbd_sendannounce.c)
     583             :                  */
     584             : 
     585       15274 :                 announce_remote(t);
     586             : 
     587             :                 /*
     588             :                  * Fulfill any remote browse sync announce requests.
     589             :                  * (nmbd_sendannounce.c)
     590             :                  */
     591             : 
     592       15274 :                 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       15274 :                 refresh_my_names(t);
     601             : 
     602             :                 /*
     603             :                  * Scan the subnet namelists and server lists and
     604             :                  * expire those that have timed out.
     605             :                  * (nmbd.c)
     606             :                  */
     607             : 
     608       15274 :                 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       15274 :                 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       15274 :                 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       15274 :                 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       15274 :                 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       15274 :                 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       15274 :                 if (lp_enhanced_browsing())
     672       15274 :                         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       15274 :                 retransmit_or_expire_response_records(t);
     681             : 
     682             :                 /*
     683             :                  * check to see if any remote browse sync child processes have completed
     684             :                  */
     685             : 
     686       15274 :                 sync_check_completion();
     687             : 
     688             :                 /*
     689             :                  * regularly sync with any other DMBs we know about
     690             :                  */
     691             : 
     692       15274 :                 if (lp_enhanced_browsing())
     693       15274 :                         sync_all_dmbs(t);
     694             : 
     695             :                 /* check for new network interfaces */
     696             : 
     697       15274 :                 reload_interfaces(t);
     698             : 
     699             :                 /* free up temp memory */
     700       15274 :                 TALLOC_FREE(frame);
     701             :         }
     702             : }
     703             : 
     704             : /**************************************************************************** **
     705             :  Open the socket communication.
     706             :  **************************************************************************** */
     707             : 
     708          39 : static bool open_sockets(bool isdaemon, int port)
     709             : {
     710             :         struct sockaddr_storage ss;
     711          39 :         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          39 :         if (!interpret_string_addr(&ss, sock_addr,
     722             :                                 AI_NUMERICHOST|AI_PASSIVE)) {
     723           0 :                 DBG_ERR("open_sockets: unable to get socket address "
     724             :                         "from string %s\n", sock_addr);
     725           0 :                 return false;
     726             :         }
     727          39 :         if (ss.ss_family != AF_INET) {
     728           0 :                 DBG_ERR("open_sockets: unable to use IPv6 socket"
     729             :                         "%s in nmbd\n",
     730             :                         sock_addr);
     731           0 :                 return false;
     732             :         }
     733             : 
     734          39 :         if (isdaemon) {
     735          39 :                 ClientNMB = open_socket_in(SOCK_DGRAM, &ss, port, true);
     736             :         } else {
     737           0 :                 ClientNMB = 0;
     738             :         }
     739             : 
     740          39 :         if (ClientNMB < 0) {
     741           0 :                 return false;
     742             :         }
     743             : 
     744          39 :         ClientDGRAM = open_socket_in(SOCK_DGRAM, &ss, DGRAM_PORT, true);
     745             : 
     746          39 :         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          39 :         BlockSignals(True,SIGPIPE);
     755             : 
     756          39 :         set_socket_options( ClientNMB,   "SO_BROADCAST" );
     757          39 :         set_socket_options( ClientDGRAM, "SO_BROADCAST" );
     758             : 
     759             :         /* Ensure we're non-blocking. */
     760          39 :         set_blocking( ClientNMB, False);
     761          39 :         set_blocking( ClientDGRAM, False);
     762             : 
     763          39 :         DBG_INFO( "open_sockets: Broadcast sockets opened.\n" );
     764          39 :         return( True );
     765             : }
     766             : 
     767             : /**************************************************************************** **
     768             :  main program
     769             :  **************************************************************************** */
     770             : 
     771          39 :  int main(int argc, const char *argv[])
     772             : {
     773          39 :         struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
     774          39 :         bool log_stdout = false;
     775             :         poptContext pc;
     776          39 :         char *p_lmhosts = NULL;
     777             :         int opt;
     778             :         struct messaging_context *msg;
     779         156 :         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          39 :                 POPT_COMMON_SAMBA
     798          39 :                 POPT_COMMON_DAEMON
     799          39 :                 POPT_COMMON_VERSION
     800             :                 POPT_TABLEEND
     801             :         };
     802             :         const struct loadparm_substitution *lp_sub =
     803          39 :                 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          39 :         talloc_enable_null_tracking();
     812          39 :         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          39 :         umask(0);
     819             : 
     820          39 :         smb_init_locale();
     821             : 
     822          39 :         ok = samba_cmdline_init(frame,
     823             :                                 SAMBA_CMDLINE_CONFIG_SERVER,
     824             :                                 true /* require_smbconf */);
     825          39 :         if (!ok) {
     826           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
     827           0 :                 TALLOC_FREE(frame);
     828           0 :                 exit(ENOMEM);
     829             :         }
     830             : 
     831          39 :         cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
     832             : 
     833          39 :         global_nmb_port = NMB_PORT;
     834             : 
     835          39 :         pc = samba_popt_get_context(getprogname(),
     836             :                                     argc,
     837             :                                     argv,
     838             :                                     long_options,
     839             :                                     0);
     840          39 :         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          39 :         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          39 :         poptFreeContext(pc);
     852             : 
     853          39 :         global_in_nmbd = true;
     854             : 
     855          39 :         StartupTime = time(NULL);
     856             : 
     857          39 :         sys_srandom(time(NULL) ^ getpid());
     858             : 
     859          39 :         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          39 :         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          39 :         BlockSignals(False, SIGHUP);
     873          39 :         BlockSignals(False, SIGUSR1);
     874          39 :         BlockSignals(False, SIGTERM);
     875             : 
     876             : #if defined(SIGFPE)
     877             :         /* we are never interested in SIGFPE */
     878          39 :         BlockSignals(True,SIGFPE);
     879             : #endif
     880             : 
     881             :         /* We no longer use USR2... */
     882             : #if defined(SIGUSR2)
     883          39 :         BlockSignals(True, SIGUSR2);
     884             : #endif
     885             : 
     886             :         /* Ignore children - no zombies. */
     887          39 :         CatchChild();
     888             : 
     889          39 :         log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
     890          39 :         if ( cmdline_daemon_cfg->interactive ) {
     891           0 :                 log_stdout = True;
     892             :         }
     893             : 
     894          39 :         if ( log_stdout && cmdline_daemon_cfg->fork ) {
     895           0 :                 DBG_ERR("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n");
     896           0 :                 exit(1);
     897             :         }
     898             : 
     899          39 :         reopen_logs();
     900             : 
     901          39 :         DBG_STARTUP_NOTICE("nmbd version %s started.\n%s\n",
     902             :                            samba_version_string(),
     903             :                            samba_copyright_string());
     904             : 
     905          39 :         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
     906           0 :             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
     907             :                 /* TODO: when we have a merged set of defaults for
     908             :                  * loadparm, we could possibly check if the internal
     909             :                  * nbt server is in the list, and allow a startup if disabled */
     910           0 :                 DBG_ERR("server role = 'active directory domain controller' not compatible with running nmbd standalone.\n"
     911             :                         "You should start 'samba' instead, and it will control starting the internal nbt server\n");
     912           0 :                 exit(1);
     913             :         }
     914             : 
     915          39 :         if (!cluster_probe_ok()) {
     916           0 :                 exit(1);
     917             :         }
     918             : 
     919          39 :         msg = messaging_init(NULL, global_event_context());
     920          39 :         if (msg == NULL) {
     921           0 :                 DBG_ERR("Failed to init messaging context!\n");
     922           0 :                 return 1;
     923             :         }
     924             : 
     925          39 :         if ( !reload_nmbd_services(False) )
     926           0 :                 return(-1);
     927             : 
     928          39 :         if (!nmbd_init_my_netbios_names()) {
     929           0 :                 return -1;
     930             :         }
     931             : 
     932          39 :         reload_nmbd_services( True );
     933             : 
     934          39 :         if (strequal(lp_workgroup(),"*")) {
     935           0 :                 DBG_ERR("ERROR: a workgroup name of * is no longer supported\n");
     936           0 :                 exit(1);
     937             :         }
     938             : 
     939          39 :         set_samba_nb_type();
     940             : 
     941          39 :         if (!cmdline_daemon_cfg->daemon && !is_a_socket(0)) {
     942          39 :                 DBG_NOTICE("standard input is not a socket, assuming -D option\n");
     943          39 :                 cmdline_daemon_cfg->daemon = true;
     944             :         }
     945             : 
     946          39 :         if (cmdline_daemon_cfg->daemon && !cmdline_daemon_cfg->interactive) {
     947          39 :                 DBG_NOTICE("Becoming a daemon.\n");
     948          39 :                 become_daemon(cmdline_daemon_cfg->fork,
     949          39 :                               cmdline_daemon_cfg->no_process_group,
     950             :                               log_stdout);
     951           0 :         } else if (!cmdline_daemon_cfg->interactive) {
     952           0 :                 daemon_status("nmbd", "Starting process...");
     953             :         }
     954             : 
     955             : #ifdef HAVE_SETPGID
     956             :         /*
     957             :          * If we're interactive we want to set our own process group for
     958             :          * signal management.
     959             :          */
     960          39 :         if (cmdline_daemon_cfg->interactive &&
     961           0 :             !cmdline_daemon_cfg->no_process_group)
     962             :         {
     963           0 :                 setpgid( (pid_t)0, (pid_t)0 );
     964             :         }
     965             : #endif
     966             : 
     967             : #ifndef SYNC_DNS
     968             :         /* Setup the async dns. We do it here so it doesn't have all the other
     969             :                 stuff initialised and thus chewing memory and sockets */
     970          39 :         if(lp_we_are_a_wins_server() && lp_wins_dns_proxy()) {
     971           0 :                 start_async_dns(msg);
     972             :         }
     973             : #endif
     974             : 
     975          39 :         ok = directory_create_or_exist(lp_lock_directory(), 0755);
     976          39 :         if (!ok) {
     977           0 :                 exit_daemon("Failed to create directory for lock files, check 'lock directory'", errno);
     978             :         }
     979             : 
     980          39 :         ok = directory_create_or_exist(lp_pid_directory(), 0755);
     981          39 :         if (!ok) {
     982           0 :                 exit_daemon("Failed to create directory for pid files, check 'pid directory'", errno);
     983             :         }
     984             : 
     985          39 :         pidfile_create(lp_pid_directory(), "nmbd");
     986             : 
     987          39 :         status = reinit_after_fork(msg, nmbd_event_context(), false);
     988             : 
     989          39 :         if (!NT_STATUS_IS_OK(status)) {
     990           0 :                 exit_daemon("reinit_after_fork() failed", map_errno_from_nt_status(status));
     991             :         }
     992             : 
     993             :         /*
     994             :          * Do not initialize the parent-child-pipe before becoming
     995             :          * a daemon: this is used to detect a died parent in the child
     996             :          * process.
     997             :          */
     998          39 :         status = init_before_fork();
     999          39 :         if (!NT_STATUS_IS_OK(status)) {
    1000           0 :                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
    1001             :         }
    1002             : 
    1003          39 :         if (!nmbd_setup_sig_term_handler(msg))
    1004           0 :                 exit_daemon("NMBD failed to setup signal handler", EINVAL);
    1005          39 :         if (!nmbd_setup_stdin_handler(msg, !cmdline_daemon_cfg->fork))
    1006           0 :                 exit_daemon("NMBD failed to setup stdin handler", EINVAL);
    1007          39 :         if (!nmbd_setup_sig_hup_handler(msg))
    1008           0 :                 exit_daemon("NMBD failed to setup SIGHUP handler", EINVAL);
    1009             : 
    1010          39 :         if (!messaging_parent_dgm_cleanup_init(msg)) {
    1011           0 :                 exit(1);
    1012             :         }
    1013             : 
    1014          39 :         messaging_register(msg, NULL, MSG_FORCE_ELECTION,
    1015             :                            nmbd_message_election);
    1016             : #if 0
    1017             :         /* Until winsrepl is done. */
    1018             :         messaging_register(msg, NULL, MSG_WINS_NEW_ENTRY,
    1019             :                            nmbd_wins_new_entry);
    1020             : #endif
    1021          39 :         messaging_register(msg, NULL, MSG_SHUTDOWN,
    1022             :                            nmbd_terminate);
    1023          39 :         messaging_register(msg, NULL, MSG_SMB_CONF_UPDATED,
    1024             :                            msg_reload_nmbd_services);
    1025          39 :         messaging_register(msg, NULL, MSG_SEND_PACKET,
    1026             :                            msg_nmbd_send_packet);
    1027             : 
    1028          39 :         TimeInit();
    1029             : 
    1030          39 :         DBG_NOTICE("Opening sockets %d\n", global_nmb_port);
    1031             : 
    1032          39 :         if ( !open_sockets( cmdline_daemon_cfg->daemon, global_nmb_port ) ) {
    1033           0 :                 kill_async_dns_child();
    1034           0 :                 return 1;
    1035             :         }
    1036             : 
    1037             :         /* Determine all the IP addresses we have. */
    1038          39 :         load_interfaces();
    1039             : 
    1040             :         /* Create an nmbd subnet record for each of the above. */
    1041          39 :         if( False == create_subnets() ) {
    1042           0 :                 kill_async_dns_child();
    1043           0 :                 exit_daemon("NMBD failed when creating subnet lists", EACCES);
    1044             :         }
    1045             : 
    1046             :         /* Load in any static local names. */
    1047          39 :         if (p_lmhosts) {
    1048           0 :                 set_dyn_LMHOSTSFILE(p_lmhosts);
    1049             :         }
    1050          39 :         load_lmhosts_file(get_dyn_LMHOSTSFILE());
    1051          39 :         DBG_NOTICE("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE());
    1052             : 
    1053             :         /* If we are acting as a WINS server, initialise data structures. */
    1054          39 :         if( !initialise_wins() ) {
    1055           0 :                 kill_async_dns_child();
    1056           0 :                 exit_daemon( "NMBD failed when initialising WINS server.", EACCES);
    1057             :         }
    1058             : 
    1059             :         /*
    1060             :          * Register nmbd primary workgroup and nmbd names on all
    1061             :          * the broadcast subnets, and on the WINS server (if specified).
    1062             :          * Also initiate the startup of our primary workgroup (start
    1063             :          * elections if we are setup as being able to be a local
    1064             :          * master browser.
    1065             :          */
    1066             : 
    1067          39 :         if( False == register_my_workgroup_and_names() ) {
    1068           0 :                 kill_async_dns_child();
    1069           0 :                 exit_daemon( "NMBD failed when creating my workgroup.", EACCES);
    1070             :         }
    1071             : 
    1072          39 :         if (!initialize_nmbd_proxy_logon()) {
    1073           0 :                 kill_async_dns_child();
    1074           0 :                 exit_daemon( "NMBD failed to setup nmbd_proxy_logon.", EACCES);
    1075             :         }
    1076             : 
    1077          39 :         if (!nmbd_init_packet_server()) {
    1078           0 :                 kill_async_dns_child();
    1079           0 :                 exit_daemon( "NMBD failed to setup packet server.", EACCES);
    1080             :         }
    1081             : 
    1082          39 :         if (!cmdline_daemon_cfg->interactive) {
    1083          39 :                 daemon_ready("nmbd");
    1084             :         }
    1085             : 
    1086          39 :         TALLOC_FREE(frame);
    1087          39 :         process(msg);
    1088             : 
    1089           0 :         kill_async_dns_child();
    1090           0 :         return(0);
    1091             : }

Generated by: LCOV version 1.14