00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 int ClientNMB = -1;
00027 int ClientDGRAM = -1;
00028 int global_nmb_port = -1;
00029
00030 extern BOOL rescan_listen_set;
00031 extern struct in_addr loopback_ip;
00032 extern BOOL global_in_nmbd;
00033
00034 extern BOOL override_logfile;
00035
00036
00037 static BOOL is_daemon;
00038
00039
00040 static BOOL Fork = True;
00041
00042
00043 static BOOL log_stdout;
00044
00045
00046 BOOL found_lm_clients = False;
00047
00048
00049
00050 time_t StartupTime = 0;
00051
00052
00053
00054
00055
00056 static void terminate(void)
00057 {
00058 DEBUG(0,("Got SIGTERM: going down...\n"));
00059
00060
00061 wins_write_database(0,False);
00062
00063
00064 release_wins_names();
00065
00066
00067 announce_my_servers_removed();
00068
00069
00070 kill_async_dns_child();
00071
00072 exit(0);
00073 }
00074
00075
00076
00077
00078
00079 static void nmbd_terminate(int msg_type, struct process_id src,
00080 void *buf, size_t len, void *private_data)
00081 {
00082 terminate();
00083 }
00084
00085
00086
00087
00088
00089 static SIG_ATOMIC_T got_sig_term;
00090
00091 static void sig_term(int sig)
00092 {
00093 got_sig_term = 1;
00094 sys_select_signal(SIGTERM);
00095 }
00096
00097
00098
00099
00100
00101 static SIG_ATOMIC_T reload_after_sighup;
00102
00103 static void sig_hup(int sig)
00104 {
00105 reload_after_sighup = 1;
00106 sys_select_signal(SIGHUP);
00107 }
00108
00109
00110
00111
00112
00113 static void fault_continue(void)
00114 {
00115 dump_core();
00116 }
00117
00118
00119
00120
00121
00122 static void expire_names_and_servers(time_t t)
00123 {
00124 static time_t lastrun = 0;
00125
00126 if ( !lastrun )
00127 lastrun = t;
00128 if ( t < (lastrun + 5) )
00129 return;
00130 lastrun = t;
00131
00132
00133
00134
00135
00136
00137
00138 expire_names(t);
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 expire_workgroups_and_servers(t);
00149 }
00150
00151
00152
00153
00154
00155
00156 static void reload_interfaces(time_t t)
00157 {
00158 static time_t lastt;
00159 int n;
00160 bool print_waiting_msg = true;
00161 struct subnet_record *subrec;
00162
00163 if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) {
00164 return;
00165 }
00166 lastt = t;
00167
00168 if (!interfaces_changed()) {
00169 return;
00170 }
00171
00172 try_again:
00173
00174
00175
00176 load_interfaces();
00177
00178
00179 for (n=iface_count() - 1; n >= 0; n--) {
00180 struct interface *iface = get_interface(n);
00181
00182 if (!iface) {
00183 DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
00184 continue;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193 if (ip_equal(iface->ip, loopback_ip)) {
00194 DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
00195 continue;
00196 }
00197
00198 for (subrec=subnetlist; subrec; subrec=subrec->next) {
00199 if (ip_equal(iface->ip, subrec->myip) &&
00200 ip_equal(iface->nmask, subrec->mask_ip)) break;
00201 }
00202
00203 if (!subrec) {
00204
00205 DEBUG(2,("Found new interface %s\n",
00206 inet_ntoa(iface->ip)));
00207 subrec = make_normal_subnet(iface);
00208 if (subrec)
00209 register_my_workgroup_one_subnet(subrec);
00210 }
00211 }
00212
00213
00214 for (subrec=subnetlist; subrec; subrec=subrec->next) {
00215 for (n=iface_count() - 1; n >= 0; n--) {
00216 struct interface *iface = get_interface(n);
00217 if (ip_equal(iface->ip, subrec->myip) &&
00218 ip_equal(iface->nmask, subrec->mask_ip)) break;
00219 }
00220 if (n == -1) {
00221
00222
00223
00224
00225
00226
00227 DEBUG(2,("Deleting dead interface %s\n",
00228 inet_ntoa(subrec->myip)));
00229 close_subnet(subrec);
00230 }
00231 }
00232
00233 rescan_listen_set = True;
00234
00235
00236 if (FIRST_SUBNET == NULL) {
00237
00238 if (print_waiting_msg) {
00239 DEBUG(0,("reload_interfaces: "
00240 "No subnets to listen to. Waiting..\n"));
00241 print_waiting_msg = false;
00242 }
00243
00244
00245
00246
00247
00248
00249 BlockSignals(false, SIGTERM);
00250
00251 while (iface_count_nl() == 0 && !got_sig_term) {
00252 sleep(5);
00253 load_interfaces();
00254 }
00255
00256
00257
00258
00259
00260 if (got_sig_term) {
00261 got_sig_term = 0;
00262 terminate();
00263 }
00264
00265
00266
00267
00268
00269 BlockSignals(true, SIGTERM);
00270 goto try_again;
00271 }
00272 }
00273
00274
00275
00276
00277
00278 static BOOL reload_nmbd_services(BOOL test)
00279 {
00280 BOOL ret;
00281
00282 set_remote_machine_name("nmbd", False);
00283
00284 if ( lp_loaded() ) {
00285 pstring fname;
00286 pstrcpy( fname,lp_configfile());
00287 if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
00288 pstrcpy(dyn_CONFIGFILE,fname);
00289 test = False;
00290 }
00291 }
00292
00293 if ( test && !lp_file_list_changed() )
00294 return(True);
00295
00296 ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
00297
00298
00299 if ( !test ) {
00300 DEBUG( 3, ( "services not loaded\n" ) );
00301 reload_nmbd_services( True );
00302 }
00303
00304 return(ret);
00305 }
00306
00307
00308
00309
00310
00311 static void msg_reload_nmbd_services(int msg_type, struct process_id src,
00312 void *buf, size_t len, void *private_data)
00313 {
00314 write_browse_list( 0, True );
00315 dump_all_namelists();
00316 reload_nmbd_services( True );
00317 reopen_logs();
00318 reload_interfaces(0);
00319 }
00320
00321 static void msg_nmbd_send_packet(int msg_type, struct process_id src,
00322 void *buf, size_t len, void *private_data)
00323 {
00324 struct packet_struct *p = (struct packet_struct *)buf;
00325 struct subnet_record *subrec;
00326 struct in_addr *local_ip;
00327
00328 DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
00329
00330 if (len != sizeof(struct packet_struct)) {
00331 DEBUG(2, ("Discarding invalid packet length from %d\n",
00332 procid_to_pid(&src)));
00333 return;
00334 }
00335
00336 if ((p->packet_type != NMB_PACKET) &&
00337 (p->packet_type != DGRAM_PACKET)) {
00338 DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
00339 procid_to_pid(&src), p->packet_type));
00340 return;
00341 }
00342
00343 local_ip = iface_ip(p->ip);
00344
00345 if (local_ip == NULL) {
00346 DEBUG(2, ("Could not find ip for packet from %d\n",
00347 procid_to_pid(&src)));
00348 return;
00349 }
00350
00351 subrec = FIRST_SUBNET;
00352
00353 p->fd = (p->packet_type == NMB_PACKET) ?
00354 subrec->nmb_sock : subrec->dgram_sock;
00355
00356 for (subrec = FIRST_SUBNET; subrec != NULL;
00357 subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00358 if (ip_equal(*local_ip, subrec->myip)) {
00359 p->fd = (p->packet_type == NMB_PACKET) ?
00360 subrec->nmb_sock : subrec->dgram_sock;
00361 break;
00362 }
00363 }
00364
00365 if (p->packet_type == DGRAM_PACKET) {
00366 p->port = 138;
00367 p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
00368 p->packet.dgram.header.source_port = 138;
00369 }
00370
00371 send_packet(p);
00372 }
00373
00374
00375
00376
00377
00378 static void process(void)
00379 {
00380 BOOL run_election;
00381
00382 while( True ) {
00383 time_t t = time(NULL);
00384
00385
00386
00387 message_dispatch();
00388
00389
00390
00391
00392
00393
00394
00395 run_election = check_elections();
00396
00397
00398
00399
00400
00401
00402 if(listen_for_packets(run_election))
00403 return;
00404
00405
00406
00407
00408
00409 if (got_sig_term) {
00410 got_sig_term = 0;
00411 terminate();
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 run_packet_queue();
00424
00425
00426
00427
00428
00429
00430
00431 run_elections(t);
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 announce_my_server_names(t);
00442
00443
00444
00445
00446
00447
00448
00449 announce_my_lm_server_names(t);
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 announce_myself_to_domain_master_browser(t);
00461
00462
00463
00464
00465
00466
00467 announce_remote(t);
00468
00469
00470
00471
00472
00473
00474 browse_sync_remote(t);
00475
00476
00477
00478
00479
00480
00481
00482 refresh_my_names(t);
00483
00484
00485
00486
00487
00488
00489
00490 expire_names_and_servers(t);
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 write_browse_list(t, False);
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 dmb_expire_and_sync_browser_lists(t);
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 check_master_browser_exists(t);
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 add_domain_names(t);
00537
00538
00539
00540
00541
00542
00543
00544 initiate_wins_processing(t);
00545
00546
00547
00548
00549
00550
00551
00552
00553 if (lp_enhanced_browsing())
00554 collect_all_workgroup_names_from_wins_server(t);
00555
00556
00557
00558
00559
00560
00561
00562 retransmit_or_expire_response_records(t);
00563
00564
00565
00566
00567
00568 sync_check_completion();
00569
00570
00571
00572
00573
00574 if (lp_enhanced_browsing())
00575 sync_all_dmbs(t);
00576
00577
00578
00579
00580
00581 clear_unexpected(t);
00582
00583
00584
00585
00586
00587 if(reload_after_sighup) {
00588 DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
00589 msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
00590 pid_to_procid(0), NULL, 0, NULL);
00591 reload_after_sighup = 0;
00592 }
00593
00594
00595
00596 reload_interfaces(t);
00597
00598
00599 lp_TALLOC_FREE();
00600 }
00601 }
00602
00603
00604
00605
00606
00607 static BOOL open_sockets(BOOL isdaemon, int port)
00608 {
00609
00610
00611
00612
00613
00614
00615
00616
00617 if ( isdaemon )
00618 ClientNMB = open_socket_in(SOCK_DGRAM, port,
00619 0, interpret_addr(lp_socket_address()),
00620 True);
00621 else
00622 ClientNMB = 0;
00623
00624 ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
00625 3, interpret_addr(lp_socket_address()),
00626 True);
00627
00628 if ( ClientNMB == -1 )
00629 return( False );
00630
00631
00632 BlockSignals(True,SIGPIPE);
00633
00634 set_socket_options( ClientNMB, "SO_BROADCAST" );
00635 set_socket_options( ClientDGRAM, "SO_BROADCAST" );
00636
00637
00638 set_blocking( ClientNMB, False);
00639 set_blocking( ClientDGRAM, False);
00640
00641 DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
00642 return( True );
00643 }
00644
00645
00646
00647
00648 int main(int argc, const char *argv[])
00649 {
00650 pstring logfile;
00651 static BOOL opt_interactive;
00652 poptContext pc;
00653 static char *p_lmhosts = dyn_LMHOSTSFILE;
00654 static BOOL no_process_group = False;
00655 struct poptOption long_options[] = {
00656 POPT_AUTOHELP
00657 {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
00658 {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
00659 {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
00660 {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
00661 {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
00662 {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
00663 {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
00664 POPT_COMMON_SAMBA
00665 POPT_COMMON_CONNECTION
00666 { NULL }
00667 };
00668
00669 load_case_tables();
00670
00671 global_nmb_port = NMB_PORT;
00672
00673 pc = poptGetContext("nmbd", argc, argv, long_options, 0);
00674 while (poptGetNextOpt(pc) != -1) {};
00675 poptFreeContext(pc);
00676
00677 global_in_nmbd = True;
00678
00679 StartupTime = time(NULL);
00680
00681 sys_srandom(time(NULL) ^ sys_getpid());
00682
00683 if (!override_logfile) {
00684 slprintf(logfile, sizeof(logfile)-1, "%s/nmbd.log", dyn_LOGFILEBASE);
00685 lp_set_logfile(logfile);
00686 }
00687
00688 fault_setup((void (*)(void *))fault_continue );
00689 dump_core_setup("nmbd");
00690
00691
00692
00693 BlockSignals(False, SIGHUP);
00694 BlockSignals(False, SIGUSR1);
00695 BlockSignals(False, SIGTERM);
00696
00697 CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
00698 CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
00699
00700 #if defined(SIGFPE)
00701
00702 BlockSignals(True,SIGFPE);
00703 #endif
00704
00705
00706 #if defined(SIGUSR2)
00707 BlockSignals(True, SIGUSR2);
00708 #endif
00709
00710 if ( opt_interactive ) {
00711 Fork = False;
00712 log_stdout = True;
00713 }
00714
00715 if ( log_stdout && Fork ) {
00716 DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
00717 exit(1);
00718 }
00719
00720 setup_logging( argv[0], log_stdout );
00721
00722 reopen_logs();
00723
00724 DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
00725 DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
00726
00727 if ( !reload_nmbd_services(False) )
00728 return(-1);
00729
00730 if(!init_names())
00731 return -1;
00732
00733 reload_nmbd_services( True );
00734
00735 if (strequal(lp_workgroup(),"*")) {
00736 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
00737 exit(1);
00738 }
00739
00740 set_samba_nb_type();
00741
00742 if (!is_daemon && !is_a_socket(0)) {
00743 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
00744 is_daemon = True;
00745 }
00746
00747 if (is_daemon && !opt_interactive) {
00748 DEBUG( 2, ( "Becoming a daemon.\n" ) );
00749 become_daemon(Fork, no_process_group);
00750 }
00751
00752 #if HAVE_SETPGID
00753
00754
00755
00756
00757 if (opt_interactive && !no_process_group)
00758 setpgid( (pid_t)0, (pid_t)0 );
00759 #endif
00760
00761 #ifndef SYNC_DNS
00762
00763
00764 if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
00765 start_async_dns();
00766 }
00767 #endif
00768
00769 if (!directory_exist(lp_lockdir(), NULL)) {
00770 mkdir(lp_lockdir(), 0755);
00771 }
00772
00773 pidfile_create("nmbd");
00774 message_init();
00775 message_register(MSG_FORCE_ELECTION, nmbd_message_election, NULL);
00776 #if 0
00777
00778 message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry, NULL);
00779 #endif
00780 message_register(MSG_SHUTDOWN, nmbd_terminate, NULL);
00781 message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services, NULL);
00782 message_register(MSG_SEND_PACKET, msg_nmbd_send_packet, NULL);
00783
00784 TimeInit();
00785
00786 DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
00787
00788 if ( !open_sockets( is_daemon, global_nmb_port ) ) {
00789 kill_async_dns_child();
00790 return 1;
00791 }
00792
00793
00794 load_interfaces();
00795
00796
00797 if( False == create_subnets() ) {
00798 DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
00799 kill_async_dns_child();
00800 exit(1);
00801 }
00802
00803
00804 load_lmhosts_file(p_lmhosts);
00805 DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));
00806
00807
00808 if( !initialise_wins() ) {
00809 DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
00810 kill_async_dns_child();
00811 exit(1);
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 if( False == register_my_workgroup_and_names() ) {
00823 DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
00824 kill_async_dns_child();
00825 exit(1);
00826 }
00827
00828
00829 BlockSignals( True, SIGTERM );
00830
00831 process();
00832
00833 if (dbf)
00834 x_fclose(dbf);
00835 kill_async_dns_child();
00836 return(0);
00837 }