~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/nmbd/nmbd.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 2 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, write to the Free Software
20
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
   
22
 
*/
23
 
 
24
 
#include "includes.h"
25
 
 
26
 
int ClientNMB       = -1;
27
 
int ClientDGRAM     = -1;
28
 
int global_nmb_port = -1;
29
 
 
30
 
extern BOOL rescan_listen_set;
31
 
extern struct in_addr loopback_ip;
32
 
extern BOOL global_in_nmbd;
33
 
 
34
 
extern BOOL override_logfile;
35
 
 
36
 
/* are we running as a daemon ? */
37
 
static BOOL is_daemon;
38
 
 
39
 
/* fork or run in foreground ? */
40
 
static BOOL Fork = True;
41
 
 
42
 
/* log to standard output ? */
43
 
static BOOL log_stdout;
44
 
 
45
 
/* have we found LanMan clients yet? */
46
 
BOOL found_lm_clients = False;
47
 
 
48
 
/* what server type are we currently */
49
 
 
50
 
time_t StartupTime = 0;
51
 
 
52
 
/**************************************************************************** **
53
 
 Handle a SIGTERM in band.
54
 
 **************************************************************************** */
55
 
 
56
 
static void terminate(void)
57
 
{
58
 
        DEBUG(0,("Got SIGTERM: going down...\n"));
59
 
  
60
 
        /* Write out wins.dat file if samba is a WINS server */
61
 
        wins_write_database(0,False);
62
 
  
63
 
        /* Remove all SELF registered names from WINS */
64
 
        release_wins_names();
65
 
  
66
 
        /* Announce all server entries as 0 time-to-live, 0 type. */
67
 
        announce_my_servers_removed();
68
 
 
69
 
        /* If there was an async dns child - kill it. */
70
 
        kill_async_dns_child();
71
 
 
72
 
        exit(0);
73
 
}
74
 
 
75
 
/**************************************************************************** **
76
 
 Handle a SHUTDOWN message from smbcontrol.
77
 
 **************************************************************************** */
78
 
 
79
 
static void nmbd_terminate(int msg_type, struct process_id src,
80
 
                           void *buf, size_t len)
81
 
{
82
 
        terminate();
83
 
}
84
 
 
85
 
/**************************************************************************** **
86
 
 Catch a SIGTERM signal.
87
 
 **************************************************************************** */
88
 
 
89
 
static SIG_ATOMIC_T got_sig_term;
90
 
 
91
 
static void sig_term(int sig)
92
 
{
93
 
        got_sig_term = 1;
94
 
        sys_select_signal(SIGTERM);
95
 
}
96
 
 
97
 
/**************************************************************************** **
98
 
 Catch a SIGHUP signal.
99
 
 **************************************************************************** */
100
 
 
101
 
static SIG_ATOMIC_T reload_after_sighup;
102
 
 
103
 
static void sig_hup(int sig)
104
 
{
105
 
        reload_after_sighup = 1;
106
 
        sys_select_signal(SIGHUP);
107
 
}
108
 
 
109
 
/**************************************************************************** **
110
 
 Possibly continue after a fault.
111
 
 **************************************************************************** */
112
 
 
113
 
static void fault_continue(void)
114
 
{
115
 
#if DUMP_CORE
116
 
        dump_core();
117
 
#endif
118
 
}
119
 
 
120
 
/**************************************************************************** **
121
 
 Expire old names from the namelist and server list.
122
 
 **************************************************************************** */
123
 
 
124
 
static void expire_names_and_servers(time_t t)
125
 
{
126
 
        static time_t lastrun = 0;
127
 
  
128
 
        if ( !lastrun )
129
 
                lastrun = t;
130
 
        if ( t < (lastrun + 5) )
131
 
                return;
132
 
        lastrun = t;
133
 
 
134
 
        /*
135
 
         * Expire any timed out names on all the broadcast
136
 
         * subnets and those registered with the WINS server.
137
 
         * (nmbd_namelistdb.c)
138
 
         */
139
 
 
140
 
        expire_names(t);
141
 
 
142
 
        /*
143
 
         * Go through all the broadcast subnets and for each
144
 
         * workgroup known on that subnet remove any expired
145
 
         * server names. If a workgroup has an empty serverlist
146
 
         * and has itself timed out then remove the workgroup.
147
 
         * (nmbd_workgroupdb.c)
148
 
         */
149
 
 
150
 
        expire_workgroups_and_servers(t);
151
 
}
152
 
 
153
 
/************************************************************************** **
154
 
 Reload the list of network interfaces.
155
 
 ************************************************************************** */
156
 
 
157
 
static BOOL reload_interfaces(time_t t)
158
 
{
159
 
        static time_t lastt;
160
 
        int n;
161
 
        struct subnet_record *subrec;
162
 
 
163
 
        if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
164
 
        lastt = t;
165
 
 
166
 
        if (!interfaces_changed()) return False;
167
 
 
168
 
        /* the list of probed interfaces has changed, we may need to add/remove
169
 
           some subnets */
170
 
        load_interfaces();
171
 
 
172
 
        /* find any interfaces that need adding */
173
 
        for (n=iface_count() - 1; n >= 0; n--) {
174
 
                struct interface *iface = get_interface(n);
175
 
 
176
 
                if (!iface) {
177
 
                        DEBUG(2,("reload_interfaces: failed to get interface %d\n", n));
178
 
                        continue;
179
 
                }
180
 
 
181
 
                /*
182
 
                 * We don't want to add a loopback interface, in case
183
 
                 * someone has added 127.0.0.1 for smbd, nmbd needs to
184
 
                 * ignore it here. JRA.
185
 
                 */
186
 
 
187
 
                if (ip_equal(iface->ip, loopback_ip)) {
188
 
                        DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
189
 
                        continue;
190
 
                }
191
 
 
192
 
                for (subrec=subnetlist; subrec; subrec=subrec->next) {
193
 
                        if (ip_equal(iface->ip, subrec->myip) &&
194
 
                            ip_equal(iface->nmask, subrec->mask_ip)) break;
195
 
                }
196
 
 
197
 
                if (!subrec) {
198
 
                        /* it wasn't found! add it */
199
 
                        DEBUG(2,("Found new interface %s\n", 
200
 
                                 inet_ntoa(iface->ip)));
201
 
                        subrec = make_normal_subnet(iface);
202
 
                        if (subrec)
203
 
                                register_my_workgroup_one_subnet(subrec);
204
 
                }
205
 
        }
206
 
 
207
 
        /* find any interfaces that need deleting */
208
 
        for (subrec=subnetlist; subrec; subrec=subrec->next) {
209
 
                for (n=iface_count() - 1; n >= 0; n--) {
210
 
                        struct interface *iface = get_interface(n);
211
 
                        if (ip_equal(iface->ip, subrec->myip) &&
212
 
                            ip_equal(iface->nmask, subrec->mask_ip)) break;
213
 
                }
214
 
                if (n == -1) {
215
 
                        /* oops, an interface has disapeared. This is
216
 
                         tricky, we don't dare actually free the
217
 
                         interface as it could be being used, so
218
 
                         instead we just wear the memory leak and
219
 
                         remove it from the list of interfaces without
220
 
                         freeing it */
221
 
                        DEBUG(2,("Deleting dead interface %s\n", 
222
 
                                 inet_ntoa(subrec->myip)));
223
 
                        close_subnet(subrec);
224
 
                }
225
 
        }
226
 
        
227
 
        rescan_listen_set = True;
228
 
 
229
 
        /* We need to shutdown if there are no subnets... */
230
 
        if (FIRST_SUBNET == NULL) {
231
 
                DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
232
 
                return True;
233
 
        }
234
 
        return False;
235
 
}
236
 
 
237
 
/**************************************************************************** **
238
 
 Reload the services file.
239
 
 **************************************************************************** */
240
 
 
241
 
static BOOL reload_nmbd_services(BOOL test)
242
 
{
243
 
        BOOL ret;
244
 
 
245
 
        set_remote_machine_name("nmbd", False);
246
 
 
247
 
        if ( lp_loaded() ) {
248
 
                pstring fname;
249
 
                pstrcpy( fname,lp_configfile());
250
 
                if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
251
 
                        pstrcpy(dyn_CONFIGFILE,fname);
252
 
                        test = False;
253
 
                }
254
 
        }
255
 
 
256
 
        if ( test && !lp_file_list_changed() )
257
 
                return(True);
258
 
 
259
 
        ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
260
 
 
261
 
        /* perhaps the config filename is now set */
262
 
        if ( !test ) {
263
 
                DEBUG( 3, ( "services not loaded\n" ) );
264
 
                reload_nmbd_services( True );
265
 
        }
266
 
 
267
 
        return(ret);
268
 
}
269
 
 
270
 
/**************************************************************************** **
271
 
 * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP
272
 
 * We use buf here to return BOOL result to process() when reload_interfaces()
273
 
 * detects that there are no subnets.
274
 
 **************************************************************************** */
275
 
 
276
 
static void msg_reload_nmbd_services(int msg_type, struct process_id src,
277
 
                                     void *buf, size_t len)
278
 
{
279
 
        write_browse_list( 0, True );
280
 
        dump_all_namelists();
281
 
        reload_nmbd_services( True );
282
 
        reopen_logs();
283
 
        
284
 
        if(buf) {
285
 
                /* We were called from process() */
286
 
                /* If reload_interfaces() returned True */
287
 
                /* we need to shutdown if there are no subnets... */
288
 
                /* pass this info back to process() */
289
 
                *((BOOL*)buf) = reload_interfaces(0);  
290
 
        }
291
 
}
292
 
 
293
 
static void msg_nmbd_send_packet(int msg_type, struct process_id src,
294
 
                                 void *buf, size_t len)
295
 
{
296
 
        struct packet_struct *p = (struct packet_struct *)buf;
297
 
        struct subnet_record *subrec;
298
 
        struct in_addr *local_ip;
299
 
 
300
 
        DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
301
 
 
302
 
        if (len != sizeof(struct packet_struct)) {
303
 
                DEBUG(2, ("Discarding invalid packet length from %d\n",
304
 
                          procid_to_pid(&src)));
305
 
                return;
306
 
        }
307
 
 
308
 
        if ((p->packet_type != NMB_PACKET) &&
309
 
            (p->packet_type != DGRAM_PACKET)) {
310
 
                DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
311
 
                          procid_to_pid(&src), p->packet_type));
312
 
                return;
313
 
        }
314
 
 
315
 
        local_ip = iface_ip(p->ip);
316
 
 
317
 
        if (local_ip == NULL) {
318
 
                DEBUG(2, ("Could not find ip for packet from %d\n",
319
 
                          procid_to_pid(&src)));
320
 
                return;
321
 
        }
322
 
 
323
 
        subrec = FIRST_SUBNET;
324
 
 
325
 
        p->fd = (p->packet_type == NMB_PACKET) ?
326
 
                subrec->nmb_sock : subrec->dgram_sock;
327
 
 
328
 
        for (subrec = FIRST_SUBNET; subrec != NULL;
329
 
             subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
330
 
                if (ip_equal(*local_ip, subrec->myip)) {
331
 
                        p->fd = (p->packet_type == NMB_PACKET) ?
332
 
                                subrec->nmb_sock : subrec->dgram_sock;
333
 
                        break;
334
 
                }
335
 
        }
336
 
 
337
 
        if (p->packet_type == DGRAM_PACKET) {
338
 
                p->port = 138;
339
 
                p->packet.dgram.header.source_ip.s_addr = local_ip->s_addr;
340
 
                p->packet.dgram.header.source_port = 138;
341
 
        }
342
 
 
343
 
        send_packet(p);
344
 
}
345
 
 
346
 
/**************************************************************************** **
347
 
 The main select loop.
348
 
 **************************************************************************** */
349
 
 
350
 
static void process(void)
351
 
