"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "xinetd/service.c" between
xinetd-2.3.15.tar.gz and xinetd-2.3.15.4.tar.xz

About: xinetd is a secure replacement for inetd, the internet services daemon (openSUSE fork).

service.c  (xinetd-2.3.15):service.c  (xinetd-2.3.15.4.tar.xz)
skipping to change at line 23 skipping to change at line 23
#include <syslog.h> #include <syslog.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_MDNS
#include "xmdns.h"
#endif
#ifndef NO_RPC #ifndef NO_RPC
#ifdef HAVE_RPC_PMAP_CLNT_H
#ifdef __sun #ifdef __sun
#include <rpc/types.h> #include <rpc/types.h>
#include <rpc/auth.h> #include <rpc/auth.h>
#endif #endif
#include <rpc/types.h> #include <rpc/types.h>
#include <rpc/xdr.h> #include <rpc/xdr.h>
#include <rpc/auth.h> #include <rpc/auth.h>
#include <rpc/clnt.h> #include <rpc/clnt.h>
#include <rpc/pmap_clnt.h> #include <rpc/pmap_clnt.h>
#endif
#include <rpc/rpc.h> #include <rpc/rpc.h>
#endif #endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h> #include <sys/file.h>
#endif
#include "sio.h" #include "sio.h"
#include "service.h" #include "service.h"
#include "util.h" #include "util.h"
#include "main.h" #include "main.h"
#include "sconf.h" #include "sconf.h"
#include "msg.h" #include "msg.h"
#include "logctl.h" #include "logctl.h"
#include "xconfig.h" #include "xconfig.h"
#include "special.h" #include "special.h"
skipping to change at line 90 skipping to change at line 82
sp = NEW_SVC() ; sp = NEW_SVC() ;
if ( sp == NULL ) if ( sp == NULL )
{ {
out_of_memory( func ) ; out_of_memory( func ) ;
return( NULL ) ; return( NULL ) ;
} }
CLEAR( *sp ) ; CLEAR( *sp ) ;
SVC_CONF(sp) = scp ; SVC_CONF(sp) = scp ;
sp->svc_pfd_index = -1;
return( sp ) ; return( sp ) ;
} }
struct service *svc_make_special( struct service_config *scp ) struct service *svc_make_special( struct service_config *scp )
{ {
struct service *sp ; struct service *sp ;
const char *func = "svc_make_special" ; const char *func = "svc_make_special" ;
if ( ( sp = svc_new( scp ) ) == NULL ) if ( ( sp = svc_new( scp ) ) == NULL )
{ {
skipping to change at line 231 skipping to change at line 224
if ( debug.on ) if ( debug.on )
msg( LOG_DEBUG, func, msg( LOG_DEBUG, func,
"Registered %d versions of %s", registered_versions, sid ) ; "Registered %d versions of %s", registered_versions, sid ) ;
return( ( registered_versions == 0 ) ? FAILED : OK ) ; return( ( registered_versions == 0 ) ? FAILED : OK ) ;
} }
#endif /* ! NO_RPC */ #endif /* ! NO_RPC */
#define MAX_BIND_ATTEMPTS 10
static status_e activate_normal( struct service *sp ) static status_e activate_normal( struct service *sp )
{ {
union xsockaddr tsin; union xsockaddr tsin;
int sd = SVC_FD( sp ) ; int sd = SVC_FD( sp ) ;
struct service_config *scp = SVC_CONF( sp ) ; struct service_config *scp = SVC_CONF( sp ) ;
uint16_t service_port = SC_PORT( scp ) ; uint16_t service_port = SC_PORT( scp ) ;
char *sid = SC_ID( scp ) ; char *sid = SC_ID( scp ) ;
const char *func = "activate_normal" ; const char *func = "activate_normal" ;
unsigned int sin_len = sizeof(tsin); unsigned int sin_len = sizeof(tsin);
int on = 1; int on = 1;
int retries = MAX_BIND_ATTEMPTS;
useconds_t bind_retry_delay= 0;
char *brd_str = NULL;
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
int v6on = 0; int v6on = 0;
#endif #endif
brd_str = getenv("XINETD_BIND_DELAY");
if (brd_str) {
bind_retry_delay = atoi(brd_str);
if (bind_retry_delay > 500000) {
bind_retry_delay = 0;
}
}
if( SC_BIND_ADDR(scp) != NULL ) if( SC_BIND_ADDR(scp) != NULL )
memcpy(&tsin, SC_BIND_ADDR(scp), sin_len); memcpy(&tsin, SC_BIND_ADDR(scp), sin_len);
else else
memset(&tsin, 0, sin_len); memset(&tsin, 0, sin_len);
if( SC_IPV4( scp ) ) { if( SC_IPV4( scp ) ) {
tsin.sa_in.sin_family = AF_INET ; tsin.sa_in.sin_family = AF_INET ;
tsin.sa_in.sin_port = htons( service_port ) ; tsin.sa_in.sin_port = htons( service_port ) ;
sin_len = sizeof(struct sockaddr_in); sin_len = sizeof(struct sockaddr_in);
} else if( SC_IPV6( scp ) ) { } else if( SC_IPV6( scp ) ) {
skipping to change at line 294 skipping to change at line 300
} }
if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) ) if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) )
{ {
if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE,
(char *)&on, sizeof( on ) ) < 0 ) (char *)&on, sizeof( on ) ) < 0 )
msg( LOG_WARNING, func, msg( LOG_WARNING, func,
"setsockopt SO_KEEPALIVE failed (%m). service = %s", sid ) ; "setsockopt SO_KEEPALIVE failed (%m). service = %s", sid ) ;
} }
if ( bind( sd, &tsin.sa, sin_len ) == -1 ) while ( bind( sd, &tsin.sa, sin_len ) == -1 )
{ {
msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ; msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
return( FAILED ) ; if (retries-- > 0) {
msg( LOG_NOTICE, func,
"bind retry attempt %i", MAX_BIND_ATTEMPTS - retries);
if (bind_retry_delay) {
usleep(bind_retry_delay);
}
} else {
return( FAILED ) ;
}
} }
#ifdef IN_MULTICAST #ifdef IN_MULTICAST
if( SC_IPV4(scp) && IN_MULTICAST(tsin.sa_in.sin_addr.s_addr) ) { if( SC_IPV4(scp) && IN_MULTICAST(tsin.sa_in.sin_addr.s_addr) ) {
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = tsin.sa_in.sin_addr.s_addr; mreq.imr_multiaddr.s_addr = tsin.sa_in.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if ( debug.on ) if ( debug.on )
msg( LOG_DEBUG, func, "Adding multicast membership." ); msg( LOG_DEBUG, func, "Adding multicast membership." );
skipping to change at line 331 skipping to change at line 345
const char *func = "svc_activate" ; const char *func = "svc_activate" ;
/* No activation for MUXCLIENTS. /* No activation for MUXCLIENTS.
*/ */
if (SC_IS_MUXCLIENT( scp )) if (SC_IS_MUXCLIENT( scp ))
{ {
return( OK ); return( OK );
} }
#ifdef HAVE_POLL
if ( ps.rws.descriptors_free <= 0 )
{
msg(LOG_ERR, func, "Maximum number of services reached") ;
return( FAILED ) ;
}
if ( sp->svc_pfd_index >= 0 )
{
SVC_POLLFD( sp ) = &ps.rws.pfd_array[sp->svc_pfd_index] ;
}
else
{
sp->svc_pfd_index = ps.rws.pfds_last ;
SVC_POLLFD( sp ) = &ps.rws.pfd_array[ps.rws.pfds_last++] ;
}
#endif /* HAVE_POLL */
if( SC_IPV4( scp ) ) { if( SC_IPV4( scp ) ) {
SVC_FD(sp) = socket( AF_INET, SVC_FD(sp) = socket( AF_INET,
SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ; SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
} else if( SC_IPV6( scp ) ) { } else if( SC_IPV6( scp ) ) {
SVC_FD(sp) = socket( AF_INET6, SVC_FD(sp) = socket( AF_INET6,
SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ; SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ;
} }
if ( SVC_FD(sp) == -1 ) if ( SVC_FD(sp) == -1 )
{ {
if (SC_BIND_ADDR(scp) == NULL && SC_IPV6( scp ))
{
/* there was no bind address configured and IPv6 fails. Try IPv4 */
msg( LOG_NOTICE, func, "IPv6 socket creation failed for service %s, try
ing IPv4", SC_ID( scp ) ) ;
M_CLEAR(SC_XFLAGS(scp), SF_IPV6);
M_SET(SC_XFLAGS(scp), SF_IPV4);
return svc_activate(sp);
}
msg( LOG_ERR, func, msg( LOG_ERR, func,
"socket creation failed (%m). service = %s", SC_ID( scp ) ) ; "socket creation failed (%m). service = %s", SC_ID( scp ) ) ;
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = 0;
SVC_FD( sp ) = 0;
#else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif /* HAVE_POLL */
return( FAILED ) ; return( FAILED ) ;
} }
if ( set_fd_modes( sp ) == FAILED ) if ( set_fd_modes( sp ) == FAILED )
{ {
(void) Sclose( SVC_FD(sp) ) ; (void) Sclose( SVC_FD(sp) ) ;
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = 0;
SVC_FD( sp ) = 0;
#else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif /* HAVE_POLL */
return( FAILED ) ; return( FAILED ) ;
} }
#ifndef NO_RPC #ifndef NO_RPC
if ( SC_IS_RPC( scp ) ) if ( SC_IS_RPC( scp ) )
status = activate_rpc( sp ) ; status = activate_rpc( sp ) ;
else else
#endif /* ! NO_RPC */ #endif /* ! NO_RPC */
status = activate_normal( sp ) ; status = activate_normal( sp ) ;
if ( status == FAILED ) if ( status == FAILED )
{ {
(void) Sclose( SVC_FD(sp) ) ; (void) Sclose( SVC_FD(sp) ) ;
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = 0;
SVC_FD( sp ) = 0;
#else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif /* HAVE_POLL */
return( FAILED ) ; return( FAILED ) ;
} }
#ifdef HAVE_MDNS
xinetd_mdns_register(scp);
#endif
if ( log_start( sp, &SVC_LOG(sp) ) == FAILED ) if ( log_start( sp, &SVC_LOG(sp) ) == FAILED )
{ {
deactivate( sp ) ; deactivate( sp ) ;
return( FAILED ) ; return( FAILED ) ;
} }
/* /*
* Initialize the service data * Initialize the service data
*/ */
SVC_RUNNING_SERVERS(sp) = SVC_RETRIES(sp) = 0 ; SVC_RUNNING_SERVERS(sp) = SVC_RETRIES(sp) = 0 ;
if ( SC_MUST_LISTEN( scp ) ) if ( SC_MUST_LISTEN( scp ) )
(void) listen( SVC_FD(sp), LISTEN_BACKLOG ) ; (void) listen( SVC_FD(sp), LISTEN_BACKLOG ) ;
ps.rws.descriptors_free-- ; ps.rws.descriptors_free-- ;
SVC_STATE(sp) = SVC_ACTIVE ; SVC_STATE(sp) = SVC_ACTIVE ;
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = POLLIN ;
#else
FD_SET( SVC_FD(sp), &ps.rws.socket_mask ) ; FD_SET( SVC_FD(sp), &ps.rws.socket_mask ) ;
if ( SVC_FD(sp) > ps.rws.mask_max ) if ( SVC_FD(sp) > ps.rws.mask_max )
ps.rws.mask_max = SVC_FD(sp) ; ps.rws.mask_max = SVC_FD(sp) ;
#endif /* HAVE_POLL */
ps.rws.active_services++ ; ps.rws.active_services++ ;
ps.rws.available_services++ ; ps.rws.available_services++ ;
return( OK ) ; return( OK ) ;
} }
static void deactivate( const struct service *sp ) static void deactivate( const struct service *sp )
{ {
(void) Sclose( SVC_FD( sp ) ) ; (void) Sclose( SVC_FD( sp ) ) ;
#ifdef HAVE_POLL
#ifdef HAVE_MDNS SVC_FD( sp ) = 0;
xinetd_mdns_deregister(SVC_CONF(sp)); #else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif #endif
if (debug.on) if (debug.on)
msg(LOG_DEBUG, "deactivate", "%d Service %s deactivated", msg(LOG_DEBUG, "deactivate", "%d Service %s deactivated",
getpid(), SC_NAME( SVC_CONF(sp) ) ); getpid(), SC_NAME( SVC_CONF(sp) ) );
#ifndef NO_RPC #ifndef NO_RPC
if ( SC_IS_RPC( SVC_CONF( sp ) ) ) if ( SC_IS_RPC( SVC_CONF( sp ) ) )
{ {
unsigned long vers ; unsigned long vers ;
skipping to change at line 437 skipping to change at line 498
void svc_deactivate( struct service *sp ) void svc_deactivate( struct service *sp )
{ {
if ( ! SVC_IS_AVAILABLE( sp ) ) if ( ! SVC_IS_AVAILABLE( sp ) )
return ; return ;
deactivate( sp ) ; deactivate( sp ) ;
ps.rws.descriptors_free++ ; ps.rws.descriptors_free++ ;
if ( SVC_IS_ACTIVE( sp ) ) if ( SVC_IS_ACTIVE( sp ) )
{ {
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = 0;
SVC_FD( sp ) = 0;
#else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ; FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif /* HAVE_POLL */
ps.rws.active_services-- ; ps.rws.active_services-- ;
} }
ps.rws.available_services-- ; ps.rws.available_services-- ;
DISABLE( sp ) ; DISABLE( sp ) ;
} }
/* /*
* Suspend a service * Suspend a service
skipping to change at line 459 skipping to change at line 525
void svc_suspend( struct service *sp ) void svc_suspend( struct service *sp )
{ {
const char *func = "svc_suspend" ; const char *func = "svc_suspend" ;
if ( ! SVC_IS_ACTIVE( sp ) ) if ( ! SVC_IS_ACTIVE( sp ) )
{ {
msg( LOG_ERR, func, "service %s is not active", SVC_ID( sp ) ) ; msg( LOG_ERR, func, "service %s is not active", SVC_ID( sp ) ) ;
return ; return ;
} }
#ifdef HAVE_POLL
/*
* don't reap the pfd from pfd_array, since we must have it allocated for
* SVC_FD( sp )
*/
SVC_EVENTS( sp ) = 0;
#else
FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ; FD_CLR( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif
ps.rws.active_services-- ; ps.rws.active_services-- ;
if ( debug.on ) if ( debug.on )
msg( LOG_DEBUG, func, "Suspended service %s", SVC_ID( sp ) ) ; msg( LOG_DEBUG, func, "Suspended service %s", SVC_ID( sp ) ) ;
SUSPEND( sp ) ; SUSPEND( sp ) ;
} }
/* /*
* Resume a suspended service. * Resume a suspended service.
*/ */
void svc_resume( struct service *sp ) void svc_resume( struct service *sp )
{ {
const char *func = "svc_resume" ; const char *func = "svc_resume" ;
#ifdef HAVE_POLL
SVC_EVENTS( sp ) = POLLIN ;
#else
FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ; FD_SET( SVC_FD( sp ), &ps.rws.socket_mask ) ;
#endif
ps.rws.active_services++ ; ps.rws.active_services++ ;
if ( debug.on ) if ( debug.on )
msg( LOG_DEBUG, func, "Resumed service %s", SVC_ID( sp ) ) ; msg( LOG_DEBUG, func, "Resumed service %s", SVC_ID( sp ) ) ;
RESUME( sp ) ; RESUME( sp ) ;
} }
/* /*
* Steps: * Steps:
* 1. Deactivate the service * 1. Deactivate the service
* 2. Free all memory used by the service and free the service itself * 2. Free all memory used by the service and free the service itself
skipping to change at line 894 skipping to change at line 973
* fd's are not closed and reconfig will fail. * fd's are not closed and reconfig will fail.
*/ */
void close_all_svc_descriptors(void) void close_all_svc_descriptors(void)
{ {
psi_h iter ; psi_h iter ;
struct service *osp ; struct service *osp ;
/* Have to close all other descriptors here */ /* Have to close all other descriptors here */
iter = psi_create( SERVICES( ps ) ) ; iter = psi_create( SERVICES( ps ) ) ;
if ( iter == NULL ) if ( iter == NULL )
{
out_of_memory( "close_all_svc_descriptors" ) ; out_of_memory( "close_all_svc_descriptors" ) ;
exit( 1 );
}
for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) ) for ( osp = SP( psi_start( iter ) ) ; osp ; osp = SP( psi_next( iter ) ) )
(void) Sclose( SVC_FD( osp ) ) ; {
#ifdef HAVE_POLL
if ( osp && SVC_POLLFD( osp ) )
#endif
(void) Sclose( SVC_FD( osp ) ) ;
}
psi_destroy( iter ) ; psi_destroy( iter ) ;
} }
 End of changes. 30 change blocks. 
18 lines changed or deleted 106 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)