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

Last change on this file since 454 was 454, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: merged changes from 3.3

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