{
352
 
        BOOL run_election;
353
 
        BOOL no_subnets;
354
 
 
355
 
        while( True ) {
356
 
                time_t t = time(NULL);
357
 
 
358
 
                /* Check for internal messages */
359
 
 
360
 
                message_dispatch();
361
 
 
362
 
                /*
363
 
                 * Check all broadcast subnets to see if
364
 
                 * we need to run an election on any of them.
365
 
                 * (nmbd_elections.c)
366
 
                 */
367
 
 
368
 
                run_election = check_elections();
369
 
 
370
 
                /*
371
 
                 * Read incoming UDP packets.
372
 
                 * (nmbd_packets.c)
373
 
                 */
374
 
 
375
 
                if(listen_for_packets(run_election))
376
 
                        return;
377
 
 
378
 
                /*
379
 
                 * Handle termination inband.
380
 
                 */
381
 
 
382
 
                if (got_sig_term) {
383
 
                        got_sig_term = 0;
384
 
                        terminate();
385
 
                }
386
 
 
387
 
                /*
388
 
                 * Process all incoming packets
389
 
                 * read above. This calls the success and
390
 
                 * failure functions registered when response
391
 
                 * packets arrrive, and also deals with request
392
 
                 * packets from other sources.
393
 
                 * (nmbd_packets.c)
394
 
                 */
395
 
 
396
 
                run_packet_queue();
397
 
 
398
 
                /*
399
 
                 * Run any elections - initiate becoming
400
 
                 * a local master browser if we have won.
401
 
                 * (nmbd_elections.c)
402
 
                 */
403
 
 
404
 
                run_elections(t);
405
 
 
406
 
                /*
407
 
                 * Send out any broadcast announcements
408
 
                 * of our server names. This also announces
409
 
                 * the workgroup name if we are a local
410
 
                 * master browser.
411
 
                 * (nmbd_sendannounce.c)
412
 
                 */
413
 
 
414
 
                announce_my_server_names(t);
415
 
 
416
 
                /*
417
 
                 * Send out any LanMan broadcast announcements
418
 
                 * of our server names.
419
 
                 * (nmbd_sendannounce.c)
420
 
                 */
421
 
 
422
 
                announce_my_lm_server_names(t);
423
 
 
424
 
                /*
425
 
                 * If we are a local master browser, periodically
426
 
                 * announce ourselves to the domain master browser.
427
 
                 * This also deals with syncronising the domain master
428
 
                 * browser server lists with ourselves as a local
429
 
                 * master browser.
430
 
                 * (nmbd_sendannounce.c)
431
 
                 */
432
 
 
433
 
                announce_myself_to_domain_master_browser(t);
434
 
 
435
 
                /*
436
 
                 * Fullfill any remote announce requests.
437
 
                 * (nmbd_sendannounce.c)
438
 
                 */
439
 
 
440
 
                announce_remote(t);
441
 
 
442
 
                /*
443
 
                 * Fullfill any remote browse sync announce requests.
444
 
                 * (nmbd_sendannounce.c)
445
 
                 */
446
 
 
447
 
                browse_sync_remote(t);
448
 
 
449
 
                /*
450
 
                 * Scan the broadcast subnets, and WINS client
451
 
                 * namelists and refresh any that need refreshing.
452
 
                 * (nmbd_mynames.c)
453
 
                 */
454
 
 
455
 
                refresh_my_names(t);
456
 
 
457
 
                /*
458
 
                 * Scan the subnet namelists and server lists and
459
 
                 * expire thos that have timed out.
460
 
                 * (nmbd.c)
461
 
                 */
462
 
 
463
 
                expire_names_and_servers(t);
464
 
 
465
 
                /*
466
 
                 * Write out a snapshot of our current browse list into
467
 
                 * the browse.dat file. This is used by smbd to service
468
 
                 * incoming NetServerEnum calls - used to synchronise
469
 
                 * browse lists over subnets.
470
 
                 * (nmbd_serverlistdb.c)
471
 
                 */
472
 
 
473
 
                write_browse_list(t, False);
474
 
 
475
 
                /*
476
 
                 * If we are a domain master browser, we have a list of
477
 
                 * local master browsers we should synchronise browse
478
 
                 * lists with (these are added by an incoming local
479
 
                 * master browser announcement packet). Expire any of
480
 
                 * these that are no longer current, and pull the server
481
 
                 * lists from each of these known local master browsers.
482
 
                 * (nmbd_browsesync.c)
483
 
                 */
484
 
 
485
 
                dmb_expire_and_sync_browser_lists(t);
486
 
 
487
 
                /*
488
 
                 * Check that there is a local master browser for our
489
 
                 * workgroup for all our broadcast subnets. If one
490
 
                 * is not found, start an election (which we ourselves
491
 
                 * may or may not participate in, depending on the
492
 
                 * setting of the 'local master' parameter.
493
 
                 * (nmbd_elections.c)
494
 
                 */
495
 
 
496
 
                check_master_browser_exists(t);
497
 
 
498
 
                /*
499
 
                 * If we are configured as a logon server, attempt to
500
 
                 * register the special NetBIOS names to become such
501
 
                 * (WORKGROUP<1c> name) on all broadcast subnets and
502
 
                 * with the WINS server (if used). If we are configured
503
 
                 * to become a domain master browser, attempt to register
504
 
                 * the special NetBIOS name (WORKGROUP<1b> name) to
505
 
                 * become such.
506
 
                 * (nmbd_become_dmb.c)
507
 
                 */
508
 
 
509
 
                add_domain_names(t);
510
 
 
511
 
                /*
512
 
                 * If we are a WINS server, do any timer dependent
513
 
                 * processing required.
514
 
                 * (nmbd_winsserver.c)
515
 
                 */
516
 
 
517
 
                initiate_wins_processing(t);
518
 
 
519
 
                /*
520
 
                 * If we are a domain master browser, attempt to contact the
521
 
                 * WINS server to get a list of all known WORKGROUPS/DOMAINS.
522
 
                 * This will only work to a Samba WINS server.
523
 
                 * (nmbd_browsesync.c)
524
 
                 */
525
 
 
526
 
                if (lp_enhanced_browsing())
527
 
                        collect_all_workgroup_names_from_wins_server(t);
528
 
 
529
 
                /*
530
 
                 * Go through the response record queue and time out or re-transmit
531
 
                 * and expired entries.
532
 
                 * (nmbd_packets.c)
533
 
                 */
534
 
 
535
 
                retransmit_or_expire_response_records(t);
536
 
 
537
 
                /*
538
 
                 * check to see if any remote browse sync child processes have completed
539
 
                 */
540
 
 
541
 
                sync_check_completion();
542
 
 
543
 
                /*
544
 
                 * regularly sync with any other DMBs we know about 
545
 
                 */
546
 
 
547
 
                if (lp_enhanced_browsing())
548
 
                        sync_all_dmbs(t);
549
 
 
550
 
                /*
551
 
                 * clear the unexpected packet queue 
552
 
                 */
553
 
 
554
 
                clear_unexpected(t);
555
 
 
556
 
                /*
557
 
                 * Reload the services file if we got a sighup.
558
 
                 */
559
 
 
560
 
                if(reload_after_sighup) {
561
 
                        DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
562
 
                        msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
563
 
                                                 pid_to_procid(0), (void*) &no_subnets, 0);
564
 
                        if(no_subnets)
565
 
                                return;
566
 
                        reload_after_sighup = 0;
567
 
                }
568
 
 
569
 
                /* check for new network interfaces */
570
 
 
571
 
                if(reload_interfaces(t))
572
 
                        return;
573
 
 
574
 
                /* free up temp memory */
575
 
                        lp_TALLOC_FREE();
576
 
        }
