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

Last change on this file since 736 was 736, checked in by Silvan Scherrer, 13 years ago

Samba Server 3.5: update branche to 3.5.16

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 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
879 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
880 DEBUG(0, ("error opening config file\n"));
881 exit(1);
882 }
883
884 if (nmbd_messaging_context() == NULL) {
885 return 1;
886 }
887
888 if ( !reload_nmbd_services(False) )
889 return(-1);
890
891 if(!init_names())
892 return -1;
893
894 reload_nmbd_services( True );
895
896 if (strequal(lp_workgroup(),"*")) {
897 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
898 exit(1);
899 }
900
901 set_samba_nb_type();
902
903 if (!is_daemon && !is_a_socket(0)) {
904 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
905 is_daemon = True;
906 }
907
908 if (is_daemon && !opt_interactive) {
909 DEBUG( 2, ( "Becoming a daemon.\n" ) );
910 become_daemon(Fork, no_process_group);
911 }
912
913#if HAVE_SETPGID
914 /*
915 * If we're interactive we want to set our own process group for
916 * signal management.
917 */
918 if (opt_interactive && !no_process_group)
919 setpgid( (pid_t)0, (pid_t)0 );
920#endif
921
922 if (nmbd_messaging_context() == NULL) {
923 return 1;
924 }
925
926#ifndef SYNC_DNS
927 /* Setup the async dns. We do it here so it doesn't have all the other
928 stuff initialised and thus chewing memory and sockets */
929 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
930 start_async_dns();
931 }
932#endif
933
934 if (!directory_exist(lp_lockdir())) {
935 mkdir(lp_lockdir(), 0755);
936 }
937
938 pidfile_create("nmbd");
939
940 if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(),
941 nmbd_event_context(), false))) {
942 DEBUG(0,("reinit_after_fork() failed\n"));
943 exit(1);
944 }
945
946 if (!nmbd_setup_sig_term_handler())
947 exit(1);
948 if (!nmbd_setup_sig_hup_handler())
949 exit(1);
950
951 /* get broadcast messages */
952 claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP);
953
954 messaging_register(nmbd_messaging_context(), NULL,
955 MSG_FORCE_ELECTION, nmbd_message_election);
956#if 0
957 /* Until winsrepl is done. */
958 messaging_register(nmbd_messaging_context(), NULL,
959 MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
960#endif
961 messaging_register(nmbd_messaging_context(), NULL,
962 MSG_SHUTDOWN, nmbd_terminate);
963 messaging_register(nmbd_messaging_context(), NULL,
964 MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
965 messaging_register(nmbd_messaging_context(), NULL,
966 MSG_SEND_PACKET, msg_nmbd_send_packet);
967
968 TimeInit();
969
970 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
971
972 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
973 kill_async_dns_child();
974 return 1;
975 }
976
977 /* Determine all the IP addresses we have. */
978 load_interfaces();
979
980 /* Create an nmbd subnet record for each of the above. */
981 if( False == create_subnets() ) {
982 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
983 kill_async_dns_child();
984 exit(1);
985 }
986
987 /* Load in any static local names. */
988 if (p_lmhosts) {
989 set_dyn_LMHOSTSFILE(p_lmhosts);
990 }
991 load_lmhosts_file(get_dyn_LMHOSTSFILE());
992 DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE()));
993
994 /* If we are acting as a WINS server, initialise data structures. */
995 if( !initialise_wins() ) {
996 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
997 kill_async_dns_child();
998 exit(1);
999 }
1000
1001 /*
1002 * Register nmbd primary workgroup and nmbd names on all
1003 * the broadcast subnets, and on the WINS server (if specified).
1004 * Also initiate the startup of our primary workgroup (start
1005 * elections if we are setup as being able to be a local
1006 * master browser.
1007 */
1008
1009 if( False == register_my_workgroup_and_names() ) {
1010 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
1011 kill_async_dns_child();
1012 exit(1);
1013 }
1014
1015 if (!initialize_nmbd_proxy_logon()) {
1016 DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n"));
1017 kill_async_dns_child();
1018 exit(1);
1019 }
1020
1021 TALLOC_FREE(frame);
1022 process();
1023
1024 if (dbf)
1025 x_fclose(dbf);
1026 kill_async_dns_child();
1027 return(0);
1028}
Note: See TracBrowser for help on using the repository browser.