Created
August 10, 2016 21:49
-
-
Save MagnusTiberius/ee8edb14a9be044b15323eb7ffb410cb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "eipeventd.h" | |
#include <algorithm> | |
#include <cstdlib> | |
#include <memory> | |
#include <string> | |
#include <vector> | |
#include <utility> | |
#include "jansson.h" | |
#include "json.h" | |
#include "timestamp.h" | |
#include "customevent.h" | |
using std::string; | |
using std::vector; | |
using std::unique_ptr; | |
int EipEventD::had_hup = 0; | |
EipEventD::EipEventD() | |
{ | |
} | |
EipEventD::~EipEventD() | |
{ | |
} | |
void EipEventD::Start() | |
{ | |
} | |
/* | |
* Convert the executable to run as a daemon. | |
*/ | |
void EipEventD::daemonize(void) | |
{ | |
pid_t pid, sid, parent; | |
int lfp = -1; | |
/* Already a daemon? */ | |
if (getppid() == 1) { | |
printf("already a daemon\n"); | |
return; | |
} | |
#ifdef SUPPORT_RUN_AS | |
if (getuid() == 0 || geteuid() == 0) { | |
struct passwd *pw = getpwnam(RUN_AS_USER); | |
if (pw) { | |
syslog(LOG_NOTICE, "Setting user to " RUN_AS_USER); | |
setuid(pw->pw_uid); | |
} | |
} | |
#endif | |
/* Trap signals we expect to receive */ | |
signal(SIGCHLD, &EipEventD::child_handler); | |
signal(SIGUSR1, &EipEventD::child_handler); | |
signal(SIGALRM, &EipEventD::child_handler); | |
/* Fork off the parent process */ | |
pid = fork(); | |
if (pid < 0) { | |
syslog(LOG_ERR, "Unable to fork daemon, error (%d)%s", errno, strerror(errno)); | |
printf("Unable to fork daemon, error \n"); | |
exit(EXIT_FAILURE); | |
} | |
/* If we got a good PID, we can exit the parent process */ | |
if (pid > 0) { | |
/* Wait for confirmation from the child via SIGTERM of SIGCHLD, or | |
* for two seconds to elapse (SIGALRM). pause() should not return. | |
*/ | |
alarm(2); | |
pause(); | |
printf("pid > 0\n"); | |
exit(EXIT_FAILURE); | |
} | |
/* At this point we are executing as the child process */ | |
parent = getppid(); | |
/* Catch, Ignore and handle signals */ | |
signal(SIGCHLD, SIG_IGN); /* Ignore child */ | |
signal(SIGTSTP, SIG_IGN); /* Ignore tty signals */ | |
signal(SIGTTOU, SIG_IGN); /* Ignore terminal output signal */ | |
signal(SIGTTIN, SIG_IGN); /* Ignore terminal input signal */ | |
signal(SIGHUP, sighup_handler); | |
signal(SIGTERM, sigterm_handler); | |
/* Change the file mode mask */ | |
umask(027); | |
/* Create a new SID for the child process */ | |
if (setsid() < 0) { | |
syslog(LOG_ERR, "Unable to create a new session, error (%d)%s", errno, strerror(errno)); | |
printf("Unable to create a new session, error \n"); | |
exit(EXIT_FAILURE); | |
} | |
/* Change running directory */ | |
if ((chdir("/")) < 0) { | |
syslog(LOG_ERR, "Unable to change directory to /, error (%d)%s", errno, strerror(errno)); | |
printf("Unable to change directory to /, error\n"); | |
exit(EXIT_FAILURE); | |
} | |
freopen("/dev/null", "r", stdin); | |
//freopen("/dev/null", "w", stdout); | |
//freopen("/dev/null", "w", stderr); | |
/* Tell the parent process that we are okay */ | |
kill(parent, SIGUSR1); | |
} | |
/* | |
* Create the pid file used to keep track of this daemon's current | |
* process id. | |
*/ | |
pid_t EipEventD::create_pidfile(void) | |
{ | |
int fd; | |
pid_t pid; | |
char buf[20]; | |
if ((fd = open(PID_FILE, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) { | |
printf("Unable to open or create pid file: %s\n", PID_FILE); | |
syslog(LOG_ERR, "Unable to open or create pid file %s: (%d)%s", PID_FILE, errno, strerror(errno)); | |
exit(EXIT_FAILURE); | |
} | |
if (flock(fd, LOCK_EX | LOCK_NB) == -1) { | |
printf("Unable to lock pid file\n"); | |
syslog(LOG_ERR, "Unable to lock pid file %s: (%d)%s", PID_FILE, errno, strerror(errno)); | |
exit(EXIT_FAILURE); | |
} | |
/* delete contents of file */ | |
if (ftruncate(fd, 0) == -1) { | |
printf("Unable to truncate pid file\n"); | |
syslog(LOG_ERR, "Unable to truncate pid file %s: (%d)%s", PID_FILE, errno, strerror(errno)); | |
exit(EXIT_FAILURE); | |
} | |
pid = getpid(); | |
snprintf(buf, sizeof(buf), "%ld\n", (long)pid); | |
if (write(fd, buf, strlen(buf)) != strlen(buf)) { | |
printf("Unable to write pid to\n"); | |
syslog(LOG_ERR, "Unable to write pid to %s: (%d)%s", PID_FILE, errno, strerror(errno)); | |
exit(EXIT_FAILURE); | |
} | |
return pid; | |
} | |
/* | |
* Destroy the pid file used to keep track of this daemon's current | |
* process id. | |
*/ | |
int EipEventD::destroy_pidfile() | |
{ | |
return unlink(PID_FILE); | |
} | |
/* | |
* Handle the HUP signal by indicating it has occurred. | |
*/ | |
void EipEventD::sighup_handler(int signum) | |
{ | |
struct sigaction act; | |
memset(&act, 0, sizeof (act)); | |
EipEventD::had_hup = 1; | |
syslog(LOG_NOTICE, "HUP received..."); | |
sigemptyset(&act.sa_mask); | |
act.sa_handler = EipEventD::sighup_handler; | |
sigaction(SIGHUP, &act, NULL); | |
} | |
/* | |
* Handle the TERM signal by exiting. | |
*/ | |
void EipEventD::sigterm_handler(int signum) | |
{ | |
printf("sigterm_handler .... exiting\n"); | |
syslog(LOG_NOTICE, "Exiting..."); | |
closelog(); | |
destroy_pidfile(); | |
exit(EXIT_SUCCESS); | |
} | |
/* | |
* This handler is only present while the parent is running and is intended | |
* to handle signals generated by the child. | |
*/ | |
void EipEventD::child_handler(int signum) | |
{ | |
switch (signum) { | |
case SIGALRM: exit(EXIT_FAILURE); break; | |
case SIGUSR1: exit(EXIT_SUCCESS); break; | |
case SIGCHLD: exit(EXIT_FAILURE); break; | |
} | |
} | |
void EipEventD::print_usage(void) | |
{ | |
printf("Usage: %s [OPTION]...\n" | |
"Copyright (C) 2013-2016 \n" | |
"\n" | |
"Event Daemon\n" | |
"\n" | |
"The following OPTIONS are supported:\n" | |
" -p, --port PORT list on PORT for incoming log messages\n" | |
" --help display this help and exit\n" | |
" --version output version information and exit\n" | |
"\n", prog_name); | |
} | |
void EipEventD::print_version(void) | |
{ | |
printf("%s %s\n", prog_name, xstr(VERSION)); | |
} | |
/* | |
* The main execution loop. | |
*/ | |
void EipEventD::run(const char *port) | |
{ | |
char *message = "ECHO Daemon v1.0 \r\n"; | |
ctr1 = 1; | |
//set of socket descriptors | |
fd_set readfds; | |
ClientEvent clientevent; | |
clientevent.Start(); | |
//initialise all client_socket[] to 0 so not checked | |
for (i = 0; i < max_clients; i++) | |
{ | |
client_socket[i] = 0; | |
} | |
//create a master socket | |
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0) | |
{ | |
perror("socket failed"); | |
exit(EXIT_FAILURE); | |
} | |
//set master socket to allow multiple connections , this is just a good habit, it will work without this | |
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) | |
{ | |
perror("setsockopt"); | |
exit(EXIT_FAILURE); | |
} | |
//type of socket created | |
address.sin_family = AF_INET; | |
address.sin_addr.s_addr = INADDR_ANY; | |
address.sin_port = htons( PORT ); | |
//bind the socket to localhost port 8888 | |
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0) | |
{ | |
perror("bind failed"); | |
exit(EXIT_FAILURE); | |
} | |
printf("Listener on port %d \n", PORT); | |
//try to specify maximum of 3 pending connections for the master socket | |
if (listen(master_socket, 3) < 0) | |
{ | |
perror("listen"); | |
exit(EXIT_FAILURE); | |
} | |
//accept the incoming connection | |
addrlen = sizeof(address); | |
puts("Waiting for connections ..."); | |
while(TRUE) | |
{ | |
//clear the socket set | |
FD_ZERO(&readfds); | |
//add master socket to set | |
FD_SET(master_socket, &readfds); | |
max_sd = master_socket; | |
//add child sockets to set | |
for ( i = 0 ; i < max_clients ; i++) | |
{ | |
//socket descriptor | |
sd = client_socket[i]; | |
//if valid socket descriptor then add to read list | |
if(sd > 0) | |
FD_SET( sd , &readfds); | |
//highest file descriptor number, need it for the select function | |
if(sd > max_sd) | |
max_sd = sd; | |
} | |
//wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely | |
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL); | |
if ((activity < 0) && (errno!=EINTR)) | |
{ | |
printf("select error"); | |
} | |
//If something happened on the master socket , then its an incoming connection | |
if (FD_ISSET(master_socket, &readfds)) | |
{ | |
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) | |
{ | |
perror("accept"); | |
exit(EXIT_FAILURE); | |
} | |
//inform user of socket number - used in send and receive commands | |
printf("New connection , socket fd is %d , ip is : %s , port : %d \n" , new_socket , inet_ntoa(address.sin_addr) , ntohs(address.sin_port)); | |
//send new connection greeting message | |
if( send(new_socket, message, strlen(message), 0) != strlen(message) ) | |
{ | |
perror("send"); | |
} | |
puts("Welcome message sent successfully"); | |
//add new socket to array of sockets | |
for (i = 0; i < max_clients; i++) | |
{ | |
//if position is empty | |
if( client_socket[i] == 0 ) | |
{ | |
client_socket[i] = new_socket; | |
printf("Adding to list of sockets as %d\n" , i); | |
break; | |
} | |
} | |
} | |
//else its some IO operation on some other socket :) | |
for (i = 0; i < max_clients; i++) | |
{ | |
sd = client_socket[i]; | |
if (FD_ISSET( sd , &readfds)) | |
{ | |
//Check if it was for closing , and also read the incoming message | |
if ((valread = read( sd , buffer, 1024)) == 0) | |
{ | |
//Somebody disconnected , get his details and print | |
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addrlen); | |
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port)); | |
//Close the socket and mark as 0 in list for reuse | |
close( sd ); | |
client_socket[i] = 0; | |
} | |
//Echo back the message that came in | |
else | |
{ | |
//set the string terminating NULL byte on the end of the data read | |
buffer[valread] = '\0'; | |
send(sd , buffer , strlen(buffer) , 0 ); | |
if (false) | |
{ | |
puts("Creating custom event"); | |
CustomEvent ce(clientevent.GetClient(), "TestEvent"); | |
puts("Get root node"); | |
ma_xml_node_t *root_node = ce.GetRootNode(); | |
ma_xml_node_t *node1; | |
ce.CreateNode(root_node, "Node1", node1); | |
puts("event send"); | |
ce.Send(); | |
} | |
if(true) | |
{ | |
printf("event send ==================...====== %d =====================\n", ctr1); | |
ma_error_t rc = MA_OK; | |
ma_custom_event_t *event = NULL; | |
ma_xml_node_t *root_node = NULL; | |
rc = ma_custom_event_create(clientevent.GetClient(), "VirusDetectionEvent", &event, &root_node); | |
ma_xml_node_t *ScannerSoftware_node = NULL; | |
ma_custom_event_node_create(root_node, "ScannerSoftware", &ScannerSoftware_node); | |
ma_custom_event_node_attribute_set(ScannerSoftware_node, "ProductName", "VirusScan Enterprise"); | |
ma_xml_node_t *node = NULL; | |
ma_custom_event_node_create(ScannerSoftware_node, "ProductName", &node); | |
ma_custom_event_node_set_data(node, "VirusScan Enterprise"); | |
rc = ma_custom_event_send(event); | |
rc = ma_custom_event_release(event); | |
printf("event send ==================^^^====== %d =====================\n", ctr1); | |
ctr1++; | |
} | |
} | |
} | |
} | |
} | |
printf("exiting loop\n"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment