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

Last change on this file since 717 was 596, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.8

File size: 25.9 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 const char *fname = lp_configfile();
374 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
375 set_dyn_CONFIGFILE(fname);
376 test = False;
377 }
378 }
379
380 if ( test && !lp_file_list_changed() )
381 return(True);
382
383 ret = lp_load(get_dyn_CONFIGFILE(), True , False, False, True);
384
385 /* perhaps the config filename is now set */
386 if ( !test ) {
387 DEBUG( 3, ( "services not loaded\n" ) );
388 reload_nmbd_services( True );
389 }
390
391#ifdef __OS2__
392 /* restore the logfile to log.nmbd always */
393 char *lfile = NULL;
394 if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
395 exit(1);
396 }
397 lp_set_logfile(lfile);
398 SAFE_FREE(lfile);
399#endif
400
401 return(ret);
402}
403
404/**************************************************************************** **
405 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
406 **************************************************************************** */
407
408static void msg_reload_nmbd_services(struct messaging_context *msg,
409 void *private_data,
410 uint32_t msg_type,
411 struct server_id server_id,
412 DATA_BLOB *data)
413{
414 write_browse_list( 0, True );
415 dump_all_namelists();
416 reload_nmbd_services( True );
417 reopen_logs();
418 reload_interfaces(0);
419}
420
421static void msg_nmbd_send_packet(struct messaging_context *msg,
422 void *private_data,
423 uint32_t msg_type,
424 struct server_id src,
425 DATA_BLOB *data)
426{
427 struct packet_struct *p = (struct packet_struct *)data->data;
428 struct subnet_record *subrec;
429 struct sockaddr_storage ss;
430 const struct sockaddr_storage *pss;
431 const struct in_addr *local_ip;
432
433 DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
434
435 if (data->length != sizeof(struct packet_struct)) {
436 DEBUG(2, ("Discarding invalid packet length from %u\n",
437 (unsigned int)procid_to_pid(&src)));
438 return;
439 }
440
441 if ((p->packet_type != NMB_PACKET) &&
442 (p->packet_type != DGRAM_PACKET)) {
443 DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
444 (unsigned int)procid_to_pid(&src), p->packet_type));
445 return;
446 }
447
448 in_addr_to_sockaddr_storage(&ss, p->ip);
449 pss = iface_ip((struct sockaddr *)&ss);
450
451 if (pss == NULL) {
452 DEBUG(2, ("Could not find ip for packet from %u\n",
453 (unsigned int)procid_to_pid(&src)));
454 return;
455 }
456
457 local_ip = &((const struct sockaddr_in *)pss)->sin_addr;
458 subrec = FIRST_SUBNET;
459
460 p->recv_fd = -1;
461 p->send_fd = (p->packet_type == NMB_PACKET) ?
462 subrec->nmb_sock : subrec->dgram_sock;
463
464 for (subrec = FIRST_SUBNET; subrec != NULL;
465 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
466 if (ip_equal_v4(*local_ip, subrec->myip)) {
467 p->send_fd = (p->packet_type == NMB_PACKET) ?
468 subrec->nmb_sock : subrec->dgram_sock;
469 break;
470 }
471 }
472
473 if (p->packet_type == DGRAM_PACKET) {
474 p->port = 138;
475 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
476 p->packet.dgram.header.source_port = 138;
477 }
478
479 send_packet(p);
480}
481
482/**************************************************************************** **
483 The main select loop.
484 **************************************************************************** */
485
486static void process(void)
487{
488 bool run_election;
489
490 while( True ) {
491 time_t t = time(NULL);
492 TALLOC_CTX *frame = talloc_stackframe();
493
494 /*
495 * Check all broadcast subnets to see if
496 * we need to run an election on any of them.
497 * (nmbd_elections.c)
498 */
499
500 run_election = check_elections();
501
502 /*
503 * Read incoming UDP packets.
504 * (nmbd_packets.c)
505 */
506
507 if(listen_for_packets(run_election)) {
508 TALLOC_FREE(frame);
509 return;
510 }
511
512 /*
513 * Process all incoming packets
514 * read above. This calls the success and
515 * failure functions registered when response
516 * packets arrrive, and also deals with request
517 * packets from other sources.
518 * (nmbd_packets.c)
519 */
520
521 run_packet_queue();
522
523 /*
524 * Run any elections - initiate becoming
525 * a local master browser if we have won.
526 * (nmbd_elections.c)
527 */
528
529 run_elections(t);
530
531 /*
532 * Send out any broadcast announcements
533 * of our server names. This also announces
534 * the workgroup name if we are a local
535 * master browser.
536 * (nmbd_sendannounce.c)
537 */
538
539 announce_my_server_names(t);
540
541 /*
542 * Send out any LanMan broadcast announcements
543 * of our server names.
544 * (nmbd_sendannounce.c)
545 */
546
547 announce_my_lm_server_names(t);
548
549 /*
550 * If we are a local master browser, periodically
551 * announce ourselves to the domain master browser.
552 * This also deals with syncronising the domain master
553 * browser server lists with ourselves as a local
554 * master browser.
555 * (nmbd_sendannounce.c)
556 */
557
558 announce_myself_to_domain_master_browser(t);
559
560 /*
561 * Fullfill any remote announce requests.
562 * (nmbd_sendannounce.c)
563 */
564
565 announce_remote(t);
566
567 /*
568 * Fullfill any remote browse sync announce requests.
569 * (nmbd_sendannounce.c)
570 */
571
572 browse_sync_remote(t);
573
574 /*
575 * Scan the broadcast subnets, and WINS client
576 * namelists and refresh any that need refreshing.
577 * (nmbd_mynames.c)
578 */
579
580 refresh_my_names(t);
581
582 /*
583 * Scan the subnet namelists and server lists and
584 * expire thos that have timed out.
585 * (nmbd.c)
586 */
587
588 expire_names_and_servers(t);
589
590 /*
591 * Write out a snapshot of our current browse list into
592 * the browse.dat file. This is used by smbd to service
593 * incoming NetServerEnum calls - used to synchronise
594 * browse lists over subnets.
595 * (nmbd_serverlistdb.c)
596 */
597
598 write_browse_list(t, False);
599
600 /*
601 * If we are a domain master browser, we have a list of
602 * local master browsers we should synchronise browse
603 * lists with (these are added by an incoming local
604 * master browser announcement packet). Expire any of
605 * these that are no longer current, and pull the server
606 * lists from each of these known local master browsers.
607 * (nmbd_browsesync.c)
608 */
609
610 dmb_expire_and_sync_browser_lists(t);
611
612 /*
613 * Check that there is a local master browser for our
614 * workgroup for all our broadcast subnets. If one
615 * is not found, start an election (which we ourselves
616 * may or may not participate in, depending on the
617 * setting of the 'local master' parameter.
618 * (nmbd_elections.c)
619 */
620
621 check_master_browser_exists(t);
622
623 /*
624 * If we are configured as a logon server, attempt to
625 * register the special NetBIOS names to become such
626 * (WORKGROUP<1c> name) on all broadcast subnets and
627 * with the WINS server (if used). If we are configured
628 * to become a domain master browser, attempt to register
629 * the special NetBIOS name (WORKGROUP<1b> name) to
630 * become such.
631 * (nmbd_become_dmb.c)
632 */
633
634 add_domain_names(t);
635
636 /*
637 * If we are a WINS server, do any timer dependent
638 * processing required.
639 * (nmbd_winsserver.c)
640 */
641
642 initiate_wins_processing(t);
643
644 /*
645 * If we are a domain master browser, attempt to contact the
646 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
647 * This will only work to a Samba WINS server.
648 * (nmbd_browsesync.c)
649 */
650
651 if (lp_enhanced_browsing())
652 collect_all_workgroup_names_from_wins_server(t);
653
654 /*
655 * Go through the response record queue and time out or re-transmit
656 * and expired entries.
657 * (nmbd_packets.c)
658 */
659
660 retransmit_or_expire_response_records(t);
661
662 /*
663 * check to see if any remote browse sync child processes have completed
664 */
665
666 sync_check_completion();
667
668 /*
669 * regularly sync with any other DMBs we know about
670 */
671
672 if (lp_enhanced_browsing())
673 sync_all_dmbs(t);
674
675 /*
676 * clear the unexpected packet queue
677 */
678
679 clear_unexpected(t);
680
681 /* check for new network interfaces */
682
683 reload_interfaces(t);
684
685 /* free up temp memory */
686 TALLOC_FREE(frame);
687 }
688}
689
690/**************************************************************************** **
691 Open the socket communication.
692 **************************************************************************** */
693
694static bool open_sockets(bool isdaemon, int port)
695{
696 struct sockaddr_storage ss;
697 const char *sock_addr = lp_socket_address();
698
699 /*
700 * The sockets opened here will be used to receive broadcast
701 * packets *only*. Interface specific sockets are opened in
702 * make_subnet() in namedbsubnet.c. Thus we bind to the
703 * address "0.0.0.0". The parameter 'socket address' is
704 * now deprecated.
705 */
706
707 if (!interpret_string_addr(&ss, sock_addr,
708 AI_NUMERICHOST|AI_PASSIVE)) {
709 DEBUG(0,("open_sockets: unable to get socket address "
710 "from string %s", sock_addr));
711 return false;
712 }
713 if (ss.ss_family != AF_INET) {
714 DEBUG(0,("open_sockets: unable to use IPv6 socket"
715 "%s in nmbd\n",
716 sock_addr));
717 return false;
718 }
719
720 if (isdaemon) {
721 ClientNMB = open_socket_in(SOCK_DGRAM, port,
722 0, &ss,
723 true);
724 } else {
725 ClientNMB = 0;
726 }
727
728 if (ClientNMB == -1) {
729 return false;
730 }
731
732 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
733 3, &ss,
734 true);
735
736 if (ClientDGRAM == -1) {
737 if (ClientNMB != 0) {
738 close(ClientNMB);
739 }
740 return false;
741 }
742
743 /* we are never interested in SIGPIPE */
744 BlockSignals(True,SIGPIPE);
745
746 set_socket_options( ClientNMB, "SO_BROADCAST" );
747 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
748
749 /* Ensure we're non-blocking. */
750 set_blocking( ClientNMB, False);
751 set_blocking( ClientDGRAM, False);
752
753 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
754 return( True );
755}
756
757/**************************************************************************** **
758 main program
759 **************************************************************************** */
760
761 int main(int argc, const char *argv[])
762{
763 static bool is_daemon;
764 static bool opt_interactive;
765 static bool Fork = true;
766 static bool no_process_group;
767 static bool log_stdout;
768 poptContext pc;
769 char *p_lmhosts = NULL;
770 int opt;
771 enum {
772 OPT_DAEMON = 1000,
773 OPT_INTERACTIVE,
774 OPT_FORK,
775 OPT_NO_PROCESS_GROUP,
776 OPT_LOG_STDOUT
777 };
778 struct poptOption long_options[] = {
779 POPT_AUTOHELP
780 {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon(default)" },
781 {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)" },
782 {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools & etc)" },
783 {"no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
784 {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
785 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 0, "Load a netbios hosts file"},
786 {"port", 'p', POPT_ARG_INT, &global_nmb_port, 0, "Listen on the specified port" },
787 POPT_COMMON_SAMBA
788 { NULL }
789 };
790 TALLOC_CTX *frame = talloc_stackframe(); /* Setup tos. */
791
792#ifdef __OS2__
793 global_Sem32Add = 1;
794#endif
795
796 load_case_tables();
797
798 global_nmb_port = NMB_PORT;
799
800 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
801 while ((opt = poptGetNextOpt(pc)) != -1) {
802 switch (opt) {
803 case OPT_DAEMON:
804 is_daemon = true;
805 break;
806 case OPT_INTERACTIVE:
807 opt_interactive = true;
808 break;
809 case OPT_FORK:
810 Fork = false;
811 break;
812 case OPT_NO_PROCESS_GROUP:
813 no_process_group = true;
814 break;
815 case OPT_LOG_STDOUT:
816 log_stdout = true;
817 break;
818 default:
819 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
820 poptBadOption(pc, 0), poptStrerror(opt));
821 poptPrintUsage(pc, stderr, 0);
822 exit(1);
823 }
824 };
825 poptFreeContext(pc);
826
827 global_in_nmbd = true;
828
829 StartupTime = time(NULL);
830
831 sys_srandom(time(NULL) ^ sys_getpid());
832
833 if (!override_logfile) {
834 char *lfile = NULL;
835 if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) {
836 exit(1);
837 }
838 lp_set_logfile(lfile);
839 SAFE_FREE(lfile);
840 }
841
842 fault_setup((void (*)(void *))fault_continue );
843 dump_core_setup("nmbd");
844
845 /* POSIX demands that signals are inherited. If the invoking process has
846 * these signals masked, we will have problems, as we won't receive them. */
847 BlockSignals(False, SIGHUP);
848 BlockSignals(False, SIGUSR1);
849 BlockSignals(False, SIGTERM);
850
851#if defined(SIGFPE)
852 /* we are never interested in SIGFPE */
853 BlockSignals(True,SIGFPE);
854#endif
855
856 /* We no longer use USR2... */
857#if defined(SIGUSR2)
858 BlockSignals(True, SIGUSR2);
859#endif
860
861 if ( opt_interactive ) {
862 Fork = False;
863 log_stdout = True;
864 }
865
866 if ( log_stdout && Fork ) {
867 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
868 exit(1);
869 }
870
871 setup_logging( argv[0], log_stdout );
872
873 reopen_logs();
874
875 DEBUG(0,("nmbd version %s started.\n", samba_version_string()));
876 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
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);
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 if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(),
940 nmbd_event_context(), false))) {
941 DEBUG(0,("reinit_after_fork() failed\n"));
942 exit(1);
943 }
944
945 if (!nmbd_setup_sig_term_handler())
946 exit(1);
947 if (!nmbd_setup_sig_hup_handler())
948 exit(1);
949
950 /* get broadcast messages */
951 claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP);
952
953 messaging_register(nmbd_messaging_context(), NULL,
954 MSG_FORCE_ELECTION, nmbd_message_election);
955#if 0
956 /* Until winsrepl is done. */
957 messaging_register(nmbd_messaging_context(), NULL,
958 MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
959#endif
960 messaging_register(nmbd_messaging_context(), NULL,
961 MSG_SHUTDOWN, nmbd_terminate);
962 messaging_register(nmbd_messaging_context(), NULL,
963 MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
964 messaging_register(nmbd_messaging_context(), NULL,
965 MSG_SEND_PACKET, msg_nmbd_send_packet);
966
967 TimeInit();
968
969 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
970
971 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
972 kill_async_dns_child();
973 return 1;
974 }
975
976 /* Determine all the IP addresses we have. */
977 load_interfaces();
978
979 /* Create an nmbd subnet record for each of the above. */
980 if( False == create_subnets() ) {
981 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
982 kill_async_dns_child();
983 exit(1);
984 }
985
986 /* Load in any static local names. */
987 if (p_lmhosts) {
988 set_dyn_LMHOSTSFILE(p_lmhosts);
989 }
990 load_lmhosts_file(get_dyn_LMHOSTSFILE());
991 DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));
992
993 /* If we are acting as a WINS server, initialise data structures. */
994 if( !initialise_wins() ) {
995 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
996 kill_async_dns_child();
997 exit(1);
998 }
999
1000 /*
1001 * Register nmbd primary workgroup and nmbd names on all
1002 * the broadcast subnets, and on the WINS server (if specified).
1003 * Also initiate the startup of our primary workgroup (start
1004 * elections if we are setup as being able to be a local
1005 * master browser.
1006 */
1007
1008 if( False == register_my_workgroup_and_names() ) {
1009 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
1010 kill_async_dns_child();
1011 exit(1);
1012 }
1013
1014 if (!initialize_nmbd_proxy_logon()) {
1015 DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n"));
1016 kill_async_dns_child();
1017 exit(1);
1018 }
1019
1020 TALLOC_FREE(frame);
1021 process();
1022
1023 if (dbf)
1024 x_fclose(dbf);
1025 kill_async_dns_child();
1026 return(0);
1027}
Note: See TracBrowser for help on using the repository browser.