Listing 2: divert.c
/*
* Divert daemon 1.00
*
* Author : A. Donkers
* Le Reseau netwerksystemen B.V.
*
*
* Main module
*/
/*
* System includes
*/
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef DEBUG
#include
#endif
#include
/*
* Application includes
*/
#include "divert.h"
/*
* defines
*/
#define EATSPACE(a) while(*a && isspace(*a)) a++
#define EATREST(a) while(*a && !isspace(*a)) a++
/*
* Locals (--Yuck)
*/
static struct sockaddr me;
static int mysocklen = sizeof(me);
static struct sockaddr them;
static int theirsocklen = sizeof(them);
static char called_as[PATHSIZE];
static char command[MAXCMDSIZE];
static char commandpath[PATHSIZE];
/*
* Entry point
*/
int main( int argc, char **argv )
{
unsigned long my_addr, their_addr;
unsigned short my_port, their_port;
char my_dots[16], his_dots[16];
void *t;
struct servent *servname;
int matched = 0;
char *service, **slist;
char *p = NULL;
char *arglist[MAXARGS+1];
int i = 0;
char *s;
/*
* Code starts here
*/
openlog( "divertd", LOG_PID|LOG_NDELAY, LOG_DAEMON );
strcpy( called_as, *argv );
syslog( LOG_INFO, "divert version %s started as %s\n",
VERSION, called_as );
/*
* TODO
* add option parsing here, so we might also be called as a standalone
* program.
*/
/*
* Get my name
*/
if( getsockname( 0, &me, &mysocklen ) < 0 ) {
syslog( LOG_ERR, "Cannot getsockname, called as %s, error %m",
called_as );
exit( -1 );
}
/*
* Get their name
*/
if( getpeername( 0, &them, &theirsocklen ) < 0 ) {
syslog( LOG_ERR, "Cannot getpeername, called as %s, error %m",
called_as );
exit( -1 );
}
if( me.sa_family != AF_INET || them.sa_family != AF_INET ) {
syslog( LOG_ERR, "Not on network" );
exit( -1 );
}
/*
* Get my address
*/
t = &me;
my_addr = ((struct sockaddr_in *)t)->sin_addr.s_addr;
my_port = ((struct sockaddr_in *)t)->sin_port;
if( (servname = getservbyport( my_port, "tcp" )) == NULL ) {
syslog( LOG_ERR, "Cannot get service name for port %d", my_port );
exit( -1 );
}
/* and their's */
t = &them;
their_addr = ((struct sockaddr_in *)t)->sin_addr.s_addr;
their_port = ((struct sockaddr_in *)t)->sin_port;
/* Try to match the service, or one of its aliases */
service = servname->s_name;
slist = servname->s_aliases;
while( !matched && service ) {
matched = chkaddr( CONFIGFILE, my_addr, service, their_addr, command );
if( matched ) {
break;
}
service = *slist++;
}
if( !matched ) {
strcpy( my_dots, inet_ntoa( *((struct in_addr *)&my_addr) ) );
strcpy( his_dots, inet_ntoa( *((struct in_addr *)&their_addr) ) );
syslog( LOG_ERR, "No match. Local address %s, remote %s",
my_dots, his_dots );
syslog( LOG_INFO, "No match. Local address %s, remote %s",
my_dots, his_dots );
closelog( );
exit( -1 );
}
/* We've got a match, try to exec a program */
if( strlen( command ) == 0 ) {
/* No command specified, call default */
/* Is service an absolute path ? */
if( *called_as == '/' ) {
strcpy( commandpath , called_as );
}
else {
strcpy( commandpath, DIVERTEDDIR );
strcat( commandpath, "/" );
strcat( commandpath, called_as );
}
/* check if we're executable */
if( access( commandpath, X_OK ) < 0 ) {
syslog( LOG_ERR, "Cannot execute %s, error %m",
called_as );
exit( -1 );
}
closelog( );
/* Ok, execv */
if( execv( commandpath, argv ) < 0 ) {
exit( -1 );
}
}
else {
/* Is command an absolute path ? */
if( *command == '/' ) {
strcpy( commandpath , command );
}
else {
strcpy( commandpath, DIVERTEDDIR );
strcat( commandpath, "/" );
strcat( commandpath, command );
}
/* check if we're executable */
/* We only need the first command word of the command string */
if( (p = strchr( commandpath, ' ' )) != NULL ) {
*p++ = '\0';
}
else {
p = commandpath;
while( isprint(*p) ) p++;
*p = '\0';
}
if( access( commandpath, X_OK ) < 0 ) {
syslog( LOG_ERR, "Cannot execute %s, error %m",
commandpath );
exit( -1 );
}
/* Ok, exec */
arglist[i++] = commandpath;
while( p && i < MAXARGS ) {
EATSPACE(p);
s = arglist[i++] = p;
/* split up the command line */
p = strchr( p, ' ' );
if( p ) {
*p++ = '\0';
}
while( isprint(*s) ) s++;
*s = '\0';
}
arglist[i++] = p;
closelog( );
if( execv( commandpath, arglist ) < 0 ) {
exit( -1 );
}
}
return 0;
}
/* end of divert.c */
|