source: trunk/server/source3/nmbd/nmbd.c@ 978

Last change on this file since 978 was 978, checked in by Silvan Scherrer, 9 years ago

Samba server: remove exceptq handling, as now globaly installed when using libcx. And libcx is mandatory for samba

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