source: branches/samba-3.5.x/source3/nmbd/nmbd.c@ 821

Last change on this file since 821 was 778, checked in by Silvan Scherrer, 12 years ago

Samba 3.5: add a maintained message

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