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

Last change on this file since 949 was 949, checked in by Silvan Scherrer, 9 years ago

samba server: revert logging changes in nmbd and asycdns

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