2008-09-22 05:57:31 +04:00
/*
Unix SMB / CIFS implementation .
process incoming connections and fork a samba3 in inetd mode
Copyright ( C ) Stefan Metzmacher 2008
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "smbd/service.h"
# include "libcli/smb2/smb2.h"
# include "system/network.h"
# include "lib/socket/netif.h"
# include "param/param.h"
# include "dynconfig/dynconfig.h"
# include "smbd/process_model.h"
/*
initialise a server_context from a open socket and register a event handler
for reading from that socket
*/
static void samba3_smb_accept ( struct stream_connection * conn )
{
int i ;
int fd = socket_get_fd ( conn - > socket ) ;
const char * prog ;
char * argv [ 2 ] ;
char * reason ;
2008-10-14 02:33:49 +04:00
extern char * * environ ;
2008-09-22 05:57:31 +04:00
close ( 0 ) ;
close ( 1 ) ;
dup2 ( fd , 0 ) ;
dup2 ( fd , 1 ) ;
2008-10-05 22:47:00 +04:00
dup2 ( fd , 2 ) ;
for ( i = 3 ; i < 256 ; i + + ) {
2008-09-22 05:57:31 +04:00
close ( i ) ;
}
2010-07-16 08:32:42 +04:00
prog = lpcfg_parm_string ( conn - > lp_ctx , NULL , " samba3 " , " smbd " ) ;
2008-09-22 05:57:31 +04:00
if ( prog = = NULL ) {
argv [ 0 ] = talloc_asprintf ( conn , " %s/%s " , dyn_BINDIR , " smbd3 " ) ;
}
else {
argv [ 0 ] = talloc_strdup ( conn , prog ) ;
}
if ( argv [ 0 ] = = NULL ) {
stream_terminate_connection ( conn , " out of memory " ) ;
return ;
}
argv [ 1 ] = NULL ;
execve ( argv [ 0 ] , argv , environ ) ;
/*
* Should never get here
*/
reason = talloc_asprintf ( conn , " Could not execute %s " , argv [ 0 ] ) ;
if ( reason = = NULL ) {
stream_terminate_connection ( conn , " out of memory " ) ;
return ;
}
stream_terminate_connection ( conn , reason ) ;
talloc_free ( reason ) ;
}
static const struct stream_server_ops samba3_smb_stream_ops = {
. name = " samba3 " ,
. accept_connection = samba3_smb_accept ,
} ;
/*
setup a listening socket on all the SMB ports for a particular address
*/
2008-12-29 22:24:57 +03:00
static NTSTATUS samba3_add_socket ( struct tevent_context * event_context ,
2008-09-22 05:57:31 +04:00
struct loadparm_context * lp_ctx ,
const struct model_ops * model_ops ,
const char * address )
{
2010-07-16 08:32:42 +04:00
const char * * ports = lpcfg_smb_ports ( lp_ctx ) ;
2008-09-22 05:57:31 +04:00
int i ;
NTSTATUS status ;
for ( i = 0 ; ports [ i ] ; i + + ) {
uint16_t port = atoi ( ports [ i ] ) ;
if ( port = = 0 ) continue ;
status = stream_setup_socket ( event_context , lp_ctx ,
model_ops , & samba3_smb_stream_ops ,
" ip " , address , & port ,
2010-07-16 08:32:42 +04:00
lpcfg_socket_options ( lp_ctx ) ,
2008-09-22 05:57:31 +04:00
NULL ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
}
return NT_STATUS_OK ;
}
/*
open the smb server sockets
*/
static void samba3_smb_task_init ( struct task_server * task )
{
NTSTATUS status ;
const struct model_ops * model_ops ;
model_ops = process_model_startup ( task - > event_ctx , " standard " ) ;
if ( model_ops = = NULL ) {
goto failed ;
}
task_server_set_title ( task , " task[samba3_smb] " ) ;
2010-07-16 08:32:42 +04:00
if ( lpcfg_interfaces ( task - > lp_ctx )
& & lpcfg_bind_interfaces_only ( task - > lp_ctx ) ) {
2008-09-22 05:57:31 +04:00
int num_interfaces ;
int i ;
struct interface * ifaces ;
2010-07-16 08:32:42 +04:00
load_interfaces ( task , lpcfg_interfaces ( task - > lp_ctx ) , & ifaces ) ;
2008-09-22 05:57:31 +04:00
num_interfaces = iface_count ( ifaces ) ;
/* 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 .
*/
for ( i = 0 ; i < num_interfaces ; i + + ) {
const char * address = iface_n_ip ( ifaces , i ) ;
status = samba3_add_socket ( task - > event_ctx ,
task - > lp_ctx ,
model_ops , address ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
}
} else {
2010-07-16 08:32:42 +04:00
/* Just bind to lpcfg_socket_address() (usually 0.0.0.0) */
2008-09-22 05:57:31 +04:00
status = samba3_add_socket ( task - > event_ctx , task - > lp_ctx ,
model_ops ,
2010-07-16 08:32:42 +04:00
lpcfg_socket_address ( task - > lp_ctx ) ) ;
2008-09-22 05:57:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
}
return ;
failed :
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " Failed to startup samba3 smb task " , true ) ;
2008-09-22 05:57:31 +04:00
}
/* called at smbd startup - register ourselves as a server service */
NTSTATUS server_service_samba3_smb_init ( void )
{
return register_server_service ( " samba3_smb " , samba3_smb_task_init ) ;
}