Cover V05, I11
Article
Figure 1
Figure 2
Listing 1
Listing 2
Listing 3
Sidebar 1

nov96.tar


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 */