1996-05-04 11:50:46 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Main SMB server routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
pstring servicesf = CONFIGFILE ;
extern pstring debugf ;
1998-04-25 05:12:08 +04:00
extern fstring global_myworkgroup ;
1998-04-30 02:27:26 +04:00
extern pstring global_myname ;
1996-05-04 11:50:46 +04:00
1996-12-10 21:00:22 +03:00
int am_parent = 1 ;
1996-05-04 11:50:46 +04:00
/* the last message the was processed */
int last_message = - 1 ;
/* a useful macro to debug the last message processed */
# define LAST_MESSAGE() smb_fn_name(last_message)
extern pstring user_socket_options ;
1998-07-29 07:08:05 +04:00
# ifdef WITH_DFS
1998-03-04 04:50:47 +03:00
extern int dcelogin_atmost_once ;
1998-07-29 07:08:05 +04:00
# endif /* WITH_DFS */
1998-03-04 04:50:47 +03:00
1996-05-04 11:50:46 +04:00
extern fstring remote_machine ;
2000-04-11 17:55:53 +04:00
/* really we should have a top level context structure that has the
client file descriptor as an element . That would require a major rewrite : (
the following 2 functions are an alternative - they make the file
descriptor private to smbd
*/
2000-05-10 02:05:39 +04:00
static int server_fd = - 1 ;
2000-04-11 17:55:53 +04:00
int smbd_server_fd ( void )
{
return server_fd ;
}
void smbd_set_server_fd ( int fd )
{
server_fd = fd ;
client_setfd ( fd ) ;
}
1996-12-10 21:00:22 +03:00
/****************************************************************************
when exiting , take the whole family
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-05 09:07:05 +04:00
static void * dflt_sig ( void )
1996-12-10 21:00:22 +03:00
{
1998-08-17 18:11:44 +04:00
exit_server ( " caught signal " ) ;
return NULL ;
1996-12-10 21:00:22 +03:00
}
1998-08-17 18:11:44 +04:00
1996-12-10 21:00:22 +03:00
/****************************************************************************
Send a SIGTERM to our process group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-05 09:07:05 +04:00
static void killkids ( void )
1996-12-10 21:00:22 +03:00
{
1998-08-17 18:11:44 +04:00
if ( am_parent ) kill ( 0 , SIGTERM ) ;
1996-12-10 21:00:22 +03:00
}
1996-05-04 11:50:46 +04:00
2001-08-28 10:34:53 +04:00
/****************************************************************************
process a sam sync message - not sure whether to do this here or
somewhere else
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void msg_sam_sync ( int msg_type , pid_t pid , void * buf , size_t len )
{
DEBUG ( 10 , ( " ** sam sync message received, ignoring \n " ) ) ;
}
/****************************************************************************
process a sam sync replicate message - not sure whether to do this here or
somewhere else
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void msg_sam_repl ( int msg_type , pid_t pid , void * buf , size_t len )
{
uint32 low_serial ;
if ( len ! = sizeof ( uint32 ) )
return ;
low_serial = * ( ( uint32 * ) buf ) ;
DEBUG ( 3 , ( " received sam replication message, serial = 0x%04x \n " ,
low_serial ) ) ;
}
1997-09-23 23:19:06 +04:00
1997-09-30 06:38:19 +04:00
/****************************************************************************
1998-08-17 17:11:34 +04:00
open the socket communication
1997-09-30 06:38:19 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 18:11:44 +04:00
static BOOL open_sockets_inetd ( void )
1997-09-30 06:38:19 +04:00
{
1998-08-17 18:11:44 +04:00
/* Started from inetd. fd 0 is the socket. */
/* We will abort gracefully when the client or remote system
goes away */
2000-04-11 17:55:53 +04:00
smbd_set_server_fd ( dup ( 0 ) ) ;
1998-08-17 18:11:44 +04:00
/* close our standard file descriptors */
close_low_fds ( ) ;
2000-04-11 17:55:53 +04:00
set_socket_options ( smbd_server_fd ( ) , " SO_KEEPALIVE " ) ;
set_socket_options ( smbd_server_fd ( ) , user_socket_options ) ;
1998-08-17 18:11:44 +04:00
return True ;
}
1997-10-02 03:32:22 +04:00
1997-09-25 04:25:44 +04:00
1998-08-17 18:11:44 +04:00
/****************************************************************************
open the socket communication
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static BOOL open_sockets ( BOOL is_daemon , int port )
1998-08-17 18:11:44 +04:00
{
int num_interfaces = iface_count ( ) ;
int fd_listenset [ FD_SETSIZE ] ;
fd_set listen_set ;
int s ;
int i ;
if ( ! is_daemon ) {
return open_sockets_inetd ( ) ;
}
1998-08-17 17:11:34 +04:00
# ifdef HAVE_ATEXIT
1998-08-17 18:11:44 +04:00
{
static int atexit_set ;
if ( atexit_set = = 0 ) {
atexit_set = 1 ;
atexit ( killkids ) ;
}
}
1998-08-17 17:11:34 +04:00
# endif
1997-10-02 07:26:07 +04:00
1998-08-17 18:11:44 +04:00
/* Stop zombies */
CatchChild ( ) ;
FD_ZERO ( & listen_set ) ;
if ( lp_interfaces ( ) & & lp_bind_interfaces_only ( ) ) {
/* We have been given an interfaces line, and been
told to only bind to those interfaces . Create a
socket per interface and bind to only these .
*/
1999-12-13 16:27:58 +03:00
if ( num_interfaces > FD_SETSIZE ) {
1998-08-17 18:11:44 +04:00
DEBUG ( 0 , ( " open_sockets: Too many interfaces specified to bind to. Number was %d \
max can be % d \ n " ,
num_interfaces , FD_SETSIZE ) ) ;
return False ;
}
/* Now open a listen socket for each of the
interfaces . */
for ( i = 0 ; i < num_interfaces ; i + + ) {
struct in_addr * ifip = iface_n_ip ( i ) ;
if ( ifip = = NULL ) {
DEBUG ( 0 , ( " open_sockets: interface %d has NULL IP address ! \n " , i ) ) ;
continue ;
}
1999-12-13 16:27:58 +03:00
s = fd_listenset [ i ] = open_socket_in ( SOCK_STREAM , port , 0 , ifip - > s_addr , True ) ;
if ( s = = - 1 )
return False ;
2001-08-09 16:52:05 +04:00
/* ready to listen */
set_socket_options ( s , " SO_KEEPALIVE " ) ;
set_socket_options ( s , user_socket_options ) ;
1999-12-13 16:27:58 +03:00
if ( listen ( s , 5 ) = = - 1 ) {
DEBUG ( 0 , ( " listen: %s \n " , strerror ( errno ) ) ) ;
close ( s ) ;
return False ;
}
1998-08-17 18:11:44 +04:00
FD_SET ( s , & listen_set ) ;
}
} else {
/* Just bind to 0.0.0.0 - accept connections
from anywhere . */
num_interfaces = 1 ;
/* open an incoming socket */
1999-12-13 16:27:58 +03:00
s = open_socket_in ( SOCK_STREAM , port , 0 ,
interpret_addr ( lp_socket_address ( ) ) , True ) ;
1998-08-17 18:11:44 +04:00
if ( s = = - 1 )
return ( False ) ;
1999-12-13 16:27:58 +03:00
/* ready to listen */
2001-08-09 16:52:05 +04:00
set_socket_options ( s , " SO_KEEPALIVE " ) ;
set_socket_options ( s , user_socket_options ) ;
1999-12-13 16:27:58 +03:00
if ( listen ( s , 5 ) = = - 1 ) {
DEBUG ( 0 , ( " open_sockets: listen: %s \n " ,
strerror ( errno ) ) ) ;
close ( s ) ;
return False ;
}
1998-08-17 18:11:44 +04:00
fd_listenset [ 0 ] = s ;
FD_SET ( s , & listen_set ) ;
}
2001-08-28 10:34:53 +04:00
/* Listen to messages */
message_register ( MSG_SMB_SAM_SYNC , msg_sam_sync ) ;
message_register ( MSG_SMB_SAM_REPL , msg_sam_repl ) ;
1998-08-17 18:11:44 +04:00
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG ( 2 , ( " waiting for a connection \n " ) ) ;
while ( 1 ) {
fd_set lfds ;
int num ;
2000-11-22 22:42:54 +03:00
/* Free up temporary memory from the main smbd. */
lp_talloc_free ( ) ;
2000-11-28 00:37:07 +03:00
/* Ensure we respond to PING and DEBUG messages from the main smbd. */
message_dispatch ( ) ;
1998-08-17 18:11:44 +04:00
memcpy ( ( char * ) & lfds , ( char * ) & listen_set ,
sizeof ( listen_set ) ) ;
2000-07-24 10:20:13 +04:00
num = sys_select ( FD_SETSIZE , & lfds , NULL ) ;
1998-08-17 18:11:44 +04:00
2000-07-24 10:20:13 +04:00
if ( num = = - 1 & & errno = = EINTR ) {
2001-06-25 06:53:13 +04:00
extern VOLATILE sig_atomic_t reload_after_sighup ;
2000-07-24 10:20:13 +04:00
/* check for sighup processing */
if ( reload_after_sighup ) {
unbecome_user ( ) ;
DEBUG ( 1 , ( " Reloading services after SIGHUP \n " ) ) ;
reload_services ( False ) ;
reload_after_sighup = False ;
}
1998-08-17 18:11:44 +04:00
continue ;
2000-07-24 10:20:13 +04:00
}
1998-08-17 18:11:44 +04:00
1999-12-13 16:27:58 +03:00
/* check if we need to reload services */
check_reload ( time ( NULL ) ) ;
1998-08-17 18:11:44 +04:00
/* Find the sockets that are read-ready -
accept on these . */
for ( ; num > 0 ; num - - ) {
struct sockaddr addr ;
2001-06-25 06:53:13 +04:00
socklen_t in_addrlen = sizeof ( addr ) ;
1998-08-17 18:11:44 +04:00
s = - 1 ;
for ( i = 0 ; i < num_interfaces ; i + + ) {
1999-12-13 16:27:58 +03:00
if ( FD_ISSET ( fd_listenset [ i ] , & lfds ) ) {
s = fd_listenset [ i ] ;
/* Clear this so we don't look
at it again . */
FD_CLR ( fd_listenset [ i ] , & lfds ) ;
1999-09-08 23:37:45 +04:00
break ;
}
1998-08-17 18:11:44 +04:00
}
2000-04-11 17:55:53 +04:00
smbd_set_server_fd ( accept ( s , & addr , & in_addrlen ) ) ;
1998-08-17 18:11:44 +04:00
2000-04-11 17:55:53 +04:00
if ( smbd_server_fd ( ) = = - 1 & & errno = = EINTR )
1998-08-17 18:11:44 +04:00
continue ;
2000-04-11 17:55:53 +04:00
if ( smbd_server_fd ( ) = = - 1 ) {
1998-08-17 18:11:44 +04:00
DEBUG ( 0 , ( " open_sockets: accept: %s \n " ,
strerror ( errno ) ) ) ;
continue ;
}
2000-05-02 06:23:41 +04:00
if ( smbd_server_fd ( ) ! = - 1 & & sys_fork ( ) = = 0 ) {
1998-08-17 18:11:44 +04:00
/* Child code ... */
/* close the listening socket(s) */
for ( i = 0 ; i < num_interfaces ; i + + )
close ( fd_listenset [ i ] ) ;
/* close our standard file
descriptors */
close_low_fds ( ) ;
am_parent = 0 ;
2000-04-11 17:55:53 +04:00
set_socket_options ( smbd_server_fd ( ) , " SO_KEEPALIVE " ) ;
set_socket_options ( smbd_server_fd ( ) , user_socket_options ) ;
1998-08-17 18:11:44 +04:00
/* Reset global variables in util.c so
that client substitutions will be
done correctly in the process . */
reset_globals_after_fork ( ) ;
1998-09-26 03:40:49 +04:00
2001-09-19 09:43:15 +04:00
/* tdb needs special fork handling */
tdb_reopen_all ( ) ;
1998-08-17 18:11:44 +04:00
return True ;
}
/* The parent doesn't need this socket */
2000-04-11 17:55:53 +04:00
close ( smbd_server_fd ( ) ) ;
1998-08-17 18:11:44 +04:00
2001-05-08 04:03:45 +04:00
/* Sun May 6 18:56:14 2001 ackley@cs.unm.edu:
Clear the closed fd info out of server_fd - -
and more importantly , out of client_fd in
util_sock . c , to avoid a possible
getpeername failure if we reopen the logs
and use % I in the filename .
*/
smbd_set_server_fd ( - 1 ) ;
1998-08-17 18:11:44 +04:00
/* Force parent to check log size after
* spawning child . Fix from
* klausr @ ITAP . Physik . Uni - Stuttgart . De . The
* parent smbd will log to logserver . smb . It
* writes only two messages for each child
* started / finished . But each child writes ,
* say , 50 messages also in logserver . smb ,
* begining with the debug_count of the
* parent , before the child opens its own log
* file logserver . client . In a worst case
* scenario the size of logserver . smb would be
* checked after about 50 * 50 = 2500 messages
* ( ca . 100 kb ) .
* */
force_check_log_size ( ) ;
1998-08-17 17:11:34 +04:00
1998-08-17 18:11:44 +04:00
} /* end for num */
} /* end while 1 */
1998-08-28 00:38:53 +04:00
/* NOTREACHED return True; */
1997-11-19 02:30:49 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
reload the services file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL reload_services ( BOOL test )
{
1998-08-14 21:38:29 +04:00
BOOL ret ;
2000-03-09 01:14:30 +03:00
1998-08-14 21:38:29 +04:00
if ( lp_loaded ( ) ) {
pstring fname ;
pstrcpy ( fname , lp_configfile ( ) ) ;
1998-08-17 17:11:34 +04:00
if ( file_exist ( fname , NULL ) & & ! strcsequal ( fname , servicesf ) ) {
pstrcpy ( servicesf , fname ) ;
test = False ;
1998-08-14 21:38:29 +04:00
}
}
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
if ( test & & ! lp_file_list_changed ( ) )
return ( True ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
lp_killunused ( conn_snum_used ) ;
2000-03-09 01:14:30 +03:00
1998-08-17 17:11:34 +04:00
ret = lp_load ( servicesf , False , False , True ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
load_printers ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
/* perhaps the config filename is now set */
if ( ! test )
reload_services ( True ) ;
1997-10-08 04:21:39 +04:00
1998-08-17 17:11:34 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
load_interfaces ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
{
2000-04-11 17:55:53 +04:00
if ( smbd_server_fd ( ) ! = - 1 ) {
set_socket_options ( smbd_server_fd ( ) , " SO_KEEPALIVE " ) ;
set_socket_options ( smbd_server_fd ( ) , user_socket_options ) ;
1998-08-17 17:11:34 +04:00
}
1998-08-14 21:38:29 +04:00
}
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
reset_mangled_cache ( ) ;
2000-05-10 15:45:16 +04:00
reset_stat_cache ( ) ;
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
/* this forces service parameters to be flushed */
become_service ( NULL , True ) ;
1998-01-31 17:31:08 +03:00
1998-08-17 17:11:34 +04:00
return ( ret ) ;
1998-01-31 17:31:08 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Catch a sighup .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2001-06-25 06:53:13 +04:00
VOLATILE sig_atomic_t reload_after_sighup = False ;
1996-05-04 11:50:46 +04:00
1998-08-17 17:11:34 +04:00
static void sig_hup ( int sig )
{
1998-08-17 18:11:44 +04:00
BlockSignals ( True , SIGHUP ) ;
DEBUG ( 0 , ( " Got SIGHUP \n " ) ) ;
1996-05-04 11:50:46 +04:00
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
(This used to be commit 44766c39e0027c762bee8b33b12c621c109a3267)
2000-06-12 19:53:31 +04:00
sys_select_signal ( ) ;
1998-08-17 18:11:44 +04:00
reload_after_sighup = True ;
BlockSignals ( False , SIGHUP ) ;
1996-05-04 11:50:46 +04:00
}
# if DUMP_CORE
/*******************************************************************
prepare to dump a core file - carefully !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL dump_core ( void )
{
1998-08-17 18:11:44 +04:00
char * p ;
pstring dname ;
pstrcpy ( dname , debugf ) ;
2001-07-04 11:36:09 +04:00
if ( ( p = strrchr_m ( dname , ' / ' ) ) ) * p = 0 ;
1998-08-17 18:11:44 +04:00
pstrcat ( dname , " /corefiles " ) ;
mkdir ( dname , 0700 ) ;
sys_chown ( dname , getuid ( ) , getgid ( ) ) ;
chmod ( dname , 0700 ) ;
if ( chdir ( dname ) ) return ( False ) ;
umask ( ~ ( 0700 ) ) ;
1996-05-04 11:50:46 +04:00
1998-07-29 07:08:05 +04:00
# ifdef HAVE_GETRLIMIT
1996-05-04 11:50:46 +04:00
# ifdef RLIMIT_CORE
1998-08-17 18:11:44 +04:00
{
struct rlimit rlp ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
rlp . rlim_cur = MAX ( 4 * 1024 * 1024 , rlp . rlim_cur ) ;
setrlimit ( RLIMIT_CORE , & rlp ) ;
getrlimit ( RLIMIT_CORE , & rlp ) ;
DEBUG ( 3 , ( " Core limits now %d %d \n " ,
( int ) rlp . rlim_cur , ( int ) rlp . rlim_max ) ) ;
}
1996-05-04 11:50:46 +04:00
# endif
# endif
1998-08-17 18:11:44 +04:00
DEBUG ( 0 , ( " Dumping core in %s \n " , dname ) ) ;
abort ( ) ;
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
# endif
2001-02-12 19:18:02 +03:00
/****************************************************************************
update the current smbd process count
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-25 04:48:28 +04:00
2001-02-12 19:18:02 +03:00
static void decrement_smbd_process_count ( void )
{
int total_smbds ;
if ( lp_max_smbd_processes ( ) ) {
2001-05-25 04:48:28 +04:00
total_smbds = 0 ;
tdb_change_int_atomic ( conn_tdb_ctx ( ) , " INFO/total_smbds " , & total_smbds , - 1 ) ;
2001-02-12 19:18:02 +03:00
}
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
exit the server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void exit_server ( char * reason )
{
1998-08-17 18:11:44 +04:00
static int firsttime = 1 ;
extern char * last_inbuf ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! firsttime ) exit ( 0 ) ;
firsttime = 0 ;
1998-08-17 10:13:32 +04:00
1998-08-17 18:11:44 +04:00
unbecome_user ( ) ;
DEBUG ( 2 , ( " Closing connections \n " ) ) ;
conn_close_all ( ) ;
1998-08-17 10:13:32 +04:00
2001-04-18 20:41:04 +04:00
invalidate_all_vuids ( ) ;
2001-01-09 00:19:15 +03:00
/* delete our entry in the connections database. */
2001-08-22 23:11:55 +04:00
yield_connection ( NULL , " " , MAXSTATUS ) ;
2001-01-09 00:19:15 +03:00
2001-04-18 20:41:04 +04:00
respond_to_all_remaining_local_messages ( ) ;
2001-02-12 19:18:02 +03:00
decrement_smbd_process_count ( ) ;
1999-12-13 16:27:58 +03:00
1998-07-29 07:08:05 +04:00
# ifdef WITH_DFS
1998-08-17 18:11:44 +04:00
if ( dcelogin_atmost_once ) {
dfs_unlogin ( ) ;
}
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
if ( ! reason ) {
int oldlevel = DEBUGLEVEL ;
DEBUGLEVEL = 10 ;
DEBUG ( 0 , ( " Last message was %s \n " , smb_fn_name ( last_message ) ) ) ;
if ( last_inbuf )
show_msg ( last_inbuf ) ;
DEBUGLEVEL = oldlevel ;
DEBUG ( 0 , ( " =============================================================== \n " ) ) ;
1996-05-04 11:50:46 +04:00
# if DUMP_CORE
1998-08-17 18:11:44 +04:00
if ( dump_core ( ) ) return ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
}
1997-01-09 21:02:17 +03:00
1998-08-17 18:11:44 +04:00
locking_end ( ) ;
1997-01-09 21:02:17 +03:00
1998-08-17 18:11:44 +04:00
DEBUG ( 3 , ( " Server exit (%s) \n " , ( reason ? reason : " " ) ) ) ;
exit ( 0 ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
initialise connect , service and file structs
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void init_structs ( void )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
/*
* Set the machine NETBIOS name if not already
* set from the config file .
*/
if ( ! * global_myname ) {
char * p ;
fstrcpy ( global_myname , myhostname ( ) ) ;
2001-07-04 11:36:09 +04:00
p = strchr_m ( global_myname , ' . ' ) ;
1999-12-13 16:27:58 +03:00
if ( p )
* p = 0 ;
}
strupper ( global_myname ) ;
1998-08-17 18:11:44 +04:00
conn_init ( ) ;
1999-12-13 16:27:58 +03:00
1998-08-17 18:11:44 +04:00
file_init ( ) ;
1999-12-13 16:27:58 +03:00
/* for RPC pipes */
init_rpc_pipe_hnd ( ) ;
1998-08-17 18:11:44 +04:00
init_dptrs ( ) ;
2000-05-08 14:42:21 +04:00
secrets_init ( ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
usage on the program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
static void usage ( char * pname )
1996-05-04 11:50:46 +04:00
{
1999-12-13 16:27:58 +03:00
2001-09-19 13:44:12 +04:00
d_printf ( " Usage: %s [-DaoPh?Vb] [-d debuglevel] [-l log basename] [-p port] \n " , pname ) ;
d_printf ( " [-O socket options] [-s services file] \n " ) ;
d_printf ( " \t -D Become a daemon \n " ) ;
d_printf ( " \t -a Append to log file (default) \n " ) ;
d_printf ( " \t -o Overwrite log file, don't append \n " ) ;
d_printf ( " \t -h Print usage \n " ) ;
d_printf ( " \t -? Print usage \n " ) ;
d_printf ( " \t -V Print version \n " ) ;
d_printf ( " \t -b Print build options \n " ) ;
d_printf ( " \t -d debuglevel Set the debuglevel \n " ) ;
d_printf ( " \t -l log basename. Basename for log/debug files \n " ) ;
d_printf ( " \t -p port Listen on the specified port \n " ) ;
d_printf ( " \t -O socket options Socket options \n " ) ;
d_printf ( " \t -s services file. Filename of services file \n " ) ;
d_printf ( " \n " ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
int main ( int argc , char * argv [ ] )
1996-05-04 11:50:46 +04:00
{
1998-08-17 18:11:44 +04:00
extern BOOL append_log ;
/* shall I run as a daemon */
BOOL is_daemon = False ;
2000-01-08 05:16:15 +03:00
BOOL specified_logfile = False ;
1998-08-17 18:11:44 +04:00
int port = SMB_PORT ;
int opt ;
extern char * optarg ;
1998-07-29 07:08:05 +04:00
# ifdef HAVE_SET_AUTH_PARAMETERS
1998-08-17 18:11:44 +04:00
set_auth_parameters ( argc , argv ) ;
1996-05-04 11:50:46 +04:00
# endif
1998-08-17 18:11:44 +04:00
/* this is for people who can't start the program correctly */
while ( argc > 1 & & ( * argv [ 1 ] ! = ' - ' ) ) {
argv + + ;
argc - - ;
1996-05-04 11:50:46 +04:00
}
2001-09-19 13:44:12 +04:00
while ( EOF ! = ( opt = getopt ( argc , argv , " O:l:s:d:Dp:h?bVaof: " ) ) )
1998-08-17 18:11:44 +04:00
switch ( opt ) {
case ' O ' :
pstrcpy ( user_socket_options , optarg ) ;
break ;
case ' s ' :
pstrcpy ( servicesf , optarg ) ;
break ;
case ' l ' :
2000-01-08 05:16:15 +03:00
specified_logfile = True ;
2001-07-18 00:42:59 +04:00
slprintf ( debugf , sizeof ( debugf ) - 1 , " %s/log.smbd " , optarg ) ;
1998-08-17 18:11:44 +04:00
break ;
case ' a ' :
1998-08-21 21:21:55 +04:00
append_log = True ;
break ;
case ' o ' :
append_log = False ;
1998-08-17 18:11:44 +04:00
break ;
case ' D ' :
is_daemon = True ;
break ;
case ' d ' :
if ( * optarg = = ' A ' )
DEBUGLEVEL = 10000 ;
else
DEBUGLEVEL = atoi ( optarg ) ;
break ;
case ' p ' :
port = atoi ( optarg ) ;
break ;
case ' h ' :
1998-08-21 21:21:55 +04:00
case ' ? ' :
1998-08-17 18:11:44 +04:00
usage ( argv [ 0 ] ) ;
exit ( 0 ) ;
break ;
1999-12-13 16:27:58 +03:00
case ' V ' :
2001-09-19 13:37:33 +04:00
d_printf ( " Version %s \n " , VERSION ) ;
1999-12-13 16:27:58 +03:00
exit ( 0 ) ;
break ;
2001-09-19 13:44:12 +04:00
case ' b ' :
build_options ( True ) ; /* Display output to screen as well as debug */
exit ( 0 ) ;
break ;
1998-08-17 18:11:44 +04:00
default :
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " Incorrect program usage - are you sure the command line is correct? \n " ) ) ;
1998-08-17 18:11:44 +04:00
usage ( argv [ 0 ] ) ;
exit ( 1 ) ;
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
# ifdef HAVE_SETLUID
/* needed for SecureWare on SCO */
setluid ( 0 ) ;
# endif
2001-06-25 04:46:34 +04:00
sec_init ( ) ;
1999-12-13 16:27:58 +03:00
2001-10-03 16:18:20 +04:00
load_case_tables ( ) ;
1999-12-13 16:27:58 +03:00
append_log = True ;
TimeInit ( ) ;
2000-05-10 13:49:55 +04:00
if ( ! specified_logfile ) {
2001-04-09 00:22:39 +04:00
slprintf ( debugf , sizeof ( debugf ) - 1 , " %s/log.smbd " , LOGFILEBASE ) ;
2000-05-10 13:49:55 +04:00
}
1999-12-13 16:27:58 +03:00
2001-02-15 22:50:34 +03:00
pstrcpy ( remote_machine , " smbd " ) ;
1999-12-13 16:27:58 +03:00
setup_logging ( argv [ 0 ] , False ) ;
/* we want to re-seed early to prevent time delays causing
client problems at a later date . ( tridge ) */
generate_random_buffer ( NULL , 0 , False ) ;
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */
gain_root_privilege ( ) ;
gain_root_group_privilege ( ) ;
fault_setup ( ( void ( * ) ( void * ) ) exit_server ) ;
CatchSignal ( SIGTERM , SIGNAL_CAST dflt_sig ) ;
/* we are never interested in SIGPIPE */
BlockSignals ( True , SIGPIPE ) ;
# if defined(SIGFPE)
/* we are never interested in SIGFPE */
BlockSignals ( True , SIGFPE ) ;
# endif
2000-10-13 01:19:49 +04:00
# if defined(SIGUSR2)
/* We are no longer interested in USR2 */
BlockSignals ( True , SIGUSR2 ) ;
# endif
2001-01-25 19:36:42 +03:00
/* POSIX demands that signals are inherited. If the invoking process has
* these signals masked , we will have problems , as we won ' t recieve them . */
BlockSignals ( False , SIGHUP ) ;
BlockSignals ( False , SIGUSR1 ) ;
1999-12-13 16:27:58 +03:00
/* we want total control over the permissions on created files,
so set our umask to 0 */
umask ( 0 ) ;
2000-06-23 09:54:49 +04:00
init_sec_ctx ( ) ;
1999-12-13 16:27:58 +03:00
1998-08-17 18:11:44 +04:00
reopen_logs ( ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
DEBUG ( 1 , ( " smbd version %s started. \n " , VERSION ) ) ;
1998-09-09 20:37:54 +04:00
DEBUGADD ( 1 , ( " Copyright Andrew Tridgell 1992-1998 \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
DEBUG ( 2 , ( " uid=%d gid=%d euid=%d egid=%d \n " ,
( int ) getuid ( ) , ( int ) getgid ( ) , ( int ) geteuid ( ) , ( int ) getegid ( ) ) ) ;
1996-05-04 11:50:46 +04:00
2001-09-19 13:44:12 +04:00
/* Output the build options to the debug log */
build_options ( False ) ;
1998-08-17 18:11:44 +04:00
if ( sizeof ( uint16 ) < 2 | | sizeof ( uint32 ) < 4 ) {
DEBUG ( 0 , ( " ERROR: Samba is not configured correctly for the word size on your machine \n " ) ) ;
exit ( 1 ) ;
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
/*
* Do this before reload_services .
*/
1999-02-08 04:46:46 +03:00
1998-08-17 18:11:44 +04:00
if ( ! reload_services ( False ) )
return ( - 1 ) ;
1996-05-04 11:50:46 +04:00
1999-02-08 04:46:46 +03:00
init_structs ( ) ;
2001-07-10 06:28:17 +04:00
/* don't call winbind for our domain if we are the DC */
if ( lp_domain_logons ( ) ) {
winbind_exclude_domain ( lp_workgroup ( ) ) ;
}
1999-12-13 16:27:58 +03:00
1999-04-01 09:22:58 +04:00
# ifdef WITH_PROFILE
if ( ! profile_setup ( False ) ) {
DEBUG ( 0 , ( " ERROR: failed to setup profiling \n " ) ) ;
return - 1 ;
}
# endif
1998-07-29 07:08:05 +04:00
# ifdef WITH_SSL
1998-08-17 18:11:44 +04:00
{
extern BOOL sslEnabled ;
sslEnabled = lp_ssl_enabled ( ) ;
if ( sslEnabled )
sslutil_init ( True ) ;
}
1998-07-29 07:08:05 +04:00
# endif /* WITH_SSL */
1998-06-16 05:35:52 +04:00
1999-12-13 16:27:58 +03:00
fstrcpy ( global_myworkgroup , lp_workgroup ( ) ) ;
1997-05-20 04:32:51 +04:00
1998-08-17 18:11:44 +04:00
CatchSignal ( SIGHUP , SIGNAL_CAST sig_hup ) ;
DEBUG ( 3 , ( " loaded services \n " ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( ! is_daemon & & ! is_a_socket ( 0 ) ) {
DEBUG ( 0 , ( " standard input is not a socket, assuming -D option \n " ) ) ;
is_daemon = True ;
}
1997-11-11 03:48:42 +03:00
1998-08-17 18:11:44 +04:00
if ( is_daemon ) {
DEBUG ( 3 , ( " Becoming a daemon. \n " ) ) ;
become_daemon ( ) ;
}
2000-02-07 19:22:16 +03:00
1998-08-17 18:11:44 +04:00
if ( ! directory_exist ( lp_lockdir ( ) , NULL ) ) {
mkdir ( lp_lockdir ( ) , 0755 ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
if ( is_daemon ) {
pidfile_create ( " smbd " ) ;
}
1996-08-15 19:11:34 +04:00
2000-10-12 23:42:18 +04:00
if ( ! message_init ( ) ) {
exit ( 1 ) ;
}
2000-11-28 00:37:07 +03:00
/* Setup the main smbd so that we can get messages. */
2001-08-22 23:11:55 +04:00
claim_connection ( NULL , " " , MAXSTATUS , True ) ;
2000-11-28 00:37:07 +03:00
2000-01-08 05:16:15 +03:00
if ( ! open_sockets ( is_daemon , port ) )
1998-08-17 18:11:44 +04:00
exit ( 1 ) ;
1998-05-19 03:57:28 +04:00
2000-01-08 05:16:15 +03:00
/*
2000-06-10 17:38:07 +04:00
* everything after this point is run after the fork ( )
2000-01-08 05:16:15 +03:00
*/
2000-06-10 17:38:07 +04:00
if ( ! locking_init ( 0 ) ) {
1999-12-13 16:27:58 +03:00
exit ( 1 ) ;
2000-06-10 17:38:07 +04:00
}
1999-12-13 16:27:58 +03:00
2000-04-16 10:22:31 +04:00
if ( ! print_backend_init ( ) ) {
exit ( 1 ) ;
}
2001-04-09 10:36:38 +04:00
if ( ! share_info_db_init ( ) ) {
exit ( 1 ) ;
}
2000-11-14 02:03:34 +03:00
if ( ! initialize_password_db ( False ) ) {
1998-08-17 18:11:44 +04:00
exit ( 1 ) ;
2000-06-10 17:38:07 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-17 18:11:44 +04:00
/* possibly reload the services file. */
reload_services ( True ) ;
2000-01-03 22:19:48 +03:00
2001-03-23 03:50:31 +03:00
if ( init_group_mapping ( ) = = False ) {
printf ( " Could not open tdb mapping file. \n " ) ;
return 0 ;
}
2000-04-12 04:37:08 +04:00
if ( ! pdb_generate_sam_sid ( ) ) {
2000-01-03 22:19:48 +03:00
DEBUG ( 0 , ( " ERROR: Samba cannot create a SAM SID. \n " ) ) ;
exit ( 1 ) ;
}
1998-08-17 18:11:44 +04:00
if ( * lp_rootdir ( ) ) {
if ( sys_chroot ( lp_rootdir ( ) ) = = 0 )
DEBUG ( 2 , ( " Changed root to %s \n " , lp_rootdir ( ) ) ) ;
}
1997-09-23 23:19:06 +04:00
2000-06-10 17:38:07 +04:00
/* Setup oplocks */
if ( ! init_oplocks ( ) ) {
1998-08-17 18:11:44 +04:00
exit ( 1 ) ;
2000-06-10 17:38:07 +04:00
}
1996-05-05 07:04:19 +04:00
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
(This used to be commit 44766c39e0027c762bee8b33b12c621c109a3267)
2000-06-12 19:53:31 +04:00
/* Setup change notify */
if ( ! init_change_notify ( ) ) {
exit ( 1 ) ;
}
1998-08-17 18:11:44 +04:00
smbd_process ( ) ;
exit_server ( " normal exit " ) ;
return ( 0 ) ;
1996-05-04 11:50:46 +04:00
}