577
 
}
578
 
 
579
 
/**************************************************************************** **
580
 
 Open the socket communication.
581
 
 **************************************************************************** */
582
 
 
583
 
static BOOL open_sockets(BOOL isdaemon, int port)
584
 
{
585
 
        /*
586
 
         * The sockets opened here will be used to receive broadcast
587
 
         * packets *only*. Interface specific sockets are opened in
588
 
         * make_subnet() in namedbsubnet.c. Thus we bind to the
589
 
         * address "0.0.0.0". The parameter 'socket address' is
590
 
         * now deprecated.
591
 
         */
592
 
 
593
 
        if ( isdaemon )
594
 
                ClientNMB = open_socket_in(SOCK_DGRAM, port,
595
 
                                           0, interpret_addr(lp_socket_address()),
596
 
                                           True);
597
 
        else
598
 
                ClientNMB = 0;
599
 
  
600
 
        ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT,
601
 
                                           3, interpret_addr(lp_socket_address()),
602
 
                                           True);
603
 
 
604
 
        if ( ClientNMB == -1 )
605
 
                return( False );
606
 
 
607
 
        /* we are never interested in SIGPIPE */
608
 
        BlockSignals(True,SIGPIPE);
609
 
 
610
 
        set_socket_options( ClientNMB,   "SO_BROADCAST" );
