/**********************************************************************
* main.c -- Contains the main() function of Raptt. Raptt stannds for *
* "Rapid automation testing tool" for administrator in linux *
* platform only.(at least the version 0.1.). This tool requires the *
* the administrator (root) password to run itself. *
* *
* **********************IMPORTANT RAPTT LICENSE TERMS*************** *
* This program is free software; you may redistribute and/or modify *
* it under the terms of the GNU General Public License as published *
* by the Free Software Foundation; Version 2. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. 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 at *
* http://www.gnu.org/copyleft/gpl.html , or in the COPYING file *
* included with Raptt. *
**********************************************************************/
///////////////////////////////////////////////////////////////////////
// $Author: rhs041163 $
// $Id: main.c,v 1.6 2014/03/13 02:48:09 rhs041163 Exp $
// $Date: 2014/03/13 02:48:09 $
// $Revision: 1.6 $
///////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <dlfcn.h>
#include <dirent.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#if defined(linux)
#include <execinfo.h> // backtrace()
#endif
#include "sne_common.h"
#include "sne_wrapper_buff.h"
#include "sne_netutils.h"
#include "sne_plugin.h"
#include "main.h"
#include "rapttCommmonLib.h"
#include "sne_master_action.h"
#include "sne_slave_action.h"
/**********************************************************************
* Some defined constant local to .c file. *
*********************************************************************/
#define MAX_ARGS_LEN 2
/**********************************************************************
* Some Defined MACROS *
***********************************************************************/
#define RAPTT_INIT_LOG_ENGINE(logEngineObject) \
do{ \
if(!logEngineObject){ \
logEngineObject = (RAPTT_logEngine_t*) calloc \
(1,sizeof(RAPTT_logEngine_t)); \
} \
else{ \
assert(0); \
} \
logEngineObject->pBuffer = (char*) calloc \
(1,sizeof(DEFAULT_BUFF_SIZE));\
logEngineObject->pBufferSize = DEFAULT_BUFF_SIZE; \
/* Set different attributes of the object RAPTT_logEngine */\
logEngineObject->list = NULL; \
logEngineObject->add = raptt_add_logger_to_logEngine; \
logEngineObject->del = raptt_del_logger_frm_logEngine; \
logEngineObject->destroy = raptt_logEngine_close; \
logEngineObject->log = raptt_logMsg_to_logEngine; \
logEngineObject->priority = RAPTT_LOG_UNDEFINED; \
}while(0)
#define RAPTT_CLOSE_LOG_ENGINE(logEngineObject) \
do{ \
if(logEngineObject){ \
ret = logEngineObject->destroy(logEngineObject); \
} \
logEngineObject = NULL; \
}while(0)
#define RAPTT_MAIN_LOG g_raptt_logger->log /* The log function*/
#define RAPTT_MAIN_LOG_FILE "/tmp/raptt_main.log"
#define sne_cmd_null (sne_cmd_cb_t)NULL
/*********************************************************************
* Some global variable. *
* RAPTT_logger -- Objct for file logging. *
* RAPTT_logEngine -- LogEngine object that contains a list of *
* RAPTT_logger objects *
********************************************************************/
/* Our log engine & logger for the RAPTT core */
/* RAPTT_logger_t *g_raptt_logger = NULL;
RAPTT_logEngine_t *g_raptt_logEngine = NULL;
*/
sne_slave_conn_t **g_conn_table_s = NULL; //For only slave
extern unsigned int g_plugInst;
static SNE_DECLARE_RUNQUEUE(g_runqueue);
/********************************************************************/
sne_cmd_t sne_cmd_list[] = {
{"openconn", sne_cmd_openconn, sne_cmd_openconn_resp },
{"config", sne_cmd_config, sne_cmd_config_resp },
{"run", sne_cmd_run , sne_cmd_run_resp },
{"stop", sne_cmd_stop , sne_cmd_stop_resp },
{"stopall", sne_cmd_stopall , sne_cmd_null },
{"quit", sne_cmd_quit , sne_cmd_null },
{"help", sne_cmd_help , sne_cmd_null },
{"connlist", sne_cmd_connlist, sne_cmd_null },
{NULL, sne_cmd_null , sne_cmd_null },
};
/*********************************************************************
* Function declation *
********************************************************************/
static int sne_slave_stdin_ready(raptt_io_event_t *event);
static int sne_slave_fmodefd_ready(raptt_io_event_t *event);
static int sne_slave_conn_io_ready(raptt_io_event_t *event);
int main(int argc,char **argv,char** env){
char chr;
FILE* fstream = NULL;
char* filename;
unsigned short count = 0;
unsigned short mode = 0;
sne_cmdl_opt_t cmdl_opt = {0};
pid_t child_pid;
static char optstring[] = ":iadf:";
static struct option long_opts[] = {
{"interactive",0,0,'i'}, /* Execute in interactive mode. */
{"all",0,0,'a'}, /* Show all modules */
{"daemon",0,0,'d'}, /* Executes in daemon mode. */
{"file",1,0,'f'}, /* Read from file & exec command */
{0,0,0,0}
};
if(argc<2){
usage();
return RAPTT_ERROR;
}
if(sne_init()<0){
fprintf(stderr,"sne_init failed.\n");
return RAPTT_ERROR;
}
optind = 1;
while((chr=getopt_long(argc,argv,optstring,long_opts,NULL))
!= INVALID){
switch(chr){
case 'i':
mode |= (SNE_TRUE<<count);
cmdl_opt.imode = SNE_TRUE;
break;
case 'a':
show_all_plugins();
break;
case 'd':
mode |= (SNE_TRUE<<count);
cmdl_opt.dmode = SNE_TRUE;
break;
case 'f':
filename = argv[optind];
if((fstream = fopen(filename,"r"))==NULL){
printf("Could not open file [%s] \n",filename);
exit(1);
}
mode |= (SNE_TRUE<<count);
cmdl_opt.fmode = SNE_TRUE;
cmdl_opt.fmode_fstream = fstream;
break;
case ':':
printf("Option [%s] requires argument.\n",argv[optind-1]);
break;
default:
printf("Invalid option [%s]\n",argv[optind-1]);
exit(1);
}
count++;
}
/* Error checking.. */
if((mode & (mode-1))){ /* If Not power of 2 Reject */
fprintf(stderr,"Usage:: %s <-i|-d|-f <filename> > \n",argv[0]);
exit(1);
}
child_pid = do_fork();
switch(child_pid){
case 0: /* Child or Master */
process_master(&cmdl_opt);
break;
case -1:
fprintf(stderr,"Error:%s\n",strerror(errno));
exit(1);
break;
default: /* parent or slave */
process_slave(&cmdl_opt);
break;
}
/* CleanUp stuffs */
sne_close();
return 0;
}
/**********************************************************************
* Cutom function Defination. *
**********************************************************************/
void usage()
{
printf("RAPTT use::<module> <arguments>\n");
printf(
"OPTIONS ::: -i - Execute in interactive mode.\n"
" ::: -a - Show all modules\n"
" ::: -d - Execute in daemon mode.\n"
" ::: -f - Execute commands from a file.\n\n");
}
/*
* Desc : This fundtion will execute the process in daemon mode.
* It receives a connection from slaves.
* It receives a xml config string for further processing.
* It will create a thread depending after parsing the config file.
* Then it will keep listening for next connection.
*
* Input : Parsed command line options.
* output: -1, for error.
* 0, success.
*/
static int process_master(sne_cmdl_opt_t* cmdl_opt)
{
int ret = 0;
int listen_sock = -1;
raptt_io_poller_t *io_poller_m = NULL; //io_poller_master
pid_t pid = getpid();
struct sockaddr_in srv_addr;
/* Prepare master to run in daemon mode. */
sne_run_as_daemon();
/* Initialize different plugins. */
sne_plugin_portscan_init();
sne_plugin_discovery_init();
//sne_plugin_osdetection_init();
//sne_plugin_attack_init();
/* Allocate the io_poller_m */
if((io_poller_m = (raptt_io_poller_t*)calloc(1,
sizeof(raptt_io_poller_t))) == NULL){
fprintf(stderr,"%s:%d Failed to alloate MEM\n",__FILE__,
__LINE__);
fflush(stderr);
ret = -1;
goto Return_Lebel;
}
/* Do the initialization. */
raptt_io_poller_init(io_poller_m);
/* Get the listing socket. */
if((listen_sock = sne_socket(AF_INET,SOCK_STREAM,0))<0){
fprintf(stderr,"%s:%d Failed to creat socket.\n",
__FILE__,__LINE__);
fflush(stderr);
ret = -1;
goto Return_Lebel;
}
/* Bind the socket. */
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
srv_addr.sin_port = htons(MASTER_PORT);
if((sne_bind(listen_sock,(struct sockaddr*)&srv_addr,
sizeof(srv_addr)))<0){
fprintf(stderr,"%s:%d Error:(%s)\n",__FILE__,__LINE__,
strerror(errno));
fflush(stderr);
close(listen_sock);
ret = -1;
goto Return_Lebel;
}
/* Set the listen queue. */
if((sne_listen(listen_sock,SOMAXCONN))<0){
fprintf(stderr,"%s:%d Error:(%s)\n",__FILE__,__LINE__,
strerror(errno));
fflush(stderr);
close(listen_sock);
ret = -1;
goto Return_Lebel;
}
/* Preapre fd for add in waitinglist. */
if((io_poller_m->prepare_fd_for_add
(io_poller_m,listen_sock,pid))<0)
{
fprintf(stderr,"%s:%d Failed to add fd.\n",__FILE__,__LINE__);
fflush(stderr);
close(listen_sock);
ret = -1;
goto Return_Lebel;
}
/* Add stdin callback. */
if((io_poller_m->add_io_callback(io_poller_m,listen_sock,
sne_master_accept_ready,io_poller_m))<0){
fprintf(stderr,"%s:%d Failed to add listen_sock callback.\n",
__FILE__,__LINE__);
fflush(stderr);
return -1;
}
/* Start processing of input/other fds commands. */
while(SNE_TRUE){
ret = io_poller_m->wait_and_send_event
(io_poller_m,100); //100 milisec timeout
if(ret != 0){
fprintf(stderr,"%s:%d Error (%s)\n",__FILE__,__LINE__,
strerror(errno));
fflush(stderr);
break;
}
ret = sne_master_runAllthreads();
if(ret<0) break;
}
/* Just for removing compilation warings. */
cmdl_opt = cmdl_opt;
Return_Lebel:
io_poller_m->shutdown_io(io_poller_m);
free(io_poller_m);
return ret;
}
/*
* Desc : This function will used to run the
* process in daemon mode.
*
* Input : None
* Output: None
*/
static
void sne_run_as_daemon()
{
int index = 0;
int fd = -1;
/* Obtain a new process group. */
setsid();
/* Changed the current working directory. */
chdir("/");
/* Change the umask for creating a file. */
umask(022);
/* Open file for logging. */
fd = open("/tmp/sne_master_process.log",O_RDWR|O_CREAT|O_APPEND
,0644);
if(fd<0){
fprintf(stderr,"Can't open file /tmp/sne_master_process.log"
".Reson :: %s\n",strerror(errno));
return;
}
else{
/* Close all opened file descriptors. */
for(index = getdtablesize();index>0;index--){
if(index!=fd){
close(index);
}
}
dup(fd); /* stdout */
dup(fd); /* stderr */
close(0); /* stdin */
close(fd);
/* Redirect the stdin to /dev/null */
fd = open("/dev/null",O_RDWR);
assert(0==fd);
}
return;
}
/*
* Desc : This function will iterate over g_runqueue and invoke
* the thread function.
*
* Input: void
*
* Output: Integer. >=0 -->succes
* <0 -->error
*/
static int
sne_master_runAllthreads()
{
int ret = 0;
sne_list_head_t *head = &(g_runqueue.obj_list_head);
sne_list_head_t *pos = NULL;
sne_list_head_t *pos_next= NULL;
sne_plugin_thread_t *thr = NULL;
unsigned int curr_time = 0;
sne_timer_t *timer = NULL;
/* :ALGO:
* We will iterate over each element of the runqueue and do the
* following.
* case 1:
* if thread is in RUNNING state.
* -- func callback will be excuted.
* case 2:
* if the thread is in sleeping state.
* -- Check out the thread specific timer.
* if expuires call the timer callback.
*/
for (pos = (head)->next; pos != (head); pos = pos_next){
pos_next = pos->next;
thr = list_entry(pos, sne_plugin_thread_t, thread_list);
sne_setcurrent_thread(&g_runqueue,thr);
timer = &(thr->timer);
switch(thr->state){
case SNE_PLUGIN_THREAD_RUNNING:
ret = thr->fn(thr->pcontext);
break;
case SNE_PLUGIN_THREAD_SLEEP:
/* Checkout the timer of the thread */
curr_time = sne_current_time();
if((timer->fn) && (curr_time > (timer->last_timestamp
+ timer->interval))){
timer->fn(thr); //CALL the timer callback;
}
break;
case SNE_PLUGIN_THREAD_DESTROY:
/* Remove the thr from runqueue. */
sne_plugin_thread_unregister(thr);
free(thr);
break;
default:
break;
}
}
return ret;
}
/*
* Desp : To set the current thr of the runqueue.
* @runqueue : The runqueue.
* @thr : The thread to be set as current thread of the above
* runqueue.
*/
static
void sne_setcurrent_thread(sne_runqueue_t *runqueue,
sne_plugin_thread_t *thr)
{
runqueue->curr_thr = thr;
}
/*
* Desp : To get the current thread from g_runqueue (Always)
* @param : void
* @return : The current thread of g_runqueue.
*/
inline
sne_plugin_thread_t * sne_getcurrent_thread()
{
return (g_runqueue.curr_thr);
}
/* sne_plugin_thread_register -- To schedule a thread for RUN
* in g_runqueue.
* @new_thr : The new thread to be schedule for run.
*/
void sne_plugin_thread_register(sne_plugin_thread_t *new_thr)
{
struct sne_list_head *head = &(g_runqueue.obj_list_head);
list_add(&(new_thr->thread_list),head);
new_thr->state = SNE_PLUGIN_THREAD_RUNNING;
}
/* sne_plugin_thread_unregister -- To remove a thread for RUN queue.
* @new_thr : The old thread to be removed from runqueue.
*/
void sne_plugin_thread_unregister(sne_plugin_thread_t *old_thr)
{
list_del(&(old_thr->thread_list));
}
/*
* Desc : This function will initiate a connection to the master.
* If sne is invoked with -d option then it immediately
* returns.
* In interactive mode it waits for "send_file" command
* from user. e.g > send_file <filename>
*
* Input : Parsed command line options.
* Output: -1, for error
* 0, Success
*/
static int process_slave(sne_cmdl_opt_t* cmdl_opt)
{
int ret = 0;
void* arglist[MAX_ARGS_LEN] = {'\0'};
raptt_io_poller_t *io_poller = NULL;
//pid_t pid = getpid();
/* If execute in daemon mode , return immediately. */
if(SNE_TRUE == (cmdl_opt->dmode)){
return 0;
}
if((g_conn_table_s = (sne_slave_conn_t**)calloc(1,
MAX_SLAVE_CONN*(sizeof(sne_slave_conn_t*))))<0){
fprintf(stderr,"%s:%d Failed to alloate MEM\n",__FILE__,
__LINE__);
return -1;
}
/* Allocate the io_poller. */
if((io_poller = (raptt_io_poller_t*)calloc(1,
sizeof(raptt_io_poller_t))) == NULL){
fprintf(stderr,"%s:%d Failed to alloate MEM\n",__FILE__,
__LINE__);
return -1;
}
/* Do the initialization. */
raptt_io_poller_init(io_poller);
if(SNE_TRUE == cmdl_opt->fmode){
arglist[0] = cmdl_opt;
arglist[1] = io_poller;
/* Add stdin callback. */
if((io_poller->add_io_callback(io_poller,
fileno(cmdl_opt->fmode_fstream),
sne_slave_fmodefd_ready,arglist))<0)
{
fprintf(stderr,"%s:%d Failed to add fmode callback.\n",
__FILE__,__LINE__);
return -1;
}
}
else{
/* Add stdin callback. */
if((io_poller->add_io_callback(io_poller,fileno(stdin),
sne_slave_stdin_ready,io_poller))<0){
fprintf(stderr,"%s:%d Failed to add stdin callback.\n",
__FILE__,__LINE__);
return -1;
}
}
/* Show help first. */
sne_cmd_help(NULL);
/* Start processing of input/other fds commands. */
while(SNE_TRUE){
ret = io_poller->wait_and_send_event
(io_poller,INFINITE_TIMEOUT); //infinite time
if(ret<0) break;
}
return ret;
}
static char *get_input_line(char *buf, int buflen)
{
#ifdef USE_READLINE
char *lineread = readline("snet> ");
if (!lineread) return NULL;
strncpy(buf, lineread, buflen);
buf[buflen-1] = 0;
free(lineread);
return buf;
#else
printf("snet> ");
fflush(stdout);
return fgets(buf, buflen, stdin);
#endif /* USE_READLINE */
}
static char *get_input_fromfile(char *buf, int buflen,FILE* fstream)
{
return fgets(buf, buflen, fstream);
}
static int sne_add_conn_to_gtable(sne_slave_conn_t *conn)
{
int index = 0;
int ret = 0;
sne_bool_t flag = SNE_FALSE;
/* Add this connection to global table entry */
for(index = 0;index <= MAX_SLAVE_CONN;index++){
if(NULL == g_conn_table_s[index]){
g_conn_table_s[index] = conn;
flag = SNE_TRUE;
break;
}
}
if(SNE_FALSE==flag) ret =-1;
return ret;
}
static int sne_del_conn_frm_gtable(unsigned int connid)
{
int index = 0;
int ret = 0;
sne_bool_t flag = SNE_FALSE;
/* Add this connection to global table entry */
for(index = 0;index <= MAX_SLAVE_CONN;index++){
if(connid == g_conn_table_s[index]->connid){
g_conn_table_s[index] = NULL;
flag = SNE_TRUE;
break;
}
}
if(SNE_FALSE==flag) ret =-1;
return ret;
}
static
sne_slave_conn_t* sne_get_conn_frm_gtable(unsigned int connid)
{
int index = 0;
sne_slave_conn_t *conn = NULL;
/* Add this connection to global table entry */
for(index = 0;(index <= MAX_SLAVE_CONN) &&
(g_conn_table_s[index]!= NULL);index++){
if(connid == g_conn_table_s[index]->connid){
conn = g_conn_table_s[index];
break;
}
}
return conn;
}
/* Function to parse command from stdin. */
static int sne_slave_cmd_processing(raptt_io_poller_t *io_poller,
char* buf,
int buflen)
{
int ret = 0;
int index = 0;
int sockfd = -1;
unsigned int connid = 0;
char cmd[MAX_CMD_LEN]
= {'\0'};
char filename[MAX_STR_LEN_MAIN]
= {'\0'};
pid_t pid = getpid();
sne_slave_conn_t *conn = NULL;
ipv_t ipv = MAX_IPTYPE;
if('\n'==buf[0]) return 0;
switch(buf[0]){
case 'o':
case 'O':
if(!strncasecmp(buf,OPENCONN_CMD,OPENCONN_CMD_LEN)){
ret = sscanf(buf,"%s %d",cmd,&connid);
if(ret<2){
fprintf(stderr,
"Usage: openconn <new_connid>\n");
return -1;
}
/* Let's hope for the best and allocate the conn. */
/* Allocate sne_slave_conn_t */
conn = (sne_slave_conn_t*)calloc(1,
sizeof(sne_slave_conn_t));
/* Try to socket. */
if((sockfd = sne_socket(AF_INET,SOCK_STREAM,0))<0){
fprintf(stderr,"Failed to open socket.(%s)\n",
strerror(errno));
return -1;
}
/* Preapre fd for add in waitinglist. */
if((io_poller->prepare_fd_for_add(io_poller,sockfd,pid))
< 0 ){
fprintf(stderr,"%s:%d Failed to add fd.\n",
__FILE__,__LINE__);
close(sockfd);
return -1;
}
/* Add sockfd callback. */
if((io_poller->add_io_callback(io_poller,sockfd,
sne_slave_conn_io_ready,conn))<0){ //check
fprintf(stderr,
"%s:%d Failed to add sockfd callback.\n",
__FILE__,__LINE__);
close(sockfd);
return -1;
}
/* Set different attributes of the conn. */
strncpy(conn->lastcmd,cmd,MAX_CMD_LEN);
snprintf(conn->lastcmdargs,MAX_STR_LEN_MAIN,"%d",
connid);
conn->connid = connid; //Set the conn id
conn->ipversion = ipv = IPv4;
conn->sock[ipv] = sockfd;
if(sne_add_conn_to_gtable(conn)<0){
fprintf(stderr,"%s:%d Connection overflow.\n",
__FILE__,__LINE__);
close(sockfd);
free(conn);
return -1;
}
}/* if end */
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
case 'c':
case 'C':
if(!strncasecmp(buf,CONFIG_CMD,CONFIG_CMD_LEN)){
ret = sscanf(buf,"%s %d %s",cmd,&connid,filename);
if(ret<3){
fprintf(stderr,
"Usage: config <connid> <filename>\n");
return -1;
}
if(NULL == (conn = sne_get_conn_frm_gtable(connid))){
fprintf(stderr,
"%s:%d Failed to retrieve conn from gtables.\n",
__FILE__,__LINE__);
return -1;
}
/* Do some validations. */
if(CONN_STATE_CONNECTED != conn->state){
fprintf(stderr,"Connection not being opened!!\n"
"Use openconn cmd to open a connection.\n");
return -1;
}
strncpy(conn->lastcmd,cmd,MAX_CMD_LEN);
sprintf(conn->lastcmdargs,"%d %s",connid,filename);
} /* If end */
else if(!strncasecmp(buf,CONN_LIST_CMD,CONN_LIST_CMD_LEN))
{
ret = sscanf(buf,"%s",cmd);
if(ret<1){
fprintf(stderr,
"Usage: connlist\n");
return -1;
}
}
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
case 'r':
case 'R':
if(!strncasecmp(buf,RUN_CMD,RUN_CMD_LEN)){
ret = sscanf(buf,"%s %d",cmd,&connid);
if(ret<2){
fprintf(stderr,
"Usage: run <connid>\n");
return -1;
}
if(NULL == (conn = sne_get_conn_frm_gtable(connid))){
fprintf(stderr,
"%s:%d Failed to retrieve conn from gtables.\n",
__FILE__,__LINE__);
return -1;
}
if(CONN_STATE_CONFIGURED != conn->state){
fprintf(stderr,"Connection not being configured!!\n"
"Use config cmd to open a connection.\n");
return -1;
}
strncpy(conn->lastcmd,cmd,MAX_CMD_LEN);
} /* If end */
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
case 's':
case 'S':
if(!strncasecmp(buf,STOP_CMD,STOP_CMD_LEN)){
ret = sscanf(buf,"%s %d",cmd,&connid);
if(ret<2){
fprintf(stderr,
"Usage: stop <connid>\n");
return -1;
}
if(NULL == (conn = sne_get_conn_frm_gtable(connid))){
fprintf(stderr,
"%s:%d Failed to retrieve conn from gtables.\n",
__FILE__,__LINE__);
return -1;
}
if(CONN_STATE_RUNNING != conn->state){
fprintf(stderr,"Connection not being n running state!!\n"
"Use run cmd to open a connection.\n");
return -1;
}
strncpy(conn->lastcmd,cmd,MAX_CMD_LEN);
} /* If end */
else if(!strncasecmp(buf,STOPALL_CMD,STOPALL_CMD_LEN)){
ret = sscanf(buf,"%s",cmd);
if(ret<1){
fprintf(stderr,
"Usage: stopall\n");
return -1;
}
} /* else if end*/
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
case 'q':
case 'Q':
if(!strncasecmp(buf,QUIT_CMD,QUIT_CMD_LEN)){
ret = sscanf(buf,"%s",cmd);
if(ret<1){
fprintf(stderr,
"Usage: quit\n");
return -1;
}
} /* If end */
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
case 'h':
case 'H':
if(!strncasecmp(buf,HELP_CMD,HELP_CMD_LEN)){
ret = sscanf(buf,"%s",cmd);
if(ret<1){
fprintf(stderr,
"Usage: help\n");
return -1;
}
}
else{
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
}
break;
default:
printf("!! Invalid command %s",buf);
sne_cmd_help(NULL);
break;
}
/* call action routine. */
for(index=0;sne_cmd_list[index].action !=
sne_cmd_null ; index++){
if(!strcasecmp(cmd,sne_cmd_list[index].cmd_str)){
ret = sne_cmd_list[index].action(conn);
if(ret<0){
if(NULL!=conn){
sockfd = conn->sock[conn->ipversion];
io_poller->del_io_callback(io_poller,sockfd);
close(sockfd);
sne_del_conn_frm_gtable(conn->connid);
free(conn);
conn = NULL;
}
}
break;
}
}
return ret;
}
static int sne_slave_fmodefd_ready(raptt_io_event_t *event)
{
void** arglist = event->userCB.pfn_arg;
raptt_io_poller_t *io_poller = arglist[1];
sne_cmdl_opt_t *cmdl_opt = arglist[0];
int buflen = 255;
char buf[255] = {'\0'};
int ret = 0;
if(!get_input_fromfile(buf,buflen,cmdl_opt->fmode_fstream)){
fprintf(stderr,"get_input_fromfile failed.\n");
return -1;
}
if('\n'==buf[0]) return 0;
ret = sne_slave_cmd_processing(io_poller,buf,buflen);
return ret;
}
static int sne_slave_stdin_ready(raptt_io_event_t *event)
{
raptt_io_poller_t *io_poller = event->userCB.pfn_arg;
int buflen = 255;
char buf[255] = {'\0'};
int ret = 0;
if(!get_input_line(buf,buflen)){
fprintf(stderr,"get_input_line failed.\n");
return -1;
}
if('\n'==buf[0]) return 0;
ret = sne_slave_cmd_processing(io_poller,buf,buflen);
return ret;
}
/* Function to be called when io is ready to i/o *
* sne_slave_conn_io_ready. */
static int sne_slave_conn_io_ready(raptt_io_event_t *event)
{
sne_slave_conn_t *conn = event->userCB.pfn_arg;
int sockfd = event->fd;
char *cmd = NULL;
int index = 0;
int ret = 0;
sne_slave_conn_state_t currstate = conn->state;
switch(currstate){
case CONN_STATE_CONNECTING:
assert(!strcasecmp(conn->lastcmd,OPENCONN_CMD));
cmd = OPENCONN_CMD;
break;
case CONN_STATE_CONFIGURING:
assert(!strcasecmp(conn->lastcmd,CONFIG_CMD));
cmd = CONFIG_CMD;
break;
case CONN_STATE_STARTING_RUN:
assert(!strcasecmp(conn->lastcmd,RUN_CMD));
cmd = RUN_CMD;
break;
case CONN_STATE_RUNNING:
cmd = RUN_CMD;
break;
case CONN_STATE_STOPPING:
assert(!strcasecmp(conn->lastcmd,STOP_CMD));
cmd = STOP_CMD;
break;
default:
/* For rest of states we will not call the callback func*/
goto Return_Level;
}
/* call resp parser routine. */
for(index=0;sne_cmd_list[index].action != sne_cmd_null ;
index++){
if(!strcasecmp(cmd,sne_cmd_list[index].cmd_str)){
ret = sne_cmd_list[index].resp_parser(conn);
if(CONN_STATE_DESTROYED == conn->state){
if(NULL!=conn){
/* Do we need "del_io_callback,really??" */
close(sockfd);
sne_del_conn_frm_gtable(conn->connid);
free(conn);
conn = NULL;
}
}
break;
}
}
Return_Level:
return ret;
}
#ifdef BUILD_SHARED_LIBRARY
int raptt_init_plugins(){
DIR *dp = NULL;
struct dirent *dirp = NULL;
int fd = INVALID;
char *lib_path = NULL;
char *raptt_home = getenv("RAPTT_HOME");
char *raptt_lib = NULL;
int raptt_lib_len = 0;
int ret = 0;
raptt_lib = (char*)calloc(1,strlen(raptt_home) +
strlen(PLUGIN_LIB) + 1); /* 1 for NULL */
sprintf(raptt_lib,"%s%s",raptt_home,PLUGIN_LIB);
raptt_lib_len = strlen(raptt_lib);
if((dp = opendir(raptt_lib))<=0){
RAPTT_MAIN_LOG(g_raptt_logger,RAPTT_LOG_CRIT,
"Can't open dir [raptt_lib = %s]",raptt_lib);
return RAPTT_ERROR;
}
while((dirp = readdir(dp)) != NULL){
lib_path = (char*)calloc(1,raptt_lib_len +
strlen(dirp->d_name) + 1);
sprintf(lib_path,"%s/%s",raptt_lib,dirp->d_name);
if((0 == strncmp(dirp->d_name,".",strlen("."))) ||
(0 == strncmp(dirp->d_name,"..",strlen(".."))) ||
((fd = open(lib_path,O_RDONLY,0))<0)){
free(lib_path);
continue;
}
/* Load plugins */
if((ret = raptt_load_plugin(lib_path))<0){
RAPTT_MAIN_LOG(g_raptt_logger,RAPTT_LOG_ERR,
"Can't load [%s]",lib_path);
}
/* Free lib_path and close fd */
close(fd);
free(lib_path);
dirp = NULL;
lib_path = NULL;
}
closedir(dp);
/* Free dynamically allocated memory */
free(raptt_lib);
return ret;
}
int raptt_load_plugin(char *path){
void *handle;
const char *error;
int (*reg_handle)(rapttPlugin_t *,void*);
handle = dlopen (path, RTLD_LAZY);
if (!handle) {
RAPTT_MAIN_LOG(g_raptt_logger,RAPTT_LOG_CRIT,
"%s.\n",dlerror());
return RAPTT_ERROR;
}
reg_handle = dlsym(handle, "raptt_reg_plugin_handle");
if ((error = dlerror()) != NULL) {
RAPTT_MAIN_LOG(g_raptt_logger,RAPTT_LOG_CRIT,
"%s.\n",dlerror());
return RAPTT_ERROR;
}
reg_handle(g_plugins[g_plugInst-1],handle);
return 0;
}
#endif /* BUILD_SHARED_LIBRARY */
void show_all_plugins(){
/* TBD */
/*
int plugin_inst = INVALID;
for(plugin_inst = 0;g_plugins[plugin_inst];plugin_inst++){
printf("Module %s - %s\n",g_plugins[plugin_inst]->name,
g_plugins[plugin_inst]->about);
}
*/
}
/*
void show_arguments(char *module){
int plugin_inst = INVALID;
int index = 0;
for(plugin_inst = 0;g_plugins[plugin_inst];plugin_inst++){
if(!(strcmp(g_plugins[plugin_inst]->name,module))){
printf("Showing arguments for %s = ",
g_plugins[plugin_inst]->name);
while (((char**)(g_plugins[plugin_inst]->args))[index]
!= NULL){
printf("%s\n",
((char**)(g_plugins[plugin_inst]->args))[index]);
index++;
}
}
}
}
*/
/*
int execute_plugin(int argc,char**argv,char* mod_name){
char chr;
int plugin_inst = INVALID;
int session = 0;
int (*startcallback)(rapttPlugin_t* self,void* option);
int (*stopcallback)(rapttPlugin_t* self);
static char substring[] = ":o:";
static struct option sub_opts[] = {
{"options",1,0,'o'}, //different args for requested module
{0,0,0,0}
};
while((chr=getopt_long(argc,argv,substring,sub_opts,NULL))
!= INVALID){
switch(chr){
case 'o':
goto out;
case ':':
printf("Sub option [%s] requires argument.\n",argv[optind]);
break;
default:
printf("Invalid sub option [%s]\n",argv[optind]);
}
}
// Find out and execute the real start method.
out:
for(plugin_inst = 0;g_plugins[plugin_inst];plugin_inst++){
if(!(strcmp(g_plugins[plugin_inst]->name,mod_name))){
startcallback = g_plugins[plugin_inst]->start;
stopcallback = g_plugins[plugin_inst]->stop;
session = startcallback(g_plugins[plugin_inst],optarg);
if(session != 0){
//printf("Exploit sucsessful Storing session\n");
//todo
}
//printf("Module has finshed\n");
//printf("Stopping module [%s] ... \n",mod_name);
stopcallback(g_plugins[plugin_inst]);
break;
}
}
return 0;
}
*/
/*
static int
raptt_logger_init(RAPTT_logger_t **raptt_logger){
FILE *fp = NULL ;
if(!(*raptt_logger)){ //If NULL
*raptt_logger = (RAPTT_logger_t*) calloc
(1,sizeof(RAPTT_logger_t));
}
if((fp=fopen(RAPTT_MAIN_LOG_FILE,"w"))<0){
fprintf(stderr,"*ERROR in opening FILE [%s]\n",RAPTT_MAIN_LOG_FILE);
return RAPTT_ERROR;
}
(*raptt_logger)->pLogFile = fp;
(*raptt_logger)->mod_type = RAPTT_MAIN_MODULE;
(*raptt_logger)->system = NULL;
(*raptt_logger)->priority = RAPTT_LOG_UNDEFINED;
(*raptt_logger)->log = raptt_msg_log;
(*raptt_logger)->del = raptt_logger_del;
return 0;
}
*/
/*********************************************************************
* This function is not applicable in raptt_main module: rather it *
* schould be used in each plugin modules to unregister it's logger *
* object in psop callback. *
*********************************************************************/
/*
static int
raptt_logger_close(RAPTT_logger_t *raptt_logger){
RAPTT_module_t mod_type = raptt_logger->mod_type;
// Assuming FILE is opened, No Errror handler
if(raptt_logger){
raptt_logger->del(raptt_logger);
// unregister it from the LogEngine
g_raptt_logEngine->list[mod_type] = NULL;
}
return 0;
}
*/
static
int sne_init(){
int ret = 0;
struct sigaction SignalAction;
struct sigaction SignalAbrtAction;
/* Install different signal handler. */
signal_set (SIGINT, sigint);
signal_set (SIGTERM, sigint);
SignalAction.sa_sigaction = SignalHandler;
sigemptyset(&SignalAction.sa_mask);
SignalAction.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &SignalAction, NULL);
SignalAbrtAction.sa_sigaction = HandleSigAbrt;
SignalAbrtAction.sa_flags = SA_SIGINFO;
sigemptyset(&SignalAbrtAction.sa_mask);
sigaction(SIGABRT, &SignalAbrtAction, NULL);
/* Initialisation of differnt tasks. */
/* RAPTT_INIT_LOG_ENGINE(g_raptt_logEngine);
ret = (raptt_logger_init(&g_raptt_logger)||
g_raptt_logEngine->add(g_raptt_logEngine,g_raptt_logger,
RAPTT_MAIN_MODULE));
*/
return ret;
}
static int sne_close(){
int ret = 0;
/* RAPTT_CLOSE_LOG_ENGINE(g_raptt_logEngine);
g_raptt_logger = NULL;
*/
return ret;
}
/* Signal wrapper. */
void
signal_set (int signo, void (*func)(int))
{
int ret;
struct sigaction old_sig;
struct sigaction new_sig;
new_sig.sa_handler = func;
sigemptyset (&new_sig.sa_mask);
new_sig.sa_flags = 0;
#ifdef SA_RESTART /* BSD SUPPORT */
new_sig.sa_flags |= SA_RESTART;
#endif /* SA_RESTART */
ret = sigaction (signo, &new_sig, &old_sig);
assert (ret >= 0);
}
/* SIGINT handler. */
static void
sigint (int sig)
{
(void) sig;
sne_close();
exit(0);
}
void
SignalHandler(int iSigNum, siginfo_t * pSigInfo, void * pVoid)
{
struct sigaction SignalAction;
WriteBackTrace(iSigNum, pSigInfo, pVoid);
// Install default signal handler and rethrow the signal. This is a fatal
// signal handler after all.
SignalAction.sa_handler = SIG_DFL;
sigemptyset(&SignalAction.sa_mask);
SignalAction.sa_flags = 0;
sigaction(iSigNum, &SignalAction, NULL);
}
void
HandleSigAbrt(int iSigNum, siginfo_t * pSigInfo, void * pVoid)
{
/* destroy all to exit cleanly */
sne_close();
WriteBackTrace(iSigNum, pSigInfo, pVoid);
/* To avoid warnings */
iSigNum = iSigNum;
pSigInfo = pSigInfo;
pVoid = pVoid;
exit(0);
}
void
WriteBackTrace(int iSigNum, siginfo_t * pSigInfo, void * pVoid)
{
FILE *fp = NULL;
FILE *fatalerrfp = stderr;
//char *format;
#if defined(linux)
void *bt[128];
#endif
int bt_size, i;
fp = fopen("/tmp/raptt_crash.log", "a");
if(fp!=NULL) {
fatalerrfp = fp;
}
else{
fp = fopen("raptt_crash.log", "a");
fatalerrfp = fp;
}
pVoid = pVoid;
/* The POSIX standard doesn't specify the third argument. On linux, it appears
to be a struct ucontext *. How universal is this?
*/
#if 0
struct ucontext * pContext = (struct ucontext *)pVoid;
#endif
fprintf(fatalerrfp, "########## FATAL SIGNAL ##########\n");
// Print gobs of signal info.
fprintf(fatalerrfp, "\n########## Signal Info ##########\n");
fprintf(fatalerrfp, " si_signo:\t%d\n", pSigInfo->si_signo);
fprintf(fatalerrfp, " si_errno:\t%d\n", pSigInfo->si_errno);
fprintf(fatalerrfp, " si_code:\t%d\n", pSigInfo->si_code);
fprintf(fatalerrfp, " si_pid:\t%d\n", pSigInfo->si_pid);
fprintf(fatalerrfp, " si_uid:\t%d\n", pSigInfo->si_uid);
fprintf(fatalerrfp, " si_status:\t%d\n", pSigInfo->si_status);
// Print stack backtrace. Will need access to a symbol table in order
// to get anything meaningful from this. Note that this is a GLIBC
// specific feature.
fprintf(fatalerrfp, "\n########## Backtrace ##########\n");
#if defined(linux)
bt_size = backtrace(bt, sizeof(bt)/sizeof(void *));
fprintf(fatalerrfp, " size: %d\n", bt_size);
for(i=0; i<bt_size; i++)
{
fprintf(fatalerrfp, " %d:\t\t%p\n", i, bt[i]);
}
#else
fprintf (fatalerrfp, "%s:%d:%s", __FILE__, __LINE__, __FUNCTION__);
fprintf(fatalerrfp,"\n");
#endif
fclose(fatalerrfp);
sleep(1);
}