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

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

Samba 3.6: use fcntl and friends for locking

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