611
 
        set_socket_options( ClientDGRAM, "SO_BROADCAST" );
612
 
 
613
 
        /* Ensure we're non-blocking. */
614
 
        set_blocking( ClientNMB, False);
615
 
        set_blocking( ClientDGRAM, False);
616
 
 
617
 
        DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
618
 
        return( True );
619
 
}
620
 
 
621
 
/**************************************************************************** **
622
 
 main program
623
 
 **************************************************************************** */
624
 
 int main(int argc, const char *argv[])
625
 
{
626
 
        pstring logfile;
627
 
        static BOOL opt_interactive;
628
 
        poptContext pc;
629
 
        static char *p_lmhosts = dyn_LMHOSTSFILE;
630
 
        static BOOL no_process_group = False;
631
 
        struct poptOption long_options[] = {
632
 
        POPT_AUTOHELP
633
 
        {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
634
 
        {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
635
 
        {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
636
 
        {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
637
 
        {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
638
 
        {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
639
 
        {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
640
 
        POPT_COMMON_SAMBA
641
 
        { NULL }
642
 
        };
643
 
 
644
 
        load_case_tables();
645
 
 
646
 
        global_nmb_port = NMB_PORT;
647
 
 
648
 
        pc = poptGetContext("nmbd", argc, argv, long_options, 0);
649
 
        while (poptGetNextOpt(pc) != -1) {};
650
 
        poptFreeContext(pc);
651
 
 
652
 
        global_in_nmbd = True;
653
 
        
654
 
        StartupTime = time(NULL);
655
 
        
656
 
        sys_srandom(time(NULL) ^ sys_getpid());
657
 
        
658
 
        if (!override_logfile) {
659
 
                slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
660
 
                lp_set_logfile(logfile);
661
 
        }
662
 
        
663
 
        fault_setup((void (*)(void *))fault_continue );
664
 
        dump_core_setup("nmbd");
665
 
        
666
 
        /* POSIX demands that signals are inherited. If the invoking process has
667
 
         * these signals masked, we will have problems, as we won't receive them. */
668
 
        BlockSignals(False, SIGHUP);
669
 
        BlockSignals(False, SIGUSR1);
670
 
        BlockSignals(False, SIGTERM);
671
 
        
672
 
        CatchSignal( SIGHUP,  SIGNAL_CAST sig_hup );
673
 
        CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
674
 
        
675
 
#if defined(SIGFPE)
676
 
        /* we are never interested in SIGFPE */
677
 
        BlockSignals(True,SIGFPE);
678
 
#endif
679
 
 
680
 
        /* We no longer use USR2... */
681
 
#if defined(SIGUSR2)
682
 
        BlockSignals(True, SIGUSR2);
683
 
#endif
684
 
 
685
 
        if ( opt_interactive ) {
686
 
                Fork = False;
687
 
                log_stdout = True;
688
 
        }
689
 
 
690
 
        if ( log_stdout && Fork ) {
691
 
                DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
692
 
                exit(1);
693
 
        }
694
 
 
695
 
        setup_logging( argv[0], log_stdout );
696
 
 
697
 
        reopen_logs();
698
 
 
699
 
        DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) );
700
 
        DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
701
 
 
702
 
        if ( !reload_nmbd_services(False) )
703
 
                return(-1);
704
 
 
705
 
        if(!init_names())
706
 
                return -1;
707
 
 
708
 
        reload_nmbd_services( True );
709
 
 
710
 
        if (strequal(lp_workgroup(),"*")) {
711
 
                DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
712
 
                exit(1);
713
 
        }
714
 
 
715
 
        set_samba_nb_type();
716
 
 
717
 
        if (!is_daemon && !is_a_socket(0)) {
718
 
                DEBUG(0,("standard input is not a socket, assuming -D option\n"));
719
 
                is_daemon = True;
720
 
        }
721
 
  
722
 
        if (is_daemon && !opt_interactive) {
723
 
                DEBUG( 2, ( "Becoming a daemon.\n" ) );
724
 
                become_daemon(Fork, no_process_group);
725
 
        }
726
 
 
727
 
#if HAVE_SETPGID
728
 
        /*
729
 
         * If we're interactive we want to set our own process group for 
730
 
         * signal management.
731
 
         */
732
 
        if (opt_interactive && !no_process_group)
733
 
                setpgid( (pid_t)0, (pid_t)0 );
734
 
#endif
735
 
 
736
 
#ifndef SYNC_DNS
737
 
        /* Setup the async dns. We do it here so it doesn't have all the other
738
 
                stuff initialised and thus chewing memory and sockets */
739
 
        if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
740
 
                start_async_dns();
741
 
        }
742
 
#endif
743
 
 
744
 
        if (!directory_exist(lp_lockdir(), NULL)) {
745
 
                mkdir(lp_lockdir(), 0755);
746
 
        }
747
 
 
748
 
        pidfile_create("nmbd");
749
 
        message_init();
750
 
        message_register(MSG_FORCE_ELECTION, nmbd_message_election);
751
 
#if 0
752
 
        /* Until winsrepl is done. */
753
 
        message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
754
 
#endif
755
 
        message_register(MSG_SHUTDOWN, nmbd_terminate);
756
 
        message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services);
757
 
        message_register(MSG_SEND_PACKET, msg_nmbd_send_packet);
758
 
 
759
 
        TimeInit();
760
 
 
761
 
        DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
762
 
 
763
 
        if ( !open_sockets( is_daemon, global_nmb_port ) ) {
764
 
                kill_async_dns_child();
765
 
                return 1;
766
 
        }
767
 
 
768
 
        /* Determine all the IP addresses we have. */
769
 
        load_interfaces();
770
 
 
771
 
        /* Create an nmbd subnet record for each of the above. */
772
 
        if( False == create_subnets() ) {
773
 
                DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
774
 
                kill_async_dns_child();
775
 
                exit(1);
776
 
        }
777
 
 
778
 
        /* Load in any static local names. */ 
779
 
        load_lmhosts_file(p_lmhosts);
780
 
        DEBUG(3,("Loaded hosts file %s\n", p_lmhosts));
781
 
 
782
 
        /* If we are acting as a WINS server, initialise data structures. */
783
 
        if( !initialise_wins() ) {
784
 
                DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
785
 
                kill_async_dns_child();
786
 
                exit(1);
787
 
        }
788
 
 
789
 
        /* 
790
 
         * Register nmbd primary workgroup and nmbd names on all
791
 
         * the broadcast subnets, and on the WINS server (if specified).
792
 
         * Also initiate the startup of our primary workgroup (start
793
 
         * elections if we are setup as being able to be a local
794
 
         * master browser.
795
 
         */
796
 
 
797
 
        if( False == register_my_workgroup_and_names() ) {
798
 
                DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
799
 
                kill_async_dns_child();
800
 
                exit(1);
801
 
        }
802
 
 
803
 
        /* We can only take signals in the select. */
804
 
        BlockSignals( True, SIGTERM );
805
 
 
806
 
        process();
807
 
 
808
 
        if (dbf)
809
 
                x_fclose(dbf);
810
 
        kill_async_dns_child();
811
 
        return(0);
812
 
}