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

Last change on this file was 836, checked in by Silvan Scherrer, 12 years ago

Samba 3.5: use fcntl and friends for locking

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